MCP Went Stateless, So What Your Servers Must Change

2026-07-28 drops protocol sessions. A local place_order went 1 to 2 orders unless I sent an order id.

·
·
MCP Went Stateless, So What Your Servers Must Change
AuthorAdham Khaled
Read3 min
  • Specification 2026-07-28 dropped the initialize handshake and Mcp-Session-Id, so one POST now carries version, method, and name and any replica can answer.
  • A hung-up local place_order still wrote: the server waited 2.5 seconds, the client aborted at about 400 milliseconds, and the log line landed anyway.
  • A naive retry with a new JSON-RPC id wrote a second line (1 to 2). The same tool with order_id=ord-42 stayed at 1 and returned wrote: false, reason: duplicate_order_id.
  • Google's August 5th Cloud post says a round-robin hop used to return 400 Session Not Found, so operators pinned clients to one instance.
  • GitHub's July 23rd MCP Server changelog already removed Redis writes on initialize and Redis reads on every call.

Tool calling used to take two HTTP requests. initialize opened the old path. The server handed back Mcp-Session-Id.

That id was a ticket for one clerk. The next tools/call had to hit the same window, or the shop had no record of you.

We all saw specification 2026-07-28 land at the end of July. One POST now carries protocol version, client capabilities, method, and name, with no handshake and no session header, so any replica can answer.

Each slip is complete. Any clerk can take the next one.

A hung-up local place_order still wrote. The server waited 2.5 seconds, the client aborted at about 400 milliseconds, and the log line landed anyway.

A naive retry used a new JSON-RPC request id and wrote a second line. The same tool with order_id=ord-42 stayed at one line.

Claude-only or Cursor-only apps can often wait on the host. Server and custom-client authors should treat a dropped answer as a full retry and make write-or-charge tools safe to run twice.

What follows is the August 14th session vs one POST, who has to change code (host app, custom client, or server), and the cut stream that wrote 1 to 2 orders unless I sent ord-42. After that: why a new request id is not an order key, and the three checks before you drop 2025-11-25.

What does a 2026 tool call look like?

The old window hands you a ticket. The new slip is complete on its own.

I ran that pair with TypeScript SDK 2.0.0 on Aug 14th and captures are on my machine.

Left is the old path: initialize, a session id, then a later tools/call that must send the ticket back. No ticket on that server was 404 unknown session.

Right is one POST: version, method, and name on the request, and no session header. Filled in, it returned HTTP 200 and resultType: "complete".

Client name alone was not enough. The SDK returned HTTP 400 and JSON-RPC -32602 (missing the per-request envelope).

That shape is what lets you drop sticky sessions. Sticky routing exists so the next request finds the box that still has your ticket.

Google's Cloud post (August 5th) says a round-robin hop to the wrong pod used to return 400 Session Not Found, so operators pinned clients to one instance.

A request with no session pin can hit any replica. Google names Cloud Run and Cloud Functions as the spin-to-zero path.

Keep reading

Don't miss what's next in AI

Join 300,000+ engineers and researchers who get the signal, not the noise. Create a free account to read the rest of this story.

  • Full access to in-depth AI research breakdowns
  • Be the first to know what's trending before it hits mainstream
  • Daily curated papers, repos, and industry moves