Build an MCP server with TypeScript
Model Context Protocol (MCP) lets you expose tools, resources, and prompts to any compatible client (Claude Code, Cursor, Claude Desktop). This guide builds a TypeScript MCP server.
Prerequisites
- +Node 20+
- +Familiarity with TypeScript and stdio
- +An MCP client to test against
Step-by-Step
- 1
Scaffold the project
Use the official TypeScript SDK. It handles stdio transport, JSON-RPC framing, and schema validation.
mkdir my-mcp && cd my-mcp pnpm init pnpm add @modelcontextprotocol/sdk zod pnpm add -D typescript tsx @types/node - 2
Create the server
Server is the top-level construct. Register tools with name, description, and a Zod input schema.
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; const server = new Server({ name: 'weather', version: '0.1.0' }, { capabilities: { tools: {} } }); - 3
Register a tool
Tools are the most common primitive. Inputs are validated against your Zod schema before your handler runs.
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [{ name: 'get_weather', description: 'Get weather for a city', inputSchema: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'] } }], })); server.setRequestHandler(CallToolRequestSchema, async (req) => { const { city } = req.params.arguments as { city: string }; return { content: [{ type: 'text', text: `It is 72F in ${city}` }] }; }); - 4
Wire stdio transport
Stdio is the canonical transport for local MCP servers. The client spawns your process and pipes JSON-RPC.
const transport = new StdioServerTransport(); await server.connect(transport); - 5
Test with the inspector
The MCP Inspector is the dev loop. It connects to your server and lets you call tools interactively.
npx @modelcontextprotocol/inspector tsx ./src/index.ts - 6
Connect from Claude Code
Add the server to .mcp.json at your project root, then run claude in that directory.
{ "mcpServers": { "weather": { "command": "tsx", "args": ["/abs/path/to/src/index.ts"] } } }
Common Pitfalls
- !Logging to stdout corrupts the JSON-RPC stream. Always log to stderr.
- !Forgetting to declare capabilities means the client cannot discover your tools.
- !Slow startup (>2s) makes every Claude Code session sluggish.
Agent Hub
Run, monitor, and orchestrate your agent fleet from one dashboard. Built for multi-agent teams.
What's Next
- ->Add resources for read-only context.
- ->Add prompts for reusable templates.
- ->Publish to npm so others can run your server with npx.
