MCP · Class 22 · Transports

How Client & Server
Actually Talk

A complete visual breakdown of MCP Transports — the roads that carry JSON-RPC messages between client and server.

Foundation

What is a Transport?

Every MCP conversation involves two parties — a Client (e.g. Claude, an IDE plugin) and a Server (a tool provider or data source). They need to exchange messages. The transport is the physical mechanism that carries those messages.

Think of it as the road between two houses. The houses stay the same — only the road changes. MCP supports two transports: stdio (direct OS pipe) and SSE (HTTP stream). Both carry identical JSON-RPC messages.

📬 JSON-RPC is the letter. The transport is how you deliver it.
Architecture Overview

MCP Stack — Where Transports Fit

Transports sit at the bottom of the MCP stack. Everything above them (Tools, Prompts, Sampling, Resources) is completely unaffected by which transport you choose.

CLIENT MCP Host (Claude / IDE) orchestrates tool use MCP Client manages server connections Protocol Layer JSON-RPC 2.0 messages stdio stdin/stdout SSE HTTP POST OS / Network Layer process spawning · sockets File system · APIs · Databases TRANSPORT CHANNEL stdio OS pipe · no network · client spawns server 1 client ↔ 1 server process SSE HTTP/1.1 · long-lived stream · server-first N clients ↔ 1 server same JSON-RPC messages travel through either channel SERVER MCP Server exposes capabilities Protocol Layer JSON-RPC 2.0 messages Tools call Prompts tmpl Rsrc data Sample LLM stdio stdin/stdout SSE SSE stream out Business Logic File system · APIs · Databases
Transport 1 of 2
Transport 1
stdio
Standard Input / Output — direct process pipe — the simplest transport

What it is

The client and server talk through a direct OS pipe — like two tin cans connected by a string. No internet, no port, no URL. Just raw stdin and stdout streams attached between a parent and child process.

The client spawns the server process itself — the server doesn't exist until the client starts it. Once spawned, they share a private pipe that no other process can interrupt or intercept.

Step-by-step

1Client executes the server as a child process (e.g. python server.py)
2OS creates two pipes: client→server (stdin) and server→client (stdout)
3Client sends JSON-RPC request by writing to server's stdin
4Server reads from stdin, parses the JSON-RPC message, executes the operation
5Server writes the JSON-RPC response to stdout — back to the client
6Client reads the response. Loop continues for next message.

When to use

Running everything on one machine
Server is a local script (server.py, server.js)
CLI tools, IDE plugins (VS Code ext), MCP Inspector
Learning MCP — zero config to get started
Dev/testing where you need fast iteration
🎙️ Whispering into someone's ear in the same room. No phone, no internet — completely private and instant.

Visual flowchart

CLIENT MCP Host / IDE ① spawn() SERVER child process ② OS PIPE CREATED private · no network · no port ③ write to stdin (JSON-RPC request) client writes reads stdin ④ process execute request ⑤ write to stdout (JSON-RPC response) writes stdout ⑥ reads result ✓ result delivered · ready for next message loop repeats for each request
Connection
Direct OS pipe
Clients
1 per server
Network
None needed
Server startup
Client spawns it
Latency
Near-zero
Setup
Zero config
Transport 2 of 2
Transport 2
SSE
Server-Sent Events over HTTP — the scalable, multi-client transport

What it is

The server runs as an independent HTTP service on a port — like a website. It doesn't need a client to start it. Clients connect over HTTP and maintain a long-lived SSE stream to receive responses in real-time.

SSE (Server-Sent Events) is a web standard where the server keeps an HTTP connection permanently open and pushes data down to the client. Requests go client→server via regular HTTP POST; responses come back through the open SSE stream.

Step-by-step

1Server starts independently and binds to a port (e.g. http://localhost:8000)
2Client makes HTTP GET to /sse — server keeps this connection permanently open
3Client sends JSON-RPC requests via HTTP POST to the server endpoint
4Server processes the request, sends response through the open SSE stream
5Client receives the streamed response. SSE connection stays open for future messages.
6Multiple clients connect simultaneously — each gets their own SSE stream, but one server handles all

When to use

Client and server on different machines
Multiple clients need to share one server
Building a production web app or remote API
Server must stay alive independently of any client
Deploying to cloud or scaling to many users
📻 A radio station on a frequency. The station (server) is always broadcasting. Anyone with a radio (client) can tune in. Many listeners, one transmitter.

Visual flowchart

SERVER ① starts, binds :8000 always running CLIENT A browser / app CLIENT B another app LISTENING SSE stream — Client A SSE stream — Client B processes each request independently + more clients... ② GET /sse ③ HTTP POST ④ SSE response ② GET /sse ③ HTTP POST ④ SSE response N clients share 1 server — each independent stream server keeps running even when clients disconnect network required — even for localhost HTTP headers add small overhead vs stdio SSE stream stays open for future messages no need to reconnect for every request
Connection
HTTP + URL
Clients
Many at once
Network
Required
Server startup
Runs on its own
Latency
HTTP overhead
Setup
Port + URL
How the layers relate

JSON-RPC vs Transports — Not Alternatives

These operate at completely different layers. JSON-RPC defines what the message says. stdio/SSE define how it travels. You always need both — like you need both a language and a postal system to send a letter.

LAYER 1 — WHAT IS SAID JSON-RPC 2.0 · {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{...}} · same format always The letter LAYER 2A — HOW IT TRAVELS (local) stdio · OS pipe · stdin → server → stdout → client · no network Hand-deliver LAYER 2B — HOW IT TRAVELS (network) SSE · HTTP · POST request → SSE stream back · network required Postal mail KEY INSIGHT: switching stdio ↔ SSE does NOT change the JSON-RPC messages — only the delivery path changes your tools, prompts, and business logic stay identical — only the transport init line in your server changes
Side-by-Side

Full Feature Comparison

FeaturestdioSSE
MechanismOS pipe (stdin / stdout)HTTP connection (URL + port)
Server startupClient spawns the serverServer runs independently; clients connect
Multiple clientsNo — 1 client per server processYes — many clients, one server
Network neededNo — zero network involvedYes — even localhost is a network socket
Client sends viawrites to stdinHTTP POST request
Server responds viawrites to stdoutlong-lived SSE stream
Connection lifetimelasts while client process runspersistent until client disconnects
SpeedVery fast — zero HTTP overheadSlightly slower — HTTP headers + TCP
Best forLocal tools, CLI, IDE plugins, testingWeb apps, remote servers, production
ComplexityDead simple — just run itNeeds server startup + port config
Real-world examplesMCP Inspector, VS Code extensions, scriptsDeployed AI assistants, cloud services
Which one to pick?

Decision Flowchart

START — Pick a Transport Same machine? client + server on same OS YES NO Multiple clients? share 1 server NO YES → Use SSE remote always needs network transport → Use stdio local · fast · zero setup needed → Use SSE multi-client · persistent server Not sure? → Start with stdio You can always migrate to SSE later — only the transport init line in your server changes REMEMBER: both transports carry the exact same JSON-RPC messages switching transport ≠ rewriting server logic · tools/prompts/resources stay identical
💡 The golden rule: Start with stdio. Zero network config, zero port setup — just run your script and you're talking MCP. When you outgrow it (multiple users, remote deployment), switching to SSE only changes the transport initialization line. Everything else stays the same.