Skip to content
Model Context Protocol (MCP)Elicitation

Senior · 7 chapters

Elicitation

A server requesting structured input from the user mid-operation

Elicitation is valuable only when the missing value belongs to the user; unsupported clients, abandoned prompts, and ambiguous failures otherwise turn a recoverable operation into a stuck agent.

Read these first

What you will know

  • Implement a server that asks the user for input mid-operation

    Preserve the operation’s correlation and state across the pause so the response is applied to the correct request rather than a later or concurrent one.

  • Run the operation against a client that supports elicitation and one that does not, recording the resulting behavior

    Capability gaps are common at the integration boundary, and an unsupported request must produce a controlled fallback rather than an opaque protocol error.

  • Validate elicited values against a schema before using them in the operation

    Treat user input as untrusted and incomplete: enforce types, bounds, required fields, and any authorization constraints before it reaches a tool or model.

  • Instrument timeout, cancellation, decline, disconnect, and malformed-response paths

    These cases must terminate the pending operation with distinct diagnostics instead of leaving server resources or agent runs waiting indefinitely.

  • Compare elicitation with returning a useful error using a stated decision rule, then implement the chosen behavior

    Ask when the user owns an unknowable value and recovery is plausible; otherwise a precise error is less disruptive than an unnecessary prompt.


Chapters

  1. 1

    Elicitation and value ownership

    Elicitation is a server asking the user for a value in the middle of handling a tool call, and the test for reaching for it is not whether a required field is missing but whether the user is the only party who could fill it. A room name sitting in the calendar invite the model already has belongs in a precise error, not retyped by a person you interrupted; a currency that is genuinely the user's choice is worth asking for. A room that is already booked is a different case, because the value it needs did not exist until the conflict did.

  2. 2

    Confirmations and destructiveHint

    The previous chapter's rule decides missing data, and a confirmation is not missing data: nobody is being asked for a datum, somebody is being asked to approve an action. That makes the real choice three-way rather than two — elicit when the user owns a value you cannot derive, return a precise error when the value is already in something you hold, and for an action that needs approval declare the tool destructive and let the host run the confirmation flow it already runs. A server that opens its own approval dialog has taken over a decision the host was making anyway, and it has no answer at all for the clients that cannot elicit.

  3. 3

    The elicitation capability check

    A client that never declared elicitation must never be sent an elicitation request, and the answer was in the initialize response all along. Sending it anyway and waiting for an error is what produces the partner report that the tool hangs forever, because what comes back may be nothing at all. Define the fallback with the previous chapter's three-way rule in hand: a precise error naming what is missing, or — when what you actually wanted was approval rather than a value — the destructive annotation that lets the host confirm, and never a silent decision to proceed.

  4. 4

    The requestedSchema restriction

    The schema you may request is one level deep — strings, numbers, booleans and enums — so a shipping address with a nested country object flattens to a code field, and the restriction follows from the fact that a client has to render it for a server it has never seen. Defaults and constraints have to be designed inside that limit. Some things must not be asked for at all: a database password belongs out of band, and eliciting it trains users to type secrets into whatever dialog appears.

  5. 5

    Accept, decline and cancel

    An elicitation response carries one of three actions, and a dismissed dialog is not a refusal, so a handler with two branches has already lost what the third outcome carried. Two concurrent create_ticket calls each eliciting a priority land correctly only if the pending operation is keyed to the elicitation request id rather than to the session. Timeout, cancellation, disconnect and malformed responses each terminate the operation with their own diagnostic instead of leaving it waiting.

  6. 6

    Validating the elicited value

    A minimum of 0 and a maximum of 100000 in the requested schema did not stop -1 and 4e9 reaching production, and neither value requires a malicious client: the schema is a rendering and UX hint, and a client that validates is being helpful rather than discharging an obligation. Enforce types, bounds, required fields and authorization constraints on arrival, before the value reaches a tool or a model. Tightening the schema further changes nothing, and an enum you built from a permission check is not a permission check.

  7. 7

    Prompts per operation

    A migrate_workspace tool that asks for source, target, conflict strategy and a final confirmation loses two-thirds of its users, and one host renders each prompt as its own modal. Combining them into a single flat elicitation is an improvement rather than the answer, since a per-collection conflict strategy will not fit the schema and four decisions before anything happens is the same interruption on one screen. Sorting each prompt into the three mechanisms disposes of three of the four, and plan-then-apply moves the survivor to a point where the answer exists.

External resources