MCP stdio vs Streamable HTTP: Choose a Transport
Use stdio when one host launches and owns a local MCP server process. Use Streamable HTTP when the server must run independently, serve remote clients, and sit behind a deliberate network, authentication, and operations boundary. Choose from topology first; streaming alone is not the deciding factor.
The transport decision matrix
| Decision signal | stdio | Streamable HTTP | Test before release |
|---|---|---|---|
| Process ownership | Client launches and supervises one server subprocess. | Server runs independently and can accept multiple client connections. | Startup, shutdown, crash, restart, and orphan handling. |
| Network boundary | No application network endpoint is required. | A single MCP HTTP endpoint is exposed through an owned network path. | Origin rejection, TLS termination, authentication, routing, and timeouts. |
| Deployment fit | Desktop clients, local developer tools, and packaged integrations. | Shared services, remote integrations, gateways, and separately scaled servers. | Version compatibility and client capability negotiation. |
| Message channel | Newline-delimited JSON-RPC on stdin and stdout; logs belong on stderr. | Each client message is an HTTP POST; a reply is JSON or a request-scoped event stream. | Framing, cancellation, malformed messages, disconnects, and proxy behavior. |
| Credentials | Inherited or locally brokered credentials need a narrow process scope. | Remote authorization, token validation, and per-request identity belong at the resource server. | Wrong audience, expired credentials, denied scopes, and redacted logs. |
| Isolation | OS process, user, working directory, and environment boundaries. | Service identity, tenant, network, gateway, and storage boundaries. | Cross-user, cross-tenant, and cross-server access attempts. |
What actually changes between the transports
stdio makes lifecycle part of the client
The official MCP stdio transport specification defines a client-launched subprocess that reads protocol messages from standard input and writes them to standard output. Each line is one JSON-RPC message. Diagnostic text can go to standard error, while non-protocol text on standard output violates the channel contract.
That shape is attractive when installation and server lifecycle belong to one host application. It removes HTTP deployment work, but it does not create a security boundary by itself. The child can still inherit environment variables, filesystem access, network access, and the host user's privileges. Restrict its working directory, credentials, executable origin, and allowed operations just as carefully as a remote service.
Streamable HTTP makes lifecycle and identity service concerns
The Streamable HTTP transport specification places the server in an independent process and exposes one MCP endpoint. Client messages travel as HTTP requests, and a response can be a JSON object or an event stream associated with that request. This supports remote topology and shared operations, but brings gateways, proxies, authentication, rate limits, deployment health, and network observability into the design.
The specification explicitly requires Origin validation for incoming connections and recommends localhost binding for locally exposed HTTP servers. Those controls address a different threat surface from stdio. If a local integration is switched to HTTP only to gain a familiar deployment shape, the team has created a network boundary that it must now defend and operate.
The protocol model stays recognizable
MCP's client-host-server architecture keeps security policy and connection coordination with the host while servers expose focused capabilities. Transport selection does not move authorization into the model, merge server trust zones, or make tool calls safe. It changes how protocol messages cross the boundary, not who is allowed to act.
Failure cases that expose a bad transport choice
- Choosing HTTP because “streaming is required.” stdio can carry progress messages; the real question is whether the server is a child process or an independently reachable service.
- Treating local as trusted. A malicious or compromised stdio executable can use inherited authority. Pin its origin and reduce its OS-level permissions.
- Putting logs on stdout. One debug line can corrupt stdio framing. Route diagnostics to stderr and test noisy dependencies.
- Exposing a local HTTP server on every interface. Bind narrowly, validate Origin, authenticate, and verify that a browser cannot reach the endpoint through DNS rebinding.
- Assuming a dropped stream means a failed action. A tool may have completed before the client disconnected. Give mutating calls idempotency and state readback.
- Ignoring version drift. Pin the supported MCP version and test negotiation and rejection. Do not infer compatibility from a successful network connection.
Whichever transport you choose, the companion MCP server testing checklist should exercise malformed input, permission denial, cancellation, partial failure, and restart behavior.
A transport implementation sequence
- Draw the topology. Name the host, client, server process, user or tenant, credential source, network hops, and side effects. If the server has an independent operator or many clients, start with HTTP; if its lifecycle is inseparable from one host, start with stdio.
- Write the channel contract. For stdio, specify executable, arguments, environment allowlist, framing, stderr capture, and shutdown. For HTTP, specify endpoint, TLS, Origin policy, authentication, timeouts, event-stream behavior, and gateway limits.
- Reduce authority. Scope filesystem and network access for the subprocess, or scope service tokens and tenant context for HTTP. Use the MCP OAuth authorization guide for the remote resource boundary.
- Test failure timing. Kill the child, interrupt a request, drop an event stream, return a malformed message, and retry a mutation. Verify the actual state rather than trusting the final response.
- Instrument ownership. Record client and server versions, request IDs, duration, cancellation, restart, and denied actions without logging secrets. The LLM observability guide shows how to join those signals to the user outcome.
- Revisit only when topology changes. Do not migrate transports for fashion. Migrate when process ownership, remote access, scaling, or trust boundaries change, then rerun contract and security tests.
Primary and official sources
- Model Context Protocol transport specification — official framing and transport responsibilities.
- MCP stdio specification and MCP Streamable HTTP specification — official channel, endpoint, and security requirements.
- MCP architecture specification — host, client, server, and security-boundary responsibilities.