MCP elicitation in 2026: the server-initiated request is gone, and page one has not noticed
Elicitation has been in MCP since June 2025, but the current 2026-07-28 revision changed how it is delivered and calls the old pattern a breaking change. A field log on the three-revision diff, why elicitationId became requestState, and why the statefulness advice inverted.
On this page
Quick answer
Elicitation is how an MCP server asks the human a question in the middle of a tool call instead of guessing or failing. It has been in the Model Context Protocol since the 2025-06-18 revision. What changed is how it gets delivered: in the current 2026-07-28 revision, servers no longer send elicitation/create as a server-initiated request. They return an InputRequiredResult, the client collects the answer, and the client retries the original call (MCP spec, 2026). The spec calls the old pattern a breaking change and says it is no longer supported. Almost everything ranking for this query still teaches the old pattern.
I went looking for a worked example of elicitation and found eight of them. Seven describe a mechanism that is no longer in the spec. This is the log of noticing that, and of working out what actually replaced it.
The version you are reading is probably the middle one
There are three revisions of elicitation, and they are genuinely different. I fetched all three.
2025-06-18 introduced it. The page says so in its own words: "Elicitation is newly introduced in this version of the specification." Form mode only. No URL mode, no elicitationId.
2025-11-25 added URL mode, for the cases where the data must not touch the client at all: OAuth, API keys, payment. It brought elicitationId, a notifications/elicitation/complete notification, and a dedicated error code -32042.
2026-07-28 is the current version (MCP versioning, 2026). It removed all three of those.
That is the part that matters. The top organic result for this query today is the 2025-11-25 spec page. It is not wrong, it is superseded, and nothing on the page tells you that while you are reading it.
Worth saying plainly, because I saw it repeated in a video published this week: elicitation was not added in July 2026. It is fifteen months old. July 2026 changed how it is carried.
What actually changed
I diffed the 2025-11-25 and 2026-07-28 elicitation pages against each other. This is the whole delta.
Scroll to see more
2025-11-25 | 2026-07-28 (current) | |
|---|---|---|
| Delivery | Server sends elicitation/create as a request | Returned inside InputRequiredResult.inputRequests; client retries the original call |
| Capability declared | capabilities.elicitation during initialize | _meta.io.modelcontextprotocol/clientCapabilities on every request |
| Correlating a URL flow | elicitationId | Opaque requestState |
| Completion signal | notifications/elicitation/complete | Removed |
| Dedicated error | -32042 URLElicitationRequiredError | Removed |
| Server state | "Most practical uses require that the server maintain state" | "Elicitations do not require that the server maintain state" |
Modes did not change. Both revisions have form mode and URL mode, and the rule that you must not ask for passwords, API keys or payment credentials through form mode is identical in both. The three response actions are identical too: accept, decline, cancel.
The request is not a request anymore
Here is the old shape. A real JSON-RPC request, with an id, travelling server to client while your tools/call sits open.
{
"jsonrpc": "2.0",
"id": 1,
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": { "name": { "type": "string" } },
"required": ["name"]
}
}
}
Here is the new shape. Same method and params, but they are now a value in a map, inside a result, keyed by a name the server picks.
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "input_required",
"inputRequests": {
"github_login": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": { "name": { "type": "string" } },
"required": ["name"]
}
}
}
},
"requestState": "AEAD-protected blob"
}
}
The client answers by putting an inputResponses map on a fresh tools/call, keyed by the same github_login string. The spec is explicit that the JSON-RPC id must differ, because the retry is a genuinely independent request.
The first call is over. It terminated. There is no open socket waiting on a human.
That is the whole point, and the spec says why: the pattern exists so servers can ask for input "without requiring a shared storage layer across server instances or requiring stateful load balancing". If you have ever tried to run an MCP server behind more than one replica and had a nested request land on the wrong box, this is the fix for that.
The capability moved out of the handshake
This one will bite people quietly.
In 2025-11-25 a client declared elicitation support once, in capabilities during initialize. In 2026-07-28 there is no initialize handshake to put it in. Every request carries its own _meta, and the client capability goes there:
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": { "form": {}, "url": {} }
}
}
}
An empty object still means form-only, for backwards compatibility. And the server-side rule is strict: a server must not put an elicitation/create into inputRequests if the client never declared elicitation.
So if your server suddenly stops eliciting against a client that used to work, the thing to check is not your elicitation code. It is whether the capability is present on this request, rather than remembered from a connection that no longer exists.
elicitationId is gone, and requestState is not a rename
Easy to skim past. They are not the same idea.
elicitationId was a UUID that identified an elicitation, so the completion notification could refer back to it. The client knew what it meant.
requestState is an opaque blob that belongs to the server. The spec tells clients they "MUST NOT inspect, parse, modify, or make any assumptions about its contents", and to echo the exact value back on the retry.
The interesting half is on the server side. Because that blob round-trips through the client, the spec treats it as attacker-controlled input, and the requirements are worth reading before you invent your own: protect its integrity with HMAC or AEAD if it influences authorization, and put the authenticated principal, a short TTL, and an identifier for the originating request inside the protected payload so it cannot be replayed by a different user or against a different call.
A base64 JSON blob with a user id in it will pass your tests and fail a pentest.
The statefulness advice inverted
Worth quoting both, because the reversal is total.
2025-11-25: "Most practical uses of elicitation require that the server maintain state about users." It went on to say state must not be associated with session IDs alone.
2026-07-28: "Elicitations do not require that the server maintain state."
Nothing about users got simpler. The state just moved into requestState and started travelling with the request. If you built a session store for elicitation under the old model, it is not wrong, it is now optional, and the new model is the one that survives horizontal scaling.
Note the carve-out though: URL mode still wants real server state, because the out-of-band interaction has to land somewhere. And the spec still says that if you must guarantee a requestState is used only once, you have to enforce that server-side. The stateless story is about the common case, not all cases.
Two things I only noticed by diffing
Both of these I am reporting as observed, not as announced. I read them off the spec pages rather than a changelog, so verify against whichever SDK you are on before you rely on either.
The string schema in 2025-11-25 includes pattern for a regex constraint. In 2026-07-28 the string schema block lists minLength, maxLength, format and default, and pattern is not there.
The security list in 2025-11-25 includes "Clients SHOULD implement rate limiting". In 2026-07-28 that line is not in the list.
Neither is dramatic. But if you were relying on pattern to validate a field client-side, check it before assuming it survived.
The tooling moved before the tutorials did
This is the bit that made me stop and write the post.
FastMCP, the most-used Python framework for this, has already migrated. Its elicitation docs talk about InputRequiredResult and the multi-round-trip result type directly, and describe tools asking for input by returning rather than by blocking mid-execution (FastMCP docs, 2026).
So the ecosystem is not lagging. The explainers are. Every third-party page ranking for this term today predates the change or ignores it, and the SERP is stable enough that a beginner will read three of them in a row and come away with a confident, wrong mental model.
If you are writing elicitation code this week and copying from a blog post, check the date on the spec it links to before you check anything else.
What I would check first
Five things, in the order that would have saved me the evening.
- Confirm which protocol revision you are actually negotiating. It is in
_meta.io.modelcontextprotocol/protocolVersionon every request now, and on Streamable HTTP in theMCP-Protocol-Versionheader. - If you are on
2026-07-28, stop looking for a place to await a client answer. There is not one. ReturnInputRequiredResultand handle the retry as a separate call. - Put the client capability on the request, not in a handshake you no longer have.
- Treat
requestStateas hostile on the way back in. Sign it, scope it to a principal, give it a TTL. - Keep form mode away from secrets. That rule did not move, and URL mode exists precisely for it.
The design is better than what it replaced. A tool call that terminates cleanly and gets retried is much easier to reason about than one parked open waiting on a human who went to lunch. It is just genuinely different, and the internet has not caught up.
If you are earlier than this and standing a server up at all, I kept a thirty day log of running one in production that covers the unglamorous half.
P.S. I found the delta by opening two spec pages side by side, which is a very stupid technique that keeps working.
Written by
Dani ReyesDani Reyes writes DevMoment field notes on AI dev workflow, tested on real work rather than demos.
Frequently asked questions
What is MCP elicitation?
Elicitation is the mechanism that lets an MCP server ask the human user for information in the middle of handling a request, instead of guessing a missing value or failing. It has two modes. Form mode collects structured data through the client using a restricted JSON Schema of flat primitive fields. URL mode sends the user to an external page for anything sensitive, such as an OAuth flow, an API key or a payment, so that the data never passes through the MCP client. Elicitation was introduced in the 2025-06-18 revision of the Model Context Protocol.
How did elicitation change in the 2026-07-28 MCP spec?
The delivery mechanism changed. Under 2025-11-25 and earlier, the server sent elicitation/create to the client as a server-initiated JSON-RPC request while the original tool call stayed open. Under 2026-07-28 the server instead returns an InputRequiredResult containing an inputRequests map, the original request terminates, and the client retries the original call with an inputResponses map and the server's requestState. The spec describes the old server-initiated pattern as a breaking change that is no longer supported.
Is elicitationId still used in MCP elicitation?
No. In the 2025-11-25 revision, URL mode elicitation required an elicitationId that was also carried by the notifications/elicitation/complete notification and the -32042 URLElicitationRequiredError. In the current 2026-07-28 revision the elicitationId, that completion notification and that error code are all absent. Correlation is handled instead by requestState, an opaque server-owned string that the client must echo back exactly on the retry without inspecting or modifying it.
Does an MCP server need to be stateful to use elicitation?
Not in the common case any more, and this reversed between revisions. The 2025-11-25 page said most practical uses of elicitation require that the server maintain state about users. The 2026-07-28 page says elicitations do not require that the server maintain state, because the server can encode what it needs into requestState and the client echoes it back. URL mode still generally needs real server-side state, and any requestState that must be redeemed only once still has to be enforced server-side.
Can an MCP server ask for an API key using form mode elicitation?
No. Both the 2025-11-25 and 2026-07-28 revisions state that servers must not use form mode elicitation to request sensitive information such as passwords, API keys, access tokens or payment credentials, and must use URL mode for those interactions. General profile information such as a name or email address is not categorically prohibited in form mode. That rule did not change between revisions.
Why do MCP elicitation tutorials disagree with the current spec?
Most of them predate the change or were written against an earlier revision. As of September 2026 the top organic result for this topic is the superseded 2025-11-25 specification page itself, and several widely read explainers date from 2025. The tooling has moved faster than the writing: FastMCP's own elicitation documentation already describes the InputRequiredResult multi round-trip model. Check which protocol revision a tutorial targets before copying its code.
Keep reading
MCP Apps in 2026: the wire calls it ui, and three announced hosts never landed
MCP Apps went stable as the first official MCP extension in January 2026. A pre-build field log on the identifier mismatch, the bilateral opt-in that fails silently, the deny-by-default CSP, and which hosts actually render one in August 2026.
MCP server in production: 30-day field log (June 2026)
A 30-day field log of running an MCP server in production: four failure modes the tutorials skip, honest latency and cost numbers, and when an MCP server is the wrong tool.
The MCP Servers I Actually Keep Installed (2026 Field Log)
A three-month field log on the best MCP servers in 2026: the five that earned a permanent slot, the ones I uninstalled, and the context and trust costs no listicle mentions.