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

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

  1. MCP no longer has sessions. The initialize handshake and the Mcp-Session-Id header are gone, so each request stands on its own and names the protocol version it speaks.
  2. A server can’t send requests to the client any more. To ask for input, it answers with an input_required result, and the client sends the request again with the answers.
  3. Every server MUST implement the new server/discover method. Calling it is optional for clients.
  4. 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.
  5. 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.

MCP specification revisions2024-11-05The first public releaseTools, resources, prompts, sampling, roots, loggingstdio and HTTP+SSE transports2025-03-26Streamable HTTP replaces HTTP+SSEAn OAuth 2.1-based authorization frameworkTool annotations and audio content2025-06-18Structured tool output, elicitation, resource links in tool resultsAuthorization moves to the OAuth resource-server modelJSON-RPC batching is removed2025-11-25Experimental tasks, URL-mode elicitationClient ID Metadata Documents, icons, tool-naming guidance2026-07-28A stateless protocol core, server/discoverMulti round-trip requests, subscriptions/listenCaching hints, standard HTTP headers, Tasks as an extensionRoots, sampling and logging deprecated

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:

ServerClientSession state lives on one server instanceinitialize (version, capabilities)InitializeResult + Mcp-Session-Idnotifications/initializedtools/call (Mcp-Session-Id)elicitation/create (server-initiated request)ElicitResultCallToolResult

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 initialize and notifications/initialized exchange is gone. Every request carries its own protocol version and client capabilities in _meta.
  • No sessions. The Mcp-Session-Id header 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_required result, 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:

Any server instanceClientClient asks the userserver/discover (optional)versions, capabilities, instructionstools/call + _meta (version, client capabilities)resultType input_required+ inputRequests + requestStatetools/call retry + inputResponses+ requestState (new request ID)resultType complete + CallToolResult

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.

#ChangeSEP
1Sessions and the Mcp-Session-Id header are removed; cross-call state moves to server-minted handles.SEP-2567
2The initialize handshake is removed. Each request carries io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities in _meta, and a version mismatch returns UnsupportedProtocolVersionError.SEP-2575
3server/discover is added, and every server MUST implement it.SEP-2575
4subscriptions/listen replaces the HTTP GET endpoint and resources/subscribe with one opt-in, long-lived notification stream.SEP-2575
5ping, logging/setLevel and notifications/roots/list_changed are removed. The log level is now set per request in _meta.SEP-2575
6Tasks move out of the core into the official io.modelcontextprotocol/tasks extension, redesigned around polling.SEP-2663
7MRTR replaces the server-initiated roots/list, sampling/createMessage and elicitation/create.SEP-2322
8Every result carries a required resultType: "complete" or "input_required".SEP-2322
9SSE 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

AreaWhat changed
CapabilitiesAn extensions field in client and server capabilities.
TracingOpenTelemetry trace-context keys in _meta: traceparent, tracestate and baggage (SEP-414).
Tool listsServers SHOULD return tools/list in a deterministic order, to improve prompt-cache hit rates for clients and models.
HTTP headersOn 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).
CachingCaching 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).
ErrorsResource not found changes from -32002 to -32602 (Invalid Params), and the range -32020 to -32099 is reserved for the MCP specification.
AuthorizationAuthorization 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).
SchemasinputSchema and outputSchema accept any JSON Schema 2020-12 keyword, and structuredContent can be any JSON value (SEP-2106).
ElicitationThe 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 to stderr on stdio, or use OpenTelemetry.
  • The HTTP+SSE transport: use Streamable HTTP.
  • The includeContext values thisServer and allServers in 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-Name header, 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
  1. What an MCP server does in 2026: much more than a list of tools
  2. MCP goes stateless: what changed in the 2026-07-28 specification
  3. server/discover: the one method every MCP server must implement
  4. Server instructions: the paragraph every model reads first
  5. Stateless MCP requests: _meta, resultType and explicit handles
  6. Caching hints and pagination in MCP
  7. MCP transports in 2026: stdio and Streamable HTTP

I’m Amir Pournasserian. I build AI and platform systems for a living, maintain FluentCMS and YeSvelte, and write here about what I find along the way.