Development Choices

Define and validate arguments for MCP prompts

Author
Joseph TrasattiMember of technical staff
Published
Section
MCP
Length
6 min read3 sources cited

Define each prompt argument with a stable name, a useful description, and an explicit required flag. On every prompts/get call, validate the final argument map before rendering. Completion may suggest valid values and improve data entry, but direct callers can bypass it, so it cannot enforce the prompt’s contract.

Prerequisites

An MCP prompt is listed, arguments are collected and validated, and messages are returned
Client-side controls improve entry; server-side checks enforce the contract.

Your server needs a prompt template and a clear contract for every value inserted into it: which values must be present, which may be omitted, and what makes a supplied string acceptable. If the server exposes prompts, it must declare the prompts capability during initialization. Treat that declaration as part of capability negotiation between MCP clients and servers, not as proof that any particular client will render your preferred form.

Steps

  1. Describe the arguments in the prompt definition

    Return an arguments array with the prompt from prompts/list. The MCP prompt specification dated 2025-11-25 defines prompts as user-controlled templates that clients can list and retrieve. Each argument has a programmatic name, an optional human-readable description, and an optional required flag.

    In practice, supply all three. The name gives the client the key it must place in params.arguments. The description tells the user what value belongs under that key. The required flag tells the client whether it should collect a value before requesting the prompt. Without those fields, a client may still invoke the prompt, but it has less information for building a useful entry form.

    {
      "name": "review_deployment",
      "description": "Review a deployment against its target environment",
      "arguments": [
        {
          "name": "environment",
          "description": "Target environment, such as staging or production",
          "required": true
        },
        {
          "name": "service",
          "description": "Service to focus on; omit to review the whole deployment",
          "required": false
        }
      ]
    }

    Keep names stable once clients depend on them. A renamed argument is a changed request contract even if the visible description remains the same. Descriptions should state the condition the value must satisfy, not merely repeat the name.

  2. Make requiredness match the template’s real dependency

    Mark an argument required when the server cannot produce the intended prompt without it. Leave it optional only when the renderer has defined behaviour for its absence. Do not mark a value optional because one client happens to remember or prefill it.

    The 2025-11-25 MCP schema reference makes PromptArgument.name mandatory while description and required are optional. It also defines GetPromptRequestParams.arguments as an optional map whose values are strings. That wire-level shape does not express application rules such as an allowed set of environment names, a maximum useful length, or whether an empty string is acceptable. Record those rules in the server’s validation logic.

    There is a concrete tradeoff. Requiring too much makes clients collect values that the renderer could have defaulted or omitted. Requiring too little moves failure from data entry into prompt rendering, where the error is harder to explain. The right test is whether omission has an intentional result.

  3. Validate the final prompts/get request on the server

    Run validation when the server receives prompts/get, before interpolating values or reading resources selected by those values. Prompt metadata helps a client collect arguments; it is not an enforcement boundary. MCP does not require clients to use a server’s preferred user interface, and a client can construct the JSON-RPC request directly.

    At minimum, validation should check the prompt name, the presence of every required argument, and every value constraint on which the renderer relies. Decide explicitly how the server handles undeclared argument names and empty strings. The protocol specifies -32602 (Invalid params) for an invalid prompt name or missing required arguments; internal failures use -32603 instead. A caller error should not be disguised as a rendering failure.

    function validateReviewDeployment(args: Record<string, string> | undefined) {
      if (!args || !args.environment) {
        throw invalidParams('environment is required')
      }
    
      const environments = new Set(['staging', 'production'])
      if (!environments.has(args.environment)) {
        throw invalidParams('environment must be staging or production')
      }
    
      return {
        environment: args.environment,
        service: args.service
      }
    }

    The allowed values in this example belong to the example server, not to MCP. The important mechanism is that the server owns the rule and applies it to the received map. Client-side checks can reduce mistakes, but they cannot protect the renderer from another client, a script, or an older cached interface.

  4. Render only from validated values

    Pass the validator’s result—not the original request object—to the prompt renderer. This creates a narrow boundary: request parsing produces untrusted strings, validation produces the values the template is allowed to use, and rendering produces the returned prompt messages.

    Do not let a fallback silently contradict the advertised required flag. If environment is required, substituting production when it is absent makes the published contract false and can produce a materially different prompt from the one the caller requested. If a default is legitimate, make the argument optional and define that default as part of the server’s behaviour.

    Validation also has to happen before an argument selects a server-side resource. The prompt specification requires implementations to validate inputs and outputs to prevent injection or unauthorized resource access. A descriptive argument field cannot constrain what a direct caller sends.

  5. Add completion only where suggestions improve entry

    If an argument has a discoverable or context-dependent value set, support completion/complete and declare the completions capability. The MCP completion specification dated 2025-11-25 lets a client send a prompt reference, an argument name, and the value typed so far. For prompts with several arguments, the client can also include previously resolved arguments as context.

    Completion is useful for values such as a service name filtered by the selected environment. It can rank suggestions and return up to 100 values, with optional total and hasMore fields. Implement the full interaction as argument completion for MCP prompts and resource templates when users would otherwise need to recall identifiers exactly.

    Do not add completion to a free-text field merely to duplicate its description. It creates extra requests, rate-limiting work, and another input surface to validate without narrowing the final contract.

  6. Keep completion and final validation separate

    Validate inputs to completion/complete, including the prompt reference, argument name, partial value, and any contextual arguments. Suggestions can expose sensitive identifiers if access checks are weaker on completion than on prompts/get.

    Then validate the completed value again when it arrives in prompts/get. A completion response is a suggestion, not a reservation or proof. The underlying data may change between the two requests, the user may edit a suggested value, and the client may skip completion entirely. Argument completion can improve entry, but it does not replace validation of the final get request.

  7. Test through the protocol boundary

    Exercise prompts/get directly rather than testing only through the client interface you expect users to see. Cover a valid request, each missing required argument, each rejected value class, omission of every optional argument, and the server’s chosen treatment of undeclared names. Verify that caller errors return -32602 and that invalid values never reach rendering.

    If completion is enabled, test it separately with partial and contextual values. Also send a valid final value without calling completion first. That last case proves the server accepts protocol-valid direct callers while still enforcing its own prompt contract.

Expected result

A completed implementation advertises named, described, explicitly required or optional prompt arguments; clients can collect values from that metadata; and every prompts/get request is validated before rendering. Completion may make valid values easier to enter, while the server remains the authority that accepts or rejects the final argument map.

Sources

  1. MCP prompt specification dated 2025-11-25modelcontextprotocol.io
  2. 2025-11-25 MCP schema referencemodelcontextprotocol.io
  3. MCP completion specification dated 2025-11-25modelcontextprotocol.io

See also