DEV Community

Nebula
Nebula

Posted on

How to Build Your First MCP Server in 10 Minutes

You keep hearing about MCP servers but every tutorial throws you into multi-agent swarms and complex architectures. Here's the simplest possible MCP server -- one file, one tool, fully runnable in 10 minutes.

The Code

Create a new project and install the SDK:

mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
Enter fullscreen mode Exit fullscreen mode

Create server.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

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

server.registerTool(
  "get-weather",
  {
    title: "Get Weather",
    description: "Get current weather 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 current = data.current_condition[0];

    return {
      content: [
        {
          type: "text",
          text: `${city}: ${current.temp_C}°C, ${current.weatherDesc[0].value}`,
        },
      ],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Weather MCP server running on stdio");
Enter fullscreen mode Exit fullscreen mode

That's it. 30 lines. A fully functional MCP server.

What's Happening

Lines 1-3 import the three things every MCP server needs: McpServer to create the server instance, StdioServerTransport for the communication layer, and zod for input validation.

Lines 5-8 create your server with a name and version. These show up when AI clients discover your server.

Lines 10-31 register a single tool called get-weather. The inputSchema uses Zod to define and validate what the tool expects -- a city name as a string. The handler function fetches real weather data from wttr.in (a free API, no key needed) and returns it as a text content block.

Lines 33-35 wire up the stdio transport and start the server. Stdio means the AI client launches your server as a child process and communicates over stdin/stdout. This is how Claude Desktop, Cursor, and most local MCP clients work.

Connect It to Claude Desktop

Add this to your Claude Desktop config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "weather": {
      "command": "npx",
      "args": ["tsx", "/full/path/to/my-mcp-server/server.ts"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Restart Claude Desktop. Ask it "What's the weather in Tokyo?" and it will call your get-weather tool.

Test It Without a Client

You can also test directly from the terminal using the MCP Inspector:

npx @modelcontextprotocol/inspector npx tsx server.ts
Enter fullscreen mode Exit fullscreen mode

This opens a web UI where you can browse your server's tools and call them manually -- useful for debugging before connecting to an AI client.

What to Build Next

Now that you have a working server, swap the weather API for anything:

  • Database queries: Register a tool that runs read-only SQL against your dev database
  • Internal APIs: Wrap your company's REST endpoints as MCP tools
  • File operations: Let AI assistants read/search your project files

Each new tool is just another server.registerTool() call with a schema and a handler. The MCP SDK handles discovery, validation, and communication automatically.

The full TypeScript SDK has examples for HTTP transports, authentication, streaming, and multi-tool servers at github.com/modelcontextprotocol/typescript-sdk.


This is part of the AI Agent Quick Tips series -- short, code-first tutorials for developers building with AI tools.

Top comments (0)