# MCP Went Stateless the Same Season It Got 106 Zero-Days Found in It. That's Not a Coincidence.

### **The July 2026 spec rewrite reads like an architecture upgrade. Read it next to the CVE list and it reads like triage.**

I spent a chunk of this spring watching MCP servers get popped in ways that were almost funny if they weren't running in production somewhere. A backdoored `postmark-mcp` package quietly BCC'ing outbound email to an attacker. A `mcp-remote` client that would shell out and execute arbitrary commands if a malicious server handed it a booby-trapped `authorization_endpoint` URL - CVSS 9.6, on a package with 437,000-plus downloads. Academic researchers pointed a scanner at 39,884 public MCP server repos in May and walked away with 106 zero-days. None of this was exotic. It was path traversal, command injection, and SSRF - the greatest hits of "we shipped fast and skipped input validation" - just wearing an agent-shaped hat.

Then, in July, the Model Context Protocol steering group shipped the 2026-07-28 specification, and it's the biggest revision since authorization was bolted on. The protocol drops its session handshake, moves to stateless requests, adds header-based routing, and hardens the auth flow with RFC 9207 issuer validation. The blog post frames it as a scalability story and it is one. But read it next to the CVE list from the preceding six months and a lot of the "why now" makes more sense. This wasn't a protocol maturing gracefully. This was a protocol getting hardened in response to the ecosystem finding out, publicly and repeatedly, how easy it was to break.

## **What MCP is, briefly**

Model Context Protocol is Anthropic's open spec for connecting LLM applications to external tools, data sources, and systems : a JSON-RPC-based contract so a client (an IDE, an agent runtime, Claude Desktop) can discover and call tools exposed by a server (a database connector, a filesystem bridge, a SaaS integration) without every pairing needing custom glue code. It shipped on November 25, 2024, as something aimed squarely at individual developers wiring up their coding tools. Twenty months later it's the connective tissue for a meaningful slice of enterprise agent deployments, which is exactly the kind of success that exposes what a spec wasn't built for.

## **The security findings, and why they weren't a surprise to anyone paying attention**

The numbers, once you line them up, describe a fairly specific failure mode. One 2026 scan of 2,614 MCP implementations found 82% had file operations prone to path traversal and 67% used code-injection-prone APIs; a separate scan of over 7,000 servers put command injection at 43% and SSRF at 36.7%. Different studies, different samples, same story. GitGuardian's 2026 secrets-sprawl scan found 24,008 unique credentials sitting in MCP-related config files on public GitHub, over 2,000 of them still live. Something like 40% of registered servers ship with no meaningful authentication at all.

None of that is protocol-specific carelessness - it's what you get when a huge number of people build servers that shell out, read files, and hit URLs based on model-generated input, and the ecosystem has no equivalent yet of "don't trust the client" muscle memory. MCP servers are, structurally, RPC endpoints that take instructions from something whose entire design goal is to be persuadable. Tool poisoning : hiding instructions inside a tool's description field so they land in the model's context as trusted text isn't a bug you patch, it's a consequence of treating tool metadata as safe just because it came from your own server's manifest. Nobody had to be clever to find these holes. Researchers pointed a scanner at 40,000 repos and the holes found themselves.

The mcp-remote RCE (CVE-2025-6514) is the case study worth sitting with, because it's not a misconfigured server - it's the client. A malicious MCP server hands back a crafted `authorization_endpoint` value during the OAuth flow, the client tries to open it, insufficient sanitization turns that into shell command execution. Versions 0.0.5 through 0.1.15 were exposed; the fix landed in 0.1.16 in June 2025. If your mental model of MCP risk was "the server is the attack surface, the client is trusted," this is the CVE that breaks that assumption. Both sides of the connection now have to assume the other is hostile, which is a genuinely different threat model than most of the early tutorials were written for.

## **What actually changed in the spec**

The 2026-07-28 release, per the [MCP blog](https://blog.modelcontextprotocol.io/posts/2026-07-28/), does four things that matter if you're building or operating servers right now.

**It drops session state from the protocol.** The `initialize`/`initialized` handshake and the `Mcp-Session-Id` header are gone. Every request now carries its own protocol version, client identity, and capabilities in `_meta`, instead of relying on a session negotiated once and held in server memory (or, more realistically, in some shared cache your ops team now owns). This is the load-balancer-friendly version of MCP - no sticky sessions, no shared state store required to scale horizontally. It's also, not incidentally, a security improvement: session hijacking and session-fixation-style attacks lose their foothold when there's no long-lived session artifact to steal.

**It adds header-based routing.** `Mcp-Method` and `Mcp-Name` now travel as HTTP headers, so gateways and rate limiters can route and enforce policy without parsing the JSON-RPC body on every request. That's a small detail with an outsized operational payoff - it's the difference between a gateway that can apply per-tool rate limits cheaply and one that has to deserialize every payload to figure out what's even being called.

**It formalizes an extensions framework**, and moves Tasks - the mechanism for long-running operations - out of core and into `io.modelcontextprotocol/tasks`, replacing server-initiated streaming with poll-based `tasks/get`/`tasks/update`. Multi Round-Trip Requests replace some of what server-initiated requests used to do: a tool can now return `resultType: "input_required"` mid-call and get the missing piece back on a follow-up request, instead of the server having to hold a stream open and push at the client.

```json
// old world: server holds a stream open, pushes a follow-up request
// new world: tool returns and waits, client re-calls with the missing piece
{
  "resultType": "input_required",
  "prompt": "Which environment: staging or prod?",
  "continuationToken": "tk_9f2a..."
}
```

**It hardens authorization.** RFC 9207 issuer validation, client credentials bound to a specific issuer, and a push from Dynamic Client Registration toward Client ID Metadata Documents. This is the part that reads most directly as a response to the CVE season - DCR was flexible and, per the security writeups, part of why so many servers ended up with weak or absent auth in the first place. CIMD narrows that.

Roots, Sampling, and Logging are deprecated with a twelve-month runway. The old HTTP+SSE transport is on the same clock. If you've got a custom implementation rather than one of the Tier 1 SDKs (TypeScript, Python, Go, C#, with Rust in beta), David Soria Parra's own framing is blunt: "it's going to be a lot of uplift to make this correct." Servers on 2026-07-28 won't necessarily talk to older clients. That's a real migration, not a minor-version bump.

## **The honest trade-offs**

Going stateless solves a scaling problem and closes a session-hijacking class of attack, and it does not touch tool poisoning, SSRF, or a server that shells out to [`subprocess.run`](http://subprocess.run)`()` with unsanitized model output. The spec changes harden the pipes; they don't harden what runs inside the pipes. Read the OWASP MCP Top 10 findings and the honest conclusion is that network allowlists, gateway-level auth, and runtime content inspection are three separate, necessary layers, and none of them is sufficient alone — the protocol update is one input to that stack, not a replacement for it.

There's also a real cost on the builder side. Twelve months sounds generous until you remember how much production MCP tooling was written against the stateful assumptions of the original spec - code that holds a session, streams server-initiated requests, expects `Mcp-Session-Id` to exist. Craig McLuckie's read -that MCP's statefulness was "a by-product of its origin as a way to support developers using coding tools" and enterprises are now bending it toward production intermediation is accurate, and it's also why this migration will be uneven. Individual developers wiring up a local tool barely notice. Teams running MCP gateways in front of internal systems are looking at real engineering work.

## **Why this matters right now**

MCP crossed the threshold from "convenient way to give Claude Desktop filesystem access" to "the thing standing between agents and production systems" faster than its security posture kept up, and 2026 is the year that gap got measured in CVE counts instead of hand-wringing blog posts. The interesting thing isn't that a young protocol had security problems - every young protocol does. It's that the fix showed up in the spec itself, not just in a wave of after-the-fact server patches. Removing session state, tightening the OAuth flow, forcing routing metadata into headers - these are the kinds of changes that come from people who watched real incidents and decided the protocol needed to make the safe thing easier, not just possible.

If you're running MCP servers in anything resembling production, the 2026-07-28 spec isn't optional homework. But treat it as half the job. The other half is the boring part nobody writes an RFC for: sanitize your inputs, pin your dependencies, don't trust tool descriptions as inert text, and assume the thing on the other end of the connection - client or server - is trying to see what it can get away with. The protocol just got better at its job. Yours didn't change.

* * *

Sources: [MCP 2026-07-28 Specification](https://blog.modelcontextprotocol.io/posts/2026-07-28/) · [The Register on MCP's stateless shift](https://www.theregister.com/devops/2026/07/23/model-context-protocol-prepares-to-break-with-its-stateful-past/5276722) · [State of MCP Security 2026, PipeLab](https://pipelab.org/blog/state-of-mcp-security-2026/) · [CVE-2025-6514, mcp-remote RCE, SentinelOne](https://www.sentinelone.com/vulnerability-database/cve-2025-6514/)
