On this page · 14 sections
- What actually changed
- The 2025-11-25 to 2026-07-28 diff
- What does not break
- The five changes that touch your code
- What the session store was costing you
- Routable, cacheable, traceable
- Authorization hardening
- Deprecations: roots, sampling and logging
- SDK migration paths
- A migration plan that matches the real deadline
- India-specific considerations
- FAQ
- How eCorpIT can help
- References
Summary. The Model Context Protocol specification revision 2026-07-28 is published on 28 July 2026, and it is the largest change to the protocol since launch. The release candidate locked on 21 May 2026. Six Specification Enhancement Proposals (SEPs) remove the initialize/initialized handshake and the Mcp-Session-Id header, so a remote MCP server can run behind a plain round-robin load balancer with no sticky routing and no shared session store. Beta SDKs for Python, TypeScript, Go and C# arrived on 29 June 2026. Roots, sampling and logging are deprecated, with a minimum of 12 months before any removal. The error code for a missing resource moves from the MCP-custom -32002 to the JSON-RPC standard -32602.
Here is the part most coverage has wrong: nothing switches off on 28 July. The SDK maintainers state it plainly. That date publishes normative text; it is not a cutover. The panic framing going around is inaccurate, and acting on it will cost you a rushed migration you did not need.
The cost angle is real, though. A shared session store is a line item. AWS documents a worked example for exactly this shape of workload, a "high-write distributed session store" on ElastiCache for Valkey across two Regions, at $3.4712 per hour all-in, which is roughly $2,500 a month at 730 hours. ElastiCache for Valkey starts at $6/month at the small end, and AWS prices Valkey 20% below Redis OSS on nodes. If the only reason that store exists is MCP's protocol session, 2026-07-28 lets you delete it.
What actually changed
In 2025-11-25, calling a tool over Streamable HTTP meant establishing a session first. The client sent initialize, the server answered with an Mcp-Session-Id, and every later request carried that header, pinning the client to whichever instance issued it. That is what forced sticky routing and a shared store across instances.
In 2026-07-28, the same call is one self-contained request:
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"search","arguments":{"q":"otters"},
"_meta":{"io.modelcontextprotocol/clientInfo":{"name":"my-app","version":"1.0"}}}}
The protocol version, client info and client capabilities that were exchanged once at connection time now travel in _meta on every request (SEP-2575). The Mcp-Session-Id header and the protocol-level session are removed (SEP-2567). A new server/discover method lets clients fetch server capabilities when they want them up front.
The draft lifecycle text is blunt about what this means for server authors. Servers MUST NOT rely on prior requests over the same connection to establish context. Servers MUST NOT require that a client reuse the same connection for related operations. An open connection or STDIO process is not a conversation: clients may interleave unrelated requests on the same transport, and a server must not treat connection identity as a proxy for session continuity.
If your server currently stashes anything in a per-connection variable, that is the code to find first.
The 2025-11-25 to 2026-07-28 diff
| Concern | 2025-11-25 | 2026-07-28 |
|---|---|---|
| Connection setup | initialize/initialized handshake |
No handshake; _meta on every request |
| Session identity | Mcp-Session-Id header, server-issued |
Removed; no protocol-level session |
| Capabilities | Exchanged once at connect | server/discover, called when needed |
| Load balancing | Sticky routing to the issuing instance | Any instance serves any request |
| Gateway routing | Parse the JSON-RPC body | Route on Mcp-Method and Mcp-Name headers |
| List caching | Long-lived SSE stream to learn of changes | ttlMs and cacheScope on list results |
| Missing resource | MCP-custom -32002 |
JSON-RPC standard -32602 |
| Version mismatch | Negotiated at initialize |
UnsupportedProtocolVersionError, code -32004 |
| Cross-call state | Protocol session, hidden in transport | Explicit server-minted handles as tool arguments |
What does not break
This is the section to read before you file a migration ticket.
The SDK leads addressed the rumour directly. Writing on 29 June 2026, Felix Weinberger (TypeScript SDK Lead), Max Isbey (Python SDK Lead) and Den Delimarsky (Lead Maintainer) at the Model Context Protocol project wrote:
"First, we want to reassure you that for existing clients and servers nothing breaks today, and nothing breaks on July 28 either. This is merely the date when the normative specification text is published and is not a switch-off for any implementers relying on the current protocol version."
Three more things soften the edge:
Clients that speak 2026-07-28 fall back to the initialize handshake when they reach a server on 2025-11-25 or earlier, so old servers and new clients keep interoperating. A Python v2 server answers both protocol revisions from one endpoint, and a v2 server still answers the legacy initialize handshake alongside server/discover. In the TypeScript and Go SDKs the opt-in extends to the wire: upgrading the package does not by itself change what your server speaks over HTTP, and serving 2026-07-28 is an explicit choice you make when you wire up the transport.
The deprecations are annotation-only. Roots, sampling and logging keep working in this release and in every specification version published within a year of it. Under the feature lifecycle policy (SEP-2577), a feature stays Deprecated for at least twelve months before it is even eligible for removal, and removing any of them requires a separate SEP.
The real deadline is not 28 July. It is whenever you decide to take the SDK major version bump, and that is your schedule, not the working group's.
The five changes that touch your code
The handshake is gone. Move anything you did in initialize (auth setup, capability checks, per-client config) to per-request handling. Implement server/discover; the draft lifecycle says servers MUST implement it. Clients MAY call it before anything else, but are free to invoke any RPC inline and handle a version error if their preferred version is not supported.
Session state becomes an explicit handle. Removing the protocol session does not make your application stateless. The MCP maintainers are clear on this point, and it is the single most misread part of the release. Servers that carry state across calls do what HTTP APIs have always done: mint an explicit handle from a tool (a basket_id, a browser_id) and have the model pass it back as an ordinary argument later. The maintainers argue this is better than what it replaces, because the model can compose handles across tools and reason about them in ways that state hidden in transport metadata never allowed.
Two headers are now required. Streamable HTTP POSTs must carry Mcp-Method, and Mcp-Name on requests that name a tool, resource or prompt (SEP-2243). Servers reject requests where the headers and body disagree. Your gateway can finally rate-limit tools/call separately from tools/list without reading bodies.
Server-to-client prompts get rebuilt. Server-initiated requests may only be issued while the server is actively processing a client request (SEP-2260). Earlier spec versions recommended this; it is now required. Multi Round-Trip Requests (SEP-2322) replace the held-open SSE stream with an InputRequiredResult:
{
"resultType": "inputRequired",
"inputRequests": {
"confirm": {
"type": "elicitation",
"message": "Delete 3 files?",
"schema": { "type": "boolean" }
}
},
"requestState": "eyJzdGVwIjoxLCJmaWxlcyI6WyJhIiwiYiIsImMiXX0="
}
The client gathers the answers and re-issues the original call with inputResponses and the echoed requestState. Any instance can pick up the retry, because everything it needs is in the payload.
Error codes move. A missing resource returns -32602 Invalid Params instead of the MCP-custom -32002 (SEP-2164). If your client matches on the literal -32002, that is a one-line fix and a silent bug if you miss it. A new UnsupportedProtocolVersionError uses -32004 and lists the versions the server supports, so the client can retry with a mutually supported one.
What the session store was costing you
The operational payoff is the reason to care. A remote MCP server that previously needed sticky sessions, a shared session store and deep packet inspection at the gateway can now run behind a plain round-robin load balancer, route on an Mcp-Method header, and let clients cache tools/list responses for as long as the server's ttlMs permits.
Put numbers on the store you may be able to retire. AWS publishes a worked pricing example for a high-write distributed session store on ElastiCache for Valkey: 25 GiB of 200-byte objects, 50,000 writes per second, a clustered architecture across three Availability Zones with three shards and two replicas per shard, replicated across two Regions with Global Datastore. On a three-year all-upfront reservation at $0.1134 per node-hour, 18 nodes come to $2.0412 per hour, plus $1.43 per hour of data transfer, for $3.4712 per hour. That is roughly $2,500 per month, on a three-year commitment, for the cheapest version of that shape.
| Line item | What it was for | After 2026-07-28 |
|---|---|---|
| Shared session store | Holding Mcp-Session-Id state across instances |
Deletable if it only served the protocol session |
| Sticky routing | Pinning a client to the issuing instance | Not needed at the protocol layer |
| Gateway body parsing | Reading JSON-RPC to route or rate-limit | Route on Mcp-Method / Mcp-Name headers |
| Long-lived SSE streams | Learning that a list changed | ttlMs and cacheScope on list results |
| Cross-AZ session replication | Store availability, at $0.01 per GiB | Gone with the store |
| Idle instance headroom | Absorbing sticky-session imbalance | Even distribution across instances |
Be honest with yourself about the first row. If your application mints handles, carries a cart, or caches an expensive upstream lookup, that store is doing application work and it stays. The spec removed MCP's session, not yours. The real saving is usually the sticky routing and the operational rules built around it, not the Redis bill.
That distinction matters for anyone doing capacity planning. The teams who see the biggest win are the ones who added a session store only because the protocol demanded one. If you are auditing this alongside a broader cost review, our notes on cutting AWS, Azure and GCP spend for Indian teams cover how to tell a load-bearing cache from a ceremonial one.
Routable, cacheable, traceable
Three smaller changes make the traffic easier to operate, and they are the ones platform teams will actually feel day to day.
List and resource read results now carry ttlMs and cacheScope, modelled on HTTP Cache-Control (SEP-2549). Clients know exactly how long a tools/list response is fresh and whether it is safe to share across users. A long-lived SSE stream is no longer the only way to learn that a list changed. The changelog also notes that servers SHOULD return tools from tools/list in a deterministic order, which enables client-side caching and improves LLM prompt cache hit rates.
W3C Trace Context propagation in _meta is now documented (SEP-414), fixing the traceparent, tracestate and baggage key names. Several SDKs were already doing this. With the names pinned in the spec, a trace that starts in a host application can follow a tool call through the client SDK, the MCP server and whatever the server calls downstream, and appear as one span tree in an OpenTelemetry-compatible backend.
Tool inputSchema and outputSchema are lifted to full JSON Schema 2020-12 (SEP-2106). Input schemas keep the type: "object" root constraint but now allow composition (oneOf, anyOf, allOf), conditionals and references ($ref, $defs). Output schemas are unrestricted, and structuredContent can be any JSON value rather than only an object. Two guardrails come with it: implementations must not auto-dereference external $ref URIs, and should bound schema depth and validation time. Both are there for good reason, and they belong on your review checklist next to the rest of your MCP server hardening work.
Authorization hardening
Six SEPs bring the authorization spec closer to how OAuth 2.0 and OpenID Connect are actually deployed.
Clients must now validate the iss parameter on authorization responses per RFC 9207 (SEP-2468). The maintainers describe this as a low-cost mitigation for a class of mix-up attack that is more prevalent in MCP's single-client, many-server deployment pattern. In a future version, clients will be expected to reject responses that omit iss, so authorization servers should start supplying it now.
Clients now declare their OpenID Connect application_type during Dynamic Client Registration (SEP-837). This is the change desktop and CLI clients will feel: it avoids the common case where an authorization server defaults them to "web" and rejects the localhost redirect URI. Clients also bind registered credentials to the issuing authorization server's issuer and re-register when a resource migrates between authorization servers (SEP-2352). The spec documents how to request refresh tokens from OpenID Connect-style authorization servers (SEP-2207), and clarifies scope accumulation during step-up (SEP-2350) and the .well-known discovery suffix (SEP-2351).
If you run multi-tenant agents, read the credential-binding change twice. Token isolation between servers is exactly where multi-tenant agent deployments leak, a theme we covered in our review of agent session isolation across AWS, Azure, Google and Anthropic.
Deprecations: roots, sampling and logging
| Feature | Replacement | Status |
|---|---|---|
| Roots | Tool parameters, resource URIs, or server configuration | Deprecated, works for at least 12 months |
| Sampling | Direct integration with LLM provider APIs | Deprecated, works for at least 12 months |
| Logging | stderr for stdio; OpenTelemetry for structured observability |
Deprecated, works for at least 12 months |
| Tasks (experimental core) | Tasks extension with a new lifecycle | Moved out of core; migration required |
tasks/list |
Removed, cannot be scoped safely without sessions | Removed |
-32002 for missing resource |
-32602 Invalid Params |
Changed |
Sampling is the one worth pausing on. It let a server ask the client's model for a completion. The replacement is to integrate with an LLM provider API directly, which means the server now owns that key, that cost and that vendor choice. For some architectures that is a simplification. For others it moves a billing relationship from the host to your server. Price it before you migrate.
Tasks shipped as an experimental core feature in 2025-11-25. Production use surfaced enough redesign that it moved to an extension instead. A server can answer tools/call with a task handle, and the client drives it with tasks/get, tasks/update and tasks/cancel. Task creation is server-directed: the client advertises the extension, and the server decides when a call should run as a task. tasks/list is removed because it cannot be scoped safely without sessions. Anyone who shipped against the experimental Tasks API has to migrate to the new lifecycle.
SDK migration paths
All four Tier 1 SDKs shipped betas on 29 June 2026. The paths are not equivalent, and the difference matters for planning.
| SDK | Beta version | Wire behaviour on upgrade | Package change |
|---|---|---|---|
| Python | mcp==2.0.0b1 |
Picks up the new revision; v2 server answers both revisions from one endpoint | FastMCP becomes MCPServer |
| TypeScript | @modelcontextprotocol/server@beta |
Opt-in at the transport; upgrading alone changes nothing on the wire | Monolithic SDK split into focused packages |
| Go | v1.7.0-pre.1 |
Opt-in: set StreamableHTTPOptions.Stateless = true |
Same module path, no API rework |
| C# | 2.0.0-preview.1 |
HTTP transport defaults to the new stateless mode | Same packages, [Obsolete] on deprecated capabilities |
Python v2 reworks the package you know. The decorator API carries over and there is still no JSON Schema to write:
from mcp.server import MCPServer
mcp = MCPServer("Demo")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
Install with an exact pin, because unpinned installs stay on v1.x:
uv add "mcp[cli]==2.0.0b1"
TypeScript v2 retires the monolithic @modelcontextprotocol/sdk in favour of @modelcontextprotocol/server and @modelcontextprotocol/client, plus thin adapters for Node.js, Express, Hono and Fastify. It is ESM-only and runs on Node.js 20+, Bun and Deno. Tool schemas use Standard Schema, so you can bring Zod v4, Valibot, ArkType or any compatible library. There is a codemod for the mechanical parts, including the .tool() to registerTool rename:
npx @modelcontextprotocol/codemod@beta v1-to-v2 .
For HTTP deployments, createMcpHandler from @modelcontextprotocol/server is the entry point. It serves 2026-07-28 per request and handles 2025-11-25 traffic from the same endpoint.
Go takes the gentlest path. Same module path, no package split, and the new revision is one flag:
go get github.com/modelcontextprotocol/go-sdk@v1.7.0-pre.1
Leave StreamableHTTPOptions.Stateless unset and clients negotiate down to 2025-11-25.
One piece of housekeeping the maintainers call out: if you publish a library that depends on the Python mcp package, add an upper bound now, for example mcp>=1.27,<2, so the stable v2 release does not surprise your users. And pin exact versions when you test a beta, because public APIs may still change between beta and stable.
A migration plan that matches the real deadline
Since 28 July is not a cutover, sequence this by risk rather than by date.
- Audit for connection-scoped state. Grep for anything cached per connection or keyed on
Mcp-Session-Id. This is the only change that can silently corrupt behaviour rather than fail loudly.
- Fix the `-32002` match. If a client matches that literal, change it to
-32602now. It is a one-line fix that produces a confusing bug if it is missed.
- Pin your dependencies. Add the
<2upper bound on the Pythonmcppackage before the stable v2 lands, not after.
- Run a beta against real traffic in a branch. The maintainers ask for exactly this, and specifically not just the happy path. If you sit behind a gateway or load balancer, serve the stateless path and check whether your routing still needs anything the protocol no longer provides.
- Design your handles before you delete anything. Work out which state is application state and which was only there to serve the protocol session. Mint explicit handles for the former. Only then look at the infrastructure bill.
- Take the SDK major bump on your own schedule. Moving to Python v2 or TypeScript v2 is a breaking change for your code and is separate from anything that happens on 28 July. The TypeScript SDK continues shipping v1.x bug fixes and security updates for at least six months after v2 ships, and the Python v1.x branch continues to receive critical bug fixes and security patches.
The real cost here is usually the audit, not the code. Finding the one handler that quietly assumed a warm connection takes longer than deleting the handshake.
India-specific considerations
For teams in India building agent infrastructure for global customers, two things stand out.
The first is data residency. Under the Digital Personal Data Protection Act 2023 (Act No. 22 of 2023, enacted 11 August 2023), the state that used to sit in an MCP session now sits in explicit handles that cross your tool boundary as ordinary arguments. That state becomes visible in tool-call payloads, logs and traces. Handles that encode personal data get logged in places protocol session state never reached. Mint opaque handles, not descriptive ones, and check what your OpenTelemetry exporter is now capturing after you turn on the newly standardised traceparent and baggage keys. Our notes on privacy-first AI architecture go into the logging trap in more detail.
The second is cost structure. The sampling deprecation moves the model bill from the host to your server if you were relying on it. For an India-based team billing a global client in dollars while paying for inference in dollars, that is a margin question, not just an architecture question. Work out who pays for the tokens before you migrate off sampling, not after.
FAQ
How eCorpIT can help
eCorpIT builds and operates agent infrastructure for teams shipping MCP servers to production, and the 2026-07-28 migration is mostly an audit problem rather than a coding one. Our senior engineering teams review connection-scoped state, design the handle patterns that replace protocol sessions, and work out which parts of your session infrastructure are load-bearing before anything is deleted. We design applications aligned with DPDP Act 2023 requirements, which matters once session state moves into tool arguments and traces. If you are planning this migration, talk to our team.
References
- The 2026-07-28 MCP Specification Release Candidate, Model Context Protocol Blog, 21 May 2026.
- Beta SDKs for the 2026-07-28 MCP Spec Release Candidate Are Here, Model Context Protocol Blog, 29 June 2026.
- Lifecycle, draft specification, Model Context Protocol.
- Key Changes, draft specification changelog, Model Context Protocol.
- SEP-2567: remove protocol-level sessions, modelcontextprotocol on GitHub.
- SEP-2575: remove the initialize handshake, modelcontextprotocol on GitHub.
- SEP-2243: required Mcp-Method and Mcp-Name headers, modelcontextprotocol on GitHub.
- SEP-2322: Multi Round-Trip Requests, modelcontextprotocol on GitHub.
- SEP-2164: standard JSON-RPC error codes, modelcontextprotocol on GitHub.
- SEP-2577: deprecation of roots, sampling and logging, modelcontextprotocol on GitHub.
- SEP-2468: iss validation per RFC 9207, modelcontextprotocol on GitHub.
- Amazon ElastiCache pricing, Amazon Web Services, accessed 17 July 2026.
- Go SDK v1.7.0-pre.1 release notes, modelcontextprotocol on GitHub.
- Python SDK v2 migration guide, Model Context Protocol.
- The Digital Personal Data Protection Act, 2023 (Act No. 22 of 2023), India Code, Ministry of Electronics and Information Technology.
Last updated: 17 July 2026.