Trango ComputeContextIQ
MCPModel Context Protocolserver/discoverMcp-Session-IdStreamable HTTPJSON-RPC 2.0AI agent protocols

MCP 2026-07-28 Explained: The Stateless Core, server/discover, and Who's Already Compliant

MCP 2026-07-28 replaces initialize and Mcp-Session-Id with a stateless server/discover core — Hugging Face and Cloudflare comply, DeepWiki still runs legacy.

July 29, 2026Trango Compute Inc.

The Model Context Protocol shipped its largest specification change since launch on 2026-07-28, superseding the previous revision from 2025-11-25. The headline change: MCP is no longer a stateful, session-based protocol. The initialize handshake and the Mcp-Session-Id header — the mechanism every MCP server has used since the protocol's earliest versions — are gone from the core spec, replaced by a fully stateless model built around a new mandatory RPC, server/discover.

This isn't a cosmetic revision. It changes how a client identifies itself, how servers advertise capabilities, how server-initiated interactions like sampling and elicitation work, and which authentication mechanisms are considered current. Here's what actually changed, what's deprecated, and — since a spec change on paper isn't the same as adoption in production — which real MCP servers already speak the new revision.

The Core Change: No More Sessions

Every prior MCP revision worked the same way: a client opened a connection, sent initialize with its protocol version and capabilities, the server replied with serverInfo and its own capabilities, the client sent notifications/initialized, and every subsequent request on that connection was implicitly scoped to that negotiated session — often tracked via an Mcp-Session-Id header.

The 2026-07-28 revision removes all of that. There is no handshake. Every single request now carries its own protocol version and capabilities via a _meta object:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": { "location": "Seattle, WA" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

A server that needs cross-call state — a long-running task, a multi-step form — no longer relies on a session to hold it. It mints an explicit handle and passes it back as an ordinary tool argument on the next call. The spec is explicit about the implication: an open connection, including a stdio process, is not a conversation. A client can interleave unrelated requests on the same transport, and a server must never treat connection identity as a proxy for session continuity.

The practical upside, spelled out directly in the spec: any request can land on any server instance behind a plain round-robin load balancer, with no shared session store required.

server/discover Replaces the Handshake

Since there's no initialize to learn a server's supported versions and capabilities, servers now must implement a new RPC: server/discover. It's stateless, takes no meaningful parameters beyond the standard _meta, and returns exactly what a client used to learn from initialize:

{
  "jsonrpc": "2.0",
  "id": "discover-1",
  "result": {
    "resultType": "complete",
    "supportedVersions": ["2026-07-28"],
    "capabilities": { "tools": {}, "resources": {} },
    "_meta": {
      "io.modelcontextprotocol/serverInfo": { "name": "ExampleServer", "version": "1.0.0" }
    },
    "instructions": "This server provides weather and resource utilities."
  }
}

Calling it first is optional for a client — any request can be sent inline, and a mismatched protocol version comes back as an UnsupportedProtocolVersionError listing what the server actually supports, at which point the client retries with a mutually agreeable version. But server/discover is the only reliable way to identify a server's era before committing to a request shape, which is exactly why it matters for anything doing external detection, monitoring, or compatibility probing.

Multi Round-Trip Requests Replace Server-Initiated Calls

The other structural change is how a server asks a client for more information mid-request — previously done via server-initiated roots/list, sampling/createMessage, or elicitation/create calls sent over an open stream. Streams are no longer guaranteed to stay open, so that pattern is gone too.

In its place: Multi Round-Trip Requests (MRTR). A server that needs input responds with resultType: "input_required" instead of a final result, listing the sub-requests it needs answered in inputRequests. The client gathers the answers and retries the original request — same method, new JSON-RPC id — with the answers in inputResponses. An opaque requestState string carries whatever context the server needs to resume, and the spec requires servers to integrity-protect it (HMAC or AEAD) since it round-trips through a client that must be treated as untrusted.

This only applies to three client-initiated calls: tools/call, resources/read, and prompts/get. Nothing else in the core protocol is allowed to return input_required.

What's Deprecated

The spec introduces a formal feature-lifecycle policy alongside this release — a minimum 12-month deprecation window before anything can actually be removed:

FeatureDeprecated inMigrationEarliest removal
Roots2026-07-28Pass paths via tool parameters, resource URIs, or config2027-07-28
Sampling2026-07-28Integrate directly with an LLM provider API2027-07-28
Logging2026-07-28Log to stderr (stdio) or use OpenTelemetry2027-07-28
Dynamic Client Registration (RFC 7591)2026-07-28Client ID Metadata Documents2027-07-28
HTTP+SSE transport (2024-11-05)2025-03-26Streamable HTTPSooner — 3 months after its own deprecation SEP finalizes

Everything in that table still works today. The point of the table is planning, not urgency — a server built last month on 2025-11-25 isn't broken, it's just no longer the current revision.

The Dynamic Client Registration → Client ID Metadata Documents (CIMD) shift is worth a second look if your server sits behind OAuth. CIMD lets a client use an HTTPS URL as its client_id — the authorization server fetches that URL, reads client_name and redirect_uris from it, and validates the request without any registration round-trip. An authorization server advertises support with "client_id_metadata_document_supported": true in its metadata; if that's absent and only registration_endpoint (DCR) is present, you're on the mechanism the spec is actively moving away from.

Error Codes and Auth Hardening

A few smaller but real changes:

  • The resource-not-found error code moved from -32002 to -32602 to align with plain JSON-RPC semantics. Three new codes are allocated in the spec-reserved range: -32020 (HeaderMismatch), -32021 (MissingRequiredClientCapability), -32022 (UnsupportedProtocolVersion).
  • Authorization responses should now include the iss parameter (RFC 9207), and clients must validate it against the recorded issuer before redeeming an authorization code — a defense against mix-up attacks between authorization servers.
  • tools/list and other list endpoints now carry ttlMs and cacheScope fields (the new CacheableResult interface), letting clients cache results and reduce polling instead of re-fetching the same tool list on every connection.
  • tools/list should now return tools in a deterministic order — a small change, but a real one for anything relying on LLM prompt-cache hit rates against a stable tool list.

Who's Already Compliant

Spec revisions are one thing; production adoption is another. We ran the same probe against several public MCP servers to see who has actually shipped server/discover:

  • Hugging Face (huggingface.co/mcp) — responds to server/discover and reports 2026-07-28 as its negotiated version. Fully modern.
  • Cloudflare Docs (docs.mcp.cloudflare.com/mcp) — same result. Fully modern, days after the spec shipped.
  • DeepWiki (mcp.deepwiki.com/mcp) — no response to server/discover; falls back to the legacy initialize handshake, negotiating 2025-06-18. Still fully functional, just not yet migrated.
  • GitHub Copilot (api.githubcopilot.com/mcp) — returns a 401 with a WWW-Authenticate challenge before any protocol negotiation happens at all. Its stateless-core status isn't observable from the outside without completing the OAuth flow first — a useful reminder that auth-gated servers are harder to audit for spec compliance than open ones.

Two adopters within days of the spec shipping is a fast start for a breaking change of this size, but it also means most of the MCP ecosystem is still on 2025-06-18 or 2025-11-25 right now — both fine, both fully supported, neither urgent to change today.

Checklist for Server Operators

  • Implement server/discover — it's a MUST for the current revision, and it's the only clean way for anything doing external compatibility checks to identify your server without guessing.
  • Drop any reliance on Mcp-Session-Id or connection-scoped state; move it into explicit handles passed as tool arguments.
  • If your server does sampling, elicitation, or reads roots — migrate to the MRTR pattern (input_required results) rather than server-initiated requests over an open stream.
  • Add ttlMs/cacheScope to your tools/list, resources/list, and prompts/list responses.
  • If you're behind OAuth, check whether your authorization server advertises client_id_metadata_document_supported — if it only offers registration_endpoint, you're on the deprecated path.

You can check where any MCP server actually stands — modern or legacy, which protocol version it negotiates, whether it still advertises deprecated capabilities like logging, and whether its authorization server has moved to Client ID Metadata Documents — with the MCP Inspector in one scan.

Try ContextIQ free

Free tools for AI engineers.

Follow Trango Compute on LinkedIn

We post updates on new tools, context engineering patterns, and LLM cost research.

Follow on LinkedIn