MCP Directory

MCP Transports: stdio vs SSE vs Streamable HTTP

Three transports, one right answer for each situation — and one you should stop using.

Hua·June 30, 2026·6 min read
Vibrant light painting of a tree sculpture at night in Stockholm, showcasing a dynamic and artistic experience.
Photo by Jakob Stöberl on Pexels

MCP has three transports, and picking between MCP SSE vs Streamable HTTP vs stdio is simpler than the spec makes it look: use stdio when the server runs on your machine, use Streamable HTTP when it runs somewhere else, and treat SSE as legacy — it was deprecated in the March 2025 spec revision. That's the whole decision. The rest of this piece explains why, and where the sharp edges are.

Transport is just the pipe that carries JSON-RPC messages between your client (Cursor, Claude, VS Code) and the server. It doesn't change what a server does — a filesystem server exposes the same tools over stdio or HTTP. It changes where the server lives, how you authenticate, and who can reach it. Get it wrong and you'll waste an afternoon debugging a config that was never going to connect.

The short answer: match the transport to where the server runs

Pick by location, not preference. Roughly 90% of MCP servers run locally over stdio, because most of what people connect to — files, git, a local database, a browser — is on the same machine as the client. If the server is a process on your laptop, stdio is correct and anything else is overhead.

Use Streamable HTTP only when the server is genuinely remote: a hosted endpoint, a shared team service, or a vendor's managed API. Use SSE for exactly one reason — an old server that hasn't migrated yet and gives you no other option.

TransportWhere the server runsAuthStatus
stdioLocal process (same machine)Env vars / OSCurrent, default
Streamable HTTPRemote / hosted endpointOAuth, bearer tokenCurrent, preferred for remote
SSERemote (legacy)Token in headerDeprecated (2025-03)

stdio: the default, and why ~90% of servers use it

stdio is the right choice for anything local, and it's the default for a reason: the client launches the server as a child process and talks to it over stdin/stdout. No ports, no TLS, no network. The server inherits the client's user and filesystem access, which is exactly what you want for a tool reading your repo.

A stdio entry is just a command the client runs. This is what the vast majority of your config looks like:

{
  "mcpServers": {
    "github": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "<your-github-pat>" }
    }
  }
}

The GitHub MCP Server ships this way — a local Docker container over stdio — and also offers a hosted remote endpoint. That dual mode is common now: run it locally when you want your own token and zero network hops, or point at the remote when you'd rather not manage the container. Exa Search is the same story: npx for a local stdio process, or a hosted remote if you don't want a Node process running.

The one gotcha with stdio: the server writes protocol messages to stdout, so anything your server prints to stdout that isn't JSON-RPC will corrupt the stream. Log to stderr. Most "server won't start" reports on stdio are a stray print() or a banner line. If you're stuck there, the troubleshooting checklist starts with exactly this.

Streamable HTTP: the modern remote transport

Streamable HTTP is what you use for any server not on your machine, and it's the successor SSE was replaced by. It runs the whole session over a single HTTP endpoint: the client POSTs JSON-RPC requests, and the server replies with either a plain JSON response or an SSE-formatted stream when it needs to push multiple messages. One URL, one connection model, real auth.

That last part matters. Remote transports need security you don't think about locally — OAuth or bearer tokens, TLS, and a server you actually trust with your requests. When the server needs no key, a remote config is just a URL:

{
  "mcpServers": {
    "aws-knowledge": {
      "url": "https://knowledge-mcp.global.api.aws"
    }
  }
}

AWS Knowledge MCP is a clean example: a fully managed remote server for AWS docs and Well-Architected guidance that needs no key at all — you just add the URL. Most remote servers do need auth, though. Jina AI Reader & Search reads web pages as Markdown and runs grounded search over HTTP, but you pass a Jina API key as a bearer token in the header rather than in the URL. Either way, someone else operates the server, patches it, and scales it. For the full local-vs-remote trade-off, see local vs remote MCP.

SSE: deprecated — don't build on it

Skip SSE for anything new. The old HTTP+SSE transport used two endpoints — one for the SSE stream, one for POSTing messages — and that split caused resumability and proxy headaches. The March 2025 spec folded both into Streamable HTTP and marked the old transport deprecated.

You'll still meet SSE in the wild: URLs ending in /sse, and older servers that only expose it. Connecting to one is fine — most clients still speak it for backward compatibility. Just don't choose it. If you're writing a server, ship Streamable HTTP. If a server you depend on is SSE-only, that's a mild signal it's not being maintained.

Transport doesn't fix your real bottleneck: the tool budget

Whichever transport you pick, it has no effect on the constraint that actually degrades your setup: the tool count. Clients feed every tool from every connected server into the model's context, and the practical ceiling is around 40 tools before selection accuracy drops and prompts get bloated. stdio vs HTTP changes none of that.

So choose transport by location, then be ruthless about which servers you connect. A remote server with 30 tools costs the same context as a local one with 30 tools. The Cursor tool limit math breaks down the budget, and browsing by capability helps you add the two tools you need instead of a server's whole surface. If you want the shortlist of servers worth the slots, start with the best MCP servers.

FAQ

Is SSE still safe to use, or do I need to migrate?

SSE still works and most clients keep backward compatibility, so an existing SSE connection won't break tomorrow. But it was deprecated in the March 2025 spec in favor of Streamable HTTP, so don't build anything new on it — migrate when you can, and prefer Streamable HTTP for any remote server going forward.

What's the difference between MCP SSE and Streamable HTTP?

Streamable HTTP is the newer transport that replaced the old HTTP+SSE one. SSE used two separate endpoints (a stream endpoint plus a POST endpoint); Streamable HTTP uses a single endpoint that returns either a plain JSON response or an SSE-formatted stream as needed. Same use case — remote servers — but simpler and current.

Should I run a server over stdio or HTTP?

Use stdio if the server runs on your own machine — it's the default and covers roughly 90% of servers. Use Streamable HTTP only when the server is genuinely remote or hosted. Location decides it, not preference.

Does the transport affect performance or which tools I get?

No. Transport only moves the same JSON-RPC messages over a different pipe — a server exposes identical tools over stdio or HTTP. Your real constraint is the ~40-tool client budget, which is unaffected by transport choice.

Can one server support more than one transport?

Yes, and many do. The GitHub MCP Server and Exa Search both offer a local stdio mode and a hosted remote endpoint, so you pick the transport per install rather than per server.

Put this into practice

Browse MCP servers by capability, or check your own setup's tool budget and security.

More essays