SuperAPI AI 工具集

mcp-builder

编程与开发

查看项目

更新于 10-15 08:55

技能介绍

MCP 服务器构建

系统化设计、实现、测试和部署 Model Context Protocol 服务器的方法论。

  1. 协议核心概念

MCP 定义三种原语:

Tools(工具):AI 助手主动调用的函数,有副作用。如搜索、创建、删除操作。

Resources(资源):AI 助手只读访问的数据源,用 URI 标识。如 users://{id}/profile。

Prompts(提示词模板):预定义交互模板,引导用户触发工作流。

选择原则: 执行操作 → Tool | 读取数据 → Resource | 引导交互 → Prompt

  1. 项目结构规范

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

  1. 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: "..." }] 格式返回

  1. 输入验证和错误处理

用 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 知道调用失败

区分错误类型 — 参数错误、权限不足、资源不存在、服务不可用

  1. 资源管理和生命周期

// 资源注册 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); });

关键点:使用连接池、所有外部调用设超时、优雅关闭清理资源。

  1. 测试策略

单元测试 — 业务逻辑与 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 覆盖正常 + 异常路径、边界值、外部服务失败模拟。

  1. 安全考虑

权限控制:

最小权限原则,读写 Tool 分离

危险操作要求确认参数(如 confirm: true)

输入安全:

SQL 注入 → 参数化查询,绝不拼接

路径遍历 → 校验路径,禁止 ../

命令注入 → 用 execFile 而非 exec

敏感数据:

密钥通过环境变量传入,不硬编码

日志不打印完整敏感信息

返回数据做脱敏处理

沙箱: 文件操作限制目录、网络请求限制白名单、设置资源配额。

  1. 部署和分发

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"]

  1. 调试技巧

关键: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 客户端观察调用模式 → 根据实际行为调整设计。

  1. 构建检查清单

设计

明确 Tools vs Resources vs Prompts 分工

Tool 命名 动词_名词,描述说明用途和返回内容

参数简洁,可选参数有合理默认值

实现

输入用 Zod/Pydantic 校验

外部调用有 try/catch 和超时

错误返回 isError: true 并附可操作信息

不用 console.log(用 stderr 或 SDK 日志)

敏感数据走环境变量

测试

核心逻辑有单元测试

有集成测试验证 MCP 协议交互

用 MCP Inspector 手动验证过

用真实 AI 客户端测试过

部署

README 含安装和配置说明

提供客户端配置 JSON 示例

遵循 semver,无硬编码密钥