What is ElicitRequest?
ElicitRequest is the message type a server sends when it needs structured input from the user during an active tool call or workflow — before it can proceed. Unlike tool results or resource reads, which flow automatically, elicitation introduces a human decision point into the MCP message graph. The server initiates the round-trip by sending an elicitation/create request to the client, which then surfaces UI to the user and returns the response. This makes ElicitRequest fundamentally different from sampling or tool invocations: the server is not asking the LLM for anything — it is asking the end user directly. The API surface exposes two modes. In "form" mode, the server supplies a requestedSchema (a JSON Schema object) that the client uses to render a type-safe input form; the response carries back validated user data. In "url" mode, the server provides a URL — typically an OAuth flow or a sensitive data entry page hosted out-of-band — and the client is expected to open it. The params.message string is always required and serves as the human-readable prompt shown to the user. The optional elicitationId allows servers to correlate responses when multiple elicitations are in flight. Servers must treat user responses as non-deterministic: the user may accept (with data), decline (without data), or cancel entirely. Failing to handle all three states is a common production bug — silently assuming a successful accept leads to null-pointer errors downstream. The requestedSchema field should be kept narrow and flat; deeply nested schemas are valid JSON Schema but many client implementations only render a single level of properties reliably, so complex nested objects should be decomposed into sequential elicitations.
When to use
When you need user input mid-tool-call (booking confirmation, missing parameters, OAuth).
When NOT to use
For sensitive data in form mode — use url mode instead.
Notes
Handle all three response states
Every elicitation can resolve as accepted, declined, or cancelled — these are distinct states, not just success vs failure. Declined means the user saw the prompt and said no; cancelled means they dismissed the dialog without choosing. Treating declined and cancelled as equivalent to accepted (by not branching on the action field) is the most common production bug in server implementations.
Keep requestedSchema flat and minimal
While requestedSchema accepts any valid JSON Schema, client implementations vary widely in how deeply they render nested object properties. Stick to a flat object with scalar properties (string, number, boolean, enum) for maximum compatibility. If you need multi-step input, chain sequential elicitations rather than embedding deeply nested schemas in a single request.
url mode is for sensitive or OAuth flows
The url mode exists specifically for cases where the client must open an external page — OAuth authorization, payment entry, or anything the server does not want to handle inline. The client is responsible for browser launch; the server receives no data from the URL visit itself unless the out-of-band flow delivers a token back through a separate channel. Do not use url mode for simple text prompts.
elicitationId is optional but worth using
The elicitationId field lets a server match a response back to its originating request when concurrent elicitations are possible. Without it, servers relying on call ordering for correlation are fragile under concurrent tool calls. Generate a short UUID or deterministic hash per elicitation and always echo it in logs to simplify debugging.
message is user-facing copy, not schema docs
The params.message string is rendered directly to the end user by the client, so it should be written as clear, non-technical instructions — not as a field description or schema comment. Keep it under 200 characters; some client surfaces truncate longer messages. Localization of this string is the server's responsibility since MCP does not negotiate locale.
Fields
| Field | Type | Required | Purpose |
|---|---|---|---|
| method | 'elicitation/create' | yes | Method identifier. |
| params.mode | 'form' | 'url' | yes | Form or URL elicitation. |
| params.message | string | yes | Explanation shown to the user. |
| params.requestedSchema | JSON Schema? | no | Required for form mode. |
| params.url | string? | no | Required for url mode. |
| params.elicitationId | string? | no | Required for url mode (for completion notifications). |
Examples
Form elicitation
{
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please confirm your booking.",
"requestedSchema": {
"type": "object",
"properties": { "confirm": { "type": "boolean" } },
"required": ["confirm"]
}
}
}
Common mistakes
❌ Treating decline like cancel
✅ Decline is explicit refusal; cancel is dismissal — handle separately.