Building MCP Servers for AI Tools
Expose custom tools and resources to AI clients via the Model Context Protocol.
Why
MCP launched in November 2024; by December 2025 it had 97M+ monthly SDK downloads, and by September 2026 the npm SDK alone reached ~204M monthly downloads (5x growth in 9 months) with 10,000+ published servers. The Model Context Protocol (MCP) is an open standard that lets AI assistants (Claude, Cursor, etc.) interact with external tools, databases, and APIs.
Building an MCP server makes your custom capabilities available to any MCP-compatible client — no per-client integration needed. This is the bridge between AI reasoning and your real-world systems.
When
Build an MCP server when: you want AI to query your database or API; you need custom code execution (e.g., run tests, deploy); you want to share team-specific tools across AI clients; or you're integrating internal services with AI workflows. Don't build one for simple HTTP API calls — a prompt with curl examples is simpler.
How
Example
Common Problems
- ⚠Error: Cannot find module '@modelcontextprotocol/sdk' → run `npm install @modelcontextprotocol/sdk zod`; the SDK requires Node.js 18+.
- ⚠Transport errors: stdio servers must not write to stdout (use stderr for logs) — stdout is the protocol channel
- ⚠Tool call returns `{"error": "Invalid params"}` → validate the input schema with zod; common cause is missing required field or wrong type.
- ⚠Error: Cannot find module '@modelcontextprotocol/sdk' → run `npm install @modelcontextprotocol/sdk zod`; the SDK requires Node.js 18+.
- ⚠"Error: transport closed" / server not listed by client → verify the stdio/HTTP transport matches on both sides; check `npx @modelcontextprotocol/inspector` output.
Best Practices
- ✓Write clear tool descriptions — the AI uses them to decide when to call your tool
- ✓Use strict JSON Schema with 'required' fields — reduces AI hallucination of optional params
- ✓Return structured content (not just strings) — helps the AI parse results correctly
- ✓Log to stderr only — stdout is reserved for the MCP protocol in stdio transport
- ✓Test with the MCP Inspector (npx @modelcontextprotocol/inspector) before deploying
- ✓Document each tool with a usage example in the description for better AI utilization
FAQ
What is the Model Context Protocol (MCP)?
MCP is an open JSON-RPC standard for AI assistants to call external tools and read resources. A server exposes tools (functions) and resources (data); any MCP-compatible client (Claude, Cursor) can use them without per-client integration.
stdio vs SSE transport: which to use?
Use stdio for local servers launched by the client (simplest, no network). Use SSE for remote/shared servers hosted as an HTTP service that multiple clients or team members reach over the network. Start with stdio in development.
How do I register an MCP server with Claude Desktop?
Add an entry under `mcpServers` in your claude_desktop_config.json with the server's launch command (stdio) or URL (SSE), then restart Claude Desktop. Verify with the MCP Inspector (`npx @modelcontextprotocol/inspector`) first.
Why must stdio servers log to stderr only?
In stdio transport, stdout is the JSON-RPC protocol channel. Any console.log to stdout corrupts the message stream and breaks the client. Use console.error (stderr) for all logging.
How do I handle errors in an MCP tool?
Return { isError: true, content: [{ type: 'text', text: '...' }] } instead of throwing. Throwing crashes the client session; a typed error result keeps the client alive and lets the AI retry or report the failure.