tutorial12 min read

如何用 TypeScript 构建 MCP 服务器(分步教程)

使用官方 SDK 用 TypeScript 构建 MCP 服务器。涵盖 Zod schema 工具、资源、提示词、测试和 Claude Code/Cursor 配置。

William Wang
William Wang · 2026年4月9日

William Wang — TokRepo & GEOScore AI 创始人,专注 AI 开发者工具和搜索可见性。

如何用 TypeScript 构建 MCP 服务器(分步教程)

一句话答案

用 TypeScript 构建 MCP Server:安装 @modelcontextprotocol/sdk v1.29.0 和 zod@3,用 McpServer + StdioServerTransport 启动,registerTool 注册工具时用 Zod 定义 inputSchema 自动生成类型和验证。比 Python 版的优势是前端团队已有 TS 技术栈,零学习成本。

目录

学习如何使用官方 @modelcontextprotocol/sdk 用 TypeScript 构建 MCP 服务器,用 Zod 验证输入,并配置到 Claude Code 和 Cursor。

前置条件

  • Node.js 16+(推荐 18+)
  • npm 或 pnpm
  • 基本 TypeScript 知识

步骤 1 — 搭建项目

mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod@3
npm install -D @types/node typescript
mkdir src && touch src/index.ts

SDK 当前版本 @modelcontextprotocol/sdk v1.29.0。

步骤 2 — 创建基础服务器

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: "my-server", version: "1.0.0" });

server.registerTool(
  "add",
  {
    description: "Add two numbers",
    inputSchema: {
      a: z.number().describe("First number"),
      b: z.number().describe("Second number"),
    },
  },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }],
  }),
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("MCP Server running");
}

main().catch(console.error);

步骤 3 — 结构化输出

server.registerTool(
  "calculate-bmi",
  {
    description: "Calculate BMI",
    inputSchema: z.object({
      weightKg: z.number(),
      heightM: z.number(),
    }),
    outputSchema: z.object({
      bmi: z.number(),
      category: z.string(),
    }),
  },
  async ({ weightKg, heightM }) => {
    const bmi = weightKg / (heightM * heightM);
    const output = { bmi: Math.round(bmi * 10) / 10, category: bmi < 18.5 ? "偏轻" : bmi < 25 ? "正常" : "偏重" };
    return { content: [{ type: "text", text: JSON.stringify(output) }], structuredContent: output };
  },
);

步骤 4 — 测试

npm run build
npx @modelcontextprotocol/inspector node build/index.js

步骤 5 — 配置

Claude Code:claude mcp add --transport stdio my-server -- node /path/to/build/index.js

Cursor(.cursor/mcp.json):

{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["/path/to/build/index.js"]
    }
  }
}

重要:stdio 模式下不要用 console.log(),用 console.error() 打日志。

FAQ

Q: 用哪个 SDK 版本? A: v1.29.0 稳定版。v2 SDK 还在 pre-alpha,生产环境用 v1.x。

下一步

常见问题

TypeScript 和 Python 版 MCP Server 该选哪个?+

前端/全栈团队选 TypeScript(技术栈统一,类型系统更强),数据科学或后端 Python 团队选 Python(FastMCP 代码更简洁)。两者功能完全对等,MCP 协议是语言无关的 JSON-RPC,Claude Code 看不出来你用的哪种语言。

为什么 inputSchema 要用 Zod 而不是 JSON Schema?+

Zod 同时给你运行时验证和 TypeScript 类型推断——写一次 schema,既能在 LLM 调用时校验参数,又能让编辑器自动补全。直接写 JSON Schema 需要维护两份(schema + 类型),Zod 通过 z.infer 自动推导,零重复。

StdioServerTransport 和 HTTP transport 有什么区别?+

Stdio 是本地进程间通信,Claude Code 启动子进程后通过 stdin/stdout 传 JSON-RPC,最简单也最常用。HTTP transport 用于远程 MCP Server,支持多客户端但需要处理认证和网络。新项目先用 Stdio,有远程需求再升级。

构建后如何打包分发?+

用 tsc 编译成 dist/index.js,在 package.json 加 bin 字段指向它,然后 npm publish。用户可以用 npx your-mcp-server 直接运行,不用手动 clone 和 build。Claude Code 的 .mcp.json 里 command 填 npx,args 填包名即可。

如何调试 TypeScript MCP Server?+

用 MCP Inspector(npx @modelcontextprotocol/inspector node dist/index.js)打开 Web UI,可视化调用每个 Tool 并看返回值。开发时配合 tsx watch 自动重启,避免每次改代码都手动 build。生产问题用 stderr 日志,不要用 stdout(会污染 JSON-RPC 协议)。