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"
}
资源建议 (Resource Links)
工具可以执行搜索,并告知宿主进一步读取某个资源:
{
"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辅助宿主进行风险控制。
练习
- 设计一个带有
idempotentHint: true(幂等)注解的数学查询工具。 - 编写一个返回包含文本和一张 Base64 图片的复合结果工具。