MCP 服务器构建方法论 — 系统化构建生产级 MCP 工具,让 AI 助手连接外部能力
56
66%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./skills/mcp-builder/SKILL.md系统化设计、实现、测试和部署 Model Context Protocol 服务器的方法论。
MCP 定义三种原语:
users://{id}/profile。选择原则: 执行操作 → Tool | 读取数据 → Resource | 引导交互 → Prompt
my-mcp-server/
├── src/
│ ├── index.ts # 入口,注册 tools/resources
│ ├── tools/ # 按功能拆分
│ ├── resources/
│ └── lib/ # 客户端封装、校验逻辑
├── tests/
├── package.json
└── tsconfig.json关键依赖:@modelcontextprotocol/sdk + zod
my-mcp-server/
├── src/my_mcp_server/
│ ├── server.py
│ ├── tools/
│ └── lib/
├── tests/
└── pyproject.toml关键依赖:mcp + pydantic
snake_case 格式,动词开头:search_users、create_issue、delete_file.describe() 描述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);content: [{ type: "text", text: "..." }] 格式返回用 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,
};
}
});错误处理四原则:
isError: true — 让 AI 知道调用失败// 资源注册
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); });关键点:使用连接池、所有外部调用设超时、优雅关闭清理资源。
// 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");
});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();npx @modelcontextprotocol/inspector node dist/index.js在浏览器中查看所有 tools/resources,手动调用并查看结果。
测试要点: 每个 Tool 覆盖正常 + 异常路径、边界值、外部服务失败模拟。
权限控制:
confirm: true)输入安全:
../execFile 而非 exec敏感数据:
沙箱: 文件操作限制目录、网络请求限制白名单、设置资源配额。
{ "bin": { "mcp-server-myservice": "dist/index.js" }, "files": ["dist"] }用户配置:
{ "mcpServers": { "myservice": { "command": "npx", "args": ["@yourorg/mcp-server-myservice"], "env": { "API_KEY": "xxx" } } } }[project.scripts]
mcp-server-myservice = "my_mcp_server.server:main"FROM node:20-slim
WORKDIR /app
COPY package*.json ./ && RUN npm ci --production
COPY dist ./dist
ENTRYPOINT ["node", "dist/index.js"]关键: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 客户端观察调用模式 → 根据实际行为调整设计。
动词_名词,描述说明用途和返回内容isError: true 并附可操作信息console.log(用 stderr 或 SDK 日志)12a4dc1
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.