Canonical: https://botbento.com/blog/mcp-stateless-cross-call-state/
Format: Markdown representation of the public HTML page.

[Home](/) / [Blog](/blog/)

FIELD NOTES / 4 MIN READ

# MCP Dropped Sessions. How Do You Keep State Across Tool Calls Now?

The Model Context Protocol's 2026-07-28 revision removed protocol-level sessions and the Mcp-Session-Id header, so a bot can no longer rely on the transport to remember it between tool calls. The spec's replacement is an explicit handle: a tool returns an identifier, and the model passes it back as an ordinary argument on later calls. This piece walks through what changed, a worked example of the handle pattern, and the specific things that break if your bot's MCP integration still assumes a session.

By BotBento Editorial · Published 2026-09-28 · Updated 2026-09-28

AI-assisted editorial: researched and drafted with AI using the primary sources linked below. Examples are illustrative; they are not measured product results. [Editorial policy](/editorial/).

## In this article

- [What the 2026-07-28 spec actually removed](#what-changed)
- [The replacement: a handle the model carries, not a session the transport hides](#the-fix)
- [What breaks if your bot still assumes sessions](#what-breaks)
- [A short checklist before you touch a bot's MCP integration](#checklist)
- [Why a single-instance bot should still care](#why-it-matters-for-small-bots)[Read as Markdown ](/text/blog/mcp-stateless-cross-call-state/index.md)

## Key takeaways

- MCP 2026-07-28 removed the initialize handshake and the Mcp-Session-Id header; requests carry their protocol context and can land on any compatible server instance.
- The replacement is an explicit, server-minted handle (like a booking\_id) that the model carries as a tool argument, not hidden session state.
- Check three things before you touch a bot's MCP integration: session-ID routing logic, a hardcoded -32002 error check, and any reliance on Roots, Sampling, or Logging.

## What the 2026-07-28 spec actually removed

The Model Context Protocol's 2026-07-28 revision makes the protocol stateless at its core. The changelog is explicit about the mechanics: the spec removes the initialize and notifications/initialized handshake, and it removes protocol-level sessions, including the Mcp-Session-Id header, from the Streamable HTTP transport. List endpoints such as tools/list, resources/list, and prompts/list no longer vary per connection either, since there's no connection-scoped state left for them to vary against.

Requests now carry protocol version and client capabilities in their metadata instead of relying on a negotiated session. The new specification says clients should also identify themselves on each request; that identity field is recommended, not a mandatory claim about every message. A compatible request can land on any server instance behind an ordinary load balancer without sticky protocol-session routing. If your integration depends on the old Mcp-Session-Id or connection-scoped state, test it against the negotiated protocol version before changing it.

Sources: [Key Changes - Model Context Protocol](https://modelcontextprotocol.io/specification/2026-07-28/changelog), [The 2026-07-28 Specification](https://blog.modelcontextprotocol.io/posts/2026-07-28/).

## The replacement: a handle the model carries, not a session the transport hides

The spec's own guidance on this is direct: if a server needs to carry state across calls, it should mint an explicit handle from a tool and have the model pass that handle back as an argument. The maintainers describe this as working better than session state hidden in the transport, because the model can see the handle and thread it between tool calls itself, rather than the server keeping track of who's calling on its behalf.

Worked example, illustrative only: say a small bot manages hotel bookings through an MCP server. An older implementation might have kept an in-progress booking tied to a protocol session. Under the new pattern, a start\_booking tool returns booking\_id; the model passes that identifier to add\_room and confirm\_booking. The server can still authenticate and authorize the caller through its normal credentials. The booking\_id identifies the in-progress work, not the caller's permission to change it. Check both the handle and the caller's authority on each step. This illustrates the explicit state pattern the maintainers recommend; it is not a BotBento feature claim.

Sources: [The 2026-07-28 Specification](https://blog.modelcontextprotocol.io/posts/2026-07-28/).

## What breaks if your bot still assumes sessions

Three migration checks are worth running against a client and server that actually negotiate 2026-07-28. First, a gateway that requires Mcp-Session-Id for routing must be updated because modern requests no longer send it. Second, the resource-not-found code changed from -32002 to -32602 (Invalid Params); handle the code according to the negotiated version rather than replacing the old branch for legacy servers. Third, tool logic that assumes the next call reaches the same process must move its work state into a durable record addressed by an explicit handle, or provide another safe recovery path.

Roots, Sampling, and Logging are formally deprecated, with a minimum twelve-month deprecation window. That does not mean their old server-to-client methods work in a new stateless 2026-07-28 session: the Python SDK says those calls need a legacy connection, while the modern flow uses Multi Round-Trip Requests or other replacements. If a tool needs user or model input mid-call, review the new input-required flow. For filesystem paths, consider tool parameters or resource URIs; for server logs, use ordinary logging or telemetry. Keep legacy behavior only where the negotiated older version supports it.

Sources: [Key Changes - Model Context Protocol](https://modelcontextprotocol.io/specification/2026-07-28/changelog), [The 2026-07-28 MCP Specification Release Candidate](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/), [Deprecated features - MCP Python SDK](https://py.sdk.modelcontextprotocol.io/deprecated/).

## A short checklist before you touch a bot's MCP integration

None of this requires a rewrite. It requires finding every place your bot's tooling assumed a session was doing work for it, and replacing that assumption with an explicit value the model can see and carry forward on its own.

- Confirm the SDK your bot's MCP client and server use actually speaks 2026-07-28 — the four Tier 1 SDKs (TypeScript, Python, Go, C#) shipped support on release day, with Rust in beta.
- Search your integration code for any check on Mcp-Session-Id or a stored per-connection object, and replace it with a handle argument the model passes back explicitly.
- Search for a hardcoded -32002 check on missing resources and handle -32602 when the peer negotiates 2026-07-28; retain the legacy branch if you support older peers.
- If you use Roots, Sampling, or Logging, test a modern connection separately from a legacy one and plan the appropriate replacement rather than assuming old callbacks work on both.

Sources: [Key Changes - Model Context Protocol](https://modelcontextprotocol.io/specification/2026-07-28/changelog), [Deprecated features - MCP Python SDK](https://py.sdk.modelcontextprotocol.io/deprecated/).

## Why a single-instance bot should still care

A personal or small-team bot usually runs on one process, not behind a load balancer, so the routing story may not bite directly. But the handle pattern is worth adopting anyway, for a reason that has nothing to do with scaling: state that's visible to the model as an argument is state you can log, replay, and debug after the fact. Hidden session state that lived only in server memory disappears the moment the process restarts, and it leaves no trace in your run records.

If you're already recording what a bot did after each run, an explicit handle gives you something concrete to write down — a booking\_id, a ticket\_id, a cart\_id — instead of a vague note that 'the session had state.' That's a small design change with an outsized effect on whether you, or anyone reviewing the bot's work later, can actually verify what it was doing partway through a multi-step task.

Sources: [The 2026-07-28 Specification](https://blog.modelcontextprotocol.io/posts/2026-07-28/).

## Primary sources

Sources checked 2026-09-28. Standards and product documentation can change; follow the linked version when implementing.

- [The 2026-07-28 Specification](https://blog.modelcontextprotocol.io/posts/2026-07-28/) — Model Context Protocol
- [The 2026-07-28 MCP Specification Release Candidate](https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/) — Model Context Protocol
- [Key Changes - Model Context Protocol](https://modelcontextprotocol.io/specification/2026-07-28/changelog) — Model Context Protocol
- [Deprecated features - MCP Python SDK](https://py.sdk.modelcontextprotocol.io/deprecated/) — Model Context Protocol

BotBento is in development. [Suggest a correction](/contact/).
