引言
本文将从零开始,带你搭建一个完整的MCP Server。不需要任何MCP开发经验,只需要基本的编程基础。
环境准备
前置条件
# Node.js >= 18.x
node --version
npm --version
# 推荐使用 TypeScript
npm install -g typescript ts-node
创建项目
# 1. 创建项目目录
mkdir my-first-mcp-server
cd my-first-mcp-server
# 2. 初始化 npm 项目
npm init -y
# 3. 安装核心依赖
npm install @modelcontextprotocol/sdk zod
# 4. 安装开发依赖
npm install -D typescript @types/node
# 5. 配置 TypeScript
npx tsc --init --target es2022 --module nodenext --moduleResolution nodenext \
--outDir dist --rootDir src --declaration true --strict true
项目结构
my-first-mcp-server/
├── src/
│ ├── index.ts # 入口文件
│ ├── tools/ # 工具实现
│ │ ├── calculator.ts
│ │ └── weather.ts
│ └── utils/ # 工具函数
│ └── validation.ts
├── package.json
├── tsconfig.json
└── README.md
基础Server实现
最简单的Server
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
// 1. 创建Server实例
const server = new Server(
{
name: "hello-world-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// 2. 注册工具列表处理器
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "greet",
description: "向用户打招呼",
inputSchema: {
type: "object",
properties: {
name: {
type: "string",
description: "你的名字",
},
},
required: ["name"],
},
},
],
};
});
// 3. 注册工具调用处理器
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "greet") {
return {
content: [
{
type: "text",
text: `你好,${args.name}!欢迎来到MCP的世界!`,
},
],
isError: false,
};
}
throw new Error(`未知工具: ${name}`);
});
// 4. 启动Server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Hello World MCP Server running on stdio");
}
main().catch(console.error);
构建与运行
编译
# 编译TypeScript
npm run build
# 或者直接运行(开发模式)
npx ts-node src/index.ts
测试
使用MCP Inspector进行测试:
# 启动Inspector
npx @modelcontextprotocol/inspector \
node dist/index.js
# 浏览器访问
open http://localhost:5173
MCP Inspector界面提供:
- 连接测试
- 工具列表查看
- 工具调用测试
- 消息日志查看
配置文件集成
Claude Desktop配置
将MCP Server添加到Claude Desktop的配置中:
{
"mcpServers": {
"hello-world": {
"command": "node",
"args": ["/path/to/my-first-mcp-server/dist/index.js"]
}
}
}
配置文件位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
独立Client测试
也可以使用Python Client进行测试:
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def test_server():
server_params = StdioServerParameters(
command="node",
args=["dist/index.js"],
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# 列出工具
tools = await session.list_tools()
print(f"可用工具: {[t.name for t in tools.tools]}")
# 调用工具
result = await session.call_tool(
"greet",
arguments={"name": "小明"}
)
print(f"结果: {result}")
asyncio.run(test_server())
进阶:实现计算器Server
多工具Server
// src/tools/calculator.ts
import { z } from "zod";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
const CalculatorArgs = z.object({
operation: z.enum(["add", "subtract", "multiply", "divide"]),
a: z.number(),
b: z.number(),
});
export function registerCalculatorTools(server: Server) {
// 工具已在 ListToolsRequestSchema 中注册
// 这里仅实现计算逻辑
}
export function executeCalculator(args: unknown) {
const parsed = CalculatorArgs.parse(args);
const { operation, a, b } = parsed;
switch (operation) {
case "add":
return { result: a + b };
case "subtract":
return { result: a - b };
case "multiply":
return { result: a * b };
case "divide":
if (b === 0) throw new Error("除数不能为0");
return { result: a / b };
}
}
// src/index.ts (更新版)
const toolsRegistry = [
{
name: "calculate",
description: "执行数学运算。支持加(add)、减(subtract)、乘(multiply)、除(divide)",
inputSchema: {
type: "object",
properties: {
operation: {
type: "string",
enum: ["add", "subtract", "multiply", "divide"],
description: "运算类型",
},
a: { type: "number", description: "第一个操作数" },
b: { type: "number", description: "第二个操作数" },
},
required: ["operation", "a", "b"],
},
},
{
name: "greet",
description: "向用户打招呼",
inputSchema: {
type: "object",
properties: {
name: { type: "string", description: "你的名字" },
},
required: ["name"],
},
},
];
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: toolsRegistry,
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "greet":
return {
content: [{ type: "text", text: `你好,${args.name}!` }],
isError: false,
};
case "calculate":
try {
const result = executeCalculator(args);
return {
content: [{ type: "text", text: `结果: ${result.result}` }],
isError: false,
};
} catch (error) {
return {
content: [{ type: "text", text: `计算错误: ${error.message}` }],
isError: true,
};
}
default:
throw new Error(`未知工具: ${name}`);
}
});
生产部署
Docker化部署
# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
CMD ["node", "dist/index.js"]
# 构建Docker镜像
docker build -t my-mcp-server .
# 运行
docker run -i my-mcp-server
PM2进程管理
# 安装PM2
npm install -g pm2
# 启动
pm2 start dist/index.js --name my-mcp-server
# 查看日志
pm2 logs my-mcp-server
# 开机自启
pm2 startup
pm2 save
常见问题
Q: MCP Server如何接收输入?
A: MCP通过 stdio(标准输入输出)通信。Transport会自动处理JSON-RPC消息的读写。
Q: 如何调试MCP Server?
A: 推荐使用 @modelcontextprotocol/inspector 进行交互式调试,或通过 console.error 输出日志到stderr。
Q: MCP Server支持HTTP吗?
A: 是的!除了stdio,还支持SSE(Server-Sent Events)传输方式,适用于远程场景。
总结
搭建MCP Server的流程:
| 步骤 | 操作 | 工具/命令 |
|---|---|---|
| 1 | 初始化项目 | npm init, 安装SDK |
| 2 | 创建Server | 使用 Server 类 |
| 3 | 注册处理器 | setRequestHandler |
| 4 | 连接Transport | StdioServerTransport |
| 5 | 测试 | MCP Inspector |
| 6 | 部署 | Docker/PM2 |
下一步学习建议:
本文最后更新于 2024-07-05。