// a result, or a request
Since the 2026-07-28 line, a tool call has two shapes of success. It can complete, or it can come back asking for something:
tools/call with an InputRequiredResult to indicate that additional input is needed before the tool call can be completed.The result carries resultType: "input_required", a map of inputRequests — each one an elicitation/create with a message and a schema for the answer — and an opaque requestState.
So far this reads like a pause. It is not one.
The retry is a new call
The client does not reply to the request that asked. It issues a fresh tools/call — same tool name, the same arguments re-sent verbatim — with the user's answers and the echoed state attached.
And then the giveaway, stated outright in the spec:
id MUST be different between the initial request and the retry.A different id is a different request. Nothing is suspended server-side waiting to continue — the first call completed, with an answer that happened to be a question. That is also why the protocol works at all with a stateless core: everything the retry needs travels in its own payload, so any instance of your server can pick it up.
Which means your handler runs again
Follow that through to your own code. Your tool function is entered a second time, with the same arguments it had the first time. Whatever it did before it asked, it is about to do again.
The fix, and the cheap version of it
Two ways out, and the first is usually enough.
Putting the side effect after the question is free and needs no bookkeeping: on the first run the tool asks and does nothing else; on the retry the answer is present, so it runs straight through. Reconstructing from requestState is the option when the work genuinely has to happen before you can even formulate the question.
If your tools are already idempotent you have most of this for free — a repeated call with the same arguments should already be safe. This is a good argument for that discipline rather than a separate one: the protocol will now re-issue calls on its own, not only when a client retries after a timeout.
Two things it doesn't mean
Your server cannot interrupt people out of nowhere. Under SEP-2260, server-initiated requests may only be issued while the server is actively processing a client request. Earlier revisions recommended it; it is now required, so every question traces back to something the user started.
And this is not the security story. requestState is a mechanism for carrying context across the two calls, not a credential — hardening it against replay belongs with the broader point that an id is not a permission, which comes from the same spec revision and is its own subject.
Sources: Model Context Protocol specification, draft — Server / Tools §Input Required Tool Results, and §Multi Round-Trip Requests (SEP-2322, SEP-2260) · MCP blog — the 2026-07-28 release candidate. Verified 2026-09-02.
One concept a week. Free.
The deeper, copy-paste version of each ToolCall short — in your inbox.
// total: 0.00 · spam: void · unsubscribe: one click
