An MCP server speaking the new 2026-07-28 protocol can sit behind an ordinary load balancer without sticky routing, a shared transport-session store, or a permanently open connection for each client. That operational consequence is the real news in the Model Context Protocol's latest revision: MCP is giving up its own session machinery so remote tool servers can behave more like normal web services. The trade is a cleaner production architecture in exchange for explicit migration work wherever developers treated a session ID as application state.
Published on July 28, the revision removes both the Mcp-Session-Id header and the mandatory initialize handshake from the modern wire format. Every HTTP request instead identifies its protocol version and carries the metadata needed to interpret it. The official 2026-07-28 release announcement says the four Tier 1 SDKs, TypeScript, Python, Go, and C#, support the revision. Rust support was described as beta at launch.
This is a breaking protocol change, not a flag that magically makes existing deployments stateless. Older 2025-era clients and servers still speak the session-capable protocol, and SDK behavior varies during the transition. For teams operating remote MCP servers, the important question is no longer simply whether an SDK supports Streamable HTTP. It is which protocol era each endpoint actually puts on the wire.
What disappeared from the wire
Earlier Streamable HTTP revisions let a server issue an Mcp-Session-Id during initialization. The client then returned that header on later requests. A client could also open a GET-based Server-Sent Events stream for server-originated traffic, end the session with DELETE, and resume streams using Last-Event-ID.
The current Streamable HTTP specification removes all of those mechanisms. A server exposes one MCP endpoint that accepts POST. Each JSON-RPC request gets its own POST, and the response is either one JSON object or an SSE stream limited to that request. GET and DELETE should return 405 Method Not Allowed; a modern server ignores Mcp-Session-Id and Last-Event-ID.
The protocol version now appears in the MCP-Protocol-Version HTTP header and in request metadata, with the two values required to match. The method and, where applicable, tool or resource name are also mirrored into HTTP headers. This makes requests easier for gateways, load balancers, and observability systems to route or inspect without first parsing a JSON-RPC body.
Removing the initialization handshake is just as consequential as removing the session header. Information that used to be negotiated once, including protocol version and client capabilities, is supplied per request. Discovery becomes a separate operation rather than one part of a connection lifecycle. In practical terms, any healthy replica should have enough information to handle the next call.
Why sessions became a scaling tax
Sessions were underspecified as a home for application state. The accepted sessionless MCP proposal, SEP-2567, says clients disagreed over whether a session lasted for a tool call, an application launch, or a page load, while few resumed them. A server therefore could not safely infer how long session-keyed data should live.
That ambiguity has infrastructure costs. If a replica stores a client's session in memory, later requests must return to the same replica or find the state in shared storage. Operators need sticky load balancing, session migration, or both. Long-lived SSE connections add another constraint, particularly on serverless and edge platforms designed around independent requests.
The maintainers sampled 1,000 open-source MCP server repositories while evaluating the change. According to SEP-2567, 90% contained no application-level reference to the MCP session ID. Another 6.3% used it only for routing boilerplate or transport setup. The proposal found 2.5% using session-keyed application state, 0.7% using it for sticky proxy or gateway routing, and 0.5% binding authentication data to it. The methodology used automated classification, so those shares are directional rather than a census, but they explain the decision: session support imposed ecosystem-wide complexity for behavior used semantically by a small minority of sampled projects.
There is also a caching benefit. When sessions are allowed to alter a server's visible tools or resources, a client cannot safely assume that a list fetched in one session applies in another. Removing protocol sessions makes list results cacheable according to explicit cache hints rather than an ambiguous connection boundary. For agent systems that contact many servers or create many workers, avoiding repeated list calls can matter as much as reducing server memory.
Stateful applications still work
Stateless protocol does not mean stateless product. A shopping basket, database transaction, or long-running job can still persist. The difference is that its identity must be visible and intentional. A tool might return a basket_id from create_basket, for example, and require that identifier in later add_item calls. State can live in a database or object store that any replica can reach.
This explicit-handle pattern makes the state boundary legible to clients and operators. It also prevents a transport detail from quietly becoming a user identity or authorization boundary. The migration deserves particular care where a server keyed OAuth verifier data, JWT claims, or client-to-user mappings by Mcp-Session-Id. SEP-2567 recommends moving such correlation to a server-generated nonce, an authenticated principal, or another purpose-built identifier. That is not a search-and-replace task; it is an authentication review.
Gateways that spawn one stdio subprocess for each HTTP session face the least mechanical migration. They need another correlation mechanism, such as an authenticated principal or gateway-issued cookie or header, because the modern protocol no longer supplies a session key. Projects depending on that topology can remain on an older negotiated protocol while redesigning it.
The other apparent loss is server-to-client interaction. Previously, a server could send an elicitation or sampling request down an open SSE stream. The new protocol handles the common case with Multi Round-Trip Requests, or MRTR. Under SEP-2322, a server can answer a tool call with an InputRequiredResult containing a request for more input. The client obtains that input, then retries the original operation with the response and an opaque state value. Any replica can process the retry because the needed state travels with it or resolves through an explicit handle.
That design costs an extra round trip and makes the state machine more visible in server code. In return, it avoids holding an execution context and an open stream while waiting for a person to approve an action, a delay that could last minutes or much longer. It also narrows server-initiated requests to defined contexts such as tool calls, resource reads, and prompt retrieval. Unsolicited changes use a dedicated subscription-listen request rather than a general session stream.
Compatibility is now the hard part
The clean architecture arrives during a deliberately mixed-era rollout. The modern spec tells clients to try a 2026 request first and fall back to the old initialization flow when the response indicates a legacy server. Servers that need older clients can host the legacy paths alongside the new POST endpoint. The original HTTP+SSE transport, however, has been deprecated since March 2025, and new implementations are told not to adopt it.
Developers should not equate installing a current package with sending the current protocol. The official TypeScript SDK migration guide says a directly constructed v2 client or server retains 2025-era behavior by default. Clients opt into automatic era negotiation or pin the 2026 revision; HTTP servers use the modern handler entry point. This conservative default avoids changing wire behavior on a dependency upgrade, but it can also make a nominally updated deployment continue using sessions unnoticed.
Migration tests therefore need to assert behavior, not package versions. A useful matrix covers a modern client with a modern server, a modern client falling back to a 2025 server, and any legacy clients the service promises to support. Teams should verify that modern requests do not mint a session ID, that GET and DELETE are rejected on the modern endpoint, and that cancellations close the request-scoped response stream. They should also check that every request is authenticated independently and that state returned through the client is integrity-protected.
The TypeScript guide makes the last point concrete: requestState is untrusted because the client echoes it. It recommends signing or encrypting the value, binding it to the authenticated principal, operation, parameters, and expiry, then rejecting failed verification. Stateless infrastructure removes a routing burden; it does not remove the need for durable storage, access control, replay defenses, or careful state design.
What to watch next
The next meaningful signal will be default wire behavior across SDKs and major MCP hosts, not another count of integrations. Watch whether client applications enable 2026-era negotiation, whether remote servers publish tested mixed-version paths, and whether gateways replace session-based stdio bridging cleanly. The revision gives MCP a more conventional HTTP foundation. Its success now depends on how quickly the ecosystem can adopt that foundation without hiding compatibility failures or moving session mistakes into poorly secured explicit tokens.