MCP transports: stdio vs Streamable HTTP (and what happened to SSE)
How to choose between stdio and Streamable HTTP for your MCP server, why SSE is deprecated, and how the 2026-07-28 stateless core changes the design maths.
Transport choice is the first real architecture decision you make with MCP, and it’s often made by accident — you copy a stdio example, it works on your laptop, and six months later you’re untangling it to deploy for your team. Here’s the decision made deliberately.
The three names you’ll see
stdio — the client launches your server as a subprocess and speaks JSON-RPC over stdin/stdout. No network, no ports, no auth layer. This is what claude mcp add --transport stdio name -- npx -y pkg sets up, and what Claude Desktop’s mcpServers config launches.
Streamable HTTP — the server exposes a single HTTP endpoint (conventionally /mcp). Clients POST JSON-RPC messages; the server replies with JSON or upgrades the response to an SSE stream when it needs to push multiple messages. Introduced in spec 2025-03-26, and the standard remote transport ever since.
HTTP+SSE — the old remote transport from spec 2024-11-05, with separate /sse and /messages endpoints. Deprecated since 2025-03-26. It still limps along in some clients (claude mcp add --transport sse exists as a legacy option), but you should not build anything new on it.
The decision table
| Your situation | Transport | Why |
|---|---|---|
| Local dev, personal tools, filesystem/CLI access | stdio | Zero infrastructure; inherits your local user’s permissions naturally |
| Server needs the user’s local machine (files, local git, local processes) | stdio | A remote server can’t see the user’s disk |
| Shared server for a team | Streamable HTTP | One deployment, many clients; central auth and logging |
| ChatGPT connectors, claude.ai connectors, any web-based client | Streamable HTTP | Web clients can’t spawn your subprocess — remote is the only option |
| Publishing for wide consumption without asking users to install a runtime | Streamable HTTP | A URL beats “install Python ≥3.10 first” |
| Existing HTTP+SSE server | Migrate to Streamable HTTP | SSE has been deprecated since 2025-03-26 |
The pattern behind the table: stdio when the server belongs to one user’s machine, Streamable HTTP when the server belongs to a network.
What each transport really costs
stdio’s hidden costs are operational, not technical. Every user runs their own copy, so every user needs the runtime (Node, Python + uv, …) installed and on the PATH — which is where Windows users meet spawn npx ENOENT and the cmd /c npx workaround. Updates mean every machine updates. Secrets live in local config files (the env block in claude_desktop_config.json). There’s no central place to see what the server did. For one developer, none of this matters. For fifty, all of it does.
Streamable HTTP’s costs are the usual costs of running a service. You deploy it, TLS-terminate it, keep it up, and — critically — you must authenticate it, because now anyone who can reach the URL can call your tools. The spec’s answer as of 2025-06-18 is OAuth 2.1 with the MCP server acting as a resource server against an external authorization server, with RFC 8707 resource indicators. That’s real work, and it’s the main reason not to reach for HTTP before you need it. You also take on the spec’s hardening requirements — validate Origin (spec 2025-11-25 requires HTTP 403 for invalid Origin) and never bind a dev server to 0.0.0.0 when 127.0.0.1 will do.
Latency favours stdio on paper — a pipe to a subprocess beats a network round trip. In practice both are dwarfed by model inference time. Choose on topology and operations, not latency, unless your tools are called in tight loops.
If you’re still on SSE
The migration is smaller than it looks. Streamable HTTP collapses SSE’s two endpoints into one and lets both SDKs do the heavy lifting:
- Server side: current official SDKs (Python
mcp1.28.1, TypeScript@modelcontextprotocol/sdk1.29.0) ship Streamable HTTP transports. In most FastMCP-style servers, migrating is changing the transport you run, not rewriting tools — tool code is transport-agnostic by design. - Client side: re-add the server with the new transport, e.g.
claude mcp add --transport http name https://your-host/mcpinstead of--transport sse. - Compatibility window: if you serve unknown clients, you can run both transports side by side during transition, but treat SSE as an off-ramp, not a feature. Errors like connection drops surfacing as
MCP error -32000: Connection closedon old SSE setups are a hint it’s time.
Design stateless now — the 2026-07-28 shift
Classic Streamable HTTP is session-oriented: an initialize handshake, an Mcp-Session-Id header, server-side state per client. That model fights everything modern hosting is good at — serverless functions, autoscaling pods behind a load balancer, zero-downtime redeploys all hate sticky sessions.
The spec is resolving that tension decisively: the 2026-07-28 release (finalising July 28, 2026) makes a stateless core the foundation — the initialize handshake and Mcp-Session-Id are removed from the core protocol, with stateful behaviour layered on top only where needed.
You don’t need to wait to benefit. Design as if it already landed:
- Keep tools self-contained — everything a call needs arrives in its arguments.
- Don’t stash per-session state in server memory; if you need continuity, key it on authenticated identity, not a session header.
- Assume any request may hit a fresh instance of your server.
A server built this way runs happily on today’s 2025-11-25 spec, deploys to serverless without contortions, and needs nothing when the stateless core lands. A session-dependent server will need rework.
Verdict
Default to stdio for anything local and personal — it’s the shortest path and the right permission model for tools that touch your own machine. Move to Streamable HTTP the moment a second person, a remote host, or a web-based client like ChatGPT enters the picture, and budget for OAuth when you do. Treat SSE as legacy to migrate away from, not a third option. And whatever you deploy, keep state out of the server process — the protocol is converging on stateless, and stateless servers are simply easier to run.
For the wider protocol picture — where transports sit under agent-to-agent protocols — see MCP vs A2A: the agent protocol stack, sorted.
Was this guide useful?
Thanks — noted. It shapes what gets written next.
newsletter
One practical MCP guide in your inbox. No news, no hype.
Tutorials and decision frameworks as they ship. Unsubscribe anytime.