MCP: Building Production Tool Servers
The wire protocol that turns hardcoded tool registries into discoverable, versioned, independently-deployable services. The platform turn. JSON-RPC 2.0, stdio/HTTP+SSE, tools/resources/prompts, capability negotiation, JSON Schema validation, registry/discovery, production failure modes. With a real TypeScript MCP server.
The platform turn. Pi's four tools are compiled-in function references. Adding one means editing source, shipping a build, restarting. MCP externalizes tools into services. A vendor ships a server; the agent discovers it at runtime. This is the structural difference between a personal harness and a platform.
Three primitives, three trust boundaries. Tools (model-initiated, untrusted input, schema-validated). Resources (user/client-initiated, semi-trusted). Prompts (user-initiated, server-authored, trusted). Confusing them — exposing as a tool what should be a resource — is a security bug: the model can now act autonomously when it shouldn't.
Capability negotiation is the contract. The initialize handshake exchanges what both sides support. The session may only use the intersection. A client built once works against every server — present, future, third-party — using whatever subset both offer.
JSON Schema is the validation boundary, not documentation. additionalProperties: false is a security control — it prevents a steered model from injecting unexpected fields (e.g., a hidden bcc on send_email). The server re-validates on every call. Never trust the model or the client to validate.
Three error classes, three recovery paths. Unknown tool (model stops calling), validation failure (model retries with fixed args), execution failure (model retries or reports). Each returns a distinguishable isError payload. Conflating them produces a confused loop.
The four production failure modes: stdout corruption (a console.log on stdio breaks the stream), schema drift (version mismatch across servers), subscription flood (volatile resource drowns the context), no graceful shutdown (orphaned requests and leaked resources). Each has a known fix.