5 min readRishi

MCP Went Stateless: What the 2026-07-28 Spec Changes for Your Server

MCP Went Stateless: What the 2026-07-28 Spec Changes for Your Server

The Model Context Protocol spec dated 2026-07-28 is the largest revision since the protocol launched, and the headline is the one server operators have been asking for: MCP is now a stateless request/response protocol. No initialize, no notifications/initialized, no Mcp-Session-Id. Every request carries what the server needs to answer it. That is what lets a server sit behind an ordinary load balancer without sticky sessions.

If you wrote a server against 2025-11-25, nothing breaks today. Clients that speak the older revision still work, and the spec says to keep accepting the old error codes they send. The changes below are what to do when you move.

Each request now carries its own context

The handshake is gone. In its place, every request includes _meta fields under the io.modelcontextprotocol/* namespace:

KeyRequiredWhat it carries
io.modelcontextprotocol/protocolVersionYesThe version for this request, for example "2026-07-28"
io.modelcontextprotocol/clientCapabilitiesYesThe client capabilities relevant to this request
io.modelcontextprotocol/clientInfoNoClient name and version
io.modelcontextprotocol/logLevelNoMinimum log level the server should emit for this request

Servers identify themselves in each result's _meta with io.modelcontextprotocol/serverInfo. A version the server does not support returns UnsupportedProtocolVersion (-32022). There is an optional server/discover for clients that want to learn about a server before calling anything, but a client no longer has to.

What this changes in code: any per-connection state your server kept between initialize and the first tools/call has to go. The spec is explicit that tools/list, resources/list, and prompts/list no longer vary per connection. If a tool needs state across calls, the server mints a handle and the client passes it back as an ordinary tool argument.

Two headers your gateway can route on

Streamable HTTP requests must include Mcp-Method and Mcp-Name. The method is the JSON-RPC method; the name is the tool, prompt, or resource being addressed. That is a small change with a large operational payoff. A rate limiter, WAF, or gateway can meter tools/call on delete_account differently from tools/list without parsing JSON bodies. If you were doing body inspection in a proxy to get the same effect, you can delete it.

List results are cacheable on purpose

tools/list, prompts/list, resources/list, and resources/read results now carry ttlMs and cacheScope. Clients use them to stop re-fetching catalogs they already have. For a server, this means two things. Set a ttlMs that reflects how often your catalog actually changes. And stop assuming a client has fetched the list recently; it may be serving a cached one, which is another reason lists cannot vary per connection.

Change notifications moved to a single stream

The old HTTP GET endpoint and resources/subscribe are replaced by subscriptions/listen: one long-lived POST response stream the client opts into, per notification type (toolsListChanged, promptsListChanged, resourcesListChanged, resourceSubscriptions). The server acknowledges and tags each notification with io.modelcontextprotocol/subscriptionId.

Request-scoped notifications — progress and log messages — still flow on the response stream of the request they belong to, not on the listen stream. If your server emitted progress on a side channel, it moves back to the request.

Tasks are an extension now

Long-running work moves out of the core into io.modelcontextprotocol/tasks. The server decides when a tools/call should become a task and returns a handle. The client polls with tasks/get, sends mid-flight input with tasks/update, and cancels with tasks/cancel. The blocking tasks/result is gone. tasks/list is gone too, because it cannot be scoped safely without sessions.

The extensions framework is the bigger structural point. New capability ships as an opt-in extension, negotiated explicitly, and stabilizes there before it is ever considered for the core. MCP Apps (server-rendered UI in a sandboxed iframe, talking to the host over the same JSON-RPC) and Enterprise Managed Authorization are extensions in the same sense.

Authorization: validate iss, plan to leave DCR

Authorization servers must return the iss parameter per RFC 9207 and clients must validate it before redeeming a code. That closes an authorization-server mix-up hole. Dynamic Client Registration is formally deprecated in favor of client metadata documents (CIMD). DCR keeps working for now; the spec has a formal deprecation policy with a minimum window between deprecation and removal, so you have time, but new servers should not start on DCR.

Also deprecated: Roots, Sampling, Logging as a negotiated capability (log level now rides on each request), the older HTTP+SSE transport, and the resource-not-found code -32002, replaced by -32602. Accept the old codes from old clients. Do not emit them.

A migration order that does not break clients

  1. Add the required _meta fields to your client and the serverInfo field to your server results. Keep answering initialize for older clients.
  2. Remove any per-connection state behind tools/list and friends. Mint handles for cross-call state.
  3. Emit and require Mcp-Method and Mcp-Name on Streamable HTTP. Update the gateway rules.
  4. Add ttlMs and cacheScope to list results.
  5. Move progress and log notifications onto the request stream; move list-changed notifications to subscriptions/listen.
  6. If you have long-running tools, adopt the Tasks extension instead of a home-grown polling endpoint.
  7. Start new auth integrations on CIMD and validate iss.

The payoff is a server you can scale horizontally without a session store, and a catalog clients stop hammering. How you describe the tools in that catalog still matters as much as before — the routing problem is covered in MCP tool descriptions that route the model. The spec and changelog are at modelcontextprotocol.io.

Keep reading

Newsletter

New posts, straight to your inbox

One email per post. No spam, no tracking pixels, unsubscribe anytime.

Comments

  • No comments yet. Be the first.