Overview
Elicitation lets a server ask the user for input in the middle of a request. In the 2026-07-28 revision the server cannot send a request to the client; it uses the multi round-trip requests (MRTR) pattern. It answers tools/call, resources/read, or prompts/get with an InputRequiredResult carrying an elicitation/create request, the client collects the answer, and it retries the original request under a new JSON-RPC id with the user’s reply attached. Clients declare support per request in _meta.io.modelcontextprotocol/clientCapabilities as elicitation: { form: {}, url: {} }; an empty elicitation: {} means form mode only, and a server must not send a mode the client did not declare. See mcp-protocol.
Use elicitation for one missing value, not a wizard
Ask when a tool cannot proceed without a value it cannot get itself: pick one of three discovered environments, confirm a destructive action. Each elicitation is a single, well-scoped interruption. Decompose multi-step flows into separate tool calls.
Carry state in requestState, not in server memory
The server returns inputRequests (a map of server-assigned keys to requests) and optionally an opaque requestState. The client must echo requestState unchanged on the retry and must put the user’s replies under the same keys in inputResponses.
{ "resultType": "input_required",
"inputRequests": { "env": { "method": "elicitation/create", "params": {
"mode": "form", "message": "Which environment should I deploy to?",
"requestedSchema": { "type": "object",
"properties": { "environment": { "type": "string", "enum": ["staging", "production"] } },
"required": ["environment"] } } } },
"requestState": "<signed blob>" }Treat requestState as attacker-controlled input. If it influences authorization or logic, protect it with an HMAC or AEAD, reject state that fails verification, and bind it to the authenticated principal, a short expiry, and the originating request. These bound replay but do not make state single-use; enforce that server-side for one-time actions. Every InputRequiredResult needs at least one of inputRequests or requestState.
Keep form schemas flat
Form mode collects data in-band against a restricted JSON Schema: a flat object of string (with minLength, maxLength, and formats email, uri, date, date-time), number or integer, boolean, and enum properties, including single and multi-select enums with titles. Nested objects and arrays of objects are not supported; collect structured input over several calls or in the tool arguments.
Handle all three response actions
accept: the user submittedcontentthat matches the schema; proceed.decline: the user refused explicitly; abort cleanly and offer alternatives.cancel: the user dismissed the dialog; make no assumption and do not apply defaults.
Treating decline or cancel as an empty accept acts on input nobody gave. If the client fails to send everything requested, return a new InputRequiredResult rather than an error.
Use URL mode for secrets and third-party OAuth
Form mode must never request passwords, API keys, access tokens, or payment credentials. URL mode (mode: "url", a url, and a message) sends the user to a page outside the client, so the data never passes through the client or the model. accept means only that the user consented to open the URL; the server learns the outcome when the client retries and it checks its own state. URL mode is for credentials the server needs from third parties, not for authorizing the client to your server.
- Never put user data or a pre-authenticated link in the URL, and use HTTPS outside development.
- Verify that the user who opens the URL is the user who started the elicitation (compare the
subclaim to your session) to block phishing and account takeover. - Clients must show the full URL, require consent, not prefetch it, and open it in a context the client and model cannot inspect.
Validate elicited values on the server
Re-validate replies against the schema server-side and never trust a client-supplied identity such as “I am joe@example.com”. A malicious server can use elicitation for social engineering; clients must show which server is asking and offer a clear decline. See mcp-security and prompt-injection-defense.