Across MCP's Tier 1 SDKs, the project is seeing close to half a billion downloads a month
- which means a lot of production servers are now staring down a migration decision. The 2026-07-28 spec shipped July 28 and the headline is statelessness, but the change that matters most for teams running approval gates is quieter: the old way of pausing an agent to ask a human is gone, replaced by a pattern called Multi Round-Trip Requests.
Here is the concrete question worth answering: does that make MCP human-in-the-loop agents easier or just different? The honest answer is both, and the distinction matters depending on what your server was already doing.
What the old elicitation pattern actually cost you
For most of its life, MCP was a stateful, bidirectional protocol. Every connection opened with an initialize/initialized handshake, and servers carried session state behind an Mcp-Session-Id header. That worked for a single process on your laptop. It fell apart the moment you tried to run a remote MCP server across more than one instance.
The human-in-the-loop problem lived inside that constraint. In many earlier HITL implementations, confirmation was implemented as a transport problem. The client opened a protocol session, kept a long-lived server-to-client stream (often SSE), and invoked the tool. Mid-call, the server pushed an elicitation - a structured "please fill this form" request - over the open stream.
Holding that stream open is expensive in practice.
Server-initiated requests such as elicitation/create depended on an open stream. Deployment of such a server required balancing the complexity around streams, cost, and request timeouts.
A human reading a confirmation dialog before approving a database migration might take 90 seconds. Keeping an SSE connection pinned for 90 seconds per concurrent approval, across a fleet of servers behind a load balancer, is not a free operation - and it fought against the infrastructure every team already had.
Pinterest's engineering teams, for instance, deployed a production-ready MCP ecosystem that allows AI agents to automate complex engineering tasks and integrate diverse internal tools. Domain-specific MCP servers, a central registry, and human-in-the-loop approval improve security, governance, and developer productivity while saving thousands of hours per month.
Because MCP servers can perform automated actions, Pinterest mandates human-in-the-loop approval for sensitive operations, using elicitation to confirm potentially dangerous actions before execution. At that scale, the stream-based approach was already a bottleneck.
How MRTR changes the approval gate
Multi Round-Trip Requests is the new answer.
Until now, when a server needed something from the client - directories through roots/list, an inference through sampling/createMessage, a value from the user through elicitation/create - it opened a request in the opposite direction, and that required a persistent stream. The new pattern reverses the direction. The server returns an InputRequiredResult with resultType: "input_required", and puts what it is missing in the inputRequests field. The client reissues the same request with inputResponses attached. No open channel - just a question travelling back inside an answer.
The server returns resultType: "input_required" with the questions it needs answered, and closes the connection. The client collects the answers and retries the original call with them attached, plus an opaque requestState token so the server knows where it left off. No open streams.
That last detail - the requestState token - is the one you should not skim.
Agent-side checkpointing (so your graph can resume after a page refresh) is useful, but it is not a substitute for server-side verification of requestState. One is UX continuity; the other is trust. That separation is the difference between a demo that works once and a fleet that survives a pod recycle while someone is still reading the confirmation dialog.
There is a hard constraint on the client side too:
servers must not send an inputRequests that the client has not declared support for in its capabilities.
So if you're rolling out MRTR-based approval gates, you need to audit your client capability declarations, not just your server code.
inputRequests schema, drafts a plain-language summary with the exact parameters the migration will changerequestState intact, migration proceedsWhat is actually easier, and what is not
| Old (session-based elicitation) | New (MRTR, 2026-07-28) | |
|---|---|---|
| Infrastructure | Sticky sessions or shared session store required | Plain round-robin load balancer works |
| Approval gap | SSE stream held open during human review | Connection closed; human takes as long as needed |
| Client support | Widely implemented | Must be declared in capabilities; not all clients support it yet |
| Migration cost | None (it was the default) | ctx.elicit() raises NoBackChannelError; server rewrite needed |
| State handling | Implicit in session | Explicit requestState token, echoed by client |
The infrastructure story is genuinely better.
A remote MCP server that previously needed sticky sessions, a shared session store, and deep packet inspection at the gateway can now run behind a plain round-robin load balancer, route traffic on an Mcp-Method header, and let clients cache tools/list responses for as long as the server's ttlMs permits.
The migration story is harder than most posts admit.
One gotcha worth internalising before you migrate: because MRTR removed the back-channel, ctx.elicit() and ctx.session.create_message() raise NoBackChannelError on a modern connection. If your server asks the user mid-call, that code needs rewriting around the input-required round trip - it's the single most likely thing to break.
The Okta Open Source MCP server, for example, now integrates the MCP Elicitation API to enforce human oversight on destructive actions - critical operations such as deleting apps or deactivating users now require explicit confirmation before execution. Okta wired this up under the new spec, but doing so required rebuilding the elicitation path from scratch, not just updating a dependency.
The tools/list cache is the quieter win
Separate from MRTR, there is a change that will silently improve most production deployments without any rewrite: cacheable list responses.
Responses from tools/list, prompts/list, resources/list, and resources/read now carry ttlMs and cacheScope. This allows clients to determine the best caching strategy for responses and reduce unnecessary re-fetching.
cacheScope is modeled directly on HTTP's Cache-Control semantics, so clients know how long a response is fresh and whether it's safe to share across users.
A client can cache the catalog of available tools instead of refetching it, and upstream prompt caches stay stable across reconnects. The result is fewer round trips and lower token cost.
The Mcp-Method header also lets you split tools/list (cacheable, idempotent) onto edge nodes and tools/call (mutating, sometimes expensive) onto warm origin nodes.
That is a real ops improvement that requires almost no code - just emit the headers and set a ttlMs that reflects how often your tool catalog actually changes.
A teammate like Beagle, whose tool catalog is stable between deploys, could set cacheScope: "public" and a ttlMs matching its release cadence - meaning clients never refetch the catalog mid-conversation unless a new version ships.
input_required and closes; client holds requestState, human takes as long as needed, retries with answer attached - pod recycles are invisible to the flowWhat to actually check before migrating
Search your server code for
ctx.elicit()andctx.session.create_message()- these are the live wires. Both raise on a 2026-07-28 connection.Declare client capabilities accurately. Servers must not send an
inputRequeststhat the client has not declared support for. If a client does not declare support for elicitation, the server must not include any elicitation/create requests in theinputRequestsfield.Emit
ttlMsandcacheScopeon every list response.ttlMsis a freshness hint (in milliseconds) allowing clients to cache responses and reduce polling;cacheScope("public" or "private") controls whether it's safe to share across users.Add
Mcp-MethodandMcp-Nameheaders to Streamable HTTP requests. The method name and the tool name now travel in HTTP headers, not just the JSON body. That means your gateway, rate limiter, or WAF can route and meter on those headers directly, without parsing the request body.Budget time for the elicitation rewrite. This is a breaking change from the old way of doing elicitations. However, it is operationally much simpler to implement, and it will allow more developers to make use of this capability to build rich agentic applications.
MCP human-in-the-loop agents: common questions
What is MCP elicitation and how does it work in the new spec?
MCP elicitation is a mechanism that lets a server pause a tool call and ask the user for input or confirmation before continuing. In the 2026-07-28 spec, it works via Multi Round-Trip Requests: the server returns resultType: "input_required" and closes the connection. The client collects the answer and retries the original call. No persistent stream is needed.
Does the 2026-07-28 spec break existing MCP servers that use elicitation?
Yes, for servers using the old server-initiated pattern. Any code calling ctx.elicit() or ctx.session.create_message() raises NoBackChannelError on a 2026-07-28 connection. Those call sites need to be rewritten around the input_required result type. The Python SDK v2 and TypeScript SDK both ship migration guides.
Can agents pause indefinitely waiting for a human under the new spec?
Effectively yes - and that is the point. Because MRTR closes the connection after returning input_required, the human can take minutes or hours to approve without keeping infrastructure pinned. The requestState token carries continuity; the server does not need to hold anything open.
What is cacheScope in MCP's tools/list response?
cacheScope is a field ("public" or "private") that tells the client whether a tools/list response can be shared across users. Paired with ttlMs (a freshness hint in milliseconds), it lets clients cache the tool catalog between sessions. The practical effect is fewer round trips and more stable upstream prompt caches across reconnects.
Which MCP clients support MRTR today?
Support is declared through client capabilities. GitHub's MCP Server shipped 2026-07-28 support ahead of the official release. Mastra's MCPClient supports MRTR with an 'auto' mode that probes the server version at connect time and falls back gracefully to the legacy handshake if the server does not support it. Check your specific client's changelog - not all have shipped production support yet.