stdio vs Streamable HTTP: Choosing the Right MCP Transport

stdio vs Streamable HTTP: Choosing the Right MCP Transport

A practical guide to understanding MCP's transport layer — what each option does, why SSE was deprecated, and when to use which.


The Model Context Protocol has become the de facto standard for connecting AI agents to external tools and data sources. But beneath all the excitement about tools, resources, and prompts, there's a foundational decision that trips up a surprising number of people: which transport should you use?

I've noticed a lot of confusion in the community about the differences between stdio, the now-deprecated Server-Sent Events (SSE) transport, and the current Streamable HTTP transport. Some people conflate SSE with Streamable HTTP. Others don't realise SSE has been deprecated at all. And plenty of builders are choosing transports based on vibes rather than architecture.

Let's fix that.

What Is a Transport in MCP?

MCP separates its architecture into two clean layers. The data layer defines the protocol itself — the JSON-RPC 2.0 messages, the capability negotiation, the tool/resource/prompt primitives. The transport layer is just the mechanism for moving those messages between client and server.

This separation is deliberate. Your tool logic, your resources, your prompts — none of that changes based on transport choice. You write your capabilities once and expose them over whichever transport makes sense for your deployment model.

All MCP communication uses JSON-RPC 2.0 — the same wire format used by the Language Server Protocol. Every message is either a request (with an id expecting a response), a response, or a notification (fire-and-forget, no id).

The transport is plumbing. Good plumbing matters, but it's not why people turn on the faucet.

The Three Transports

The MCP specification has defined three transports across its lifetime. Two are current; one is deprecated.

1. stdio — The Local Workhorse

stdio is the simplest transport and, today, the most widely deployed. The client spawns the MCP server as a child process and communicates through the operating system's standard input and output streams. The client writes JSON-RPC messages to the server's stdin; the server writes responses to stdout.

That's it. No network. No ports. No authentication. Just two processes talking through pipes.

{
  "mcpServers": {
    "my-tool": {
      "command": "node",
      "args": ["./server.js"],
      "env": { "API_KEY": "your-key" }
    }
  }
}

The client launches the process, negotiates capabilities via the MCP handshake, and you're live.

What makes stdio great:

  • Zero network overhead. Messages travel through OS pipes, not TCP sockets. In practice, stdio can achieve 10,000+ operations per second — an order of magnitude faster than HTTP-based transports under typical conditions.
  • No security surface. The server never opens a network port. There's no authentication to configure, no TLS to set up, no CORS headers to worry about. The process boundary is the security boundary.
  • Dead simple deployment. Package a binary or script, tell the client how to launch it, done. No infrastructure, no hosting, no DNS.
  • Universal client support. Every major MCP client — Claude Desktop, Claude Code, Cursor, Windsurf, Roo Code — supports stdio. It's the lowest common denominator in the best sense.

What makes stdio limiting:

  • Local only. The server must run on the same machine as the client. You can't share it across a team, deploy it to the cloud, or serve multiple users from one instance.
  • 1:1 relationship. One client spawns one server process. There's no concept of multiple clients connecting to a shared server.
  • stdout is sacred. Because the protocol uses stdout for message delivery, you cannot use console.log() or print() for debugging — it'll corrupt the JSON-RPC stream. All logging must go to stderr or to file.
  • No streaming notifications. The server can't push unsolicited messages to the client outside of the request/response cycle (though the spec does support notifications within the protocol layer).

Use stdio when: You're building personal tools, local file system wrappers, CLI utilities, database connectors running alongside your IDE, or anything where the server and client live on the same machine. If you're prototyping a new MCP server, start here.

2. SSE (Server-Sent Events) — The Deprecated Middle Child

When MCP first needed a remote transport (spec version 2024-11-05), it adopted Server-Sent Events. SSE used a two-endpoint architecture: clients would open a persistent GET connection to an /sse endpoint to receive streaming responses, and send requests via POST to a separate /messages endpoint.

This worked, but it had architectural friction:

  • Two endpoints to manage. The server had to maintain a mapping between SSE connection IDs and POST requests to route responses correctly. This added stateful complexity that made horizontal scaling awkward.
  • Unidirectional streaming. SSE only streams server-to-client. Client-to-server communication required the separate POST channel, creating an asymmetric architecture.
  • Infrastructure compatibility. Many load balancers, API gateways, and CDNs handle long-lived SSE connections poorly. Timeouts, buffering, and connection management became operational headaches at scale.
  • No session management. The original SSE transport had no built-in concept of sessions, making it difficult to maintain state across reconnections.

SSE was officially deprecated in spec version 2025-03-26 when Streamable HTTP was introduced. The latest spec (2025-11-25) retains backwards compatibility guidance — servers can still host SSE endpoints alongside the new transport — but all new implementations should use Streamable HTTP.

If you have an existing SSE server: Don't panic. It still works, and the spec provides clear backwards compatibility paths. But when you next touch that code, migrate to Streamable HTTP.

If you're building something new: Skip SSE entirely.

3. Streamable HTTP — The Modern Standard

Streamable HTTP, introduced in March 2025, is the current recommended transport for any MCP server that needs to operate over a network. It addresses every architectural limitation of SSE while remaining conceptually simple.

The key design decision: one endpoint, multiple interaction patterns.

The server exposes a single HTTP endpoint (e.g., https://example.com/mcp) that accepts both POST and GET requests. Clients send JSON-RPC messages via POST. The server can respond with either a standard HTTP response (for simple request/response patterns) or upgrade the connection to an SSE stream (for streaming results, progress updates, or server-initiated notifications).

Client                          Server
  |                                |
  |---- HTTP POST /mcp ---------->|  (client request)
  |                                |  (processes request)
  |<--- HTTP Response / SSE ------|  (response or stream)
  |                                |

This flexibility means a basic MCP server can be stateless and handle requests like any HTTP API, while a more sophisticated server can leverage streaming for long-running operations, real-time progress tokens, and server-to-client notifications — all through the same endpoint.

What makes Streamable HTTP the right choice for remote:

  • Single endpoint simplicity. One URL. One set of CORS headers. One load balancer rule. One firewall exception. The operational surface area is dramatically smaller than SSE's two-endpoint model.
  • Multi-client by design. The server runs as an independent process handling multiple connections. Deploy once, serve your entire team.
  • Session management. The spec defines an MCP-Session-Id header mechanism, allowing servers to maintain stateful sessions across requests. Session IDs must be cryptographically secure (UUIDs, JWTs, or hashes).
  • Authentication & authorisation. Running over standard HTTP means you can layer on OAuth, API keys, mTLS, or whatever your infrastructure already uses. The spec mandates Origin header validation to prevent DNS rebinding attacks.
  • Progressive capability. A server can start as a simple request/response HTTP service and add streaming later without changing the endpoint or breaking existing clients.
  • Cloud-native. Standard HTTP semantics mean Streamable HTTP works naturally with API gateways, load balancers, CDNs, container orchestrators, and serverless platforms.

What to be aware of:

  • Infrastructure overhead. You need to host, secure, and operate an HTTP service. That's more moving parts than stdio's "just run the binary" model.
  • Latency. HTTP introduces network round-trips. Depending on deployment, you'll see 100–1,000 operations per second versus stdio's 10,000+. For most AI agent workloads, this is fine — the bottleneck is the LLM, not the transport.
  • Security is your responsibility. Unlike stdio's implicit process-boundary security, you must implement authentication, TLS, input validation, and Origin header checking.

Use Streamable HTTP when: You're building a shared team tool, deploying a server to the cloud, serving multiple clients from one instance, building a SaaS integration, or need authentication and access control.

The Decision Framework

Choosing between stdio and Streamable HTTP comes down to one question: does the server need to be reachable over a network?

If the answer is no — the server runs on the same machine as the client, serves a single user, and accesses local resources — use stdio. It's faster, simpler, and has zero security configuration overhead.

If the answer is yes — multiple users need access, the server runs on remote infrastructure, or you need authentication — use Streamable HTTP. It's the modern standard, it scales, and it plays nicely with existing web infrastructure.

Don't use SSE for anything new. Full stop.

Here's a more granular breakdown:

ScenarioTransportWhy
Personal CLI toolstdioLocal, single-user, no network needed
IDE plugin (Cursor, Claude Code)stdioRuns alongside the editor on the same machine
Local database connectorstdioAccessing localhost resources
Shared team knowledge baseStreamable HTTPMultiple users, needs auth
SaaS product integrationStreamable HTTPRemote, multi-tenant, needs OAuth
Cloud-deployed API wrapperStreamable HTTPHosted remotely, scalable
Prototyping / learning MCPstdioFastest path to working code
Enterprise file connectorStreamable HTTPACL-aware, multi-user, centralised

What About the Hybrid Pattern?

In practice, many production architectures use both transports. A common pattern is a gateway architecture: a stdio server runs locally to handle file system access and local resources, while connecting upstream to Streamable HTTP servers for specialised cloud capabilities.

This gives you the best of both worlds — local operations stay fast and don't require network access, while shared or computationally expensive operations route through a centralised service.

Some frameworks (like mcp-remote and Cloudflare's supergateway) exist specifically to bridge these worlds, wrapping remote HTTP servers as local stdio processes for clients that only support local connections.

The Spec Timeline

For reference, here's how MCP's transport story has evolved:

  • 2024-11-05 — Initial MCP specification. Defined stdio and SSE as the two standard transports.
  • 2025-03-26 — Streamable HTTP introduced, SSE officially deprecated. The TypeScript SDK added support in version 1.10.0 (April 2025).
  • 2025-11-25 — Current specification. Defines stdio and Streamable HTTP as the two standard transports. SSE retained only for backwards compatibility.

Practical Advice

If you're just getting started with MCP: Start with stdio. Get your tools working locally. Validate the integration. Make sure your tool descriptions are clear and your responses are useful. Don't overthink the transport — it's the least interesting part of your server.

If you need to go remote: Move to Streamable HTTP. The migration path is straightforward because MCP's transport-agnostic design means your tool logic doesn't change — only the transport wiring.

If you're maintaining an SSE server: Add Streamable HTTP support alongside your existing SSE endpoints. The spec provides a clean backwards compatibility path: servers can host both transports simultaneously, and clients can auto-detect which one the server supports by attempting a POST to the MCP endpoint first.

If you're building for enterprise: Streamable HTTP with proper auth, session management, and TLS is the only serious option. The session ID mechanism, Origin validation, and standard HTTP security patterns give you the controls enterprise deployments require.

The protocol is the plumbing. Good plumbing matters — but the real value is in the tools you build on top of it.


Disclaimer: Yes, I have used AI to help with the structure and flow my write up - I'm an engineer after all! The tests, knowledge and findings are all real-world research and can be verified and reproduced on-demand.