Same protocol, two very different deployments. An MCP server can be a program running on your own laptop, talking to the host through standard input and output — or a service on the internet serving thousands of users over HTTP. The messages are identical; almost everything else — authentication, security posture, operational burden — is not. This short lesson is how to choose, and the two questions that decide it.
The two transports
stdio — the server as a local subprocess
The host launches the server as a child process and they exchange JSON-RPC messages over stdin and stdout. No ports, no network exposure, no TLS to configure. The server runs with the user's own local permissions, so credentials typically come from the environment.
if __name__ == "__main__":
mcp.run() # stdio by default: reads stdin, writes stdoutThis is the most common setup for desktop and developer tooling — filesystem access, local git, a database on your machine. It's also the simplest to reason about: if the data never leaves the machine, neither should the protocol.
💡 The trap everyone hits once: on stdio, stdout is the wire. Any print() in your server corrupts the message stream and produces baffling parse errors. Logs go to stderr or a file — never stdout (lesson 8).
Streamable HTTP — the server as a network service
For remote servers, MCP uses streamable HTTP — HTTP-based messaging with streaming support. (Earlier revisions of the spec paired HTTP with SSE; knowing that history is worth a mark, because plenty of tutorials still show the older approach.)
Now the server is an ordinary internet-facing service, and inherits every ordinary obligation: authentication, per-user authorization, tenant isolation, rate limiting, TLS, logging, uptime. Nothing about MCP removes those — it just means the payloads happen to be JSON-RPC.
Wait — where do credentials come from?
This is the sharpest practical difference between the two.
stdio: the server is already running as the user, so it typically picks up credentials from the local environment — an environment variable, a config file, an existing session. There's no separate identity to establish, because the process is the user.
Remote HTTP: the server has no idea who is calling until told. It needs real authentication (commonly OAuth-based) and, just as importantly, per-user authorization — the tools must act with the calling user's permissions, not with a single powerful service account that can see everything.
A shared super-user token behind a multi-user MCP server is the classic security mistake — every user effectively inherits every permission the token has, and the model becomes a very cooperative way to exercise them.
What stays the same
The protocol itself: the same JSON-RPC messages, the same capability handshake, the same tools, resources and prompts. Your server's logic and tool definitions don't change with the transport — which is why a server can often move from local to remote with configuration rather than a rewrite.
That separation is the point of having a transport layer at all, and it's a clean thing to say in an interview: transport changes delivery and security posture, not semantics.
Choosing — just two questions
| Ask | If… | Then |
|---|---|---|
| Who else needs this? | just me, on this machine | stdio |
| Who else needs this? | a team, a company, or customers | remote HTTP |
| Does the data leave the machine? | no — local files, local database | stdio (don't create a network surface for nothing) |
| Does the data leave the machine? | yes — it's central, shared, multi-tenant | remote HTTP, with real auth and isolation |
Selection-round radar: "What transports does MCP support and when would you use each?" Answer: stdio for local subprocess servers (one user, local data, credentials from the environment); streamable HTTP for remote multi-user servers (real authentication, per-user authorization, rate limiting) — and note that streamable HTTP replaced the earlier HTTP+SSE approach.
Common mistakes
- Printing logs to stdout in a stdio server — corrupts the protocol stream.
- Exposing a local, single-user tool over HTTP and creating an attack surface for nothing.
- Running a multi-user remote server on one shared super-user token.
- Assuming a remote MCP server needs less hardening than any other internet-facing service.
- Citing HTTP+SSE as the current remote transport — it was superseded by streamable HTTP.
Quick recap
| stdio | Streamable HTTP | |
|---|---|---|
| Deployment | local subprocess of the host | remote network service |
| Users | one | many |
| Credentials | from the local environment | real auth (often OAuth) + per-user authorization |
| Extra duties | keep stdout clean | isolation, rate limits, TLS, audit logs, uptime |
| Protocol | identical — same messages, handshake and primitives | |
Practice Zone — PYQs from real selection rounds
Six MCQs and a routing task — pick the transport for four real deployments and justify each.
The stdio transport is used when:
Asked in

For a remote MCP server accessed over the network, the current transport is:
Asked in

How does authentication differ between the transports?
Asked in

Which is a genuine risk specific to remote MCP servers?
Asked in

For a personal developer tool that reads local files, the sensible transport is:
Asked in

What stays the same across transports?
Asked in

Hands-on task:
Pick stdio or remote HTTP for each, with reasoning: 1) a server exposing the developer's local git repo; 2) a company-wide server exposing the ticketing system to many employees' assistants; 3) a SaaS vendor letting customers connect their AI tools; 4) a server wrapping a local database on the user's laptop.
Asked in

FAQ
Can one server support both transports?
Usually yes — SDKs let you run the same server over stdio or HTTP, since the handlers are transport-agnostic. What must change is the security model: the HTTP deployment needs authentication and per-user authorization that the local one got for free.
Is stdio slower than HTTP?
No — local pipes are typically faster than a network round trip. Transport choice is about who needs access and where the data lives, not performance.
How do remote servers handle long-running operations?
Streaming support in the transport allows progressive responses, and long tasks are usually modelled as a start-then- poll pattern with an id rather than one blocking call — the same design you'd use for any slow API.
Next lesson: write one yourself — Lesson 5: Build an MCP Server →


