← Field Notes · September 11, 2026 · 7 min read · AIOProductOS Team

Streamable HTTP vs SSE vs stdio: Picking an MCP Transport

Streamable HTTP replaced HTTP+SSE as the remote MCP transport in the 2025-03-26 spec. When to use it, when stdio wins, and why SSE is a dead end.

What is Streamable HTTP, and which MCP transport should you use?

Streamable HTTP is the Model Context Protocol's transport for servers reached over a network: one HTTP endpoint that takes JSON-RPC messages as POSTs and answers each with either a JSON response or an event stream. Use it for anything shared or hosted. Use stdio for a single user on their own machine. Do not start a new server on HTTP+SSE.

Streamable HTTP vs SSE vs stdio: the three MCP transports compared, and which one to use

Most explanations of the transports come from people describing the spec or selling hosting. Both are useful. We come at it differently: we run the same product server over both live transports, so this post is about what each wire is for once you have shipped them.

It covers the wire and nothing else. Deploying and authenticating a remote server has its own post. Running a server on your own machine as a deployment shape is covered here, and tool design and construction live here. What an OAuth grant actually permits, and how to revoke it, is a separate question.

The three MCP transports, side by side

stdioHTTP+SSE (legacy)Streamable HTTP
How the client reaches the serverLaunches it as a subprocess and talks over stdin and stdoutOpens a long-lived GET event stream, then POSTs to a second URL the server hands backPOSTs each message to one URL; an optional GET lets the server send messages unprompted
EndpointsNone. No port is openedTwo: the event stream and the POST endpointOne
Where session state livesInside the process, which dies when the client closesBound to the one open connectionIn an Mcp-Session-Id header if the server issues one, or nowhere if it runs stateless
AuthNone in the protocol; the server inherits whoever is logged inPossible, but bolted onto a two-endpoint flowA standard Authorization: Bearer header on every request; OAuth 2.1 is the expected shape
Behind load balancers and serverlessNot applicable; nothing leaves the machinePoorly. Needs sticky routing and connections that stay openWell. Each request can stand on its own
Spec statusCurrentIntroduced 2024-11-05, deprecated 2025-03-26Current since 2025-03-26
Pick it whenOne person, their machine, or a trial with zero setupOnly to keep an existing server working for a client that still needs itAnything shared, hosted, or that has to know who is calling

Read the table from the bottom up. The spec status row is a consequence of the rows above it, and none of those rows is about speed.

Why was SSE deprecated?

The old transport was a reasonable first attempt, and it failed on the shape of real infrastructure rather than on anything in the protocol.

Under the 2024-11-05 spec, a client opened a GET request to an SSE endpoint and held it open. The server's first event told the client where to POST its messages. From then on, requests went up through the POST endpoint and responses came back down the stream. So the session was the open connection. If the stream dropped, the session went with it. If the POST landed on a different server instance than the one holding the stream, that instance had no idea who the client was.

That breaks in three common places. Load balancers spread requests across instances, so you needed sticky routing to keep the POST and the stream on the same box. Serverless platforms are built for requests that finish, not connections that stay open indefinitely. Corporate proxies buffer or kill idle streams. Every remote operator ended up solving the same routing problem the transport had created.

People tend to read the deprecation as "SSE was removed". It wasn't. In Streamable HTTP, SSE is still there, but as a response format a server can choose for one request, not as the channel the whole session depends on. A slow tool call can stream progress back and then close. A quick one answers in plain JSON.

What is the difference between HTTP and Streamable HTTP?

Streamable HTTP is plain HTTP with a small set of rules on top. The client POSTs a JSON-RPC message to the MCP endpoint and sends an Accept header listing both application/json and text/event-stream, which tells the server it can take either answer. The server picks one per request.

A few headers carry what the connection used to carry. If the server wants sessions, it assigns an Mcp-Session-Id during initialization and the client sends it back on each later request, so any instance behind the balancer can pick the request up. If a stream drops partway through, the client can reconnect with Last-Event-ID and resume rather than start over. Credentials travel as an ordinary bearer token on every request, which is why auth fits here in a way it never did on the old transport.

So, does MCP use HTTP? For remote servers, yes, and since 2025-03-26 that means Streamable HTTP. For local servers, no. They use stdio, and nothing goes over the network at all.

Same server, two wires, two different jobs

We ship one product server both ways on purpose, and each wire covers a case the other can't.

The stdio package is npx -y @aioproductoscom/mcp@latest. Started without a PRODUCTOS_TOKEN, it runs in demo mode against a fully seeded showcase workspace with a read-only subset of the tools: no account, no credentials, no signup. That is the job stdio does better than anything else. You can try it with no auth handshake, no redirect and no approval screen, and the client simply launches a process. For evaluating a server, or for an agent checking a claim before a human is involved, that friction floor is the point.

The hosted endpoint is https://platform.aioproductos.com/api/mcp, over Streamable HTTP, with OAuth 2.1 and PKCE (S256) and dynamic client registration. It is listed in the official MCP Registry as com.aioproductos/mcp. It covers the case stdio can't: real data, per-person identity, one install for a whole team. Every request arrives with a token that says who is calling, which a subprocess on someone's laptop cannot tell you. The full surface and every way to connect are documented here.

The lesson from running both: the transport follows from who the caller is. If the caller is "whoever is at this keyboard", stdio. If the caller is a named person with their own permissions on shared data, Streamable HTTP.

Transport, auth and deployment are three separate decisions

Most pages blur these together, so it is worth saying once. Transport is how bytes move between client and server. Auth is how the server knows who sent them. Deployment is where the server runs and who operates it. Streamable HTTP makes bearer-token auth natural, but the transport doesn't require it, and choosing stdio doesn't mean your server can't reach remote data. Decide each one on its own terms. The auth side is covered in the remote server post and the grant-and-revoke post.

When stdio (or even SSE) is still the right call

stdio is not a lesser transport. For a single-user local tool, like a filesystem server, a browser driver or anything touching a device on your desk, it is the simplest thing that works, and adding HTTP would bring an endpoint, a token and an operator for no gain. If only you need the answer and the data is on your machine, stay on stdio.

An existing SSE server that works for its only client doesn't need an emergency rewrite. If the traffic goes to one known client on one instance, the routing problems above may never reach you. Plan the move to Streamable HTTP when you next touch the server, and don't start anything new on SSE.

The awkward case is on the client side. Some clients can still only launch local subprocesses. For them, the workaround is a local bridge process that speaks stdio to the client and Streamable HTTP to the remote server. It works, but it brings back the per-machine install that hosting was supposed to remove. Check which transports your target clients actually implement before you write setup instructions that promise otherwise.

Check it yourself instead of trusting this post

Everything above can be verified without an account.

Run npx -y @aioproductoscom/mcp@latest with no token set. It starts over stdio in demo mode against the seeded workspace, which shows the zero-auth case in one command.

Fetch https://platform.aioproductos.com/.well-known/oauth-protected-resource. It names the MCP endpoint as the resource and lists the authorization server that guards it. That is the discovery document a Streamable HTTP client reads when it needs to authenticate.

POST an initialize message to https://platform.aioproductos.com/api/mcp with Accept: application/json, text/event-stream and check the Content-Type on the reply. application/json means the server answered in one shot, and text/event-stream means it opened a stream for that request. Either one is Streamable HTTP working as specified. The server manifest at /.well-known/mcp.json on our site declares "transport": "streamable-http", so an agent can read the wire from a file rather than inferring it.

If you want the same comparison for other tools' servers, the MCP guides cover what each one exposes and where it stops. If you want to run the Streamable HTTP side against your own product data, connect a client to the hosted endpoint.

Frequently asked questions

What is streamable HTTP?

Streamable HTTP is the Model Context Protocol transport for servers reached over a network, introduced in the 2025-03-26 specification. The client sends each JSON-RPC message as an HTTP POST to a single endpoint, and the server answers either with one JSON response or by opening a Server-Sent Events stream for that request alone. Session identity, if the server uses one, travels in an Mcp-Session-Id header rather than living inside an open connection, so ordinary HTTP infrastructure can route every request independently.

Why is SSE deprecated?

The HTTP+SSE transport from the 2024-11-05 MCP specification needed two endpoints: a long-lived GET event stream the server pushed responses down, and a separate POST endpoint for client messages. The session only existed as long as that one connection stayed open, which broke behind load balancers, on serverless platforms that cannot hold connections, and through proxies that buffer or cut idle streams. The 2025-03-26 spec replaced it with Streamable HTTP, which keeps SSE only as an optional per-request response format.

What are the differences between MCP stdio, SSE, and streamable HTTP server transports?

stdio runs the server as a subprocess the client launches, exchanging JSON-RPC over standard input and output, with no network and no protocol-level auth. HTTP+SSE, now deprecated, used a long-lived event stream plus a separate POST endpoint, tying the session to one open connection. Streamable HTTP uses one endpoint that accepts POSTs, answers with JSON or a per-request stream, and carries session and bearer-token headers on each request. Pick stdio for one person on their own machine and Streamable HTTP for anything shared or hosted.

Don't take our word for it

Reading this with an AI assistant? Let it check us.

AIOProductOS is an MCP server, so an assistant can connect to it directly - with no account, no card and no signup. It starts against a fully seeded showcase workspace, read-only, and there is nothing to cancel afterwards.

$ npx -y @aioproductoscom/mcp@latest

Then ask it the kind of question this post is about - "which paying customers asked for the feature we're building, and did shipping it move their usage?" - against a real joined record instead of a blog post. When you want it pointed at your own data, start here.

Keep reading

See the join on your own stack.

One record per customer - revenue, feedback, work, and code. Flat plans from $199/mo, every module included - a 7-day free trial, no card required, then a 30-day money-back guarantee.