Chapter 1 — The protocol leaks into your assumptions
Opening chapter · approx. 4 minute readSix months of shipping Model Context Protocol servers against real Claude clients — not tutorial fixtures, live ones with timeouts, retries, and customers downstream — and the same shape of bug keeps showing up. It is not the SDK. It is the protocol leaking into the assumptions you brought with you from the last stack.
The hello-world version is honest about almost nothing. tools/list returns. The example tool echoes a string. The client renders it. You ship. A week later a user runs the same tool while a background log writer flushes to stdout and the frame stream desynchronizes mid-call. The client throws a parse error; the agent retries on a connection that is already poisoned; your handler runs twice and creates two records. Nothing you wrote is wrong on its own. The shape of the protocol — newline-delimited JSON-RPC over a process pipe, no recovery semantics on the wire — does not forgive any of it.
The discipline is small and unglamorous. Treat stdout as a binary channel that belongs to one writer; redirect everything else to stderr before any other module loads. Wrap your top-level handler so the failure path always emits a valid JSON-RPC error envelope — -32603 as the catch-all, structured logs to stderr, no stack traces on the wire. Accept a client-generated idempotency_keyon anything that mutates state. Set an explicit timeout on every outbound I/O. Classify errors before you surface them. Truncate large results at the boundary so a single tool call never eats more than a tenth of the model’s context window.
None of those rules are clever. They are the version of production hygiene you already practice on HTTP services, applied to a transport that is less forgiving and a caller that does not ask before retrying. The reason this chapter exists is that the MCP ecosystem is young enough that most example code skips them, and the bugs they prevent only show up at the seams between your server and a client you do not control.
The rest of the Playbook walks the same discipline through schema versioning, transport selection, structured observability, and a deployment story that does not depend on anyone running tail -f in a tmux pane. The next section of this preview is the short version of the ten-tip checklist — same operator voice, fewer paragraphs, more rules.
