跳到主要内容

MCP 工具系统 (Tools)

Tools 是 MCP 服务器暴露的可执行函数。它们允许 AI 模型主动采取行动,如搜索数据库、查阅 API 或修改本地文件。

1. 核心原理

工具系统遵循“模型决定,宿主执行”的逻辑。

2. 工具定义规范

每个工具都必须通过 JSON Schema 严格定义其输入参数:

{
"name": "calculate_tax",
"description": "计算特定地区的消费税",
"inputSchema": {
"type": "object",
"properties": {
"amount": { "type": "number", "description": "原始金额" },
"region": { "type": "string", "enum": ["CN", "US", "EU"], "description": "地区代码" }
},
"required": ["amount", "region"]
}
}

关键字段说明

  • name: 唯一标识。建议使用 snake_case
  • description: 至关重要。这是 LLM 用于判断何时使用该工具的依据。描述越清晰,LLM 调用越准确。
  • inputSchema: 驱动 LLM 生成正确调用参数的结构定义。

3. 多样化的返回内容

工具不仅可以返回文本,还可以返回富媒体内容:

文本返回

{ "type": "text", "text": "计算结果为 105.00" }

图像返回 (Base64)

用于返回图表、截图等:

{
"type": "image",
"data": "iVBORw0KGgoAAA...",
"mimeType": "image/png"
}

工具可以执行搜索,并告知宿主进一步读取某个资源:

{
"type": "resource_link",
"uri": "file:///tmp/result_data.json",
"name": "结果详情"
}

4. 关键特性:人类参与 (Human-in-the-loop)

针对敏感操作,MCP 建议宿主实现以下交互模式:

  • 审批对话框:在执行 destructiveHint: true(如删除文件)的工具前提示用户。
  • 预授权设置:允许用户将特定的“只读”工具(如搜索)设置为始终放行。
  • 日志记录:宿主应记录所有工具调用的参数,供用户事后审查。

5. 开发实践:异常处理

在开发 Server 时,不要直接抛出代码层面的 Exception。应该使用 isError: true 来告诉 LLM 执行失败了,并给出友好提示。

TypeScript 推荐写法

try {
const data = await doSomething(args);
return { content: [{ type: "text", text: data }] };
} catch (e) {
return {
content: [{ type: "text", text: `操作失败: ${e.message}` }],
isError: true // 告诉模型这是业务失败,模型可能会尝试重试
};
}

6. 进阶:动态更新

如果你的工具列表是动态生成的(例如根据插件加载情况),你可以发送通知:

{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}

收到通知后,宿主(Client)会自动重新调用 tools/list 来刷新其能力库。

小结

  • 描述是关键指标:LLM 依赖 description 而非函数签名。
  • 支持多媒体结果:工具可以产出文本、图片和资源链接。
  • 安全性闭环:通过 annotations 辅助宿主进行风险控制。

练习

  1. 设计一个带有 idempotentHint: true(幂等)注解的数学查询工具。
  2. 编写一个返回包含文本和一张 Base64 图片的复合结果工具。