MCP Elicitation Explained: How Servers Request User Input Mid-Workflow
MCP elicitation lets servers pause mid-workflow and ask users for structured input instead of guessing. Here's how it works, with real code examples and security rules.
Mohammed Kafeel
Machine Learning Researcher
On this page
- What Is MCP Elicitation?
- Why Does MCP Elicitation Matter?
- How Does MCP Elicitation Work? (Step-by-Step)
- What Data Types Can You Request?
- The Two Modes of MCP Elicitation
- Real-World Use Cases for MCP Elicitation
- Security Rules You Must Follow
- Which MCP Clients Support Elicitation?
- MCP Elicitation vs. Other Approaches
- How to Implement MCP Elicitation (Quick Start)
- Key Takeaways
- Frequently Asked Questions
- Ready to Build With It?
- Useful Sources
Picture this: you ask your AI agent to schedule a team standup for "tomorrow morning." It doesn't know your timezone. Instead of asking, it books the meeting at 9 AM UTC - which is 2 AM for your team in Chicago. Or worse: you tell it to "clean up the old project files," and it silently deletes 47 folders you actually needed, because it had to guess what "old" meant.
That's exactly what MCP elicitation solves.
What Is MCP Elicitation?
MCP elicitation is a runtime capability in the Model Context Protocol (MCP) that lets servers pause a workflow and ask the user for structured input before continuing. Think of it as a formalized "human-in-the-loop" handshake - the server hits a decision point, raises its hand, and waits for a real answer before proceeding.
It was introduced as a first-class feature in MCP spec version 2025-06-18, with URL mode added in the subsequent spec version 2025-11-25. (New to the protocol? Start with what MCP is.)
Before elicitation existed, the two options were ugly: either the AI model guessed (and got it wrong), or it asked via chat in plain text - which is unstructured, hard to validate, and easy to misinterpret. Elicitation replaces both with a clean, schema-validated, mid-workflow prompt that the client renders as a native UI form.
The human-in-the-loop concept here is simple. The server doesn't have to be omniscient. It can pause, collect exactly the piece of context it's missing, and then resume - with validated data, not a best guess. (For the broader pattern, see human-in-the-loop workflows.)
Why Does MCP Elicitation Matter?
The core problem elicitation solves is missing context at runtime. Workflows often start with incomplete information, and the old approaches - guessing, hallucinating, or asking in chat - are all unreliable.
Here's where guessing goes badly wrong:
- Wrong timezone - a scheduling tool books a meeting at the wrong local time for the user's team.
- Wrong account - a deployment tool pushes to the wrong AWS account because the user has three and didn't specify.
- Wrong scope - a cleanup script deletes files in the wrong directory because "old" was ambiguous.
- Irreversible action without confirmation - an email tool sends a mass message before the user realizes it was going to all 2,000 contacts.
Structured data beats conversational back-and-forth in every one of these cases. A schema-validated form field for timezone is faster, more reliable, and machine-readable. No parsing, no ambiguity, no "did you mean America/Chicago or US/Central?"
The MCP spec introduced elicitation in June 2025 as a first-class protocol feature - not a workaround, not a convention. It's now part of the official elicitation client capability.
How Does MCP Elicitation Work? (Step-by-Step)
Here's the full lifecycle of an MCP elicitation request, from the moment the server realizes it's missing something to the moment the workflow resumes.
Step 1 - The Server Detects Missing Information
During tool execution, the server hits a point where it can't safely continue without more context. It doesn't guess. It doesn't fabricate. It stops and prepares a request.
Example: A scheduling tool is about to book a meeting. It has the title, the attendees, and the date - but not the user's timezone. Without it, any time it picks is a coin flip.
Step 2 - The Server Sends an elicitation/create Request
The server sends a JSON-RPC message to the MCP client. The message has two key parts: message (what the user sees) and requestedSchema (the shape of the data the server expects back, defined as JSON Schema).
{
"jsonrpc": "2.0",
"id": 1,
"method": "elicitation/create",
"params": {
"message": "What timezone are you in?",
"requestedSchema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "Your local timezone (e.g., America/New_York)"
}
},
"required": ["timezone"]
}
}
}
The message field is the human-readable prompt. The requestedSchema tells the client exactly what to collect and validate - so there's no ambiguity on either end.
Step 3 - The Client Shows a UI Prompt
The MCP client - whether that's VS Code, Claude Desktop, or MCP Inspector - renders a native UI form based on the schema. This is not a chat message. It's a proper input form, generated automatically from the JSON Schema definition. (You can try the flow end-to-end in MCP Inspector.)
The user sees a labeled field, fills it in, and gets three buttons: Accept, Decline, and Cancel.
Step 4 - The User Responds (Accept, Decline, or Cancel)
There are exactly three possible responses. Each means something different, and your server needs to handle all three:
| Response | Meaning | What the server should do |
|---|---|---|
accept |
User filled in the form and submitted | Continue workflow with the provided data |
decline |
User chose not to provide the info | Gracefully degrade or offer an alternative |
cancel |
User dismissed the prompt entirely | Treat as workflow interruption; stop or ask again |
Here's what an accept response looks like on the wire:
{
"action": "accept",
"content": {
"timezone": "America/Chicago"
}
}
Step 5 - The Workflow Resumes
The server receives the response, validates the content against the schema, and continues execution with the user-provided data. Clean, deterministic, no guessing.
One rule you can't skip: servers MUST handle decline and cancel gracefully. Never assume the user will always accept. A server that hangs or crashes on a decline is broken by design.
What Data Types Can You Request?
Elicitation supports a flat JSON Schema subset - no nested objects, no $ref, no anyOf, no complex arrays. This is intentional: it keeps client implementations simple and ensures any compliant client can render the form.
Here's what you can use:
| Type | Use case | Special options |
|---|---|---|
string |
Names, usernames, free text | formats: email, uri, date, date-time; minLength, maxLength, pattern |
number / integer |
Quantities, limits, counts | minimum, maximum, default |
boolean |
Yes/No confirmations | default |
enum |
Single-select from a list | enum array or oneOf with const/title |
array |
Multi-select from a list | items with enum |
Not supported: nested objects, $ref, anyOf, and complex arrays. If you need those, you're outside the spec's elicitation scope.
The Two Modes of MCP Elicitation
Elicitation in MCP comes in two flavors, and choosing the right one matters a lot for security.
Form Mode (In-Band) - The Default
In form mode, the data flows through the MCP client and is visible to the LLM. The client renders a form, the user fills it in, and the response travels back through the protocol.
Best for: non-sensitive info - names, preferences, confirmations, dates, timezone, repo selection.
Requires: MCP protocol version 2025-06-18 or later, with the elicitation capability declared during the initialize handshake.
This is the mode you'll use for 90% of MCP workflow user input scenarios.
URL Mode (Out-of-Band) - For Sensitive Data
URL mode was introduced in spec version 2025-11-25. Instead of a schema, the server sends a URL. The user completes the interaction in a browser. The data never passes through the MCP client or the LLM - it stays fully private.
Best for: OAuth flows, API key entry, payment info, credentials, anything that shouldn't touch the protocol stack.
Here's what a URL mode elicitation request looks like:
{
"jsonrpc": "2.0",
"id": 3,
"method": "elicitation/create",
"params": {
"mode": "url",
"elicitationId": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://mcp.example.com/ui/set_api_key",
"message": "Please provide your API key to continue."
}
}
If a client doesn't support URL mode, it returns error code -32042 (URLElicitationRequiredError). Your server should handle this gracefully too.
Real-World Use Cases for MCP Elicitation
Here's where elicitation in MCP really shines. These aren't toy examples - they're the scenarios that make the difference between a tool users trust and one they don't.
1. Confirming Irreversible Actions
Before deleting files, sending emails, deploying code, or dropping a database - ask. A single confirmation prompt prevents catastrophic mistakes.
Example: "You're about to delete 47 files in /projects/legacy. Type 'confirm' to proceed." The server waits for accept before touching anything.
2. Resolving Ambiguity at Runtime
A user has multiple GitHub repos, AWS accounts, or Stripe subscriptions. The server can't know which one. Instead of picking randomly, it asks.
Example: "Which GitHub repo should I push to?" - rendered as a dropdown of the user's repos, populated dynamically.
3. Collecting Missing Context
Timezone, locale, deadline, team size - info the server needs but wasn't given upfront. This is the classic MCP workflow user input scenario.
Example: A scheduling tool asks for timezone before booking a meeting. Simple, targeted, zero ambiguity.
4. Progressive Input Gathering
Complex workflows that need info in stages: first the deadline, then team size, then budget. FastMCP's multi-turn elicitation pattern handles this elegantly - you chain multiple ctx.elicit() calls, each waiting for the previous answer.
Better UX than a giant form upfront. Ask only what's needed, exactly when it's needed.
5. Secure Authentication Flows (URL Mode)
OAuth, API key entry, payment - redirect the user to a secure URL. The data never touches the LLM. This is the MCP human-in-the-loop pattern for sensitive credentials, and it's the right way to handle anything you wouldn't want logged.
Security Rules You Must Follow
This section is non-negotiable. Get it wrong and you're either building a broken server or a security hole.
What Servers MUST NOT Request (Form Mode)
Never use form mode to collect:
- Passwords or passphrases
- API keys or access tokens
- Payment card numbers
- Social Security Numbers or national IDs
- Any personally identifiable information (PII)
Use URL mode for all of the above. The spec is explicit: servers MUST NOT use elicitation to request sensitive information through the in-band flow.
What Clients Should Do
- Show which server is making the request - especially in multi-server setups. Transparency is mandatory.
- Let users approve or deny elicitation per-server - users should be able to block a specific server from ever eliciting.
- Implement rate limiting - a misbehaving server shouldn't be able to spam the user with 50 prompts in a row.
- Validate all responses against the declared schema - don't trust the data just because the user submitted it.
- Display the target domain clearly before opening any URL in URL mode (SSRF prevention).
What Servers Should Do
- Always handle
declineandcancelgracefully - never crash, hang, or loop infinitely. - Validate the response content before using it in your workflow logic.
- Never store sensitive data beyond immediate use - if you asked for a timezone, use it and move on.
- Implement rate limiting on your end too - don't send elicitation requests in a tight loop.
Which MCP Clients Support Elicitation?
Not every client supports elicitation yet. Here's the current landscape as of June 2025:
- VS Code (Insiders build) - the first major client to ship a native elicitation UI, integrated directly into the Command Palette-style interface.
- Claude Desktop - check the official Anthropic docs for current support status, as it evolves quickly.
- MCP Inspector - the official testing tool supports elicitation, making it ideal for dev and debugging workflows.
- FastMCP framework - server-side Python library with built-in
ctx.elicit()support. The cleanest way to add elicitation to a new server. - AI SDK (Vercel) - elicitation support is tracked in GitHub issue #7978 but is not yet implemented as of mid-2026. Use FastMCP or the raw MCP SDK for now.
Critical rule: clients MUST declare the elicitation capability during the initialize handshake. If they don't, servers cannot send elicitation requests - the protocol won't allow it. (Its sibling capability, where the server asks the model for a completion rather than the user for input, is covered in MCP sampling.)
MCP Elicitation vs. Other Approaches
Here's how model context protocol elicitation stacks up against the alternatives:
| Approach | How it works | Structured data? | Secure for credentials? | Mid-workflow? |
|---|---|---|---|---|
| MCP Elicitation (Form) | Server requests schema-validated input | ✅ Yes | ❌ No | ✅ Yes |
| MCP Elicitation (URL) | Server redirects to secure URL | N/A | ✅ Yes | ✅ Yes |
| Chat/conversational | LLM asks in chat, parses response | ❌ No | ❌ No | ✅ Yes |
| Upfront tool parameters | All input required before tool runs | ✅ Yes | ❌ No | ❌ No |
| Custom tool for input | Build a dedicated input-collection tool | ✅ Yes | ❌ No | ✅ Yes |
The chat approach is the most common today - and the most fragile. Parsing "America/Chicago" out of a free-text response is fine until the user types "Chicago time" or "CST" or "same as New York but one hour behind." Elicitation eliminates that entire class of bug. (Elicitation is a runtime capability rather than one of the core building blocks covered in our MCP primitives overview.)
How to Implement MCP Elicitation (Quick Start)
Here's what you actually need to write. Two sides: server and client.
Server Side (Node.js / TypeScript Example)
The key is calling server.request() with the elicitation/create method and handling all three response actions:
// Example: Request user's timezone during tool execution
async function requestTimezone(server: McpServer): Promise<string | null> {
const response = await server.request(
{
method: "elicitation/create",
params: {
message: "What timezone are you in?",
requestedSchema: {
type: "object",
properties: {
timezone: { type: "string", description: "e.g. America/New_York" }
},
required: ["timezone"]
}
}
},
ElicitResultSchema
);
if (response.action === "accept") {
return response.content.timezone;
}
return null; // Handle decline/cancel gracefully
}
If you're using FastMCP (Python), it's even cleaner - ctx.elicit() handles the protocol details for you and returns a typed result object with .action and .data.
Client Side - Declaring Elicitation Capability
During the initialize handshake, the client must include the elicitation capability. Without this declaration, the server cannot send elicitation requests - the protocol blocks it entirely.
{
"capabilities": {
"elicitation": {}
}
}
That's it. One object. But it's the gate that enables the whole feature.
Key Takeaways
Let's recap the essentials before the FAQ:
- MCP elicitation is a runtime mechanism for servers to request structured user input mid-workflow - no guessing, no chat parsing.
- It was introduced in MCP spec 2025-06-18 (June 18, 2025). URL mode arrived in spec 2025-11-25.
- Servers send
elicitation/createwith a flat JSON Schema. Clients render a native form. Users respond withaccept,decline, orcancel. - Form mode is for non-sensitive data. URL mode is for credentials and OAuth - data never touches the LLM.
- Servers must handle
declineandcancelgracefully. Clients must declare theelicitationcapability at init. - VS Code Insiders and MCP Inspector support it today. FastMCP makes server-side implementation trivial.
Frequently Asked Questions
What is MCP elicitation?
MCP elicitation is a runtime feature in the Model Context Protocol that lets servers pause a workflow and ask the user for structured, schema-validated input before continuing. It's the official "human-in-the-loop" mechanism built into the MCP spec.
When was MCP elicitation introduced?
Elicitation was introduced as a first-class feature in MCP spec version 2025-06-18, released on June 18, 2025. URL mode elicitation - for out-of-band sensitive data flows - was added in the subsequent spec version 2025-11-25.
Is MCP elicitation secure for passwords and API keys?
Form mode: no. The spec explicitly prohibits servers from requesting sensitive information (passwords, API keys, tokens, PII) through the in-band elicitation flow. URL mode: yes. URL mode redirects the user to a browser-based flow where sensitive data never passes through the MCP client or the LLM.
Which MCP clients support elicitation?
As of June 2025: VS Code Insiders (first major client with native UI), MCP Inspector (for testing), and FastMCP (server-side framework). Claude Desktop support is evolving - check the official MCP docs. The Vercel AI SDK does not yet support elicitation (tracked in GitHub issue #7978).
What happens if a user declines an elicitation request?
The server receives a response with action: "decline". It must handle this gracefully - offering an alternative path, skipping the step, or stopping the workflow cleanly. A server that crashes or hangs on a decline is non-compliant and broken. The same applies to cancel.
How is MCP elicitation different from just asking in chat?
Chat-based asking is unstructured: the LLM asks in plain text, the user responds in plain text, and something has to parse the answer - which fails on edge cases. MCP elicitation is structured, validated, and rendered as a native UI form. The client generates the form from a JSON Schema, validates the input before sending it back, and the server gets clean, typed data. No parsing, no ambiguity.
Ready to Build With It?
If you're building an MCP server and you've been working around missing context with guesses or chat prompts, elicitation is worth adding today. The VS Code Insiders build supports it natively, FastMCP makes the server side trivial, and the spec is stable enough to build on.
Start with the official MCP elicitation spec for the authoritative reference. Then check the FastMCP elicitation docs for the cleanest server-side implementation path.
Useful Sources
- MCP Specification - Elicitation (2025-06-18) - Official spec page, the authoritative reference for all protocol details.
- WorkOS Blog - MCP Elicitation: Request User Input at Runtime - Excellent explainer with diagrams and security breakdown.
- den.dev - Stop Guessing: MCP Elicitations Come to VS Code - First-hand walkthrough of VS Code Insiders implementation with real code.
- FastMCP - User Elicitation Docs - Complete server-side reference for
ctx.elicit()with Python examples. - MCP Specification - URL Mode Elicitation (2025-11-25) - Spec page for the out-of-band URL mode introduced in November 2025.
Keep reading
The Three-Layer AI Agent Stack: MCP, A2A, and Streamable HTTP Explained
MCP, A2A, and Streamable HTTP are the three protocols that form the modern AI agent stack. Here's exactly how they fit together — and why it matters for every developer building with AI.
MCP Sampling Explained: How Servers Query LLMs During Tool Execution
MCP sampling lets servers request LLM completions through the client — no API keys required. Here's the full technical breakdown, with the schema, a Python example, and security rules.
Best MCP Servers in 2026: GitHub, Notion, Google Drive, and More
There are over 9,600 MCP servers out there — but only a handful are worth your time. Here's a curated breakdown of the best MCP servers in 2026, with setup tips and real use cases.



