On July 28, the Model Context Protocol released its most consequential redesign yet. The official 2026-07-28 revision removes protocol-level sessions and describes MCP’s core as stateless.12
Listen to the audio overview
A 7-minute audio overview of this article, narrated by our robot.
That sentence is accurate, but it is easy to misunderstand.
MCP has not abolished state. A tool can still create a shopping basket, start a research job, open a coding workspace, or build a long-running workflow. A server can still use a database. An agent can still return tomorrow and continue yesterday’s work.
What changed is where the protocol assumes that state lives.
The previous MCP lifecycle allowed later messages to depend on a client-server session established earlier. The new design makes each request describe itself. Protocol version and client capabilities travel with the request, while stateful application data must be represented explicitly.23
That sounds like a narrow plumbing change. It is not. It changes how MCP services can sit behind load balancers, how gateways inspect requests, how clients recover from failures, and how developers reason about the boundary between protocol mechanics and application behavior.
The old MCP lifecycle
Before this revision, an MCP connection began with an initialization exchange. A client sent initialize, the server responded with its version and capabilities, and the client sent notifications/initialized.
That handshake established context for the messages that followed. Under Streamable HTTP, a server could also assign an Mcp-Session-Id. Later requests could therefore depend on information associated with that protocol session.2
This is familiar architecture. Many systems establish a session and then rely on the server to remember what was negotiated. It can also complicate distributed deployments.
Imagine three identical MCP server instances behind a load balancer. If a request depends on a session stored only inside Server 2, the next request needs to return to Server 2. The infrastructure must use sticky routing, or every instance must share the session data through an external store.
Not every MCP server used sessions heavily. The deeper issue was that protocol behavior could depend on a conversation that happened earlier. Infrastructure could not safely treat each request as independent.
What changed on the wire
The 2026-07-28 revision removes the initialize and notifications/initialized exchange. It also removes protocol-level sessions and the Mcp-Session-Id header.245
Instead, every request carries the protocol version and client capabilities in its _meta object. Clients SHOULD also identify themselves on each request, and servers SHOULD identify themselves in each result. Those identity fields are recommendations, not requirements.2
The difference is not that MCP sends less information. Some metadata is now repeated. The difference is that a server does not need a prior handshake to interpret the next request.
The specification also introduces server/discover. Servers MUST implement it so they can advertise supported protocol versions and capabilities. Clients MAY call it before doing other work, but they do not have to. A client can send a normal request with its preferred version, receive an unsupported-version error if necessary, and retry using a version the server reports.26
Negotiation did not disappear. It moved from a session lifecycle into self-contained request handling.
For infrastructure teams, that is the important architectural shift. At the protocol layer, any compliant instance has enough protocol information to understand any request. A gateway can route and meter HTTP traffic using standardized headers. List responses now carry cache lifetime and scope hints, and servers SHOULD return tools in deterministic order to improve client-side caching.2
There is an essential qualifier: an instance may understand a request and still lack the application data needed to complete it. Protocol statelessness does not replicate your database.
Where application state goes
Consider an MCP server that helps an agent assemble a parts order.
In a session-oriented design, a create_basket tool might put a basket into session memory. A later add_item call could assume that the current session already identifies the correct basket.
In the new model, create_basket can return an opaque handle:
{
"basket_id": "bkt_7f3a9c"
}
Later calls pass that handle explicitly:
{
"basket_id": "bkt_7f3a9c",
"part_number": "GPU-BRACKET-02",
"quantity": 4
}
The basket is still stateful. The server may store it in PostgreSQL, Redis, an object store, or another system. What changed is that the state is named in the application’s vocabulary instead of being hidden behind a transport session. The specification recommends server-minted handles as this application pattern.25
Explicit state can be more durable and composable. An agent can reconnect and continue using the same handle. An orchestrator can share one research job with a child agent while withholding another. A transcript can preserve the identifier needed to resume work without a separate protocol-session restoration feature.
It also makes responsibilities more visible.
The application needs an expiration policy and cleanup behavior. Every call must check whether the authenticated user may access the referenced object. A state handle should not automatically be treated as an authorization token, especially because handles can appear in chat history, logs, copied text, or subagent prompts.
Explicit handles are a design pattern, not a new typed MCP primitive. They are ordinary tool results and arguments. Their meaning, lifetime, storage, and security remain the application developer’s job.
Stateless does not mean connectionless
The new MCP design still supports streams.
An individual HTTP response can stream through Server-Sent Events. Change notifications move to subscriptions/listen, a long-lived POST response stream that clients use to opt into events such as tool-list or resource changes.24
What disappeared is the assumption that the protocol needs one persistent, bidirectional session to coordinate everything.
The same principle appears in the Multi Round-Trip Request pattern. Suppose a tool needs the user to confirm a purchase, or a server needs the client to perform model sampling. The server returns an input_required result describing what it needs. The client gathers the response and retries the original request with that input attached.2
The interaction can still span several exchanges. Correlation is explicit in the request and result instead of depending on a hidden server-initiated conversation inside a session.
The retry trap
Removing session affinity can make failure recovery easier, but it does not make every operation safe to repeat.
The new specification removes SSE message redelivery and stream resumability. If a response stream breaks, the in-flight request is lost and the client issues a new request with a new request ID.24
For a read-only tool, retrying may be harmless. For a tool that transfers money, creates an issue, sends an email, or deploys software, a repeated request could repeat the side effect.
That is an application-level idempotency problem. A mutating tool may need its own operation key, durable execution record, or status-check method. “Stateless protocol” should never be translated into “retries are free.”
Migration is not a package update
The July 28 release publishes a new protocol revision. It does not switch every existing client and server overnight.
Modern clients and servers need to agree on the protocol era. Dual-era implementations can continue speaking earlier session-oriented versions while negotiating the new version with compatible peers. Modern-only and legacy-only implementations cannot communicate directly.6
SDK behavior differs. The TypeScript v2 packages support the new revision, but code must choose the appropriate version-negotiation and serving configuration. Installing v2 alone does not guarantee that a 2026-07-28 request goes on the wire.78 Python v2 negotiates the modern and legacy eras through its own client and server defaults.9
Inspector 2.0 combines its web interface, CLI, and TUI in one package. It requires Node.js 22.19 or newer and changes important command-line flags, including the meanings of --config and --catalog.10
The reliable question is not, “Did we install SDK v2?” It is, “Which protocol revision did this client and server negotiate?”
Teams evaluating migration should ask:
- Did any workflow depend on
Mcp-Session-Idor per-session memory? - Which application objects now need explicit handles?
- Can every server instance resolve those handles?
- Does every call independently enforce authorization?
- Are mutating requests idempotent or otherwise safe to recover?
- Are time-to-live and cleanup policies clear?
- Are both sides actually negotiating 2026-07-28?
- Which deprecated features need a future replacement?
That final question requires some calm. Roots, Sampling, Logging, Dynamic Client Registration, and the older HTTP plus SSE transport are deprecated under the new lifecycle rules, but deprecated does not mean removed today. Existing implementations have a formal migration window. New designs should avoid building deeper dependencies on those paths.211
The larger design lesson
MCP’s stateless turn reflects a clean separation of concerns.
The protocol should tell a server enough to understand and route a request. The application should define the durable objects, permissions, and workflows that give the request meaning.
That separation makes the protocol easier to scale across ordinary infrastructure. It also prevents a transport session from becoming an accidental container for every kind of state an agent might create.
The trade is explicitness. Developers now have to name state, pass it, secure it, expire it, and decide what retries mean. Those responsibilities already existed. The new protocol makes them harder to hide.
MCP did not get rid of state. It stopped pretending one transport session was the right place to put every kind of it.
Footnotes
-
Model Context Protocol. “Specification 2026-07-28.” modelcontextprotocol.io ↩
-
Model Context Protocol. “Key Changes: 2026-07-28.” modelcontextprotocol.io ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12
-
Model Context Protocol. “Architecture.” modelcontextprotocol.io ↩
-
Model Context Protocol. “SEP-2575: Make MCP Stateless.” GitHub ↩ ↩2 ↩3
-
Model Context Protocol. “SEP-2567: Sessionless MCP via Explicit State Handles.” GitHub ↩ ↩2
-
Model Context Protocol. “Versioning and Compatibility.” modelcontextprotocol.io ↩ ↩2
-
Model Context Protocol TypeScript SDK. “Supporting protocol revision 2026-07-28.” GitHub ↩
-
Model Context Protocol TypeScript SDK. “v2 package releases.” GitHub ↩
-
Model Context Protocol. “Deprecated Features.” modelcontextprotocol.io ↩