Skip to main content
StudioMeyer
Build Your Own MCP Server: Step-by-Step with TypeScript
Back to Blog
AI & Automation April 3, 2026 8 min readby Matthias Meyer

Build Your Own MCP Server: Step-by-Step with TypeScript

Build an MCP server in under 30 minutes: from setup through tool definition to deployment. Using the official Anthropic SDK with practical code examples.

An MCP server is a program that exposes structured tools to AI models via the standardized Model Context Protocol. Using the official TypeScript SDK, you can build a working MCP server in under 30 minutes. This article covers every step: from setup to deployment.

MCP (Model Context Protocol) has become the de facto standard for AI tool integration since November 2024. Over 10,000 MCP servers already exist. But most developers use pre-built servers — missing the potential of building custom tools tailored to their exact needs.

What do I need to build an MCP server?

An MCP server requires three things: Node.js (version 18+), the official MCP SDK, and an MCP-compatible client for testing (Claude Desktop, Claude Code, or Cursor).

The basic structure is simple:

mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/server @modelcontextprotocol/node zod
npm install -D typescript @types/node
npx tsc --init

The SDK offers two transport options: stdio (local server, reads from stdin/stdout) and Streamable HTTP (remote server, runs as a web service). For getting started, we recommend stdio — it works immediately without any network setup.

How do I define tools in the MCP schema?

Tools are the core of every MCP server. A tool has a name, a description (which the AI model reads to decide whether to use the tool), and an input schema with Zod validation.

import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/node";
import { z } from "zod";

const server = new McpServer({
  name: "my-server",
  version: "1.0.0",
});

server.registerTool(
  "get_weather",
  {
    description: "Get current weather data for a city",
    inputSchema: z.object({
      city: z.string().describe("City name"),
    }),
  },
  async ({ city }) => {
    const res = await fetch(
      `https://wttr.in/${encodeURIComponent(city)}?format=j1`
    );
    const data = await res.json();
    const temp = data.current_condition[0].temp_C;
    return {
      content: [{ type: "text", text: `${city}: ${temp}°C` }],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

Important: The tool description determines whether the AI calls it. Write it from the model's perspective: "Get current weather data for a city" is better than "Weather API wrapper".

How do I connect the server to Claude Desktop?

After building (npx tsc), the server must be registered in the Claude Desktop config. The file is located at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["/path/to/my-mcp-server/dist/index.js"]
    }
  }
}

Restart Claude Desktop. A tool icon appears in the chat — your tool is now available. Test with: "What's the weather in Berlin?"

For Claude Code, it's even simpler:

claude mcp add my-server node /path/to/dist/index.js

What are the best practices for production MCP servers?

Going from prototype to production requires five measures:

  1. Error handling: MCP tools must never crash. Catch every error and return a readable message. The AI can work with "API unreachable", but not with a stack trace.

  2. Input validation: Zod validates automatically, but define tight schemas. z.string().max(100) instead of z.string(). AI models sometimes send unexpected inputs.

  3. Timeouts: External API calls need timeouts. AbortSignal.timeout(10_000) prevents hanging requests.

  4. Logging: Use server.sendLoggingMessage() instead of console.log. This routes logs to the MCP client, not the transport stream.

  5. Rate limiting: If your server calls external APIs, implement server-side rate limiting. AI models invoke tools more aggressively than human users.

How do I deploy an MCP server remotely?

For remote deployment, switch from stdio to Streamable HTTP transport. The current SDK uses NodeStreamableHTTPServerTransport:

import { createServer } from "node:http";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/server";
import {
  NodeStreamableHTTPServerTransport,
} from "@modelcontextprotocol/node";

const server = new McpServer({
  name: "my-server",
  version: "1.0.0",
});

// Register tools here (as above)

const transports = new Map<string, NodeStreamableHTTPServerTransport>();

createServer(async (req, res) => {
  if (req.url === "/mcp" && req.method === "POST") {
    const sessionId = req.headers["mcp-session-id"] as string | undefined;

    if (sessionId && transports.has(sessionId)) {
      await transports.get(sessionId)!.handleRequest(req, res);
      return;
    }

    // New session
    const transport = new NodeStreamableHTTPServerTransport({
      sessionIdGenerator: () => randomUUID(),
      onsessioninitialized: (sid) => transports.set(sid, transport),
    });
    transport.onclose = () => {
      if (transport.sessionId) transports.delete(transport.sessionId);
    };
    await server.connect(transport);
    await transport.handleRequest(req, res);
  }
}).listen(3100);

Clients connect via URL. In Claude Desktop:

{
  "mcpServers": {
    "my-server": {
      "url": "https://my-server.example.com/mcp"
    }
  }
}

Security: Remote MCP servers need authentication. The protocol supports OAuth 2.1 — or you can use API keys in the Bearer header. Without auth, your server is publicly accessible.

Conclusion

Building your own MCP server gives you full control over what tools your AI can use. The barrier to entry is low (one npm package, one file), the potential is high. Start with a simple tool, test it in Claude Desktop, and expand step by step.

Further reading: What is the MCP Protocol? | MCP Server Architecture | MCP Tools Installation Tutorial

Matthias Meyer

Matthias Meyer

Founder & AI Director

Founder & AI Director at StudioMeyer. Has been building websites and AI systems for 10+ years. Living on Mallorca for 15 years, running an AI-first digital studio with its own agent fleet, 680+ MCP tools and 5 SaaS products for SMBs and agencies across DACH and Spain.

mcptutorialtypescriptsdkserverbuild