Skip to main content

MCP 2026-07-28: The Biggest Revision Since Launch Goes Stateless. Here's What Breaks.

Server rack corridor in a darkened data center with symmetrical blue LED lighting

The biggest revision to the Model Context Protocol spec since launch drops July 28, and it has real breaking changes for anyone running MCP servers in production today. Not the kind where you bump a version number and everything still works. The kind where your infrastructure assumptions need to change.

I've been through the release candidate. Here's what actually matters.

The Stateless Core Is the Real Story

The headline change: MCP is now stateless at the protocol layer. The initialize/initialized handshake is gone. The Mcp-Session-Id header is gone. Client metadata, previously exchanged once at connection setup, now travels in _meta on every request.

The practical consequence: any server instance can handle any request. No more sticky sessions, no more shared session store, no more deep packet inspection at the gateway to route a client to the right backend. The MCP team puts it plainly: a remote server that needed all of that "can now run behind a plain round-robin load balancer."

This is the right call. Session pinning was one of the most annoying ops constraints in running MCP servers at scale. It ruled out standard autoscaling groups and added a stateful routing layer most teams didn't want to maintain. Stateless HTTP is what you'd design from scratch.

The flip side: you have to update how your servers manage state. The spec introduces an "explicit-handle pattern" where servers mint identifiers that models pass back as tool arguments. State doesn't vanish, it just moves from the protocol session into the tool call itself. An order ID, a basket handle, a task token. For anything multi-step, you're now responsible for threading that handle through each call.

That's actually better design. Hidden protocol state was always a debugging nightmare.

What Actually Breaks

Several changes require real migration work.

The Tasks API is the one most likely to affect you if you shipped anything against the experimental Tasks feature in the 2025-11-25 spec. Tasks moved from an experimental core feature to an official extension, and the API was redesigned top to bottom. tools/call now returns task handles. Clients drive execution through tasks/get, tasks/update, and tasks/cancel. The earlier lifecycle structure is not compatible.

The error code for missing resources changes from -32002 to -32602. Small change, but painful if your error handling pattern-matches on that value.

Tool schemas now support full JSON Schema 2020-12, including composition and $ref. If you've been working around the flat-schema limitations, you can stop. If your validation code makes assumptions about schema shape, check it.

The TypeScript SDK split into two packages: @modelcontextprotocol/server and @modelcontextprotocol/client. It's also ESM-only and requires Node.js 20+. If you're on Node 18, that's a real blocker you need to resolve.

What's New and Worth Using

Two official extensions ship with this release.

MCP Apps lets servers render interactive HTML UIs directly in the client, inside sandboxed iframes. The UI communicates back over the same JSON-RPC channel everything else uses, which means you get an audit trail automatically. The most obvious use: form flows and file pickers where a tool needs structured input that plain text can't capture cleanly.

Tasks (as an extension rather than core) redesigns async work around stateless operations throughout. No session state involved in task tracking. tools/call returns a handle, clients poll and control via tasks/get and tasks/update. The old experimental version had enough production edge cases that it got pulled back and rebuilt. I'll take a clean redesign over papering over a broken API.

There's also proper cache control now: ttlMs and cacheScope on list and read results let clients and proxies cache intelligently rather than hammering servers for data that rarely changes. And W3C Trace Context propagation in _meta makes distributed tracing across an MCP call chain actually feasible instead of an afterthought.

Server-initiated requests are now constrained to happen only during active client request processing, replacing the old Server-Sent Events streams with InputRequiredResult payloads. Any server instance can continue a multi-step interaction because the request state is in the payload, not the connection.

Three features enter deprecation: Roots, Sampling, and Logging. The policy gives a minimum 12-month window before removal, so nothing disappears on July 28. But plan now: Roots should become tool parameters or resource URIs; Sampling should be direct LLM API calls; Logging should be stderr for stdio servers or OpenTelemetry for structured output.

Auth Finally Means Something

The authorization changes are quiet but significant. The spec now aligns with OAuth 2.1 and OpenID Connect in ways that make it enterprise-credible: required iss parameter validation, credential binding to the authorization server issuer, and Protected Resource Metadata (RFC 9728) so clients can discover the correct auth server automatically without configuration.

MCP auth was always the weak spot. Most production deployments I've seen handle it at the proxy layer and treat the MCP layer itself as trusted. That works until it doesn't. The new auth story isn't perfect, but it's something a security team can actually review and reason about.

What to Do Before July 28

Install the betas now and test against your real traffic patterns. For Python: pip install "mcp[cli]==2.0.0b1". For TypeScript: npm install @modelcontextprotocol/server@beta. Go (v1.7.0-pre.1) and C# (2.0.0-preview.1) betas are also out.

v1.x gets critical patches for at least six months after the final release, so July 28 is not a hard cutover. But SDK implementers need feedback from production workloads during the validation window, and testing now means you know your actual migration scope before you're forced to move.

Check your Tasks API usage first. That's where the migration will hurt most. Then audit your gateway config for anything that assumes sticky routing. Then look at your error-handling code for the -32002 to -32602 change.

The stateless shift is the right architectural move. It just has real migration cost attached to it.

Comments

Popular posts from this blog

AngularJs call one method of controller in another controller .

I have seen many question about calling one method of one controller in another controller or extending scope of one controller in another controller.so here are the ways. if you want to call one controller into another or extending scope of controllers there are four methods available $rootScope.$emit() and $rootScope.$broadcast() If Second controller is child ,you can use Parent child communication . Use Services Kind of hack - with the help of angular.element() 1. $rootScope.$emit() and $rootScope.$broadcast() Controller and its scope can get destroyed, but the $rootScope remains across the application, that's why we are taking $rootScope because $rootScope is parent of all scopes . If you are performing communication from parent to child and even child wants to communicate with its siblings, you can use $broadcast If you are performing communication from child to parent ,no siblings invovled then you can use $rootScope.$emit HTML <body ng-app = ...

Closures in javascript and how do they work ?

JavaScript Closures for Dummies  Closures Are Not Magic This page explains closures so that a programmer can understand them — using working JavaScript code. It is not for gurus or functional programmers. Closures are  not hard  to understand once the core concept is grokked. However, they are impossible to understand by reading any academic papers or academically oriented information about them! This article is intended for programmers with some programming experience in a mainstream language, and who can read the following JavaScript function: function sayHello ( name ) { var text = 'Hello ' + name ; var sayAlert = function () { alert ( text ); } sayAlert (); } An Example of a Closure Two one sentence summaries: a closure is the local variables for a function — kept alive  after  the function has returned, or a closure is a stack-frame which is  not deallocated  when the function returns (as if a 'stack-fr...

250,000 AI Agent Instances Exposed on the Internet — Is Yours One of Them?

If You're Running OpenClaw, You May Want to Read This A public watchboard has surfaced listing over 250,000 OpenClaw instances that are directly reachable from the internet. Some of these instances have leaked credentials. Many are running on infrastructure already flagged for known CVEs and threat actor activity. This isn't theoretical. It's happening right now. You can check the exposure list yourself at openclaw.allegro.earth . Why This Is a Big Deal OpenClaw is a powerful AI agent framework. That power comes with serious responsibility. A typical OpenClaw deployment runs with: Personal API keys — OpenAI, Anthropic, Google, cloud provider credentials Broad system permissions — file access, shell execution, network requests Autonomous execution capabilities — the agent can act without human approval Complex codebases — large attack surfaces that haven't been fully audited When one of these instances is publicly reachable without authentication...