MCP goes stateless: what changed in the 2026-07-28 specification

What struck me most about the 2026-07-28 revision of the Model Context Protocol (MCP) is how much it takes away. The handshake is gone, sessions are gone, and a server can no longer send requests to the client. It’s the fifth revision of the specification, and its changes reach every layer of a server.
This is part 2 of my series on what an MCP server does under the 2026-07-28 specification; part 1 was about why a server is much more than a list of tools. I’ve summed up this change in a paragraph twice before, in my review of MCP testing tools and in what AI hosts require of an MCP server. This is the longer version, with the facts as I read them in October 2026.
In brief
- MCP no longer has sessions. The
initializehandshake and theMcp-Session-Idheader are gone, so each request stands on its own and names the protocol version it speaks. - A server can’t send requests to the client any more. To ask for input, it answers with an
input_requiredresult, and the client sends the request again with the answers. - Every server MUST implement the new
server/discovermethod. Calling it is optional for clients. - Tasks moved into an extension, and roots, sampling and logging are deprecated. A deprecated feature keeps working for at least twelve months, with two exceptions.
- I see this as mostly good news for a server in the cloud. Any request can land on any instance; what stays long-lived or stateful needs deliberate design.
Five revisions, named by date
MCP versions are named by their release date, not by a number. Each revision has its own changelog, and the specification’s home page always points at the latest one. Here are the five so far, with the headline changes of each.
The original HTTP transport, HTTP with Server-Sent Events (SSE), known as HTTP+SSE, gave way to Streamable HTTP in the 2025-03-26 revision and is now on its way out. Sampling, roots and elicitation all arrived in earlier revisions, and all three relied on the server sending requests to the client. That mechanism is what 2026-07-28 takes away.
The headline: no more sessions
MCP used to be a stateful, bidirectional protocol. A client opened a session with an initialize handshake, the server handed back an Mcp-Session-Id, and the two sides could send requests to each other for as long as the session lasted. Under the 2025-11-25 revision, a tool call that needed the user’s input went like this:
That model fits a long-running desktop process well. It fits a horizontally scaled cloud service badly: you need sticky load balancing or shared session storage, and a dropped connection takes its context with it.
The 2026-07-28 revision removes all of that:
- No handshake. The
initializeandnotifications/initializedexchange is gone. Every request carries its own protocol version and client capabilities in_meta. - No sessions. The
Mcp-Session-Idheader is gone, and list results no longer vary per connection. A server that needs state across calls mints explicit handles and passes them as ordinary tool arguments. - No server-initiated requests. A server that needs input returns an
input_requiredresult, and the client retries the original request with the answers. This is the Multi Round-Trip Requests (MRTR) pattern.
The same tool call now looks like this. The retry is a new request with a new ID, and it carries the answers and the requestState the server returned:
Required of servers, optional for clients
My earlier summaries called server/discover mandatory, and that’s true from the server’s side: every server MUST implement server/discover, which advertises its versions, capabilities and identity. Calling it is optional for clients, which is why the diagram marks it optional. A client may skip it and send its first request straight away.
What it means for a server in the cloud
The specification describes the protocol, not how to host it, so this part is my advice. I see statelessness as mostly good news for cloud servers. Any request can land on any instance, so serverless hosting, autoscaling and blue/green deployments become simpler. The cost moves to two places: what really is long-lived (subscriptions/listen streams and Tasks) and what really is stateful (the handles a server mints). Those need deliberate design and a shared store, and later parts of this series show how.
The full list of changes
Nine major changes
Each change came in through a Specification Enhancement Proposal (SEP), MCP’s change process. The first three rows and row 7 are the headline again, with their SEP numbers and the exact _meta keys.
| # | Change | SEP |
|---|---|---|
| 1 | Sessions and the Mcp-Session-Id header are removed; cross-call state moves to server-minted handles. | SEP-2567 |
| 2 | The initialize handshake is removed. Each request carries io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities in _meta, and a version mismatch returns UnsupportedProtocolVersionError. | SEP-2575 |
| 3 | server/discover is added, and every server MUST implement it. | SEP-2575 |
| 4 | subscriptions/listen replaces the HTTP GET endpoint and resources/subscribe with one opt-in, long-lived notification stream. | SEP-2575 |
| 5 | ping, logging/setLevel and notifications/roots/list_changed are removed. The log level is now set per request in _meta. | SEP-2575 |
| 6 | Tasks move out of the core into the official io.modelcontextprotocol/tasks extension, redesigned around polling. | SEP-2663 |
| 7 | MRTR replaces the server-initiated roots/list, sampling/createMessage and elicitation/create. | SEP-2322 |
| 8 | Every result carries a required resultType: "complete" or "input_required". | SEP-2322 |
| 9 | SSE resumability is removed. A broken stream loses the request in flight, and the client re-issues it with a new ID. | SEP-2575 |
Smaller changes worth knowing
| Area | What changed |
|---|---|
| Capabilities | An extensions field in client and server capabilities. |
| Tracing | OpenTelemetry trace-context keys in _meta: traceparent, tracestate and baggage (SEP-414). |
| Tool lists | Servers SHOULD return tools/list in a deterministic order, to improve prompt-cache hit rates for clients and models. |
| HTTP headers | On Streamable HTTP, Mcp-Method is required on every request, and Mcp-Name on tools/call, prompts/get and resources/read. Tool parameters can be mirrored to headers with x-mcp-header (SEP-2243). |
| Caching | Caching hints become required: complete results of server/discover, the list methods and resources/read MUST carry ttlMs and cacheScope, and an input_required result carries none (SEP-2549). |
| Errors | Resource not found changes from -32002 to -32602 (Invalid Params), and the range -32020 to -32099 is reserved for the MCP specification. |
| Authorization | Authorization servers SHOULD include iss in authorization responses, and clients MUST validate it (SEP-2468). Dynamic Client Registration requires an appropriate application_type (SEP-837). Credentials are bound to the authorization server that issued them (SEP-2352). |
| Schemas | inputSchema and outputSchema accept any JSON Schema 2020-12 keyword, and structuredContent can be any JSON value (SEP-2106). |
| Elicitation | The URL-elicitation completion notification and elicitationId are removed. |
Deprecated, not yet removed
These six are deprecated: they still work, but new implementations shouldn’t adopt them. Each has a replacement:
- Roots: pass directories or files as tool parameters, resource URIs or server configuration.
- Sampling: call your own model provider’s API from the server.
- Logging (
notifications/message): log tostderron stdio, or use OpenTelemetry. - The HTTP+SSE transport: use Streamable HTTP.
- The
includeContextvaluesthisServerandallServersin sampling requests: omit the field, or use"none". - Dynamic Client Registration: use Client ID Metadata Documents. Registration remains for older authorization servers.
How long do they keep working? The feature-lifecycle policy (SEP-2596) sets a floor of twelve months. The specification’s deprecated registry makes roots, sampling, logging and Dynamic Client Registration eligible for removal no earlier than the first revision released on or after 2027-07-28. The includeContext values follow sampling’s schedule. The floor has two exceptions:
- a feature that presents an active security risk can be removed sooner, after at least 90 days;
- the HTTP+SSE transport, deprecated since 2025-03-26, has only a three-month grace period, counted from SEP-2596 reaching Final.
Even when its window has passed, a feature only becomes eligible for removal. Taking it out is a decision for the core maintainers.
Method and caveats
- Built from chapter 2 of my guide to MCP servers in 2026, and written against the 2026-07-28 specification and its changelog as I read them in October 2026.
- Where the specification is more precise than my notes (how long a deprecated feature keeps working, which requests need the
Mcp-Nameheader, which results carry caching hints), this article follows the specification’s own pages, as checked on 8 October 2026. - The smaller changes are given in brief. Later parts of this series cover caching and the HTTP headers in detail, and the deprecations in full, with each old pattern and what replaces it.
SeriesWhat an MCP server actually does in 2026Part 2 of 35
- What an MCP server does in 2026: much more than a list of tools
- MCP goes stateless: what changed in the 2026-07-28 specification
- server/discover: the one method every MCP server must implement
- Server instructions: the paragraph every model reads first
- Stateless MCP requests: _meta, resultType and explicit handles
- Caching hints and pagination in MCP
- MCP transports in 2026: stdio and Streamable HTTP