MCP Overhaul: What to Adopt First, What Breaks
An adopt-first guide to the latest MCP revision: which changes are drop-in, which need auth and transport rework, and a migration checklist for production.
The latest Model Context Protocol revision is not a tuning pass. Sessions are gone. The initialize handshake is gone. SSE resumability is gone. If you run MCP servers in production, the question is not whether the protocol changed — it changed — but which of those changes you can absorb by bumping an SDK version, and which ones touch your auth, your transport, or your state model.
This is an adopt-first guide. Everything below was verified against the live spec and changelog at modelcontextprotocol.io (revision 2026-07-28), not against secondhand summaries. Where the spec says MUST, we say MUST. Where the picture is incomplete, we say so.
(If you're still picking servers, start with our hands-on MCP server catalog — this post assumes you already have servers running and need to move them forward.)
What changed, at a glance
| Change | What it replaces | Migration cost | |---|---|---| | Stateless requests; protocol version and capabilities per-request in _meta | initialize / notifications/initialized handshake | Medium — client and server SDK bumps; custom clients need rework | | Server-minted handles as tool arguments for cross-call state | Protocol-level sessions and Mcp-Session-Id header | Medium — app-level redesign for stateful servers | | server/discover RPC | Startup version negotiation via handshake | Low — server-side implement once, mostly mechanical | | subscriptions/listen (single long-lived POST stream) | HTTP GET endpoint, resources/subscribe/unsubscribe | Medium — rework push-notification plumbing | | InputRequiredResult (Multi Round-Trip Requests) | Server-initiated requests (roots/list, sampling/createMessage, elicitation/create) | Medium — different control flow; retry-with-answers pattern | | Required resultType on all results | — | Low — clients treat missing field as "complete" | | Required ttlMs + cacheScope on list/read results | — | Low — mechanical server change, real infra payoff | | Standard request headers (Mcp-Method, Mcp-Name) on Streamable HTTP POSTs | — | Low | | Client ID Metadata Documents | OAuth Dynamic Client Registration (deprecated, not removed) | High if you run a DCR-dependent auth server | | Roots, Sampling, Logging deprecated | — | Deferred — no removal date pressure yet, but stop building on them | | Registry publishing: DNS-verified namespaces, public servers only | Ad-hoc server discovery | Medium — private servers need a private registry |
The headline change: MCP is now stateless
The biggest structural shift is also the one most teams will feel least, because good SDKs will absorb most of it. The protocol removed the initialize handshake. Every request now carries its protocol version and client capabilities in _meta, under namespaced keys like io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. Servers identify themselves in each result's _meta. A version mismatch returns UnsupportedProtocolVersionError.
In exchange, the spec adds server/discover: a single RPC every server must implement that advertises supported versions, capabilities, and identity. Clients can call it up front, or use it as a backward-compatibility probe over stdio.
Why it matters for production: stateless protocols scale horizontally without sticky sessions. If you've been running your MCP layer behind a load balancer and pinning connections to specific backends, that constraint is going away. Server-side, the work is implementing server/discover and accepting per-request metadata. Client-side, if you wrote your own MCP client rather than using an SDK, you own the rework.
Sessions are gone — state moves into your tool arguments
Related, and more disruptive for servers that kept per-connection state: the protocol removed sessions and the Mcp-Session-Id header from Streamable HTTP. List endpoints (tools/list, resources/list, prompts/list) no longer vary per connection. Servers that need cross-call state are told to mint explicit handles and pass them back as ordinary tool arguments.
That is a deliberate push. The old session model put application state inside the transport, which made servers hard to scale and hard to reason about. The new model makes your state visible in your tool signatures — which means it's also auditable. If you run a tool-governance layer in front of your agents (as we've argued you should in production governance for agent firewalls), explicit state handles are far easier to log, rate-limit, and revoke than opaque session IDs.
The migration cost depends on your server. A stateless query tool migrates by doing nothing. A multi-step workflow server that relied on session context has real design work ahead: figure out what state survives between calls, mint a handle for it, and carry it in arguments.
Transport: `subscriptions/listen` replaces SSE resumability
Two transport changes land together:
resources/subscribe,resources/unsubscribe, and the HTTP GET endpoint are replaced by a singlesubscriptions/listenRPC — a long-lived POST-response stream. Clients opt in to specific notification types, and the server tags notifications with a subscription ID.- SSE stream resumability and message redelivery (
Last-Event-ID, SSE event IDs) are removed. A broken response stream loses the in-flight request; clients must re-issue it as a new request.
The second one is the one to plan for. If your client logic assumed a dropped connection resumes with delivery guaranteed, that assumption is now wrong by spec. Idempotency is your problem again. Design your tool calls so a retry is safe, or accept the cost of re-executing on flaky networks. For long-running operations, the tasks extension (more below) plus your own idempotency keys is the sane pattern.
Auth: the rework lives mostly on the server operator
The authorization spec keeps OAuth 2.1 and Protected Resource Metadata as the backbone. Three changes deserve attention:
- Client ID Metadata Documents are now the preferred client registration mechanism, and OAuth 2.0 Dynamic Client Registration is deprecated — retained for backward compatibility, not removed. If your auth server issues client IDs through DCR per-connection, start planning the metadata-document flow now. It's a deprecation with a stated minimum window, not an emergency.
- Issuer validation tightened. Authorization servers should include the
issparameter in authorization responses, and clients must validate it against the recorded issuer before redeeming an authorization code. - Credentials are bound to their issuer. Clients must key persisted credentials by the authorization server's identifier, must not reuse them with a different server, and must re-register when the server changes. If your client pool shares tokens across environments, that practice is now a spec violation, not just a smell.
Also in the hardening bucket: standard request headers (Mcp-Method, Mcp-Name) are required on Streamable HTTP POSTs, and an error-code allocation policy now partitions the JSON-RPC server-error range so spec-defined codes stop colliding with implementation-defined ones.
Schema and caching: the drop-in wins
Two changes cost almost nothing and pay immediately:
- Loosened schemas.
inputSchemaandoutputSchemanow accept any JSON Schema 2020-12 keywords, andstructuredContentaccepts any JSON value, with resource bounds on composition keywords. If you fought the old subset restrictions, that fight is over. - Required cache hints.
tools/list,prompts/list,resources/list,resources/read, andresources/templates/listresults now carryttlMs(a freshness hint) andcacheScope(publicorprivate). This is the cheapest production win in the whole revision: servers declare how long their listings are valid, clients stop polling, and shared intermediaries know what they may cache. Deterministictools/listordering is recommended too, which directly improves LLM prompt cache hit rates.
One deprecation to respect in new code: Roots, Sampling, and Logging are deprecated. They still work, and there's a stated minimum deprecation window, but the spec's suggested migrations — pass paths via tool parameters, integrate with LLM APIs directly, log to stderr or OpenTelemetry — are where new implementations should go.
The registry question
Server discovery is consolidating. The official MCP Registry is a centralized metadata repository for publicly accessible servers, with namespace management through DNS verification. It explicitly does not support private servers — anything on a private network or private package registry is out, and the recommendation for those is to host your own private registry.
If all your servers are internal, this affects you less than the transport changes. If you publish servers, DNS verification and public availability are now the bar. If you run a mix, you're operating two registries, and your client configuration should treat them with different trust levels — the same way you'd treat a public package index versus an internal artifact mirror.
Migration checklist
Work top to bottom. Items 1–3 are low-cost and unblock everything else.
- Inventory your MCP surface. Which servers, which SDK versions, which transport (stdio, Streamable HTTP, legacy HTTP+SSE). Flag anything still on HTTP+SSE — it's now formally deprecated and the migration target is Streamable HTTP.
- Adopt the caching fields. Add
ttlMsandcacheScopeto list/read results and deterministictools/listordering. Cheap, immediately useful, no breaking surface. - **Implement
server/discover.** It's mandatory, and it's mechanical. - Audit state. Find every place a server assumed a session. Decide what state becomes an explicit handle passed in tool arguments. Anything stateless stays stateless.
- Test the stateless client path. Confirm your client sends protocol version and capabilities per request and handles
UnsupportedProtocolVersionError. If you wrote the client yourself, this is your biggest line item. - Plan for broken streams. Remove any reliance on SSE resumability or
Last-Event-ID. Make tool calls idempotent or accept re-execution on retry. - Rework multi-step flows to Multi Round-Trip Requests. Anywhere you depended on server-initiated requests (sampling, elicitation, roots), migrate to the
InputRequiredResultretry pattern and setresultTypeon your results. - Tighten auth. Add
issvalidation, key credentials by issuer, and prototype Client ID Metadata Documents before DCR's deprecation window closes on you. - Route new feature work away from deprecated features. No new Roots, Sampling, or Logging dependencies; new elicitation flows use
requestState, notelicitationId. - Sort your registries. Public servers into the official registry with DNS verification; private servers into a private registry; document which clients trust which.
What we'd adopt first
If you only do three things this quarter: implement the caching fields, implement server/discover, and make your tool calls idempotent. The first two are mandated and cheap. The third is insurance against the resumability removal, and it's the kind of work that pays off the next time a network blip eats a request mid-flight.
The auth and session work is real but not on fire. DCR is deprecated with a defined window, not removed, and the deprecation policy now guarantees a minimum twelve-month notice period for future removals — which is itself one of the more underrated changes in this revision. Production teams finally have a lifecycle contract, not just a changelog.
Adopt in that order, and the overhaul stops being a rewrite and becomes a series of scheduled upgrades.
Frequently Asked Questions
What is the biggest breaking change in the latest MCP revision?
The removal of protocol-level state. The initialize handshake, sessions and the Mcp-Session-Id header, and SSE resumability are all gone from the spec. Requests now carry protocol version and capabilities per call, cross-call state moves into server-minted handles passed as tool arguments, and a dropped connection means re-issuing the request.
Do I need to rewrite my MCP server to stay compliant?
Probably not a rewrite. Stateless servers need only server/discover, per-request _meta handling, and the new required cache fields — all small. The heavy cases are servers that kept per-session state, servers relying on server-initiated requests (now replaced by the Multi Round-Trip Requests pattern), and auth servers built on Dynamic Client Registration, which is deprecated.
Is OAuth Dynamic Client Registration removed?
No. It is deprecated as a client registration mechanism in favor of Client ID Metadata Documents, and it remains available for backward compatibility with authorization servers that don't support the metadata-document flow. The spec's feature lifecycle policy guarantees a minimum deprecation window before removal.
What happens to MCP servers on private networks?
The official MCP Registry only supports publicly accessible servers, with namespace management via DNS verification. Private servers are excluded by design; the recommended path is hosting your own private MCP registry, which many organizations will need to run alongside the public one.
Are Roots, Sampling, and Logging going away?
They are deprecated but still fully functional, with removal governed by the spec's feature lifecycle policy. New implementations should not build on them. The suggested migrations: pass directories or files as tool parameters instead of Roots, integrate with LLM provider APIs directly instead of Sampling, and log to stderr or OpenTelemetry instead of the Logging feature.
---
You built it. We optimize it.