MCP Without Sessions: How a Server Asks the User Mid-Call
Your tool needs the user’s answer mid-call, and the retry may land on another server instance. How does it pick up where it stopped?

IN 30 SECONDS
Multi Round-Trip Requests (MRTR) is the 2026-07-28 way for an MCP server to ask the user something mid-call: it returns input_required, and the client retries with the answers. Its half-done work can travel in a sealed requestState, checked on every retry.
KEY TAKEAWAYS · 3
- MRTR replaces the elicitation and sampling requests a server used to send: the server returns input_required, and the client retries.
- requestState passes through the client, so the spec says to treat it as attacker-controlled and to protect it, for example with HMAC or AEAD, when it affects authorization or business logic.
- Binding it to the principal, a short expiry and the request bounds replay. Single use needs a server-side check.
On this page
Asking the user mid-call, step by step
IN SHORT With MRTR, the server can hand its half-done work back to the client in an optional requestState, so the retry can land on any instance.
Anything marked as a proposal is my opinion, not the standard. Checks on the caller assume an HTTP server that authenticates each call. The spec makes authorization optional.
WORDS TO KNOW
- Elicitation
- The server asking the user for input in the middle of a tool call.
- requestState
- An optional, opaque token the server returns when it needs input. The client sends it back unchanged when it retries.
- Principal
- The user or service a request acts for, shown by its access token.
Elicitation The server asking the user for input in the middle of a tool call. See the glossary used to be a request the server sent on an open stream. So the same process had to be alive when the answer came back. Sampling, where the server asks a model through the client, worked the same way.
The Multi Round-Trip Requests pattern (MRTR) replaces both. Its stated goal is to work
“without requiring a shared storage layer across server instances or requiring stateful load balancing.”
ONE CALL, TWO INSTANCES
Step 1. First call. The app calls a tool with id 1. The load balancer picks instance A.
- First call The app calls a tool with id 1. The load balancer picks instance A.
- Ask for input A answers input_required, with a question and a sealed requestState. Then it forgets the call.
- Ask the user The app asks the user and collects the answers, called inputResponses.
- Retry The app sends the same call with a new id (2), the answers and the exact requestState. It lands on B.
- Verify, then answer B checks the seal, the caller, the expiry and the original call, then returns the result with resultType complete.
- Edited: refused A retry whose requestState was edited fails the seal check. B rejects it and runs nothing.
The retry gets a new id, so the id can’t link it to the first call. The fingerprint of the original call, sealed inside the state, does that job.
Sampling is also Deprecated in 2026-07-28, along with Roots and Logging, with a window of at least 12 months. They still work, but new implementations shouldn’t add them.
Why the server checks the sealed state
IN SHORT Because requestState passes through the client, servers “MUST treat requestState as an attacker-controlled input.”
If the state “influences authorization, resource access, or business logic”, the server must protect it from tampering, for example with HMAC or AEAD.
IN PLAIN WORDS
HMAC is a keyed seal that reveals tampering. AEAD is encryption that also detects it.
ADAM says: A seal isn’t a secret: with HMAC alone, the client may still read what’s inside. If the client must not read it, use AEAD.
To limit replay (the same state sent again), the spec says servers should seal three things inside it: the authenticated Principal The user or service a request acts for, shown by its access token. See the glossary, a short expiry, and an id for the original request.
ITEM GET
Treat it as hostile input
Those bindings bound replay, but they don’t make the state single-use. A one-time use needs a check on the server side.
The principal, from the access token
The expiry. Keep it short
Method, tool name and a digest of the original arguments
Whatever the server needs to resume
The tool name matters: every tool shares the method tools/call. Hash a canonical JSON encoding of the arguments, so key order can’t change the digest.
FAQ
HMAC gives integrity, not secrecy: if the payload is only base64-encoded, the client can decode it. If the state holds anything the client shouldn’t read, use AEAD. My advice either way: rotate the key on a schedule with an overlap window, since every instance must check what another one sealed.
STAGE CLEAR
What you now know
- How MRTR lets any instance finish a call that needed the user’s input.
- Why the server verifies the returned state before trusting any of it.
Check yourself
Tap or click a question to see the answer.
The same user’s client sends one valid requestState twice, unchanged, before it expires. Does the seal stop the second retry?
Not by itself. The seal proves nobody edited it, and the expiry limits the window. Stopping a second use needs the server to record that the state was used.
Former CTO of Integra. Named author (1 of 5) of ERC-3643, first author of ERC-6960, co-author of ERC-7410, and co-author of ERC-8203, which is still a draft. Building production AI and regulated Web3 systems.
Have a project to ship or a role to fill?
Discuss your project or roleFollow the engineering notes
Get new articles on production AI and smart contracts by email.

