Home · Guides

stdio or streamable HTTP

Choose stdio when the server needs the user's machine: their files, their clipboard, their local database, their credentials already on disk. Choose streamable HTTP when the server needs something you run: your API, your data, your rate limits, your ability to fix a bug without asking anyone to reinstall. Everything else follows from that.

What each one is

stdio. The client launches the server as a subprocess and talks to it over the subprocess's standard streams. One newline-delimited JSON-RPC message per line, stdin in, stdout out. There is no header layer at all; the protocol version and client capabilities travel inline in _meta.io.modelcontextprotocol/* in the message body.

Streamable HTTP. The server is an independent process exposing a single endpoint that accepts POST. Every client message is its own HTTP POST. The server answers each request with either one JSON object or an SSE stream scoped to that request, carrying progress notifications and then the final response. It was introduced in protocol version 2025-03-26 to replace the HTTP+SSE transport from 2024-11-05.

The comparison that decides it

stdioStreamable HTTP
Who runs itthe user, as a child processyou, on a host
Reaches local filesyesno
Concurrent usersone per launched processmany on one deployment
Ship a fixthe user reinstallsyou deploy
Secrets liveon the user's disk, in their configon your host
Install cost to the usera runtime, a path, a config entrya URL
Cost to you when nobody uses itnothingthe host bill
Cancellationa notifications/cancelled notificationclose the request's response stream

What breaks on stdio

Anything you print. The specification is explicit: the server MUST NOT write anything to stdout that is not a valid MCP message. One stray console.log, one dependency banner, one progress bar, and the client is parsing your greeting as JSON-RPC. Logging goes to stderr, which the client MAY capture, forward or ignore, and which clients are told not to read as an error signal on its own.

The environment. A desktop application launching a subprocess passes on a limited, platform-dependent subset of environment variables. The PATH your shell has is frequently not the PATH your client has, which is why spawn npx ENOENT is the single most common MCP failure report: GitHub's issue search returned 1,428 results for that exact phrase on 2026-09-08. Absolute paths fix it.

Shutdown. The client closes your stdin and waits. A server that does not exit on EOF gets escalated to SIGTERM and then SIGKILL on POSIX, or TerminateProcess on Windows. Honour EOF and you never meet the escalation.

What breaks on streamable HTTP

Origin, and DNS rebinding. Servers MUST validate the Origin header and answer an invalid one with 403. A local HTTP server without that check can be driven by any web page the user has open. Bind to 127.0.0.1 rather than 0.0.0.0 when running locally.

Client transport defaults. Cline falls back to the legacy SSE transport when type is omitted, so a correct streamable HTTP endpoint fails against a config that looks right. Claude Code reads a JSON entry that has a url but no type as a stdio server, skips it, and says so. Claude Code accepts streamable-http as an alias for http, so a config copied from a server's own docs works unchanged.

The revision boundary. Revision 2026-07-28 removed the GET stream endpoint and removed protocol-level sessions from streamable HTTP. Server-to-client interactions such as sampling, elicitation and roots are now embedded in results as input requests rather than sent as separate requests on a stream. A client written against 2025-03-26 through 2025-11-25 expects the old behaviour, so a server that must serve both needs the compatibility path described in the specification's backward compatibility section.

The headers a streamable HTTP request carries

POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather

Mcp-Method is required on all requests and Mcp-Name on tools/call, resources/read and prompts/get. They mirror fields that are already in the body, so an intermediary can route and inspect without parsing JSON. The body stays the source of truth. Clients MUST send an Accept header listing both application/json and text/event-stream, because either can come back.

What the registry chose

Counted on 2026-09-08 across 2,211 distinct servers in a paginated sample of the official registry: 1,985 declare a remote endpoint and 311 declare an installable package. Among the remote transports, streamable-http appeared 1,986 times and sse 68. So the published population has already moved to hosted servers over streamable HTTP, whatever the tutorials still show.

You can do both

97 servers in that sample declare both, which is the honest answer for most tools: the same handlers behind two entry points. This repository's 30 servers run as stdio subprocesses from a bundle and as streamable HTTP endpoints from one worker, off the same code. The only part that genuinely differs is where the data lives, and that is a product decision rather than a transport one.

Questions

Is SSE still a valid MCP transport?

HTTP+SSE was the 2024-11-05 transport and streamable HTTP replaced it in 2025-03-26. Streamable HTTP still uses SSE for a response stream, so the technology is not gone, but a server whose transport type is sse is speaking the old binding. In the registry sample it was 68 servers against 1,986.

Can a stdio server be remote?

Not as launched, but the framing travels. The specification says the stdio wire format is just newline-delimited JSON-RPC over a reliable bidirectional byte stream, and that custom transports over Unix domain sockets or TCP SHOULD reuse it rather than inventing framing. Only the process lifecycle rules are specific to standard streams.

Which one should a first server be?

stdio, unless the server needs a secret you cannot give away. It has no hosting bill, no auth to design and no uptime to hold, and you can convert it later because the handlers do not change.

Does streamable HTTP still have sessions?

Not at the protocol level after revision 2026-07-28, which removed them along with the GET stream endpoint. Anything you were storing per session now needs to be carried in the request or held by your own application.

How do I cancel a long tool call?

It differs by transport, which is easy to miss. On stdio the client sends notifications/cancelled with the request id. On streamable HTTP it closes the request's response stream, and no cancellation message is sent at all.

Related

All MCP servers and prices · All guides · Buy the bundle $39