Now in early access, book a 30-minute demo →
← Back to blog Guide

Stateless MCP: What the 2026-07-28 Specification Changes for Security and Identity

TL;DR
  • The 2026-07-28 MCP specification turns MCP from a bidirectional stateful protocol into a request/response stateless one. The initialize/initialized handshake and the Mcp-Session-Id header are gone.
  • Every request is now self-contained. Protocol version, client identity and capabilities travel in params._meta (or top-level _meta, per the method schema) on each call rather than being agreed once at connection time.
  • Streamable HTTP requests must carry Mcp-Method and Mcp-Name headers, so a gateway, rate limiter or WAF can route and meter without parsing JSON bodies - and servers reject requests where headers and body disagree, closing a real class of routing/security mismatch.
  • The security model changes shape. With no session there is no session-scoped authorization state, so every request must be authorized on its own merits. That is stricter in principle and easier to get wrong in practice.
  • Client identity in _meta is a claim, not proof. If you do not bind it to the authenticated principal, you have self-reported identity in your audit trail. This is the single most important thing to get right.
  • MRTR (Multi Round-Trip Requests) lets a stateless server ask for input mid-call - resultType: "input_required", then the client retries with inputResponses. It restores interactivity, and it gives a server a sanctioned channel to ask the client for things. Treat those prompts as untrusted.

The 2026-07-28 MCP specification is the largest change to the protocol since it shipped. MCP was designed as a stateful, bidirectional connection: a client and server performed an initialize/initialized handshake, agreed protocol version and capabilities once, and thereafter shared a session identified by the Mcp-Session-Id header. The new revision removes all of that. MCP becomes request/response and stateless, every call carries its own context, and sticky sessions are gone.

Most of the commentary has framed this as an infrastructure story - and operationally it is a good one. But the security consequences are more interesting than the deployment ones, and they cut both ways: some real vulnerability classes close, and one new failure mode opens that is easy to build straight into a first implementation. This guide covers what changed, what it means for authorization, identity and audit, and what to check.

What actually changed

AreaBefore2026-07-28
Connection modelStateful, bidirectional, long-livedStateless request/response
Handshakeinitialize / initialized exchangeRemoved - no handshake
SessionMcp-Session-Id header identifies the sessionRemoved - no session identifier
Protocol versionAgreed once at connection timeSent on every request
Client identity + capabilitiesExchanged once at connection timeIn params._meta (or top-level _meta) on every request
RoutingRequires sticky sessions; body parsing to routeMcp-Method and Mcp-Name headers; plain round-robin works
Header/body consistencyNot specifiedServers reject requests where headers and body disagree
InteractivityNative to the bidirectional sessionMRTR - resultType: "input_required" then retry with inputResponses

The practical upshot for operators is that any server instance can serve any request behind a plain round-robin load balancer. No session affinity, no sticky routing, no draining connections on deploy. For anyone who has run MCP at scale behind a proxy, that alone justifies the revision.

What gets safer

Three genuine improvements, and they are not marginal.

  1. Session hijacking stops being a category. No session identifier means no long-lived bearer of authority to steal, replay or fixate. A leaked Mcp-Session-Id used to be a durable capability; now there is nothing equivalent to leak.
  2. Header/body disagreement is now an error. Servers must reject requests whose Mcp-Method and Mcp-Name headers do not match the body. That closes a smuggling class where a gateway routes or authorizes on one value while the server acts on another - the same desync that produces request-smuggling bugs in HTTP proxies.
  3. Policy enforcement gets cheaper and more reliable. Because method and tool name are in headers, a gateway can make an allow/deny decision without parsing a JSON body. Less parsing means fewer parser-differential bugs between your gateway and your server, and it makes per-tool rate limiting and authorization practical at the edge - relevant if you run an AI gateway or proxy.

What gets riskier

Authorization has to be re-decided on every request, and identity is now something the client asserts. Those two facts together are where implementations will go wrong.

Under the old model it was tempting - and workable - to authorize at handshake and treat the session as trusted thereafter. That shortcut is now impossible, which is an improvement. But the replacement has a trap: client identity and capabilities arrive in _meta on each request, and _meta is transport-level metadata supplied by the caller. It is a *claim*. If a server reads the client identity out of _meta and uses it for authorization decisions or writes it into an audit log without binding it to the authenticated principal - the OAuth token, mTLS certificate, or whatever actually establishes who is calling - then it has built self-reported identity into its security decisions. An attacker with any valid credential can then present themselves as a different client.

This matters especially for audit. An agent-layer audit trail is only worth what its identity field is worth, and *the caller told us who it was* is worth very little under scrutiny. If you are relying on that record for ISO 42001 or NIST AI RMF evidence, the identity in each entry needs to derive from authentication, with the _meta claim recorded separately as what the client asserted. The distinction is small in code and large in an audit. Our OAuth for MCP servers guide covers establishing the authenticated principal, and AI gateway OAuth passthrough covers what happens to it in transit.

The second new surface is MRTR. Multi Round-Trip Requests restore interactivity to a stateless protocol: a server can return resultType: "input_required" along with the things it needs answered, and the client retries the original call with the answers attached in inputResponses. This is a sensible design. It also formalises a channel in which a server asks a client for input, and the text of that request reaches the model. Treat input_required prompts as untrusted content, exactly as you would a tool result - this is the delivery path that MCP tool poisoning and indirect prompt injection already exploit, and DuneSlide showed a zero-click RCE arriving via an MCP response. A server that can prompt for input can ask for a credential and have the request look like protocol.

ChangeDirectionWhat to do about it
No session identifierSaferNothing - one whole class of hijacking is gone
Header/body must agreeSaferConfirm your server enforces the rejection rather than ignoring it
Routing on headersSaferMove gateway allow/deny to headers; stop body-parsing to authorize
Per-request authorizationStricter, easy to botchAuthorize every call; never cache a decision as though it were a session
Identity in _metaRiskierBind to the authenticated principal; log the claim separately
MRTR input_requiredNew surfaceTreat prompts as untrusted; never auto-answer with secrets

Migration checklist

  • Confirm which spec revision each of your MCP servers and clients implements. Mixed fleets are the normal state during a transition, and the two models have different security assumptions - do not reason about them as one system.
  • Audit every place your servers read client identity or capabilities from _meta. Bind identity to the authenticated principal for any authorization decision, and record the _meta claim as an assertion rather than a fact.
  • Remove any authorization shortcut that assumed a session. If a decision was made once per connection, it now needs making per request.
  • Move gateway routing, metering and allow/deny to Mcp-Method and Mcp-Name headers, and verify your gateway and server agree on the values - the spec requires servers to reject mismatches, so a disagreement should now fail loudly rather than diverge quietly.
  • Treat MRTR input_required prompts as untrusted input in the model's context. Never wire an automatic responder that can supply credentials or approve actions without a policy check.
  • Re-check rate limits and quotas. Stateless means retries and MRTR round trips multiply request counts, so limits tuned per-session will behave differently per-request.
  • Re-examine your audit schema so each entry carries the authenticated principal, the asserted client identity, the method and the tool name - which the headers now make straightforward to capture.
  • Reconcile the servers your fleet actually talks to against a reviewed set, per building an MCP server registry. A protocol change is a good moment to discover which servers exist.

Where Anomity fits

A protocol revision does not change the underlying governance problem: an MCP server is a program launched with a user's permissions, and most organisations cannot enumerate the ones running on their endpoints. MCP servers are one of the eight AI artifact types Anomity inventories per endpoint - alongside AI agents, extensions, plugins, skills, secrets, hooks and CLIs - which is what makes "which servers do we talk to, and which revision do they speak" an answerable question rather than a survey.

The stateless model also makes the enforcement point cleaner. Because every request is self-describing, the tool call is the natural unit of decision - which is where Anomity already operates. Where an agent exposes a hook, such as the PreToolUse event in Claude Code, each call is evaluated against policy and returns allow, deny, or log before it runs, and decisions land in a queryable 90-day audit trail with the method and tool name that the new headers make explicit. That is runtime governance reading the same fields your gateway now routes on. Anomity collects metadata only, with on-endpoint secret redaction, is SOC 2 Type II, and complements EDR, DLP, network and GRC tooling.

You can't govern what you can't see.The Anomity principle

The 2026-07-28 revision is a good change badly served by being described as an infrastructure upgrade. Dropping sessions removes a hijacking class and makes edge policy enforcement genuinely practical. But it relocates identity into per-request metadata that the caller supplies, and adds a sanctioned channel for servers to prompt clients - so the work is to bind identity to authentication and treat MRTR prompts as untrusted. Get those two right and the new model is stricter than the old one. Get the first wrong and your audit trail records whatever the caller claimed. For the full trust model see the MCP Server Security guide, for identity foundations AI identity security explained and non-human identity governance, and for lifecycle placement ADLC. To see which MCP servers your fleet actually runs, request early access.

Frequently asked questions

What changed in the 2026-07-28 MCP specification?

It converts MCP from a bidirectional stateful protocol into a stateless request/response one. The initialize and initialized handshake is removed, and so is the Mcp-Session-Id header. Every request becomes self-contained: protocol version, client identity and capabilities travel in params._meta, or in a top-level _meta depending on the method schema, on each call rather than being agreed once at connection time. Streamable HTTP requests must include Mcp-Method and Mcp-Name headers, and servers must reject requests where the headers and the body disagree. Interactivity returns through MRTR, Multi Round-Trip Requests, where a server responds with resultType input_required and the client retries the original call with answers attached in inputResponses.

Is stateless MCP more secure than the stateful model?

In two respects, clearly yes. Removing the session identifier eliminates session hijacking, replay and fixation as a category, because there is no long-lived bearer of authority to steal. And requiring that headers agree with the body closes a smuggling class where a gateway authorizes on one value while the server acts on another. But it is not uniformly safer. Authorization must now be decided per request, which is stricter in principle but easy to implement badly, and client identity has moved into caller-supplied metadata. The net security depends almost entirely on whether implementations bind that asserted identity to the authenticated principal.

Why is client identity in _meta a risk?

Because _meta is transport metadata supplied by the caller, so the client identity it carries is a claim rather than proof. If a server reads that value and uses it to make authorization decisions, or writes it into an audit log, without binding it to the principal established by authentication - an OAuth token, an mTLS certificate, or equivalent - then anyone holding any valid credential can present themselves as a different client. The fix is small: derive the identity used for decisions and audit entries from authentication, and record the _meta value separately as what the client asserted. This matters most for audit, because an agent audit trail is only worth what its identity field is worth, and the caller told us who it was does not survive scrutiny.

What is MRTR and why does it need care?

MRTR stands for Multi Round-Trip Requests, and it restores interactivity to a protocol that no longer has a session. A server that needs more information returns resultType input_required together with the items it needs answered, and the client retries the original call with the answers in inputResponses. The design is reasonable. The caution is that it formalises a channel where a server asks a client for input, and the text of that request reaches the model's context. Treat input_required prompts as untrusted content exactly as you would any tool result: a server that can prompt for input can ask for a credential in language that looks like protocol. Never wire an automatic responder that can supply secrets or approve actions without a policy check.

Do we have to migrate immediately?

No, but you do need to know where you stand, because mixed fleets are the normal state during a transition and the two revisions carry different security assumptions. Inventory which revision each client and server implements and stop reasoning about them as one system. Then work through the specifics: remove authorization shortcuts that assumed a session, bind _meta identity to authentication, move gateway routing and allow/deny onto the Mcp-Method and Mcp-Name headers, treat MRTR prompts as untrusted, and re-tune rate limits since retries and round trips change request counts per operation.

What does statelessness mean for running MCP behind a gateway?

It gets substantially simpler. Because every request is self-describing, any server instance can serve any request behind a plain round-robin load balancer - no session affinity, no sticky routing, no connection draining on deploy. Security-wise the gain is that Mcp-Method and Mcp-Name are in headers, so a gateway can route, meter and make allow/deny decisions without parsing a JSON body. That removes a category of parser-differential bug between gateway and server, and makes per-tool rate limiting and authorization practical at the edge. Just confirm your gateway and server agree on those header values, since the spec now requires servers to reject mismatches.

Does the new spec change what we need to inventory?

It adds a field rather than changing the problem. You still need to know which MCP servers exist across your endpoints, because a server is a program launched with a user's permissions regardless of which protocol revision it speaks - that is what makes an unexplained server a potential compromise rather than a configuration detail. What the revision adds is that you should now also record which revision each client and server implements, since your authorization reasoning differs between them. The practical benefit is that the new headers make method and tool name explicit, so audit entries can carry the authenticated principal, the asserted client identity, the method and the tool name without body parsing.

How does this interact with prompt injection risks?

It does not reduce them, and MRTR modestly expands the surface. MCP tool responses are already an established delivery path for indirect prompt injection - the DuneSlide vulnerabilities in Cursor, CVE-2026-50548 and CVE-2026-50549, were zero-click precisely because an MCP server response or a poisoned search result could carry the injected instructions. MRTR adds a second, protocol-sanctioned way for a server to place text in front of the model. So the mitigations are unchanged and now apply in one more place: treat everything arriving from a server as untrusted input, and put the enforcement at the tool call, where an action can be evaluated regardless of which text prompted it.

Ask AI about Anomity
ChatGPT Claude Perplexity Google AI Grok