Transports
stdio vs Streamable HTTP — how MCP messages actually travel, and why the old standalone SSE transport is gone
Transports
TL;DR
MCP defines exactly two transports: stdio, for local processes on the same machine, and Streamable HTTP, for remote servers reachable over a network. Server-Sent Events are not a separate transport anymore — they're an optional streaming mode within Streamable HTTP. The same JSON-RPC 2.0 message format runs over both; only how the bytes travel changes.
| Property | Value |
|---|---|
| Level | Intermediate |
| Reading time | ~18 minutes |
| Prerequisites | Elicitation |
| You will understand | The two transports, when to reach for each, and how the auth story differs between them |
Two Transports, Not Three
Early MCP tutorials — and a fair amount of content still circulating — describe three transport options: stdio, HTTP, and a standalone SSE (Server-Sent Events) transport. That third option doesn't exist anymore. The current spec defines exactly two:
The two current transports
Stdio transport
RecommendedStandard input/output streams, for direct process communication between local processes on the same machine.
Streamable HTTP transport
HTTP POST for client-to-server messages, with optional Server-Sent Events for streaming responses back.
SSE is a mode, not a transport. If you've seen a server described as using "the SSE transport," that's describing an older version of the protocol. Today, Server-Sent Events are an optional streaming capability that Streamable HTTP can use when a response benefits from incremental delivery — they aren't a third thing to choose between stdio and HTTP.
Both transports carry the exact same JSON-RPC 2.0 message shapes covered in The MCP Architecture — tools/call, resources/read, server/discover, and so on. Nothing about the data layer changes based on which transport is underneath it. The transport layer's whole job is to abstract that away.
Stdio: Local, Direct, No Network
Stdio transport means the client and server are two processes on the same machine, communicating by writing JSON-RPC messages to each other's standard input and standard output streams.
MCP Host (e.g. Claude Desktop)
│
│ spawns as a subprocess
▼
MCP Server process
│
│ stdin ← JSON-RPC requests
│ stdout → JSON-RPC responses
▼
(your filesystem, database, local tool, etc.)Two properties fall directly out of that shape:
No network overhead. There's no socket, no TLS handshake, no DNS lookup — just two processes on the same kernel passing bytes through pipes the OS already manages. This makes stdio the fastest transport available, and the reason it's the default for anything that doesn't need to leave the machine.
Typically one client per server. Because the host spawns the server process directly (usually as a child process it owns), a stdio server is naturally scoped to that one host instance. If you close Claude Desktop, the filesystem server it spawned goes away with it. This is fundamentally different from a long-running network service that many clients connect to independently.
# A host launches a stdio server roughly like this under the hood
python weather_server.py
# communicating over stdin/stdout, not a portStdio is what you reach for when the answer to "who needs to connect to this?" is "just me, on this machine, right now." A local filesystem server, a personal script wrapped as a tool, a database running on your laptop — all stdio's natural territory.
Streamable HTTP: Remote, Shared, Networked
Streamable HTTP transport uses ordinary HTTP POST requests for client-to-server messages, with the server able to respond either as a single JSON response or as a stream of Server-Sent Events when incremental delivery helps.
MCP Client A ──┐
MCP Client B ──┼──→ HTTPS ──→ MCP Server (remote, long-running)
MCP Client C ──┘ │
▼
(a hosted service — a SaaS API,
a company database, anything
the server owner runs and exposes)This is the shape a hosted, third-party MCP server takes — the Sentry MCP server, a GitHub MCP server, or any server one organization runs and many clients connect to. Because it's ordinary HTTP, it inherits ordinary HTTP infrastructure for free: load balancers, standard authentication headers, existing reverse proxies, and — critically — standard authentication methods.
Streamable HTTP supports bearer tokens, API keys, and custom headers directly, and MCP recommends OAuth specifically for obtaining those tokens. That recommendation is strong enough that it gets its own full page: Authorization & Security.
Streamable HTTP is what you need the moment more than one party needs to reach the server independently — a team sharing a company data source, a service your own application calls, or anything you intend to run once and let many clients use. Reaching for stdio in that situation means reimplementing what a real network service already gives you.
Choosing Between Them
The actual decision
A concrete example from each side: a server that reads files from your own project directory and formats them — stdio, spawned locally, no reason to ever leave your machine. A server that lets a whole engineering team query a shared production database — Streamable HTTP, run once as a real service, reached by everyone's client independently, protected by OAuth so only the right people can query it.
The Auth Implication, Foreshadowed
This is worth stating plainly before the next page goes deep on it: stdio and Streamable HTTP have fundamentally different relationships to authorization.
| Stdio | Streamable HTTP | |
|---|---|---|
| Typical credential source | The environment — an API key already in an env var, a config file already on disk | The MCP authorization spec itself — OAuth 2.1, tokens over the wire |
| Why | The server process runs as you, on your machine — it already has whatever access you have | The server runs somewhere else, for potentially many different users — it needs a real way to know who's asking |
A stdio server generally shouldn't try to implement the full OAuth flow described in the next page — there's no meaningful "who is this" question to answer when the process is a direct child of your own host, already running with your own permissions. That question becomes real, and unavoidable, the instant the server is reachable over a network.
Concept Checks
Check yourself
A colleague says their server 'uses the SSE transport.' What's actually true today?
There's no standalone SSE transport in the current spec — they mean their server uses Streamable HTTP with Server-Sent Events as the streaming mode for responses. The distinction matters because "SSE transport" as a separate protocol choice is outdated terminology from an earlier version of MCP.
Why does stdio typically serve exactly one client, while Streamable HTTP typically serves many?
A stdio server is usually spawned directly as a child process of the host that needs it, so its lifecycle and access are tied to that one host instance. A Streamable HTTP server is a long-running network service, independent of any one client's process, so any number of clients can open their own connection to it over the network.
Why doesn't a stdio server typically need to implement OAuth?
Because it runs as a direct subprocess of the host, on the same machine, already operating with whatever permissions the user running the host has — there's no separate identity to establish. OAuth exists to answer "who is making this request" over a network where that isn't otherwise knowable, which isn't a question a same-machine subprocess needs answered.
You're building a server for a shared company data source that multiple team members' AI tools will query independently. Which transport, and why?
Streamable HTTP — the server needs to run once as an independent, long-running service that many different clients connect to over the network, which is exactly the shape stdio's one-client-per-process model doesn't fit. It also gets you standard HTTP authentication for free, which a shared, sensitive data source needs.
Key Concepts Recap
| Concept | One-line summary |
|---|---|
| Two transports | stdio (local) and Streamable HTTP (remote) — no separate SSE transport anymore |
| SSE is a mode | Server-Sent Events are an optional streaming capability within Streamable HTTP |
| Same data layer, both transports | JSON-RPC 2.0 messages are identical regardless of transport |
| Stdio: no network overhead | Direct process-to-process pipes, the fastest option available |
| Stdio: one client, typically | Spawned as a subprocess, scoped to one host instance |
| Streamable HTTP: many clients | A long-running network service, reachable independently by anyone |
| Streamable HTTP: standard HTTP auth | Bearer tokens, API keys, custom headers — OAuth recommended |
| Stdio's implicit auth | The environment — the process already runs with the user's own permissions |
Next
Streamable HTTP's authentication story deserves its own deep dive — the full OAuth 2.1 flow, and the security principles that apply regardless of transport: Authorization & Security.