MCP's 2026-07-28 Spec: What Changes for AI Agents

Your MCP server worked fine on your laptop, then fell over the moment you put it behind a load balancer with two instances. Session state, handshake negotiation, and server-initiated requests were the usual culprits, and the newest revision of the Model Context Protocol is built to remove exactly those problems. Here is what changed, what breaks, and what to do about it.
One framing note up front: this is not news from today. The 2026-07-28 specification was released on July 28, 2026, so the update has been out for a few months. This post is a working guide to what it means if you run, or plan to run, MCP servers.
What shipped, and how to read the "biggest update ever" claim
The 2026-07-28 spec is the largest revision of MCP since launch, and it contains breaking changes. That is the maintainers' own description. The release candidate locked on May 21, 2026, and the final spec plus SDKs for building clients and servers went out on July 28, 2026, per the official release post by lead maintainers David Soria Parra and Den Delimarsky. The release candidate announcement is where the "largest revision" language appears.
Two things to keep straight:
- "Biggest ever" is a self-description. The maintainers say it. Press coverage quotes Soria Parra calling it "probably the biggest change we've ever made," and some people jokingly call it a v2. There is no official "v2" of the protocol. The version is simply
2026-07-28. - "Ready for massive enterprise deployments" is a claim from the maintainers and backers. Treat it as a design goal the spec now supports, not a guarantee about your deployment. The changes below are the actual evidence.
For context on governance: in December 2025, Anthropic donated MCP to the Agentic AI Foundation (AAIF), a directed fund under the Linux Foundation co-founded by Anthropic, Block and OpenAI. At that time Anthropic cited 97M+ monthly SDK downloads across Python and TypeScript. That is Anthropic's own figure from the December announcement, so it describes adoption at that moment, not today. Check the primary source for whichever figure you plan to cite.
The headline change: a stateless protocol core
MCP no longer has a session. The initialize handshake and the Mcp-Session-Id header are removed, and every request now carries its protocol version and client capabilities in _meta (see the changelog).
This sounds like plumbing, but it changes how you deploy. Before, a client negotiated capabilities once, got a session ID, and then every later request had to reach a server that remembered that session. That forced sticky routing or shared session storage. Now any request can land on any server instance behind a plain round-robin load balancer, with no shared session storage. That is the operational win the maintainers highlight.
Conceptually, each request now carries its protocol version and client capabilities in _meta instead of negotiating them once. The exact field names and payload layout are in the changelog, so confirm them there when you implement rather than copying a sketch.
What if your tool genuinely needs state?
Some workflows are stateful by nature: a shopping basket, a draft document, a multi-step form. The spec's answer is explicit handles. A tool mints an identifier (the release candidate post uses basket_id as the example), and the model passes it back as an ordinary argument on later calls.
# Illustrative pattern: state lives in YOUR datastore, keyed by a handle.
@mcp_tool
def start_quote(customer_id: str) -> dict:
quote_id = db.create_draft_quote(customer_id) # your database, not process memory
return {"quote_id": quote_id}
@mcp_tool
def add_line_item(quote_id: str, sku: str, qty: int) -> dict:
db.append_line(quote_id, sku, qty)
return {"quote_id": quote_id, "lines": db.count_lines(quote_id)}
The practical rule I'd follow: if your server keeps anything in process memory between calls, move it to a database or cache keyed by a handle the model carries. Then every instance can serve every request.
Routing, caching, and the transport changes
Three smaller changes make MCP servers behave like ordinary HTTP services you can put real infrastructure in front of.
Routing headers. The Streamable HTTP transport now requires Mcp-Method and Mcp-Name headers (SEP-2243). Load balancers, gateways and rate-limiters can route on the operation without parsing the request body. In practice that means you can rate-limit tools/call for an expensive tool differently from cheap tools/list calls using only header rules.
Cache hints on list results. List responses (tools/list, prompts/list, resources/list and others) must now carry ttlMs and cacheScope (SEP-2549). ttlMs is a freshness hint in milliseconds; cacheScope is "public" or "private". If your tool list is the same for every user, mark it public and give it a sensible TTL so clients stop re-fetching it. If it varies by user permissions, mark it private.
HTTP+SSE is formally deprecated. The older HTTP+SSE transport had been deprecated since protocol version 2025-03-26 and is now classified Deprecated under the new lifecycle policy. The migration path is Streamable HTTP. If you are still running an SSE-based server from an early tutorial, this is your nudge.
| Concern | Before | 2026-07-28 |
|---|---|---|
| Session handling | initialize + Mcp-Session-Id |
Removed; version and capabilities in _meta on every request |
| Load balancing | Sticky routing or shared session store | Plain round-robin works |
| Gateway routing | Parse request body | Mcp-Method / Mcp-Name headers required |
| List caching | No standard hints | ttlMs + cacheScope required on list results |
| Legacy transport | HTTP+SSE | Deprecated; use Streamable HTTP |
Asking the user mid-task: Multi Round-Trip Requests
Server-initiated requests such as elicitation/create are replaced by Multi Round-Trip Requests, or MRTR (SEP-2322). Instead of the server opening a request back to the client, the server returns a result with resultType set to "input_required". The client then retries the original call with the answers in inputResponses.
Sketch of the flow (shape per the spec GA post source; check exact field layout there before coding):
// 1. Client calls the tool
{ "method": "tools/call", "params": { "name": "send_invoice", "arguments": { "invoice_id": "inv_9" } } }
// 2. Server needs a decision, so it returns instead of calling the client
{ "resultType": "input_required", "...": "description of what it needs" }
// 3. Client retries the SAME call, now with the user's answers
{ "method": "tools/call", "params": { "name": "send_invoice", "arguments": { "invoice_id": "inv_9" }, "inputResponses": { "...": "..." } } }
Why this matters: it fits the stateless model. The server doesn't hold an open conversation waiting on the client; each leg is a normal request that any instance can handle. For anything with human-in-the-loop approval (confirm before sending an email, pick between two matching customers), design the tool so the retry carries everything needed to finish.
Long-running work: Tasks become an extension
Tasks moved out of the experimental core into the official io.modelcontextprotocol/tasks extension (SEP-2663). It uses polling through tasks/get and a new tasks/update, and tasks/list was removed.
If you build agents that kick off slow jobs (report generation, a bulk import, a crawl), the pattern is: start the work, return a task reference, and have the client poll. Because tasks are an extension, you opt in rather than getting them by default. If you'd built against the experimental core version, expect to revisit that code, especially anything that relied on tasks/list.
Authorization: tighter by default
The auth changes are the ones security reviewers will care about.
- RFC 9207 issuer validation (SEP-2468). Authorization servers SHOULD include the
issparameter. MCP clients MUST validate a presentissagainst the recorded issuer before redeeming the authorization code. Note the nuance: it is not universally mandatory. Servers should include it, and clients must check it when it's there. Some coverage overstates this as blanket enforcement; the changelog is more careful. - Dynamic Client Registration is deprecated. The replacement is Client ID Metadata Documents (CIMD). DCR keeps working for backward compatibility but will be removed in a future spec version.
- Enterprise Managed Authorization. This is an official extension, with a corporate identity provider acting as gatekeeper. I haven't retrieved the detailed spec text, so I won't describe its mechanics beyond that.
For a small business, the practical takeaway: if your MCP server fronts anything sensitive (your CRM, billing, a customer database), plan the auth work now. Moving from DCR to CIMD is a migration you can schedule, not an emergency, but it is on the calendar.
Deprecations and the 12-month clock
The spec adopts a formal feature lifecycle (SEP-2596) with three states: Active, Deprecated, Removed. There is a minimum twelve-month deprecation window, measured from the release of the spec revision that first marks a feature Deprecated. Per the policy text, twelve months is a minimum, and removal is not automatic.
Deprecated as of 2026-07-28 (SEP-2577), with earliest removal on 2027-07-28:
| Deprecated feature | Replacement |
|---|---|
| Roots | Tool parameters / resource URIs |
| Sampling | Direct LLM provider APIs |
| Logging | stderr / OpenTelemetry |
Also deprecated: HTTP+SSE (use Streamable HTTP) and Dynamic Client Registration (use CIMD). Both are covered above, and neither gets the same earliest-removal date stated here.
The twelve-month window applies to individual features under SEP-2596.
MCP Apps: servers that ship UI
The third official extension alongside Tasks and Enterprise Managed Authorization is MCP Apps (SEP-1865). It lets servers ship interactive HTML interfaces that hosts render in a sandboxed iframe. Useful when a text reply is the wrong output: an approval screen, a filterable table, a form. It's an extension, so host support will vary. Check your target client before building a product on it.
Migrating: a practical order of operations
You probably don't need to rewrite everything this week. The SDK story is gentle: beta SDKs for the release candidate were published for Python, TypeScript, Go and C#, and existing servers keep working. A Python v2 server answers both protocol revisions from one endpoint, and TypeScript's createMcpHandler also serves 2025-11-25 traffic (see the SDK beta post).
Here is the order I'd work in:
- Inventory your servers. For each: which transport, what state it holds between calls, whether it uses sampling, roots, logging, or elicitation.
- Upgrade the SDK and run old and new clients against the same endpoint, since both revisions can be served together.
- Move in-memory state to handles. This is the real engineering work, and the thing that unlocks round-robin scaling.
- Add
ttlMsandcacheScopeto list results. Start withprivateif unsure; loosen later. - Replace elicitation flows with
input_required/inputResponsesretries. - Move off HTTP+SSE to Streamable HTTP if you haven't.
- Plan the auth migration: issuer validation on the client side, and DCR to CIMD on your own schedule.
- Replace deprecated features (Roots, Sampling, Logging) before the earliest removal date of 2027-07-28.
If you're a solo builder with one small server, steps 1 to 3 may take an afternoon. If you have several servers with real state, budget for step 3 properly and test with two instances behind a round-robin balancer before you call it done.
Where this fits in practice
I build AI automations for small teams, and the part that keeps paying off is the plain layer between a model and the software a business already uses: a CRM, an invoicing tool, an inbox, an internal database, exposed to Claude with sensible permissions so the agent works on real data. The 2026-07-28 changes make that layer easier to run, since the stateless core removes a class of deployment headaches and the caching and routing headers make gateways straightforward.
When you scope an integration like this, the first questions are what state the workflow really needs, what the agent should be allowed to touch, and what happens when it asks for approval. Those map directly onto the handle pattern, the auth model, and the input-required flow described above.
Work with BizFlowAI
If you'd rather have this built for you, that's what we do: production AI automation for solo founders and small teams — agents, integrations, and document pipelines that actually ship.
Request a free discovery call — 30 minutes, we map the highest-ROI automation in your workflow. No pitch deck, just engineering.
More guides like this on the BizFlowAI blog.
Frequently asked questions
What changed in the MCP 2026-07-28 specification?
The 2026-07-28 revision of the Model Context Protocol is the largest since launch and includes breaking changes. It removes the initialize handshake and the Mcp-Session-Id header, making the protocol core stateless. Streamable HTTP now requires Mcp-Method and Mcp-Name routing headers, and list results must carry ttlMs and cacheScope cache hints. HTTP+SSE is deprecated, tasks moved into an extension, and authorization got stricter.
How do I run an MCP server behind a load balancer without sticky sessions?
With the 2026-07-28 spec, every request carries its protocol version and client capabilities in _meta, so there is no session for a specific instance to remember. Any request can land on any server instance behind a plain round-robin load balancer. If your tools keep state in process memory, move it to a database or cache keyed by an identifier the model passes back as an argument. That way every instance can serve every request.
How do I handle stateful tools like a shopping basket in a stateless MCP server?
Use explicit handles instead of sessions. A tool creates a record in your own datastore and returns an identifier such as a basket_id or quote_id. The model passes that identifier back as a normal argument on later tool calls. The state lives in your database rather than server memory, so any instance can handle any call.
How does MCP ask the user for input mid-task now that elicitation/create is replaced?
The new Multi Round-Trip Requests (MRTR) mechanism replaces server-initiated requests like elicitation/create. When a tool needs a decision, the server returns a result with resultType set to input_required instead of calling back into the client. The client then retries the original call with the user's answers in inputResponses. Each step is a normal request, so it fits the stateless model and works across multiple server instances.
Should I still use HTTP+SSE for my MCP server?
No. The HTTP+SSE transport has been deprecated since protocol version 2025-03-26 and is now formally classified Deprecated under the new lifecycle policy. The migration path is the Streamable HTTP transport. Streamable HTTP also adds required Mcp-Method and Mcp-Name headers, so gateways and rate-limiters can route requests without parsing the body.