// what changed, and when
The current MCP protocol version is 2026-07-28, and the version string is itself the news: MCP names releases "following the format YYYY-MM-DD, to indicate the last date backwards incompatible changes were made." Something broke on that date, by design.
What broke is sessions. From the release notes:
initialize/initialized handshake is removed.The
Mcp-Session-Id header and the protocol-level session that came with it are also removed.This is a good change and it is worth saying so plainly. A session pinned a client to one server instance; without it, "any MCP request can land on any server instance", so sticky routing and a shared session store stop being requirements. The release notes are also explicit that "removing the protocol-level session does not mean your application has to be stateless."
But something moved onto you
The specification states the consequence directly:
So a shopping cart, a workflow, a long-running job — anything that outlives a single call — is now referenced by an ID your server mints and hands back, which the client returns as an ordinary tool argument every time.
Which means every MCP server with state is now issuing identifiers, whether or not anyone on the team stopped to decide what an identifier is.
The trap has a name: state handle hijacking
The security guidance describes it in four plain steps:
2. The attacker obtains or guesses the handle.
3. The attacker calls the MCP server's tools with the handle as an argument.
4. The MCP server does not check whether the handle belongs to the caller and operates on the original user's state.
Read "obtains or guesses" carefully, because it is two different attacks. Guessing is defeated by unpredictable IDs. Obtaining is not — a handle that leaked through a log line, a screenshot, a shared trace or a support ticket is exactly as valid as one you guessed, and no amount of entropy helps.
That is why the common advice — "use a UUID" — is half a fix, and the more dangerous half to stop at, because it feels complete.
The rule, in RFC 2119 language
Having the number is not the same as being allowed. And the mitigation is unusually concrete for a security document:
<user_id>:<handle> where the user ID is derived from the verified token rather than supplied by the client, and reject a handle presented by any other principal.Then, as defence in depth rather than as the control: "use secure, non-deterministic handles generated with secure random number generators. Avoid predictable or sequential identifiers... Expiring handles can also reduce the risk."
Sources: MCP Versioning · Specification — Statelessness · Security Best Practices — State Handle Hijacking · the 2026-07-28 release post. All loaded 2026-08-17; MCP revises, so check the version banner. Related: tokens issued for somebody else · never pass a token onward.
One concept a week. Free.
The deeper, copy-paste version of each ToolCall short — in your inbox.
// total: 0.00 · spam: void · unsubscribe: one click
