If you deployed a remote MCP server in 2025, you probably hit the same wall I did: it worked fine on localhost, then fell apart behind a load balancer. Request two landed on a different pod and came back with a session error. The fix was always some combination of sticky sessions, Redis, or a custom gateway. That was not a bug in your code. It was the protocol.
The 2026-07-28 Model Context Protocol (MCP) specification changes that. MCP is now stateless at the transport layer. Each Hypertext Transfer Protocol (HTTP) request carries everything the server needs. Any replica can answer it. For teams treating MCP as production infrastructure, not a local dev trick, this is the biggest shift since remote MCP launched.
Key abbreviations in this post
- API — Application Programming Interface
- AWS — Amazon Web Services
- HTTP — Hypertext Transfer Protocol
- JSON — JavaScript Object Notation
- JSON-RPC — JSON Remote Procedure Call
- K8s — Kubernetes
- LLM — Large Language Model
- MCP — Model Context Protocol
- MRTR — Multi Round-Trip Requests
- OAuth — Open Authorization
- OpenTelemetry — open standard for traces, metrics, and logs
- PEP — Python Enhancement Proposal
- REST — Representational State Transfer
- RFC — Request for Comments
- RPC — Remote Procedure Call
- SaaS — Software as a Service
- SDK — Software Development Kit
- SEP — Specification Enhancement Proposal
- SSE — Server-Sent Events
- SKU — Stock Keeping Unit
- stdio — standard input/output
MCP in 60 Seconds
The Model Context Protocol (MCP) is an open standard for connecting AI applications to external tools, data, and prompts. Think of it as a structured Application Programming Interface (API) layer built for Large Language Model (LLM) hosts rather than generic Representational State Transfer (REST) clients.
The architecture has three roles (Model Context Protocol, n.d.):
- Host — the AI app you actually use (Cursor, Claude Desktop, an internal agent platform).
- Client — one client per server connection, living inside the host. It speaks JSON Remote Procedure Call (JSON-RPC) 2.0 on behalf of the host.
- Server — your integration. It exposes tools (callable functions), resources (readable data), and prompts (templates).
Local servers usually run over stdio (standard input/output): the host spawns a subprocess and talks over stdin/stdout. Remote servers use Streamable HTTP (Hypertext Transfer Protocol) on a real port. That is the deployment path that needed statelessness.
That is the whole stack in brief. The rest of this post is about what changed when MCP stopped pretending every HTTP (Hypertext Transfer Protocol) deployment was a single long-lived conversation.
What "Stateless MCP" Actually Means
Before spec version 2026-07-28, a remote MCP client had to:
- Send an
initializerequest with protocol version and capabilities. - Receive an
Mcp-Session-Idheader from the server. - Include that session ID on every later call, often over a held-open Server-Sent Events (SSE) stream.
The server kept session state in memory (or Redis). The client was pinned to whichever instance created that session. Scale-out required sticky routing and shared session stores (Model Context Protocol, 2026; Van Gent & Blount, 2026).
Stateless MCP removes that contract entirely. Each change below is tracked as a numbered Specification Enhancement Proposal (SEP), MCP's formal design document for spec changes (similar to a Python Enhancement Proposal (PEP) in Python or a Request for Comments (RFC) on the web):
- SEP-2575 (Specification Enhancement Proposal) retires the
initialize/initializedhandshake. - SEP-2567 (Specification Enhancement Proposal) removes the
Mcp-Session-Idheader. - Every request includes client identity and capabilities in a
_metaobject. - Optional
server/discoverRemote Procedure Call (RPC) replaces "connect first, then ask what you can do." - SEP-2243 (Specification Enhancement Proposal) puts
Mcp-MethodandMcp-Namein HTTP (Hypertext Transfer Protocol) headers so gateways can route without parsing JSON (JavaScript Object Notation) bodies.
Working process step by step
- The host decides to call a tool (for example,
search_inventorywith a Stock Keeping Unit (SKU)). - The MCP client builds a JSON Remote Procedure Call (JSON-RPC)
tools/callpayload and attaches_metawith protocol version, client name, and capabilities. - The client POSTs to
/mcpwith headersMCP-Protocol-Version,Mcp-Method, andMcp-Name. - A load balancer forwards the request to any healthy server instance.
- The server validates headers against the body, runs the tool handler, and returns a JSON response. No session lookup.
- If the tool needs user input mid-flight, the server returns a Multi Round-Trip Requests (MRTR)
inputRequiredresult with arequestStateblob. The client retries on any instance with answers attached (Model Context Protocol, 2026).
One nuance worth stating clearly: stateless protocol does not forbid application state. If your workflow spans multiple tool calls, mint an explicit handle (a task ID, a draft ID) from the first tool and pass it back as an argument. That is visible to the model and survives load balancing. Hidden session state in the transport was the part that had to go.
Why We Needed This
MCP exploded as the default way to wire agents to Software as a Service (SaaS) APIs, databases, and internal services. Downloads across Tier 1 Software Development Kits (SDKs) crossed into the hundreds of millions per month (Model Context Protocol, 2026). Most of that growth pointed at remote HTTP (Hypertext Transfer Protocol) servers, not local stdio (standard input/output) subprocesses.
The old session model created real production pain (Van Gent & Blount, 2026; New Relic, 2026):
- Broken round-robin. Standard load balancers sent the second request to a pod that never saw the session.
- Sticky session tax. Affinity rules skew traffic and fight autoscaling.
- Fragile deploys. Rolling updates dropped in-memory sessions and surfaced transient 400 errors to active chats.
- Extra infrastructure. Teams bolted on Redis or gateway packet inspection just to keep MCP alive at scale.
- Gateway blind spots. Rate limits and audit rules could not key off method or tool name without parsing JSON (JavaScript Object Notation) bodies.
Stateless MCP makes remote servers behave like normal HTTP (Hypertext Transfer Protocol) microservices. That sounds obvious. For a protocol born on stdio (standard input/output), it is a necessary maturation step.
Stateful vs Stateless MCP
| Aspect | Stateful MCP (pre-2026-07-28) | Stateless MCP (2026-07-28) |
|---|---|---|
| Connection setup | initialize handshake required |
No handshake; optional server/discover |
| Session tracking | Mcp-Session-Id on every request |
No protocol-level session ID |
| Client context | Sent once at connect time | Sent in _meta on every request |
| Load balancing | Sticky sessions or shared session store | Plain round-robin across replicas |
| Serverless / scale-to-zero | Poor fit; sessions die on cold start | Natural fit (Cloud Run, Lambda, Workers) |
| Gateway routing | Often requires JSON (JavaScript Object Notation) body inspection | Mcp-Method and Mcp-Name headers |
| Mid-call user prompts | Open bidirectional Server-Sent Events (SSE) stream | Multi Round-Trip Requests (MRTR) with requestState retry |
| Long-running work | Block connection or custom hacks | Tasks extension with poll-based status |
| Payload size trade-off | Smaller per-call payloads after handshake | Slightly larger requests (metadata repeated) |
| Best transport locally | stdio (standard input/output) still fine either way | stdio (standard input/output) unchanged; HTTP (Hypertext Transfer Protocol) gains the most |
Real Use Cases
Stateless MCP is not academic. It unlocks patterns teams were already hacking together:
- Enterprise tool gateways. One MCP endpoint fronting dozens of internal APIs (Application Programming Interfaces), rate-limited per tool name at the edge (Microsoft Foundry, Amazon Web Services (AWS) Bedrock AgentCore, and others ship variations of this).
- Multi-tenant SaaS (Software as a Service) MCP. GitHub and similar providers removed Redis session stores after upgrading, cutting latency on every call (Van Gent & Blount, 2026).
- Global deployment. Any region, any replica, same request shape. No cross-region session replication.
- Agent fleets at scale. Thousands of concurrent agent sessions hitting the same tool server without affinity tuning.
- Serverless MCP. Spin down to zero between bursts; the next request is self-contained.
- Compliance-friendly auditing. Log
Mcp-Nameand auth subject per request without holding connection state.
Deployment Architecture
A production layout looks familiar if you have shipped REST (Representational State Transfer) APIs before. The protocol no longer fights you.
Benefits in this layout:
- Horizontal pod autoscaling on Central Processing Unit (CPU) or request rate, not session count.
- Zero-downtime deploys without draining sessions.
- Open Authorization (OAuth) at the gateway with Request for Comments (RFC) 9207 issuer validation (SEP-2468 (Specification Enhancement Proposal)).
- OpenTelemetry traces correlated per request, not per opaque session.
ttlMs(time-to-live in milliseconds) andcacheScopeon list responses (SEP-2549 (Specification Enhancement Proposal)) so clients cache tool catalogs safely.
Example: Stateless MCP Server in Python
The v2 Python Software Development Kit (SDK) targets spec 2026-07-28. The high-level Application Programming Interface (API) is MCPServer. Transport options belong on run(), not the constructor (Model Context Protocol, n.d.-b).
# server.py — stateless inventory MCP server
from mcp.server import MCPServer
mcp = MCPServer(
"InventoryTools",
instructions="Look up product stock by SKU.",
)
@mcp.tool()
def search_inventory(sku: str) -> str:
"""Return stock level for a warehouse SKU."""
# Replace with a real DB/API call in production.
catalog = {"SKU-1001": 42, "SKU-2002": 0}
qty = catalog.get(sku.upper())
if qty is None:
return f"No product found for {sku!r}."
return f"{sku.upper()}: {qty} units in stock."
if __name__ == "__main__":
mcp.run(
transport="streamable-http",
host="0.0.0.0",
port=8000,
stateless_http=True,
json_response=True,
)
Install and run:
pip install "mcp[cli]>=2.0.0"
python server.py
# or: uv run mcp dev server.py
What each piece does:
@mcp.tool()registers a callable the host can invoke. Docstrings become tool descriptions for the model.transport="streamable-http"exposes the server on a port at/mcpfor remote clients over Hypertext Transfer Protocol (HTTP).stateless_http=Truecreates a fresh transport per request with no session tracking. This aligns the SDK (Software Development Kit) with the stateless protocol core.json_response=Truereturns one JSON body per POST instead of a Server-Sent Events (SSE) stream. Good default for simple tool servers behind load balancers.
A client call (from the same Software Development Kit (SDK)) looks like this:
import asyncio
from mcp import Client
async def main() -> None:
async with Client("http://localhost:8000/mcp") as client:
result = await client.call_tool(
"search_inventory",
{"sku": "SKU-1001"},
)
print(result.structured_content)
asyncio.run(main())
Each call_tool is an independent HTTP (Hypertext Transfer Protocol) round trip. Hit the server from three terminals at once and any replica can serve any call. That is the behavior you want in staging before you trust it in production.
Migration Checklist
If you are upgrading from MCP v1 SDKs (Software Development Kits) or pre-2026 HTTP (Hypertext Transfer Protocol) servers:
- Bump to Software Development Kit (SDK) v2 (Python
mcp>=2.0, TypeScript@modelcontextprotocol/server@betaor later). - Replace
FastMCPimports withMCPServer. - Move
stateless_httpand port settings from the constructor torun(). - Delete sticky-session config and shared Redis session stores used only for MCP transport.
- Replace session-keyed application state with explicit IDs returned from tools.
- Rewrite elicitation flows around Multi Round-Trip Requests (MRTR) instead of open back-channels.
- Add
ttlMs(time-to-live in milliseconds) /cacheScopeto list handlers where catalog caching helps.
Important Links and Repositories
- Official spec (2026-07-28): modelcontextprotocol.io/specification/2026-07-28
- Release announcement: The 2026-07-28 Specification
- Architecture overview: MCP Architecture Docs
- Python SDK (Software Development Kit) (v2): github.com/modelcontextprotocol/python-sdk
- Python SDK docs: Running your server
- TypeScript SDK (Software Development Kit): github.com/modelcontextprotocol/typescript-sdk
- Go SDK (Software Development Kit): github.com/modelcontextprotocol/go-sdk
- Google deep dive on stateless updates: Scaling AI Agent Infrastructure with MCP Stateless Updates
- Microsoft Azure perspective: MCP Just Went Stateless on App Service
Bottom Line
MCP started as a clean way to plug tools into a local AI assistant. Stateless HTTP (Hypertext Transfer Protocol) turns it into something you can run the way you run the rest of your stack: behind a load balancer, across regions, on serverless, with ordinary observability.
The trade is slightly larger requests and a migration sprint if you built on sessions. The payoff is boring scaling, which is exactly what you want once agents stop being a demo and start being a product surface.
If you are starting fresh, build on 2026-07-28 and skip the session workarounds entirely. If you are maintaining an existing remote server, treat this like any other protocol upgrade: staged rollout, benchmark your payload sizes, delete the Redis session layer when receipts prove you do not need it.
Bibliography
- Model Context Protocol. (2026, July 28). The 2026-07-28 specification. Model Context Protocol Blog. https://blog.modelcontextprotocol.io/posts/2026-07-28/
- Model Context Protocol. (n.d.). Architecture. https://modelcontextprotocol.org/docs/learn/architecture
- Model Context Protocol. (n.d.-b). Running your server. MCP Python SDK. https://py.sdk.modelcontextprotocol.io/v2/run/
- New Relic. (2026). MCP is going stateless: What the new spec means for AI agents. https://newrelic.com/blog/ai/mcp-is-going-stateless
- Van Gent, K., & Blount, A. (2026, August 5). Scaling AI agent infrastructure with the MCP stateless updates. Google Developers Blog. https://developers.googleblog.com/scaling-ai-agent-infrastructure-with-the-mcp-stateless-updates/
