MCP removed the session from its modern protocol core. Your application still has to remember what it is doing.
That distinction sounds obvious until a workflow survives its first request.
A user approves a purchase. A job keeps running after the response ends. A tool needs one more piece of information. A network timeout leaves the outcome uncertain. The next request may land on another server instance, but it still needs to continue the same piece of work.
Stateless MCP changes where that continuity lives. It does not make continuity disappear.
What became stateless
The 2026-07-28 MCP specification removed the initialize/initialized handshake and the Mcp-Session-Id header from the modern protocol path. Protocol version, client information, and capabilities now travel with each request. A request can reach any compatible server instance without sticky routing or a shared protocol-session store (MCP 2026-07-28 release).
That is valuable infrastructure work.
It makes ordinary HTTP scaling easier. Gateways can route requests without preserving an MCP transport session. A failed server instance does not take a hidden client session with it. Deployments do not need session affinity merely to keep the protocol working.
But the removed state was protocol state.
It was not the user’s approval, the status of a background job, the result of a payment, the selected resource, or the evidence needed to decide whether a retry is safe.
The state did not vanish. It became explicit
A production workflow usually carries several kinds of state at once.
| State | Example | Where it should live |
|---|---|---|
| Identity | Which user or service is calling | Authentication and authorization layer |
| Authority | What this caller approved | Application policy record |
| Workflow | Which step is next | Durable application store or signed continuation state |
| Operation | Whether an external action started or completed | Operation or task record |
| Result | What changed in the business system | Source system plus an application receipt |
| Conversation | What the model and user discussed | Host application, not the MCP transport session |
Putting all of this behind one session ID was never a complete design. It made some transitions convenient, but it also hid important business state inside connection machinery.
The modern pattern is to make continuity addressable.
A tool can return a basket_id, browser_id, operation_id, or another explicit handle. The model or application passes that handle into the next tool call. The official MCP release describes this as the way applications can preserve state across calls without restoring protocol sessions (stateless protocol, stateful applications).
For example:
{
"operation_id": "op_7f91",
"status": "awaiting_approval",
"next_action": "approve_registration"
}
Then later:
{
"operation_id": "op_7f91",
"approved_max_price": 18.00,
"currency": "USD"
}
The handle does not grant authority by itself. The server must bind it to the correct principal, validate its status, enforce expiry, and reject transitions that do not belong to the workflow.
Visible state is easier to trace. It is not automatically trusted state.
A domain registration shows the difference
Consider a domain-registration workflow.
The user asks an agent to register a name if it is available for no more than a stated amount. The workflow checks availability, obtains a quote, confirms contact readiness, collects approval, submits the registration, and verifies the result.
There may be six MCP calls. There may be two. The protocol does not decide the business boundary.
A useful application record might look like this:
workflow_id: reg_01JCE8M6
account_id: acct_204
domain: example-name.com
term_years: 1
quote:
amount: 14.80
currency: USD
observed_at: 2026-11-10T10:12:00Z
approval:
status: granted
max_amount: 15.00
granted_at: 2026-11-10T10:13:08Z
registration:
status: submitted
provider_reference: ord_99182
verification:
status: pending
This is application state. It should survive a client restart, a server deployment, and the loss of a model conversation.
It also answers questions that an MCP session never could:
- Which exact name and term were approved?
- Was the quote still within the approved limit?
- Did the registrar accept the order?
- Is the current outcome confirmed or merely unknown?
- Would repeating the call create a second charge or conflicting operation?
If the registration request times out, the next server instance can load reg_01JCE8M6, inspect the provider reference or account state, and reconcile the result. It does not need the old transport session. It does need the durable workflow record.
The same pattern applies outside domains. Replace registration with a deployment, transfer, invoice, data export, support escalation, or access request.
Approval is state too
An authenticated request does not carry unlimited permission to act.
For a write operation, preserve the approved inputs outside the model’s prose. Compare the proposed tool call with the approval before execution. A changed resource, amount, destination, or term may require a new decision even when the same user remains logged in.
This matters more in a stateless architecture because each request should be evaluated on its own evidence.
A server should not reason like this:
This client approved something earlier in the session, so the next write is probably fine.
It should be able to establish:
Principal A approved action B against resource C within constraint D, and this request still matches that decision.
That policy check can be repeated on any instance. It is also much easier to audit later.
In-progress work needs a durable handle
Some tool calls do not finish during one HTTP request.
The official MCP Tasks extension lets a server return a task handle for long-running tools/call work. The client can poll with tasks/get, provide additional input with tasks/update, or signal cancellation with tasks/cancel. The task has explicit states including working, input_required, completed, failed, and cancelled (MCP Tasks extension).
That is a protocol-level shape for exposing asynchronous application work. It is not a free task runner.
The server still needs to create the task durably before returning its ID. The client should preserve the ID so polling can resume after a restart. The application needs to define retention, ownership, cancellation behavior, result storage, and what happens after the task’s time to live expires.
Cancellation also needs careful language. In the Tasks extension it is cooperative: an acknowledgement means the server received the cancellation request, not that the underlying work definitely stopped. The task may still finish first.
For a real workflow, distinguish:
- cancellation requested
- cancellation accepted by the application
- external operation stopped
- external operation already committed
One status word cannot safely stand in for all four.
Mid-call input moved into the request flow
The stateless protocol also changed how a server asks the client for information while processing a request.
Multi Round-Trip Requests let a server return resultType: "input_required" with one or more input requests. The client obtains the answer and retries the original call with inputResponses. An opaque requestState can carry continuity between rounds (MCP Multi Round-Trip Requests).
That requestState should be treated as untrusted input when it comes back. The TypeScript SDK migration guidance recommends integrity protection, binding it to the principal and originating request, and adding an expiry (MCP TypeScript SDK migration guide).
Use the mechanism for short continuations inside one logical request: a missing field, a confirmation, or another bounded interaction.
Do not use it as a substitute for durable workflow storage when the work may last hours, cross a deployment, require reconciliation, or support audit and recovery.
Results need to survive the model conversation
The model may summarize a tool result correctly. It may also lose detail, omit an identifier, or disappear when the conversation ends.
Persist the operational result before relying on the summary.
For each state-changing call, record:
- the workflow and operation IDs
- the authenticated principal
- the approved action and constraints
- the exact attempted arguments
- the time and idempotency key
- the immediate server response
- the verified business result
- any unresolved or compensating action
Do not store raw access tokens in the receipt. Keep secrets in the authentication system and reference the relevant identity or grant safely.
The business system remains the source of truth for what it owns. Your workflow record connects the intent, attempt, and observed result so another process or human can understand what happened.
Design every transition to survive another instance
A useful test for stateless MCP is simple:
If the next request reaches a fresh server process with no memory of the previous one, can the workflow continue safely?
The answer should come from explicit data:
- The caller presents valid authentication.
- The request names the workflow, operation, or task it concerns.
- The server loads or verifies the current state.
- Policy checks the proposed transition.
- The operation executes with duplicate protection.
- The result is persisted before success is reported.
If the design instead depends on “the same process probably still has the object,” it is stateful in the least reliable place.
There are valid reasons to keep short-lived process state for performance. Cache it. Do not make correctness depend on it.
Stateless is an infrastructure property, not a product promise
The modern MCP protocol makes requests easier to route and servers easier to scale. That is the win.
It does not remove the state that makes a workflow understandable and recoverable. Approvals still need records. Jobs still need handles. Paid actions still need idempotency and reconciliation. Results still need receipts. Users still need to know whether the system completed, failed, or simply does not know yet.
Stateless MCP is not an argument for less state.
It is an argument for putting state where the business meaning lives.
Frequently asked questions
Does MCP 2026-07-28 remove all sessions?
It removes the protocol-level session from the modern path. Your identity provider, application, browser, database, or external service may still use its own sessions and durable records.
Should workflow state be passed through the model?
Pass explicit handles when the tool contract calls for them, but keep the authoritative state in a controlled application store or integrity-protected continuation. Do not rely on conversational memory as the only record.
When should I use requestState instead of a task ID?
Use requestState for bounded multi-round-trip continuation within one logical request. Use a durable task or operation ID for work that continues asynchronously, must survive restarts, or needs later inspection.
Can a stateless server still support long-running tools?
Yes. The work lives behind a durable task or operation handle. The MCP Tasks extension standardizes one polling-based pattern for long-running tool calls.