环境准备
开发 MCP Server 需要以下环境。本章以 TypeScript + Node.js 为主,同时介绍 Python SDK 的对应写法。
Node.js 环境要求
- Node.js 18.0 或更高版本(推荐 LTS 版本 20+)
- npm 9+ 或 pnpm 8+(推荐 pnpm,速度更快)
- TypeScript 5.0+(通过 tsx 直接运行 .ts 文件)
# 检查 Node.js 版本 node --version # 应显示 v18.x 或更高 npm --version # 安装 pnpm(可选,但推荐) npm install -g pnpm # 安装 tsx(用于直接运行 TypeScript) npm install -g tsx
Python 环境要求
- Python 3.10 或更高版本
- uv 包管理器(推荐)或 pip
# 安装 uv(Python 包管理器) curl -LsSf https://astral.sh/uv/install.sh | sh # 检查 Python 版本 python3 --version # 应显示 3.10 或更高
@modelcontextprotocol/sdk 用法
Anthropic 官方提供了 TypeScript 和 Python 两个 SDK,封装了所有底层协议细节,让开发者只需关注业务逻辑。
@modelcontextprotocol/sdk(TypeScript)
官方 TypeScript/Node.js SDK,提供
McpServer、StdioServerTransport 等核心类,内置 Zod 类型验证。mcp(Python)
官方 Python SDK,提供
FastMCP 高级接口和低级 Server 类,支持装饰器风格定义 Tools。SDK 核心类概览
TypeScript SDK 核心类
McpServer— 高级 Server 封装Server— 低级 Server 类StdioServerTransport— stdio 传输SSEServerTransport— SSE 传输(旧)StreamableHTTPServerTransport— 新 HTTP 传输CallToolResult— 工具调用结果类型
Python SDK 核心类
FastMCP— 高级声明式接口Server— 低级 Server 类stdio_server()— stdio 上下文管理器@mcp.tool()— 工具装饰器@mcp.resource()— 资源装饰器@mcp.prompt()— 提示词装饰器
创建最简 MCP Server
步骤一:初始化项目
- 创建项目目录并初始化 npm
- 安装 MCP SDK 和必要依赖
- 配置 TypeScript
- 编写 Server 代码
- 测试运行
# 创建项目目录 mkdir my-first-mcp-server cd my-first-mcp-server # 初始化 package.json npm init -y # 安装 MCP SDK 和 Zod(参数验证) npm install @modelcontextprotocol/sdk zod # 安装 TypeScript 开发工具 npm install -D typescript @types/node tsx
步骤二:配置 tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
步骤三:编写 Server 主文件
创建 src/index.ts,这是一个包含两个工具的最简 MCP Server:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; // 创建 MCP Server 实例 const server = new McpServer({ name: "my-first-server", // Server 名称 version: "1.0.0", // Server 版本 }); // ─── 工具一:加法计算器 ─────────────────────────────────────── server.tool( "add", // 工具名称 "将两个数字相加并返回结果", // 描述(AI 据此决定何时调用) { a: z.number().describe("第一个数字"), b: z.number().describe("第二个数字"), }, async ({ a, b }) => ({ content: [{ type: "text", text: `${a} + ${b} = ${a + b}` }], }) ); // ─── 工具二:问候语生成器 ────────────────────────────────────── server.tool( "greet", "生成一条个性化问候语", { name: z.string().describe("要问候的人名"), language: z.enum(["zh", "en", "ja"]) .default("zh") .describe("语言:zh=中文 en=英文 ja=日文"), }, async ({ name, language }) => { const greetings = { zh: `你好,${name}!欢迎使用 MCP 协议。`, en: `Hello, ${name}! Welcome to MCP protocol.`, ja: `こんにちは、${name}さん!MCPプロトコルへようこそ。`, }; return { content: [{ type: "text", text: greetings[language] }], }; } ); // ─── 启动 Server ────────────────────────────────────────────── async function main() { const transport = new StdioServerTransport(); await server.connect(transport); // 注意:Server 运行时不要向 stdout 输出任何内容 // 所有日志应写入 stderr process.stderr.write("MCP Server started\n"); } main().catch(console.error);
重要:stdio 模式下禁止写入 stdout
使用 stdio 传输时,
stdout 是 MCP 协议消息的专用通道。任何非 JSON-RPC 消息的输出(包括 console.log)都会污染协议流,导致 Client 解析失败。调试日志必须写入 stderr 或文件。
Python 版本对比
同样的功能用 Python FastMCP 实现更加简洁:
from mcp.server.fastmcp import FastMCP mcp = FastMCP("my-first-server") @mcp.tool() def add(a: float, b: float) -> str: """将两个数字相加并返回结果""" return f"{a} + {b} = {a + b}" @mcp.tool() def greet(name: str, language: str = "zh") -> str: """生成一条个性化问候语""" greetings = { "zh": f"你好,{name}!", "en": f"Hello, {name}!", } return greetings.get(language, greetings["zh"]) if __name__ == "__main__": mcp.run() # 默认使用 stdio 传输
在 Claude Desktop 中注册测试
Claude Desktop 通过一个 JSON 配置文件来管理所有已注册的 MCP Server。
配置文件位置
macOS
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows
%APPDATA%\Claude\claude_desktop_config.jsonLinux
~/.config/Claude/claude_desktop_config.json配置文件格式
{
"mcpServers": {
"my-first-server": {
"command": "node",
"args": [
"/absolute/path/to/my-first-mcp-server/dist/index.js"
],
"env": {
"NODE_ENV": "production"
}
},
"another-server": {
"command": "python3",
"args": ["/path/to/server.py"]
}
}
}
开发模式使用 tsx
开发阶段不需要先编译,可以直接使用
tsx 运行 TypeScript 文件:
"command": "npx","args": ["tsx", "/path/to/src/index.ts"]
配置后重启 Claude Desktop
修改配置文件后,需要完全退出 Claude Desktop 并重新启动(不是最小化,是完全退出)。成功加载后,你会在 Claude 对话界面的输入框附近看到工具图标,表示 MCP Server 已就绪。
调试技巧
查看 MCP 日志
Claude Desktop 会将 MCP Server 的 stderr 输出记录到日志文件:
# macOS tail -f ~/Library/Logs/Claude/mcp-server-my-first-server.log # 查看所有 MCP 相关日志 ls ~/Library/Logs/Claude/
使用 MCP Inspector(最佳调试工具)
MCP Inspector 是官方提供的可视化调试工具,无需 Claude Desktop 就能直接测试 Server:
# 启动 MCP Inspector,连接到你的 Server npx @modelcontextprotocol/inspector node dist/index.js # 如果使用 tsx 直接运行 npx @modelcontextprotocol/inspector tsx src/index.ts
Inspector 会在浏览器打开一个 Web 界面,可以可视化查看 Server 的所有能力,并手动触发工具调用来测试返回值。
添加结构化日志
// 封装一个安全的日志函数,写入 stderr function log(level: string, message: string, data?: unknown) { const entry = { timestamp: new Date().toISOString(), level, message, data, }; process.stderr.write(JSON.stringify(entry) + "\n"); } // 使用示例 log("info", "Tool called", { tool: "add", params: { a, b } }); log("error", "File not found", { path: filePath });
常见问题排查
Server 未出现在 Claude 界面
检查配置文件 JSON 格式是否正确;确认命令路径使用绝对路径;查看 Claude 日志文件是否有启动错误。
工具调用无响应
确认没有向 stdout 输出非 JSON-RPC 内容;检查工具处理函数是否有未捕获的异常;使用 Inspector 直接测试工具。
JSON 解析错误
通常是 stdout 被污染导致。搜索代码中所有
console.log 调用,改为写入 stderr。