C.W.K.
Stream
Lesson 01 of 05 · published

stdio Transport

~22 min · stdio, subprocess, local, framing

Level 0Curious Reader
0 XP0/48 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

The simplest MCP transport is stdio: the host launches the server as a subprocess and they exchange JSON-RPC messages over the child's stdin/stdout pipes. There is no network, no port, no TLS. The host's lifecycle owns the server; when the host exits, the subprocess goes with it.

Framing on stdio is line-delimited JSON: each JSON-RPC message is exactly one line, terminated by a newline. The server MUST NOT print anything else to stdout — diagnostics, logs, and warnings go to stderr. A stray print() in your server code can corrupt the stream and hang the host. This is the single most common bug new MCP server authors hit.

Stdio is the right transport for personal tools: a calculator server, a personal-notes server, a local filesystem server you trust with your files. The model is "the user pays for what they install" — installing the server is the trust event, and once installed it lives at the user's permission level.

Stdio is the wrong transport for shared services. You cannot put a stdio server "on the network" because there is no network protocol; you cannot scale it because each client launches its own subprocess copy. The moment you want one server to back many users, you graduate to Streamable HTTP.

Code

Connecting to a stdio server (Python client)·python
from mcp.client.stdio import StdioServerParameters, stdio_client
from mcp.client.session import ClientSession

params = StdioServerParameters(command="uvx", args=["my-cool-server"])
async with stdio_client(params) as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()
        tools = await session.list_tools()
        print(tools)
Common stdio gotcha — print() corrupts the stream·python
# WRONG — pollutes stdout
@app.tool()
def add(a: int, b: int) -> int:
    print(f"Adding {a} + {b}")  # leaks to stdout, host now sees garbage
    return a + b

# RIGHT — diagnostics go to stderr (or a log file)
import sys
@app.tool()
def add(a: int, b: int) -> int:
    print(f"Adding {a} + {b}", file=sys.stderr)
    return a + b

External links

Exercise

Run any community MCP server over stdio and add a single misplaced print() statement to stdout in one of its tools. Watch the client hang or report a parse error. Now move it to stderr and watch everything heal. The fragility of stdout is something you only have to learn once.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.