I've been seeing news everywhere that MCP just went stateless, but I had no clue what it means. So I decided to dig into it and write a blog post about it.

Stateless MCP for Beginners

The Model Context Protocol (MCP) connects AI assistants to tools, databases, and external applications. In the 2026-07-28 specification revision, MCP removed protocol-level sessions and became stateless.

That change makes remote MCP servers easier to operate. They can scale behind ordinary load balancers without sticky routing or a shared MCP session store. Clients can safely cache tool definitions, and agents get more control over which application resources they share.

But stateless does not mean MCP servers can no longer remember anything. A browser can still have open tabs, a database transaction can still have uncommitted changes, and a shopping cart can still hold items. The difference is how the client refers to that state.

Why MCP Sessions Became a Problem

State is information a system remembers between requests. Imagine an MCP server that controls a web browser. An agent might call open_browser, followed by navigate, click, and take_screenshot. The server needs to know that all four actions refer to the same browser.

In earlier MCP versions, the connection could provide that context. The client began with an initialize request. Under Streamable HTTP, the server could respond with an Mcp-Session-Id, which the client attached to later requests. The server could then use that ID to recover information associated with the session.

This worked naturally when one client talked to one server process. It became more complicated when an MCP service ran across several machines behind a load balancer. If Server A created a session and the next request reached Server B, Server B needed some way to recover that session. Infrastructure teams typically solved this with sticky routing, which kept the client tied to Server A, or a shared database that every server could use for session lookup.

Sessions also meant different things in different clients. A session could last for one tool call, one conversation, one page load, or the lifetime of an application. Server authors could store a browser or shopping cart inside a session, but they could not reliably predict how long that state would survive or which conversations might share it.

What Changed in Stateless MCP

Under the 2026-07-28 revision, the initialize and notifications/initialized handshake is gone. Servers no longer issue MCP session IDs, and clients no longer store or resend them.

Instead, every request carries the protocol information needed to understand it, including the protocol version and client capabilities. A client can also call server/discover to learn which versions and features a server supports without opening a session.

This means any compatible server instance can understand an incoming MCP request without recovering information from an earlier handshake. If a tool manages application state, such as a running browser, the service still needs a way to locate that resource. Stateless MCP removes protocol session state, not application state.

Making Application State Explicit

When a tool needs state across calls, the server can return an explicit identifier, often called a handle. A handle is not a special MCP data type. It is an ordinary value returned by one tool and passed to another.

For example, a browser server might work like this:

// Open a browser and receive its handle
open_browser()
// Returns: { "browser_id": "browser_abc123" }

// Pass the handle into later calls
navigate({
  "browser_id": "browser_abc123",
  "url": "https://example.com"
})

Enter fullscreen mode Exit fullscreen mode

The browser still lives on the server and keeps its tabs, cookies, and history. The relationship between calls is now visible in the tool arguments instead of hiding inside the connection.

Explicit handles also give orchestrators more control over shared state. If three agents are shopping together, they can share one cart_id while each receives a separate browser_id. A single MCP session could not express those two state boundaries cleanly.

Handling Multi-Step Work

Some tools need more information before they can finish. A deployment tool might ask for confirmation before publishing to production. Under the Multi Round-Trip Requests (MRTR) pattern, the tool returns an input_required result describing what it needs. The result may include an opaque requestState value, which the client returns with the requested answers when it retries the original call. The information needed to continue travels with the retried request instead of remaining tied to an open connection.

For longer-running or durable work, servers can use task handles through the Tasks extension. The client can check or update the task later without keeping a network connection open.

Making Tool Lists Easier to Cache

In previous MCP versions, the tools returned by tools/list could vary by session. A server might expose a connect_database tool first, then add query_database after the connection was established. Because the list could depend on session history, clients could not safely reuse it elsewhere.

Tool lists can still change when a server is updated or a user's permissions change, but they no longer vary by MCP connection. Servers return ttlMs and cacheScope values that tell clients how long a result should remain fresh and whether it can be shared. This allows an orchestrator to reuse tool definitions across subagents, reducing redundant requests and improving prompt-cache reuse.

What MCP Server Authors Need to Change

If you build or maintain an MCP server:

  • Update your SDK and version configuration: Use an SDK that supports 2026-07-28 and enable the new revision if your framework requires an explicit opt-in.
  • Replace session state with explicit handles: Return identifiers such as browser_id or connection_id and require them in later calls.
  • Plan for cleanup: Give temporary resources expiration policies or explicit cleanup tools instead of relying on a connection closing.
  • Authorize every handle: Treat an ID as the name of a resource, not proof that the caller can access it.
  • Make side effects safe to retry: Use idempotency keys where appropriate for operations such as charging a card or triggering a deployment.

The Takeaway

MCP began with a connection-oriented model that worked naturally for local processes running on a single machine. As the ecosystem expanded into cloud services, hosted gateways, and multi-agent systems, connection-level state became a scaling bottleneck.

The 2026-07-28 specification separates these concerns. Protocol details travel with the request, application state uses explicit handles, interactive workflows pass continuation state, and tool definitions are cached cleanly. MCP servers still remember everything they need to remember. They just name that state directly inside the request.