If MCP is stateless, where does the shopping basket live?
A browser agent already has twelve tabs open. How does the next tool call know which browser context to use? If an agent has created a workspace but has not finished the task, what lets a later request continue from that workspace?
Those questions are more useful than starting with the claim that stateless systems scale better. If stateless is interpreted as “the server cannot remember anything”, the rest of the architecture quickly becomes muddled: serverless, load balancing, failover, and even the role of an MCP gateway.
MCP 2026-07-28 removes the protocol-level session. The initialize / initialized exchange and Mcp-Session-Id leave the new protocol core, while each request carries the protocol context it needs. A request no longer has to return to the server instance that created a session.[1]
If a client wants the server’s capabilities up front, it may call server/discover. The discovery call is optional: it is not a replacement handshake for initialize, and a normal modern request already carries the protocol context required for that call.[1]
The application can still retain state.
This article is about that boundary.
Version scope: this article targets MCP
2026-07-28and was last checked on 18 August 2026. Compatibility and migration for older clients and servers are reserved for Part 03.
Start by separating four kinds of state
The difficult part of a stateful-versus-stateless discussion is often that the word state is being used for several different things.
A useful first cut is to separate four layers:
| Layer | Example | What happens in 2026-07-28 |
|---|---|---|
| Protocol context | protocol version, client info, capabilities | travels with the request rather than living in a protocol session |
| Application / workflow state | basket_id, browser_id, workspace_id | can be located or carried through explicit state handles; the real state lives in an application backend |
| Domain data | a Google Sheet, CRM record, issue, invoice, database row | stays in its existing source of truth |
| Identity / authorisation | user, token, principal, permission | evaluated separately from the handle and, where required, checked on each call |
Once those layers are separated, stateless MCP becomes much less mysterious.
The protocol no longer maintains an invisible table saying which client belongs to which continuing session. If an application needs to remember something across requests, it has to make that state addressable and pass the relevant identifier explicitly.

Figure 1-1 | Stateless MCP removes the protocol session. Application state, domain data, and authorisation still exist, but their responsibilities are clearer.
What did 2026-07-28 actually remove?
Start with the older model.
Under the 2025-11-25 Streamable HTTP design, a client performed initialize, and a server could establish an Mcp-Session-Id. Later requests returned with that session identifier.[5]
If the server attached several pieces of information to the session, such as:
- which capabilities had already been initialised
- the current browser context
- the current shopping basket
- the workspace being edited
- an intermediate workflow position
then the load balancer inherited a constraint.
A later request sent to an instance that knew nothing about the session could not simply continue.
Two common answers are familiar from other stateful services.
One is sticky routing, where requests from the same session keep returning to the same instance.
The other is a shared session store, such as Redis or another external store, so every instance can recover the session context.
Both approaches are workable. The cost is that the protocol session starts shaping the deployment architecture.
2026-07-28 removes that coupling. Each JSON-RPC message over the modern Streamable HTTP transport is handled as its own HTTP POST, carrying its protocol version and client metadata without relying on a protocol session.[1][3]
From the MCP protocol’s point of view, the next request can therefore land on another instance.
That sentence needs one important qualifier:
“No shared protocol-session store is required” does not mean “the application no longer needs shared state”.
A collaborative workspace still has to be stored somewhere. Idempotency records, queues, database transactions, locks, and other durable application concerns do not disappear because the MCP transport is stateless.
The protocol has given up one responsibility. The system has not lost its memory.
Explicit state handles: move hidden session state into tool data
SEP-2567 documents a practical pattern for cross-call state: explicit state handles.[2]
Consider a shopping workflow.
A session-oriented implementation might effectively behave like this:
Session abc123
└── basket = [shoe, sock]
A later add_item call does not need to say which basket it means because the server assumes “the basket attached to this session”.
The explicit-handle version looks more like this:
create_basket()
→ basket_id = bsk_a1b2c3
add_item(
basket_id = "bsk_a1b2c3",
sku = "shoe"
)
basket_id is an ordinary field in a tool result and later an ordinary tool argument.
MCP does not introduce a handles/* RPC or a special protocol-level handle type. From the wire’s point of view, the identifier is simply tool data.[2]
That small change has a useful consequence.
One agent can carry several state scopes at once
Suppose a parent agent starts three subagents to help assemble one order.
The three subagents should share the shopping basket, but each needs its own browser context.
A single session scope is awkward:
- share the session and the basket is shared, but browser state may collide
- isolate the sessions and the browser state is safe, but the basket is split into three copies
Explicit handles can represent the intended boundary directly:
shared basket_id
browser_id_A
browser_id_B
browser_id_C
The transport no longer decides which pieces of state share a lifetime or scope. The orchestrator can share or isolate them according to the application itself.[2]
This is one of the more interesting consequences of the stateless redesign. It does more than simplify horizontal scaling. It forces some state that was hidden in transport semantics back into application design, where its scope is visible.
Where does the real state live?
A handle is an address, not the house.
basket_id = bsk_a1b2c3 normally does not contain the basket itself. The server receives the identifier and resolves the underlying data from an application backend.
That backend might be a:
- relational database
- key-value store
- object store
- Durable Object
- workflow engine
- durable resource already managed by the application service
MCP does not prescribe one.
“External state store” should therefore not be read as a new MCP requirement. SEP-2567 explicitly treats handles as a tool-design pattern rather than a protocol primitive. Where and how the server stores the underlying state remains an application-architecture decision.[2]
There is also a security boundary worth keeping separate:
A handle is not automatically authorisation.
For an authenticated server, knowing a basket_id should not be enough to operate on that basket. The SEP guidance is to validate (handle, auth_context) on every call where authorisation exists.[2]
The principle is the same as an ordinary web API. Knowing /orders/12345 does not grant permission to read order 12345.
Why the cloud architecture becomes simpler
Once the protocol session disappears, a remote MCP server starts to resemble a conventional stateless HTTP service.
A session-affine deployment may look like this:
Client
↓
Load Balancer
↓ sticky route
MCP Server A
↓
Protocol Session State
If Server A fails, failover is no longer just a matter of selecting Server B. Server B also needs the session context that Server A was carrying.
Alternatively, the deployment may externalise the session state:
MCP Server A ─┐
MCP Server B ─┼→ Shared Session Store
MCP Server C ─┘
With the 2026-07-28 protocol, the protocol layer can instead look like:
Client
↓
Round-robin Load Balancer
↓
MCP Server A / B / C
Any instance can process the new request. If the application genuinely needs durable state, each instance can resolve that state from the same application backend.[1][3]

Figure 1-2 | The modern MCP protocol no longer requires sticky sessions or a shared protocol-session store. Whether application storage is shared depends on the business state, not on a protocol requirement.
Several operational patterns therefore become more ordinary:
- round-robin load balancing
- instance replacement
- rolling deployment
- autoscaling
- serverless or edge hosting
- failover
Netlify’s launch-day engineering article describes the new MCP server as an ordinary HTTP workload, with the operational emphasis on no longer building the hosting model around session management.[4]
There is still a boundary to preserve.
Stateless MCP and serverless MCP are not synonyms.
Serverless is a hosting and execution model. Statelessness is a property of the protocol.
A stateless MCP server can run on a long-lived VM, Kubernetes, a container service, a function platform, or a worker runtime. The protocol change simply makes request-driven hosting easier because the platform no longer has to preserve protocol-session affinity first.
A Google Sheets MCP example: where is the data actually stored?
Consider a small tool:
append_row(sheet_id, values)
An agent asks an MCP server to append a row to a Google Sheet.
An illustrative serverless arrangement might be:
Agent / MCP Client
↓
MCP Request
↓
Serverless MCP Handler
↓
Google Sheets API
↓
Google Sheet
At least three different kinds of data exist in this picture.
1. The current MCP request
It exists for the request lifecycle. The handler can disappear once the request has been processed.
2. The data in Google Sheets
The durable business data is stored by Google Sheets. A later MCP request may run on a different function instance and the appended row still exists.
3. Cross-call workflow state, if the workflow has any
Perhaps the tool does more than append one row. It creates a temporary import workspace that will be committed in a later call.
The server could return:
workspace_id = ws_7f29
Later calls pass workspace_id explicitly, while the underlying state for ws_7f29 lives in a database, Durable Object, or another application store.
So the question “does MCP store the Google Sheet data?” is missing a layer.
A better question is:
Is this protocol context, workflow state, or business data, and which system is its source of truth?
This example only illustrates responsibility boundaries; real Google Sheets MCP implementations may choose different hosting and storage designs.
If I do not want data retained, statelessness does not solve that automatically
Another tempting assumption is that a stateless protocol means data disappears after use.
It does not.
Protocol statelessness only means that the protocol does not depend on a hidden session across requests. Data may still be retained in:
- the business system behind the tool
- an application database
- logs, traces, or audit systems
- a queue or workflow backend
- durable state referenced by an explicit handle
- the client’s own conversation and tool-result history
Retention policy still has to be defined at each layer.
If a piece of information must not be persisted, the useful questions are:
- Did the tool write it to the source of truth?
- Did the application backend persist it?
- Did logs or traces capture the payload?
- When does handle-backed state expire or get destroyed?
- Does the client retain the tool result?
Stateless should not be used as a substitute for a data-retention policy.
Why enterprise gateways become easier, without becoming mandatory
The stateless core has another architectural consequence.
When requests no longer require session affinity, and operation metadata can be exposed at the HTTP boundary, load balancers, gateways, WAFs, rate limiters, and observability tooling can deal with MCP traffic through more familiar HTTP mechanisms.[1][3]
That makes the common MCP gateway / registry / control-plane pattern easier to implement, with responsibilities such as:
- identity
- routing
- rate limiting
- policy
- audit
- registry and discovery
- PII handling
concentrated at a clearer platform boundary.
That topology should not be described as a requirement of MCP.
The specification does not say every enterprise must deploy a gateway, and statelessness does not automatically create tenant isolation, authorisation, or auditability.
A more precise statement is:
The new wire semantics reduce gateway coupling to protocol sessions, so existing HTTP control-plane infrastructure can understand and govern MCP more easily.
Part 02 will look at the mechanisms that make that possible, including Mcp-Method, Mcp-Name, cache hints, and trace context.
What I would check before changing the hosting platform
If you already run a remote MCP server, moving it to a worker or function runtime is not the useful first step.
A better first check follows these boundaries:
- Failover: if one instance dies, can another instance process the next request? If not, find out whether the dependency is protocol state or application state.
- State identifier: does cross-call state have an explicit identifier? If the only copy lives in process memory, failover still loses it.
- Handle storage: where does the data behind the handle actually live? Having a
workspace_iddoes not solve durability by itself. - Authorisation boundary: are the handle and authorisation checked separately? Knowing an identifier should not imply permission to use it.
- Lifetime: who defines the state lifetime? A browser context, basket, workspace, and transaction rarely need identical expiry and cleanup rules.
The second failure mode can produce a convincing form of fake statelessness.
The HTTP request contains no session ID, yet the application quietly stores current_workspace in global memory on one instance. The demo works. Autoscaling or a restart arrives, and the state disappears with the process.
A stateless protocol makes the boundary easier to express, while durability, lifetime, and cleanup still belong to the application.
Return to the original question: where did the state go?
MCP 2026-07-28 redraws responsibility for state.
The protocol no longer owns a cross-request session. Continuing application state can be represented through ordinary tool data such as explicit handles, while the real data lives in an application backend. Business data remains in its existing source of truth. Authorisation remains a separate boundary.
The practical gain is larger than removing one session identifier.
Load balancing, failover, autoscaling, and serverless hosting no longer have to accommodate a hidden protocol-session scope first. At the same time, state sharing, isolation, lifetime, and authorisation become application decisions that have to be made explicitly.
Part 02 starts from the next problem:
Without a long-lived session, how does MCP support human input, multi-round interaction, long-running work, gateway routing, caching, and tracing?
That is where MRTR, HTTP routing headers, the Tasks extension, and trace context enter the picture.
References
- Model Context Protocol, The 2026-07-28 Specification, 28 July 2026. https://blog.modelcontextprotocol.io/posts/2026-07-28/
- Model Context Protocol, SEP-2567: Sessionless MCP via Explicit State Handles. https://modelcontextprotocol.io/seps/2567-sessionless-mcp
- Model Context Protocol, Streamable HTTP: 2026-07-28 Specification. https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http
- Netlify, MCP goes stateless and extensible, 28 July 2026. https://www.netlify.com/blog/mcp-goes-stateless-and-extensible/
- Model Context Protocol, The 2026-07-28 MCP Specification Release Candidate, 21 May 2026. https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/