This article records a real MCP Server debugging session: every automated test of story-cli passed, yet in a real environment the MCP Server couldn't respond to any request at all. The root cause turned out to be 3 bugs, each touching low-level details of the Node.js process model and the stdio protocol.

TL;DR

If you're building an MCP Server (or any long-running process that speaks a stdio protocol), remember three iron rules:

Never call process.exit() inside a run() function — MCP Servers, --watch modes, and any other long-running command are not one-shot CLI tools. process.exit() kills the process before it even starts listening. If you must make an exception, extract the "long-running" abstraction (e.g. isLongRunning) instead of enumerating specific commands.

Never print debug logs to stdout — stdout is the MCP protocol channel. Any output that isn't JSON-RPC pollutes the message stream and makes the client unable to parse any response. Diagnostics belong on stderr.