mcp-builder
MCP 服务器构建方法论 — 系统化构建生产级 MCP 工具,让 AI 助手连接外部能力
#mcp
Install
npx skills add https://github.com/jnMetaCode/superpowers-zh/tree/main/skills/mcp-builder
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install jnmetacode-superpowers-zh@llmmart
git clone https://github.com/jnMetaCode/superpowers-zh.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole jnmetacode/superpowers-zh collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
MCP 服务器构建
系统化设计、实现、测试和部署 Model Context Protocol 服务器的方法论。
1. 协议核心概念
MCP 定义三种原语:
- Tools(工具):AI 助手主动调用的函数,有副作用。如搜索、创建、删除操作。
- Resources(资源):AI 助手只读访问的数据源,用 URI 标识。如
users://{id}/profile。 - Prompts(提示词模板):预定义交互模板,引导用户触发工作流。
选择原则: 执行操作 → Tool | 读取数据 → Resource | 引导交互 → Prompt
2. 项目结构规范
TypeScript
my-mcp-server/
├── src/
│ ├── index.ts # 入口,注册 tools/resources
│ ├── tools/ # 按功能拆分
│ ├── resources/
│ └── lib/ # 客户端封装、校验逻辑
├── tests/
├── package.json
└── tsconfig.json
关键依赖:@modelcontextprotocol/sdk + zod
Python
my-mcp-server/
├── src/my_mcp_server/
│ ├── server.py
│ ├── tools/
│ └── lib/
├── tests/
└── pyproject.toml
关键依赖:mcp + pydantic
3. Tool 设计原则
命名
snake_case格式,动词开头:search_users、create_issue、delete_file- 名称自解释,AI 助手靠名称选工具,模糊命名导致误调用
参数
- 每个参数有类型约束和
.describe()描述 - 可选参数给默认值,减少 AI 决策负担
- 用枚举代替布尔开关
server.tool("search_issues", {
query: z.string().describe("搜索关键词"),
status: z.enum(["open", "closed", "all"]).default("open").describe("状态筛选"),
limit: z.number().min(1).max(100).default(20).describe("返回上限"),
}, async ({ query, status, limit }) => { /* ... */ });
描述
说明用途 + 返回内容 + 限制,这是 AI 选择工具的关键依据:
server.tool("search_users",
"根据姓名或邮箱搜索用户。返回 ID、姓名、邮箱列表。模糊匹配,最多 50 条。",
schema, handler);
输出
- 结构化数据 → JSON,人类可读内容 → Markdown
- 始终用
content: [{ type: "text", text: "..." }]格式返回
4. 输入验证和错误处理
用 Zod/Pydantic 做 Schema 级校验,业务级校验放 handler 开头:
server.tool("get_user", { id: z.string() }, async ({ id }) => {
try {
const user = await db.getUser(id);
if (!user) {
return {
content: [{ type: "text", text: `用户 ${id} 不存在,请检查 ID。` }],
isError: true,
};
}
return { content: [{ type: "text", text: JSON.stringify(user, null, 2) }] };
} catch (err) {
return {
content: [{ type: "text", text: `查询失败:${err.message}` }],
isError: true,
};
}
});
错误处理四原则:
- 永远不让服务器崩溃 — try/catch 包裹所有外部调用
- 返回可操作的错误信息 — 告诉 AI 问题是什么、能做什么
- 使用
isError: true— 让 AI 知道调用失败 - 区分错误类型 — 参数错误、权限不足、资源不存在、服务不可用
5. 资源管理和生命周期
// 资源注册
server.resource("user-profile", "users://{userId}/profile", async (uri) => {
const profile = await db.getProfile(extractId(uri));
return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(profile) }] };
});
// 生命周期:先初始化 → 再 connect → 监听关闭信号
const db = await Database.connect(config.dbUrl);
await server.connect(new StdioServerTransport());
process.on("SIGINT", async () => { await db.disconnect(); await server.close(); process.exit(0); });
关键点:使用连接池、所有外部调用设超时、优雅关闭清理资源。
6. 测试策略
单元测试 — 业务逻辑与 MCP 注册分离
// tools/search.ts 导出纯函数
export async function searchUsers(query: string, limit: number) { /* ... */ }
// search.test.ts 独立测试
test("返回匹配结果", async () => {
const results = await searchUsers("alice", 10);
expect(results[0].name).toContain("Alice");
});
集成测试 — 用 SDK Client 做端到端验证
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
const client = new Client({ name: "test", version: "1.0.0" });
await client.connect(clientTransport);
const result = await client.callTool("search_users", { query: "test" });
expect(result.isError).toBeFalsy();
MCP Inspector — 交互式调试
npx @modelcontextprotocol/inspector node dist/index.js
在浏览器中查看所有 tools/resources,手动调用并查看结果。
测试要点: 每个 Tool 覆盖正常 + 异常路径、边界值、外部服务失败模拟。
7. 安全考虑
权限控制:
- 最小权限原则,读写 Tool 分离
- 危险操作要求确认参数(如
confirm: true)
输入安全:
- SQL 注入 → 参数化查询,绝不拼接
- 路径遍历 → 校验路径,禁止
../ - 命令注入 → 用
execFile而非exec
敏感数据:
- 密钥通过环境变量传入,不硬编码
- 日志不打印完整敏感信息
- 返回数据做脱敏处理
沙箱: 文件操作限制目录、网络请求限制白名单、设置资源配额。
8. 部署和分发
npm 发布
{ "bin": { "mcp-server-myservice": "dist/index.js" }, "files": ["dist"] }
用户配置:
{ "mcpServers": { "myservice": { "command": "npx", "args": ["@yourorg/mcp-server-myservice"], "env": { "API_KEY": "xxx" } } } }
pip 发布
[project.scripts]
mcp-server-myservice = "my_mcp_server.server:main"
Docker — 适用于复杂依赖或隔离场景
FROM node:20-slim
WORKDIR /app
COPY package*.json ./ && RUN npm ci --production
COPY dist ./dist
ENTRYPOINT ["node", "dist/index.js"]
9. 调试技巧
关键:MCP 用 stdio 通信,不能用 console.log,会破坏协议流。
// 错误
console.log("debug");
// 正确
console.error("[DEBUG]", info);
// 更好
server.sendLoggingMessage({ level: "info", data: "处理中" });
常见问题:
| 症状 | 原因 | 解决 |
|---|---|---|
| 启动无响应 | transport 未连接 | 检查 server.connect() |
| Tool 不出现 | 注册在 connect 之后 | 先注册再 connect |
| AI 不调用 Tool | 描述不清晰 | 改善名称和描述 |
| 参数总错 | Schema 不明确 | 添加 .describe() |
| 调用超时 | 外部服务慢 | 加超时和缓存 |
调试流程: Inspector 验证基本功能 → 手动调用确认输入输出 → 连接真实 AI 客户端观察调用模式 → 根据实际行为调整设计。
10. 构建检查清单
设计
- 明确 Tools vs Resources vs Prompts 分工
- Tool 命名
动词_名词,描述说明用途和返回内容 - 参数简洁,可选参数有合理默认值
实现
- 输入用 Zod/Pydantic 校验
- 外部调用有 try/catch 和超时
- 错误返回
isError: true并附可操作信息 - 不用
console.log(用 stderr 或 SDK 日志) - 敏感数据走环境变量
测试
- 核心逻辑有单元测试
- 有集成测试验证 MCP 协议交互
- 用 MCP Inspector 手动验证过
- 用真实 AI 客户端测试过
部署
- README 含安装和配置说明
- 提供客户端配置 JSON 示例
- 遵循 semver,无硬编码密钥
Files (superpowers-zh)
-
SKILL.md 7.8 KB
--- name: mcp-builder description: 在构建 MCP 服务器或 MCP 工具时使用 —— 系统化的生产级 MCP 构建方法论,覆盖工具设计、错误处理、传输层选择与测试,让 AI 助手连接外部能力 version: "1.0.0" license: MIT metadata: hermes: tags: [mcp, development] --- # MCP 服务器构建 系统化设计、实现、测试和部署 Model Context Protocol 服务器的方法论。 ## 1. 协议核心概念 MCP 定义三种原语: - **Tools(工具)**:AI 助手主动调用的函数,有副作用。如搜索、创建、删除操作。 - **Resources(资源)**:AI 助手只读访问的数据源,用 URI 标识。如 `users://{id}/profile`。 - **Prompts(提示词模板)**:预定义交互模板,引导用户触发工作流。 **选择原则:** 执行操作 → Tool | 读取数据 → Resource | 引导交互 → Prompt ## 2. 项目结构规范 ### TypeScript ``` my-mcp-server/ ├── src/ │ ├── index.ts # 入口,注册 tools/resources │ ├── tools/ # 按功能拆分 │ ├── resources/ │ └── lib/ # 客户端封装、校验逻辑 ├── tests/ ├── package.json └── tsconfig.json ``` 关键依赖:`@modelcontextprotocol/sdk` + `zod` ### Python ``` my-mcp-server/ ├── src/my_mcp_server/ │ ├── server.py │ ├── tools/ │ └── lib/ ├── tests/ └── pyproject.toml ``` 关键依赖:`mcp` + `pydantic` ## 3. Tool 设计原则 ### 命名 - `snake_case` 格式,动词开头:`search_users`、`create_issue`、`delete_file` - 名称自解释,AI 助手靠名称选工具,模糊命名导致误调用 ### 参数 - 每个参数有类型约束和 `.describe()` 描述 - 可选参数给默认值,减少 AI 决策负担 - 用枚举代替布尔开关 ```typescript server.tool("search_issues", { query: z.string().describe("搜索关键词"), status: z.enum(["open", "closed", "all"]).default("open").describe("状态筛选"), limit: z.number().min(1).max(100).default(20).describe("返回上限"), }, async ({ query, status, limit }) => { /* ... */ }); ``` ### 描述 说明**用途 + 返回内容 + 限制**,这是 AI 选择工具的关键依据: ```typescript server.tool("search_users", "根据姓名或邮箱搜索用户。返回 ID、姓名、邮箱列表。模糊匹配,最多 50 条。", schema, handler); ``` ### 输出 - 结构化数据 → JSON,人类可读内容 → Markdown - 始终用 `content: [{ type: "text", text: "..." }]` 格式返回 ## 4. 输入验证和错误处理 用 Zod/Pydantic 做 Schema 级校验,业务级校验放 handler 开头: ```typescript server.tool("get_user", { id: z.string() }, async ({ id }) => { try { const user = await db.getUser(id); if (!user) { return { content: [{ type: "text", text: `用户 ${id} 不存在,请检查 ID。` }], isError: true, }; } return { content: [{ type: "text", text: JSON.stringify(user, null, 2) }] }; } catch (err) { return { content: [{ type: "text", text: `查询失败:${err.message}` }], isError: true, }; } }); ``` **错误处理四原则:** 1. 永远不让服务器崩溃 — try/catch 包裹所有外部调用 2. 返回可操作的错误信息 — 告诉 AI 问题是什么、能做什么 3. 使用 `isError: true` — 让 AI 知道调用失败 4. 区分错误类型 — 参数错误、权限不足、资源不存在、服务不可用 ## 5. 资源管理和生命周期 ```typescript // 资源注册 server.resource("user-profile", "users://{userId}/profile", async (uri) => { const profile = await db.getProfile(extractId(uri)); return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(profile) }] }; }); // 生命周期:先初始化 → 再 connect → 监听关闭信号 const db = await Database.connect(config.dbUrl); await server.connect(new StdioServerTransport()); process.on("SIGINT", async () => { await db.disconnect(); await server.close(); process.exit(0); }); ``` 关键点:使用连接池、所有外部调用设超时、优雅关闭清理资源。 ## 6. 测试策略 ### 单元测试 — 业务逻辑与 MCP 注册分离 ```typescript // tools/search.ts 导出纯函数 export async function searchUsers(query: string, limit: number) { /* ... */ } // search.test.ts 独立测试 test("返回匹配结果", async () => { const results = await searchUsers("alice", 10); expect(results[0].name).toContain("Alice"); }); ``` ### 集成测试 — 用 SDK Client 做端到端验证 ```typescript const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); await server.connect(serverTransport); const client = new Client({ name: "test", version: "1.0.0" }); await client.connect(clientTransport); const result = await client.callTool("search_users", { query: "test" }); expect(result.isError).toBeFalsy(); ``` ### MCP Inspector — 交互式调试 ```bash npx @modelcontextprotocol/inspector node dist/index.js ``` 在浏览器中查看所有 tools/resources,手动调用并查看结果。 **测试要点:** 每个 Tool 覆盖正常 + 异常路径、边界值、外部服务失败模拟。 ## 7. 安全考虑 **权限控制:** - 最小权限原则,读写 Tool 分离 - 危险操作要求确认参数(如 `confirm: true`) **输入安全:** - SQL 注入 → 参数化查询,绝不拼接 - 路径遍历 → 校验路径,禁止 `../` - 命令注入 → 用 `execFile` 而非 `exec` **敏感数据:** - 密钥通过环境变量传入,不硬编码 - 日志不打印完整敏感信息 - 返回数据做脱敏处理 **沙箱:** 文件操作限制目录、网络请求限制白名单、设置资源配额。 ## 8. 部署和分发 ### npm 发布 ```json { "bin": { "mcp-server-myservice": "dist/index.js" }, "files": ["dist"] } ``` 用户配置: ```json { "mcpServers": { "myservice": { "command": "npx", "args": ["@yourorg/mcp-server-myservice"], "env": { "API_KEY": "xxx" } } } } ``` ### pip 发布 ```toml [project.scripts] mcp-server-myservice = "my_mcp_server.server:main" ``` ### Docker — 适用于复杂依赖或隔离场景 ```dockerfile FROM node:20-slim WORKDIR /app COPY package*.json ./ && RUN npm ci --production COPY dist ./dist ENTRYPOINT ["node", "dist/index.js"] ``` ## 9. 调试技巧 **关键:MCP 用 stdio 通信,不能用 `console.log`,会破坏协议流。** ```typescript // 错误 console.log("debug"); // 正确 console.error("[DEBUG]", info); // 更好 server.sendLoggingMessage({ level: "info", data: "处理中" }); ``` **常见问题:** | 症状 | 原因 | 解决 | |------|------|------| | 启动无响应 | transport 未连接 | 检查 `server.connect()` | | Tool 不出现 | 注册在 connect 之后 | 先注册再 connect | | AI 不调用 Tool | 描述不清晰 | 改善名称和描述 | | 参数总错 | Schema 不明确 | 添加 `.describe()` | | 调用超时 | 外部服务慢 | 加超时和缓存 | **调试流程:** Inspector 验证基本功能 → 手动调用确认输入输出 → 连接真实 AI 客户端观察调用模式 → 根据实际行为调整设计。 ## 10. 构建检查清单 ### 设计 - [ ] 明确 Tools vs Resources vs Prompts 分工 - [ ] Tool 命名 `动词_名词`,描述说明用途和返回内容 - [ ] 参数简洁,可选参数有合理默认值 ### 实现 - [ ] 输入用 Zod/Pydantic 校验 - [ ] 外部调用有 try/catch 和超时 - [ ] 错误返回 `isError: true` 并附可操作信息 - [ ] 不用 `console.log`(用 stderr 或 SDK 日志) - [ ] 敏感数据走环境变量 ### 测试 - [ ] 核心逻辑有单元测试 - [ ] 有集成测试验证 MCP 协议交互 - [ ] 用 MCP Inspector 手动验证过 - [ ] 用真实 AI 客户端测试过 ### 部署 - [ ] README 含安装和配置说明 - [ ] 提供客户端配置 JSON 示例 - [ ] 遵循 semver,无硬编码密钥
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.