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.
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.
| stdio | Streamable HTTP | |
|---|---|---|
| Who runs it | the user, as a child process | you, on a host |
| Reaches local files | yes | no |
| Concurrent users | one per launched process | many on one deployment |
| Ship a fix | the user reinstalls | you deploy |
| Secrets live | on the user's disk, in their config | on your host |
| Install cost to the user | a runtime, a path, a config entry | a URL |
| Cost to you when nobody uses it | nothing | the host bill |
| Cancellation | a notifications/cancelled notification | close the request's response stream |
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
All MCP servers and prices · All guides · Buy the bundle $39