MCP Just Dropped the Session — Here's What That Breaks

The 2026-07-28 spec removes the initialize handshake, the session ID, and server-initiated requests. Google pushed for it because session-pinned servers can't scale horizontally. We run an MCP server in production — here's the honest audit of what it costs us, and what you'll need to change.

The Model Context Protocol shipped a new specification revision on 28 July, and it is not a normal one. It removes the connection handshake. It removes the session. It removes server-initiated requests. It deprecates three whole features that plenty of servers are built on today.

If you maintain an MCP server, this is a migration, not an upgrade.

We run one — /mcp/insights, 25 tools, OAuth, production traffic from real customers' coding agents — so this isn't a neutral explainer. It's the notes from reading the changelog with a sinking feeling and then working out what it actually costs.

Short version: most of it is fine, one part is genuinely annoying, and the direction is obviously correct.

#Why This Happened

MCP was designed for a very specific shape of deployment: a server running on your laptop, spoken to over stdio by one client, for the length of one conversation. In that world a stateful protocol is not just acceptable, it's convenient. You do a handshake, you negotiate capabilities once, you keep a session, and everything after that is cheap.

Then people started putting MCP servers behind load balancers.

Google published their side of this alongside the spec, and the complaint is one anybody who has run a web service will recognise instantly: the protocol-level session model required persistent state per connection, which meant requests had to be pinned to the instance holding that state. Sticky sessions. In 2026. Every autoscaling group, every rolling deploy, every instance that dies at an unhelpful moment turns into a protocol-level failure rather than a retry.

So the fix is the fix it always is. Make every request self-contained and let the load balancer do its job.

#What Actually Changed

The initialize handshake is gone, along with notifications/initialized. There is no connection setup step anymore. Every request now carries its own protocol version and client capabilities in _metaio.modelcontextprotocol/protocolVersion, io.modelcontextprotocol/clientCapabilities. Clients should identify themselves per request; servers should identify themselves in each result. Version mismatches come back as UnsupportedProtocolVersionError.

Mcp-Session-Id is gone from the Streamable HTTP transport. List endpoints — tools/list, resources/list, prompts/list — no longer vary per connection, which is what made caching them impossible before. If your server genuinely needs cross-call state, you now mint an explicit handle and pass it as an ordinary tool argument. State becomes application data instead of protocol magic.

server/discover is new and mandatory. Servers MUST implement it. It advertises supported protocol versions, capabilities and identity. Clients may call it up front for version selection, or use it as a backwards-compatibility probe over stdio.

Every result now carries resultType — either "complete" or "input_required". Clients must treat a missing field from an older server as "complete".

Server-initiated requests are replaced by Multi Round-Trip Requests. This is the biggest conceptual change. Previously a server could call back to the client mid-request — sampling/createMessage, elicitation/create, roots/list. In a stateless world there's no open channel to call back on. Instead the server returns an InputRequiredResult carrying inputRequests, and the client retries the original request with inputResponses attached. The interaction becomes a retry loop rather than a conversation.

The HTTP GET endpoint and resources/subscribe/unsubscribe are replaced by subscriptions/listen — one long-lived POST-response stream, with clients opting in to specific notification types and the server tagging each with a subscription ID. Progress and log messages still flow on the response stream of the request they belong to, not on this one.

SSE resumability is gone. No Last-Event-ID, no event IDs, no message redelivery. A broken stream loses the in-flight request and the client must re-issue it with a new request ID.

ping, logging/setLevel and notifications/roots/list_changed are removed. Log level is set per request via _meta, and servers must not emit notifications/message for requests that didn't ask for it.

Tasks moved out of core into an official io.modelcontextprotocol/tasks extension, redesigned around polling with tasks/get rather than a blocking tasks/result.

#What's Deprecated

Deprecation now runs under a formal lifecycle policy with a minimum twelve-month window, which is a meaningful governance improvement — you get a registry of deprecated features and a guaranteed runway rather than a surprise.

On the list: Roots, Sampling and Logging. All three remain functional for now, and all three have suggested migrations. Pass directories and files as tool parameters or resource URIs instead of Roots. Integrate directly with an LLM provider API instead of Sampling. Log to stderr or use OpenTelemetry instead of Logging.

Also deprecated: HTTP+SSE transport (already soft-deprecated since March 2025, now formally on the clock), and OAuth Dynamic Client Registration, superseded by Client ID Metadata Documents — though DCR stays available for authorization servers that don't support the new mechanism yet.

If you built on Sampling in particular, start planning. The whole point of Sampling was that the server could borrow the client's model, and the replacement is "bring your own API key," which is a different cost structure, not just a different call.

#The Parts That Are Straightforwardly Good

Not everything here is a bill.

List results are now cacheable. tools/list, prompts/list, resources/list, resources/read and resources/templates/list all return ttlMs and cacheScope via a new CacheableResult interface. cacheScope is "public" or "private", controlling whether shared intermediaries may cache. Combined with removing per-connection variance in list endpoints, this kills a genuinely silly amount of repeat traffic.

Servers should return tools in deterministic order, explicitly so clients can cache and so LLM prompt caches hit more often. A one-line change on most servers with a real, measurable payoff on token spend.

OpenTelemetry trace context propagation is documentedtraceparent, tracestate and baggage conventions in _meta. If you've ever tried to trace a request from an agent through an MCP server into a database and given up, this is the fix.

Authorization got harder to get wrong. Authorization servers should include iss per RFC 9207 and clients must validate it before redeeming a code. Clients must key persisted credentials by issuer, must not reuse them across authorization servers, and must re-register when the authorization server changes. Clients must specify application_type during registration to avoid OIDC redirect URI conflicts. These are all real-world footguns being closed.

Error codes have an allocation policy-32000 to -32019 implementation-defined and grandfathered, -32020 to -32099 reserved for the spec — which means the next revision won't quietly collide with your custom codes.

#What It Costs Us

Honest accounting on our own server, because "here's a changelog" is worth less than "here's the diff we have to write."

server/discover is new work. It's not hard work, but it's MUST-level, so it's not optional either.

Every result needs resultType. Mechanical across 25 tools, and the sort of change that's fine if your tools return through one shared path and miserable if they each hand-roll a response.

Capability and version handling moves into per-request _meta. We currently negotiate once. Now it's read per call, and every tool needs to tolerate a version mismatch arriving mid-session rather than at connect time.

Our OAuth flow needs an audit against the new client-registration rules — iss validation, credentials keyed by issuer, the move toward Client ID Metadata Documents. We've already spent more time than we'd like on MCP OAuth edge cases, and this is another pass through the same code.

Anything holding state across calls has to become an explicit handle. For us that's mostly team resolution, and we're in reasonable shape here by accident: our tools already resolve the team per call, from an explicit repository argument or a query-string binding, rather than leaning on session state. That decision was made for a completely different reason — a user on several teams kept getting the wrong team's data — and it happens to be exactly what this spec now requires. Sometimes you get lucky.

We already don't offer the GET SSE stream, which the new transport removes anyway. Our GET /mcp/insights returns a 405 with a pointer at where to authenticate, because a bare 405 told GET-probing clients nothing useful. One thing we don't have to change.

The uncomfortable one is losing SSE resumability. A dropped stream now means the in-flight request is gone and the client re-issues with a fresh request ID. For read-only tools that's a non-event. For anything with a side effect — and we ship tools that trigger deploys and post review requests — "the client will retry it" is a sentence that should make you check your idempotency story very carefully. That's the item on this list most likely to produce a real incident somewhere, for somebody, in the next six months.

#What This Means If You're Not Writing Servers

Most people reading this don't maintain an MCP server. Here's the version that matters anyway.

MCP stopped being a developer-laptop protocol. Everything in this revision points the same way: horizontal scaling, cacheable responses, standard HTTP routing, trace propagation, hardened auth, a formal deprecation policy. That's not the changelog of an experiment. That's the changelog of something that expects to be load-bearing infrastructure with a compliance review attached.

The integrations your agents rely on are about to have a rough few months. Every MCP server in your stack has a migration ahead of it, and they won't all land it cleanly or at the same time. If your team has agents wired into internal tools, expect breakage, and expect some of it to be silent — a deprecated feature quietly not working is much harder to notice than a 500.

Ask your vendors where they are on this. "Which MCP spec revision do you implement, and what's your plan for 2026-07-28" is now a reasonable procurement question. A vendor who can answer it crisply is telling you something useful about how they run everything else.

If you're choosing what to build on, build on the new shape. Don't add Sampling, Roots or Logging to anything new. Don't build on DCR if Client ID Metadata Documents are available to you. The twelve-month deprecation window is generous, but it's still a window.

#The Take

This revision is MCP admitting what it became. It was designed as a neat local integration layer, it got adopted as connective tissue for enterprise agent infrastructure, and the protocol's original assumptions didn't survive that promotion. Sessions are lovely until you need four instances behind a load balancer, and then they're the reason you can't have four instances behind a load balancer.

The bill lands on every server maintainer at once, which is unpleasant but not unfair — this is the cheapest moment this change will ever be. The alternative was carrying sticky sessions into a protocol that's on track to be in a lot of production stacks.

Ours has a migration in front of it. Yours probably does too. Read the changelog properly before you plan it, because the parts that will bite are not the parts in the headline — it's resultType on every response, and the retry semantics you inherited when resumability went away.

#Related Reading


Coderbuds serves your team's delivery data to coding agents over MCP — what your standards are, what's blocking, what shipped — so the agent writing the code already knows how your team works. See the MCP docs.

Coderbuds Team
Written by

Coderbuds Team

The Coderbuds team writes about DORA metrics, engineering velocity, and software delivery performance to help development teams improve their processes.

View all posts

You're subscribed!

Check your email for a confirmation link. You'll start receiving weekly engineering insights soon.

Want more insights like this?

Join 500+ engineering leaders getting weekly insights on DORA metrics, AI coding tools, and team performance.

We respect your privacy. Unsubscribe anytime.