A production-ready MCP server: 6 core architecture rules
Six architectural decisions that turn Model Context Protocol servers from tutorial demos into production systems: server factories, dual transports, Zod validation and SSRF safeguards.
Most MCP (Model Context Protocol) tutorials stop at a single stdio tool, leaving out everything needed to run a server in production. This piece distills a reusable, production-grade MCP server template into six architectural principles, born from repeatedly rebuilding the same plumbing for real deployments.
The central idea is treating the server as a factory function rather than a singleton: in stateless HTTP mode a fresh instance is created per request, while stdio mode calls the same function once at startup. This lets a single codebase serve both editor clients like Claude Desktop or Cursor and a scalable remote HTTP server. Other principles include validating all configuration and tool inputs with Zod so failures surface as clear errors instead of silent bugs, and hardening network tools like fetch_url against SSRF with hostname allowlists, byte caps, and timeouts.
A particularly critical, often-missed rule is never logging to stdout in stdio mode, since that channel carries JSON-RPC traffic — a single stray log line corrupts the protocol stream and typically surfaces as a mysterious 'random disconnect' bug rather than an obvious logging error. For testing, the SDK's InMemoryTransport.createLinkedPair() lets a real client talk to a real server without sockets or separate processes, enabling fast, deterministic CI runs. Together these six rules form a practical checklist for turning an MCP server prototype into something safe to expose in production.