إنتقل إلى المحتوى الرئيسي

MCP 2026-07-28: The Stateless Spec

متقدّم

On July 28, 2026 the Model Context Protocol locked its biggest revision since launch. The headline: MCP is stateless. The initialize handshake and Mcp-Session-Id header are gone; every request carries its own identity in _meta; any server instance behind a load balancer can answer any call. Serverless MCP is no longer a workaround — it's the shape of the protocol.

What you'll learn
  • What actually changed in the 2026-07-28 spec — the four removals and the four additions that matter
  • Multi Round-Trip Requests (MRTR): how a stateless server asks the user a follow-up question without a session
  • The Extensions framework and the two official extensions: MCP Apps and Tasks
  • Authorization hardening: OAuth 2.1, RFC 9207 iss validation, and what Dynamic Client Registration now requires
  • A concrete migration path that doesn't break your 2025-11-25 clients — with the SDK beta versions to install today

The one paragraph version

Before: initialize handshake → Mcp-Session-Id cookie → sticky client/server pair for the life of the session. After: no handshake, no session id, no stickiness. Client identity and capabilities ride on every request inside a _meta object. A new server/discover method replaces the initial capability exchange. Application state — a shopping cart, an in-flight task — lives in handles the tool returns and the client passes back on the next call, exactly like a REST resource id. That single change is what unlocks serverless and edge deployment, real horizontal scaling, and the ability for two competing implementations to sit behind the same URL.

What got removed

Watch out
  • Mcp-Session-Id header — and the entire notion of a protocol-level session
  • initialize / initialized handshake — replaced by _meta on every request + server/discover on demand
  • Roots, Sampling, and Logging — deprecated. Roots: pass paths as tool params. Sampling: call the LLM yourself. Logging: use stderr or OpenTelemetry.
  • tasks/list — removed even inside the new Tasks extension, because listing tasks without a session leaks across tenants

The Roots/Sampling/Logging deprecations are the ones most existing servers actually touch. All three assumed a persistent, bidirectional server↔client channel. In a stateless world the client owns the LLM, the paths, and the log sink — the server just answers the tool call.

What got added

Guided walkthrough1 of 7
  1. A stateless RPC clients call whenever they need to know what a server offers. Replaces the capabilities the old handshake used to return. Cache the response with the new ttlMs / cacheScope fields on the response itself — the spec inherits HTTP Cache-Control semantics.

The one JSON change that catches everyone

Missing-resource error code moved from -32002 to -32602 (Invalid Params). If your client has an if (err.code === -32002) branch anywhere, it silently stops firing on July 28. This is the single most common integration bug in the RC.

Before / After

// BEFORE (2025-11-25): stateful handshake
POST /mcp { "method": "initialize", "params": { "capabilities": {...} } }
→ sets Mcp-Session-Id: abc123
POST /mcp Mcp-Session-Id: abc123
{ "method": "tools/call", "params": { "name": "search", ... } }
// server assumes it "knows" you because of the session cookie
// AFTER (2026-07-28): self-describing request
POST /mcp Mcp-Method: tools/call
Mcp-Name: search
MCP-Protocol-Version: 2026-07-28
{
"method": "tools/call",
"params": { "name": "search", "arguments": {...} },
"_meta": {
"clientInfo": { "name": "claude-code", "version": "..." },
"capabilities": { "extensions": { "com.anthropic.apps": "1" } },
"traceparent": "00-..."
}
}
// any instance can serve it; no session, no stickiness

Multi Round-Trip Requests, concretely

The elegant part of the spec. A server that needs to ask "which calendar?" mid-execution doesn't need to hold a socket open. It replies:

{
"resultType": "input_required",
"inputRequests": {
"calendarId": { "type": "string", "prompt": "Which calendar?" }
},
"requestState": "base64(<opaque server-signed blob>)"
}

The client shows the prompt, gathers inputResponses, and re-fires the original request with both fields. The server treats requestState as authoritative — often signing it — so it doesn't need to remember the earlier attempt at all. That's the whole trick behind stateless elicitation: the state travels on the wire, not on the server.

The two official extensions

What you'll learn
  • MCP Apps (SEP-1865): a server can ship an HTML UI, rendered in a sandboxed iframe by the client. Every action inside the UI still goes through the same JSON-RPC audit path as a normal tool call — no back-door writes. Think interactive report + confirm-before-execute, not arbitrary web pages.
  • Tasks (SEP-2663): the long-running-operation pattern, redesigned for a session-free world. tools/call returns a task handle; the client drives tasks/get and tasks/update to poll or stream, and tasks/cancel to abort. tasks/list is intentionally gone — enumerating tasks without a session is a cross-tenant leak.
  • Breaking change: the 2025-11-25 experimental Tasks API is not compatible with the new extension. If you shipped against it, treat the migration as a rewrite, not an upgrade.

Authorization: the OAuth cleanup

The old spec was OAuth-ish. The new one is OAuth 2.1 / OIDC-shaped:

  • Clients must validate the iss parameter on authorization responses per RFC 9207 — the fix for the mix-up attacks that hit MCP servers earlier this year.
  • Dynamic Client Registration now requires clients to declare an OpenID Connect application_type, so an identity provider can enforce different rules for native vs web vs machine clients.
  • Refresh tokens follow the standard OIDC refresh flow — meaning enterprise SSO (Entra, Okta, PingID) works without custom middleware for the first time.

Practical read: if you were building custom OAuth glue to make MCP fit Okta, you can delete most of it.

Install the beta today

Python — mcp v2.0.0b1 (single endpoint serves both revisions)

uv add "mcp[cli]==2.0.0b1"
# or
pip install "mcp[cli]==2.0.0b1"

TypeScript — split packages, explicit opt-in for stateless

npm install @modelcontextprotocol/server@beta
npm install @modelcontextprotocol/client@beta

Go — v1.7.0-pre.1

go get github.com/modelcontextprotocol/go-sdk@v1.7.0-pre.1

C# — v2.0.0-preview.1

dotnet add package ModelContextProtocol --prerelease

Compatibility promise from the SDK team: "nothing breaks today, and nothing breaks on July 28 either." New clients auto-negotiate down to the old handshake when they hit a 2025-11-25 server; the Python v2 server answers both revisions from the same endpoint by default; TypeScript and Go require an explicit opt-in to expose the stateless variant. TypeScript v1.x gets bug fixes and security updates for at least six months.

Migration playbook

Guided walkthrough1 of 7
  1. They still work through July 28, 2027. Do not build new servers against them. For paths: accept them as tool arguments. For LLM calls: use your own client. For logs: write to stderr and let the harness aggregate.

Gotchas people are actually hitting in the RC

Watch out
  • Sticky load balancers still ‘work’ — until they don't. A stateless server behind a sticky LB looks fine in dev and shreds cache hit rate in prod. Turn stickiness off explicitly.
  • requestState is opaque to the client — but it is not free storage. Servers that pack half a megabyte of context into it will blow up client memory. Sign a small handle, store the rest server-side keyed on the handle.
  • MCP Apps iframes are sandboxed, not sanitized. A malicious server can still exfiltrate anything the user types into its UI. Treat an MCP App like third-party code — allowlist which servers are allowed to render UIs at all.
  • server/discover has no auth requirement in the base spec. Anything you expose there is discoverable by any client that reaches your URL. Do not put internal tool metadata there.
  • The JSON Schema 2020-12 upgrade means clients that hand-wrote a validator against the old subset can now silently under-validate. Use a real JSON Schema library, not a hand-roll.

Where this lands on the AILmanac map

  • MCP Apps: Interactive UIs Inside a Tool Call — a full deep-dive on the first official extension: capability negotiation, the ui:// scheme, the postMessage bridge, and the security model.
  • MCP & Connecting to Tools — the API-side connector. Still current; the connector abstracts the transport, so the wire change is invisible to that request shape. Only the servers the connector talks to migrate.
  • MCP in Claude Code — how Claude Code speaks MCP to local + remote servers. The stateless model is the reason you can finally point Claude Code at a serverless MCP endpoint without weird timeouts.
  • The MCP Token Tax — deferred loading is the token-side lever; the extensions framework is the protocol-side lever for the same problem.
  • Securing MCP Servers — the NSA's May 2026 MCP security guidance and the RC's authorization hardening reinforce each other. Read both.

Quick check

Check yourself

0/4
  1. In the 2026-07-28 spec, where does a client's identity and capability list travel?
  2. A tool in the middle of executing needs to ask the user which calendar to write to. In the stateless spec, how does it do that without a session?
  3. Which of these clients-side changes silently breaks on July 28 if you skip it?
  4. Which feature is NOT deprecated by the 2026-07-28 spec?

Vocabulary you'll see on GitHub this week

MCP 2026-07-28 terminology
اضغط Enter أو مفتاح المسافة لقلب البطاقة. استخدم مفتاحي السهمين الأيسر والأيمن للتنقل بين البطاقات.تم إظهار المصطلح.
1 / 11

Sources & further reading