MCP Goes Stateless on July 28. Its Poisoning Problem Stays

MCP Goes Stateless on July 28. Its Poisoning Problem Stays
MCP Goes Stateless on July 28. Its Poisoning Problem Stays

On July 28, 2026, the Model Context Protocol ships its biggest rewrite since launch. The headline change is that MCP becomes stateless: no handshake, no session ID, no sticky routing. Any request can land on any server instance, which is exactly the property a protocol needs to scale behind an ordinary load balancer instead of custom session-aware infrastructure. Every writeup published since the release candidate locked on May 21 has covered that scaling story. None of them have connected it to the specific attack that made headlines the same month: a multi-tool poisoning technique called ShareLock that hides malicious instructions across cached tool descriptions using cryptographic secret sharing. The two stories are not separate. The new caching rules the spec introduces to make statelessness fast change exactly the variable that kind of attack depends on: how long a poisoned tool description sits in a client’s memory before anyone looks at it again.

What actually changes on July 28

The current specification, dated 2025-11-25, requires a client to open a session before it can call a tool. The client sends an initialize request, the server hands back an Mcp-Session-Id header, and every following request must carry that ID, which pins the client to whichever server instance issued it. That works fine for a single MCP server running on someone’s laptop. It becomes an operational headache at scale, because a remote MCP server serving many concurrent agents needs sticky sessions, a shared session store, and often deep packet inspection at the load balancer just to route traffic correctly.

The 2026-07-28 specification, built from six Specification Enhancement Proposals working through the MCP Working Group, removes the handshake and the session ID entirely. A tool call becomes one self-contained HTTP request carrying its own protocol version and client identity inside a _meta field. Two new required headers, Mcp-Method and Mcp-Name, let infrastructure route requests by operation without parsing the JSON body, and a new server/discover method replaces the old initialize handshake for clients that need to learn a server’s capabilities up front. Maintainers David Soria Parra and Den Delimarsky describe the practical effect plainly: a server that previously needed sticky sessions and a shared session store can now run behind a plain round-robin load balancer.

Removing sessions does not remove state from applications that need it. The spec’s suggested replacement is what the maintainers call the explicit-handle pattern: a tool like create_basket returns a basket_id, and the model passes that same ID back as an ordinary argument on the next call. State moves from hidden transport metadata into the model’s own visible reasoning chain, where it can be composed and reasoned about across tool calls rather than managed invisibly by the protocol.

The other headline addition is caching. List and resource read results now carry two new fields, ttlMs and cacheScope, modeled directly on HTTP’s Cache-Control header. A client that calls tools/list once can now trust the response is fresh for as long as the server’s declared ttlMs permits, and cacheScope tells it whether that cached list is safe to share across different users of the same deployment. Before this release, the only way to learn a tool list had changed was to hold open a long-lived Server-Sent Events stream. Now a client can simply cache the answer and stop asking.

Three smaller pieces round out the release: extensions become a first-class, independently versioned mechanism (with MCP Apps for server-rendered UI and a redesigned Tasks extension as the first two official ones), authorization gets six hardening proposals aligning it more closely with how OAuth 2.0 and OpenID Connect actually deploy in production, and three older features, Roots, Sampling, and Logging, are formally deprecated with a guaranteed twelve-month runway before anything breaks.

The Tasks extension is worth a closer look on its own, because it inherits the same statelessness the rest of the protocol just adopted. Under the old model, a long-running operation could hold a connection open. Under the new one, a server answers a tools/call with a task handle, and the client drives progress with tasks/get, tasks/update, and tasks/cancel calls that, like every other request in this release, can land on any server instance. The related Multi Round-Trip Requests mechanism works the same way for mid-call prompts: instead of holding a stream open to ask the user a question, a server returns an InputRequiredResult carrying an opaque requestState blob, the client collects an answer, and reissues the original call with that state echoed back. Any server instance can pick up the retry because everything needed to resume is in the payload itself. That design is elegant for horizontal scaling. It also means the resumability of a long-running task now depends entirely on the contents of a client-held token that travels outside any session boundary, which raises a narrower version of the same question the caching change does: what re-validates that a task handle or requestState blob has not been tampered with or replayed between the moment it was issued and the moment some other server instance resumes it. The specification does not currently mandate signing or expiry on these values the way it does for authorization tokens elsewhere in the same release, an asymmetry worth flagging even though nothing in the public record suggests it has been exploited yet. It is the same category of trust-boundary question this site raised in The Anchor Problem in AI Agent Delegation Chains: a credential or state token that outlives the specific connection that issued it needs its own validation story, not an inherited one.

Where this intersects the poisoning problem

Every tool description an agent reads comes from the same place a ShareLock share would be planted: the response to a tools/list call. That is the exact response the July 28 spec just made cacheable for the first time.

Under the outgoing 2025-11-25 specification, a client re-establishes its session periodically and, in practice, many implementations re-fetch the tool list on every new session rather than holding it indefinitely. Under 2026-07-28, a server can attach a long ttlMs to its tools/list response and a client is explicitly permitted, even encouraged, to treat that list as valid without re-checking it. That is the entire design goal: fewer round trips, less redundant traffic, better performance at scale. It is also, mechanically, a longer window during which a poisoned tool description sits trusted in a client’s cache without a fresh registration event that a security scanner might catch.

This matters specifically for threshold-based attacks like ShareLock, the Shanghai Jiao Tong University technique published in June 2026 that splits a malicious instruction into several benign-looking numeric fragments using Shamir’s Secret Sharing, then scatters those fragments across multiple tool descriptions on a single compromised server. ShareLock’s own paper notes that its attack activates once an agent has aggregated enough shares across the tools it calls during a normal task, triggered by a disguised initialization tool the researchers modeled on the earlier Rug Pull attack pattern, where a server’s legitimate-looking update silently swaps in new tool behavior. A longer cache lifetime on tools/list does not make the underlying cryptography any stronger. It does mean a share, once fetched and cached, persists in the client’s working knowledge of available tools for longer before whatever periodic re-vetting process a defender runs gets a fresh look at it.

To be precise about what changes and what does not: the July 28 spec closes off a different, unrelated class of MCP risk. Removing the session ID and the initialize handshake eliminates protocol-level session hijacking, the attack where a stolen or guessed Mcp-Session-Id lets an outsider impersonate a legitimate client mid-conversation, a risk the NSA flagged by name in its May 2026 Cybersecurity Information Sheet on MCP, the same document this site cross-referenced against MITRE’s ATLAS framework for AI attack techniques. That is a genuine security improvement, and Akamai’s security research team, reviewing the same release candidate, credits it as such while separately warning that the protocol’s shift toward application-managed state and richer async capabilities moves security responsibility onto developers rather than the protocol itself. Statelessness fixes session hijacking. It says nothing about tool description trust, and the caching layer built on top of it, while orthogonal in design intent, extends exactly the exposure window a threshold-poisoning attack is built to exploit.

Why it matters

MCP server operators reading the July 28 spec for its performance wins are reading it correctly, and should ship the migration. The stateless core is a real, necessary fix for anyone running MCP at more than toy scale, and the authorization hardening closes gaps that mattered independently of any poisoning research. But the caching mechanics deserve a second read from whoever owns tool vetting, not just whoever owns infrastructure.

The practical question a defender should ask before setting a long ttlMs on a production tools/list response is how that interacts with whatever re-scanning cadence catches poisoned or updated tool descriptions. If a security scanner re-audits connected MCP servers daily but a client caches tools/list for a week because the server declared a generous ttlMs, that gap is new attack surface introduced by a spec change that had nothing to do with security scanning in mind. The spec does not mandate any particular ttlMs value; that choice sits entirely with each server implementation, which means the actual exposure window varies server by server and nobody has measured it yet across real deployments.

Three concrete decisions fall out of that gap for anyone operating an MCP client or server past July 28. First, server operators setting ttlMs on tools/list responses are making a security decision, not just a performance one, and should set it no longer than the interval at which the server’s own tool descriptions are actually re-audited, not the interval that maximizes cache-hit performance. Second, client implementers building or buying MCP gateways should treat cacheScope and ttlMs as inputs to a security policy, invalidating cached tool lists on any signal that a connected server changed ownership, updated its version, or tripped a guard-model flag, rather than trusting the server’s self-declared freshness window unconditionally. Third, anyone building detection specifically for threshold-poisoning schemes like ShareLock needs to stop treating each tools/list response as an independent, point-in-time artifact and start correlating numeric-looking fields across a server’s full toolset and across cache refreshes, since a share that looks like inert metadata in one snapshot only becomes suspicious in relation to the others it was split alongside.

What happens next

The release candidate locked May 21, 2026, giving SDK maintainers and client implementers a ten-week validation window before the final specification publishes July 28. Tier 1 SDKs are expected to ship support within that window, and the 2025-11-25 wire format keeps working during a transition period, so this is not an overnight cutover for existing deployments.

What is worth watching over the next quarter is whether any of the MCP security tooling ecosystem, the guard models and scanners the ShareLock paper names as current defenses, updates its threat model to account for cache-aware auditing rather than point-in-time registration checks. None of the vetting tools built against the 2025-11-25 session model were designed with a persistent, server-declared cache lifetime in mind, because that concept did not exist in the protocol until this release. A scanner that only inspects a tool description at connection time, and trusts the client’s cache for the declared ttlMs after that, inherits a blind spot the spec itself just created as a side effect of solving an unrelated scaling problem. The fix is not complicated in principle: treat cache freshness and content trust as two separate properties, and re-validate tool descriptions on a cadence independent of how long the protocol says a client is allowed to skip re-fetching them. Whether MCP client implementations and their surrounding security tooling actually build that separation before July 28, or discover the gap the way most protocol security gaps get discovered, after someone demonstrates it working in production, is the open question this release leaves behind.

Discover more from My Written Word

Subscribe now to keep reading and get access to the full archive.

Continue reading