工具
使 LLM 能够通过您的服务器执行作
工具是模型上下文协议 (MCP) 中一个强大的原语,它使服务器能够向客户端公开可执行功能。通过工具,LLM 可以与外部系统交互、执行计算并在现实世界中采取行动。
一、概述
MCP 中的工具允许服务器公开可执行函数,这些函数可由客户端调用,并由 LLM 用于执行作。工具的关键方面包括:
- 发现:客户端可以通过终端节点列出可用工具
tools/list
- 调用:使用终端节点调用工具,其中服务器执行请求的作并返回结果
tools/call
- 灵活性:工具范围从简单的计算到复杂的 API 交互
与资源一样,工具由唯一名称标识,并且可以包含说明以指导其使用。但是,与资源不同的是,工具表示可以修改状态或与外部系统交互的动态操作。
特别注释
《模型上下文协议中文网》附注:工具在业务上的本质,就是你对外所提供的核心价值点之一(业务功能),最终计算之后以结果数据形式返回。理论上,完全可以统一成大“资源”概念,减少一级概念的复杂的。之所以明确区分,是希望业务表达清晰:
- 资源 → 我是“读取静态数据”的能力。
- 工具 → 我是“执行动态功能”的能力。
如果将 MCP 形象比如成一个工厂:
二、工具定义结构
每个工具都使用以下结构定义:
typescript
{
name: string; // 工具的唯一标识符(字符串类型)
description?: string; // (可选)对工具的简要人类可读描述
inputSchema: { // 工具输入参数的 JSON Schema 定义
type: "object", // 表示参数是一个对象类型
properties: { // 定义该对象的具体属性(参数)
}
}
}
三、实施工具
以下是在 MCP 服务器中实现基本工具的示例:
TypeScript 范例
下面是一个计算器工具
typescript
// 引入 MCP 协议的 Server 类,用于创建服务器
const server = new Server({
name: "example-server", // 定义服务器名称
version: "1.0.0" // 定义服务器版本
}, {
capabilities: {
tools: {} // 声明该服务器支持 tools(工具)功能
}
});
// 注册 ListToolsRequestSchema 请求的处理器,返回可用工具的列表
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "calculate_sum", // 工具名称,唯一标识
description: "Add two numbers together", // 工具描述,用于告诉用户工具用途
inputSchema: { // 工具的参数定义,符合 JSON Schema 规范
type: "object", // 参数是一个对象类型
properties: { // 参数具体属性定义
a: { type: "number" }, // 参数 a,是数字类型
b: { type: "number" } // 参数 b,是数字类型
},
required: ["a", "b"] // 必填参数,a 和 b 都是必填的
}
}
]
};
});
// 注册 CallToolRequestSchema 请求的处理器,用于执行指定工具
server.setRequestHandler(CallToolRequestSchema, async (request) => {
// 检查请求的工具名是否是 calculate_sum
if (request.params.name === "calculate_sum") {
// 从请求参数中提取 a 和 b 的值
const { a, b } = request.params.arguments;
// 返回工具执行结果,MCP 协议需要返回 content 数组
return {
content: [
{
type: "text", // 内容类型是文本
text: String(a + b) // 将计算结果转为字符串返回
}
]
};
}
// 如果请求的工具不存在,抛出错误
throw new Error("Tool not found");
});
四、示例工具模式
以下是服务器可以提供的工具类型的一些示例:
1、系统操作
与本地系统交互的工具:
typescript
{
name: "execute_command",
description: "运行 shell 命令",
inputSchema: {
type: "object",
properties: {
command: { type: "string" },
args: { type: "array", items: { type: "string" } }
}
}
}
2、API 集成
包装外部 API 的工具:
typescript
{
name: "github_create_issue",
description: "创建一个GitHub 问题",
inputSchema: {
type: "object",
properties: {
title: { type: "string" },
body: { type: "string" },
labels: { type: "array", items: { type: "string" } }
}
}
}
3、数据处理
转换或分析数据的工具:
typescript
{
name: "analyze_csv",
description: "分析一个 CSV 文件",
inputSchema: {
type: "object",
properties: {
filepath: { type: "string" },
operations: {
type: "array",
items: {
enum: ["sum", "average", "count"]
}
}
}
}
}
其他
《模型上下文协议中文网》附注:下面部分新手可先不关注
1、最佳实践
实施工具时:
- 提供清晰的描述性名称和说明
- 对参数使用详细的 JSON 架构定义
- 在工具描述中包含示例,以演示模型应如何使用它们
- 实施适当的错误处理和验证
- 使用进度报告进行长时间作
- 保持工具作的重点和原子性
- 记录预期返回值结构
- 实施适当的超时
- 考虑对资源密集型作进行速率限制
- 用于调试和监控的日志工具使用情况
2、安全注意事项
公开工具时:
输入验证
- 根据架构验证所有参数
- 清理文件路径和系统命令
- 验证 URL 和外部标识符
- 检查参数大小和范围
- 防止命令注入
存取控制
- 根据需要实施身份验证
- 使用适当的授权检查
- 审计工具使用情况
- 速率限制请求
- 监控滥用情况
错误处理
- 不要向客户端公开内部错误
- 记录与安全相关的错误
- 适当地处理超时
- 出错后清理资源
- 验证返回值
3、工具发现和更新
MCP 支持动态工具发现:
- 客户可以随时列出可用的工具
- 服务器可以在工具更改时使用
notifications/tools/list_changed
- 可以在运行时添加或删除工具
- 工具定义可以更新(但应谨慎进行)
4、错误处理
工具错误应在结果对象中报告,而不是作为 MCP 协议级错误报告。这允许 LLM 查看并可能处理错误。当工具遇到错误时:
- 在结果中设置为
isError``true
- 在数组中包含错误详细信息
content
以下是正确处理工具错误的示例:
TypeScript范例
typescript
try {
// 工具操作
const result = performOperation();
return {
content: [
{
type: "text",
text: `操作成功: ${result}`
}
]
};
} catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `操作错误: ${error.message}`
}
]
};
}
这种方法使 LLM 能够看到发生的错误,并可能采取纠正措施或请求人工干预。
5、测试工具
MCP 工具的全面测试策略应包括:
- 功能测试:验证工具是否使用有效输入正确执行,并适当地处理无效输入
- 集成测试:使用真实和模拟依赖项测试工具与外部系统的交互
- 安全测试:验证身份验证、授权、输入清理和速率限制
- 性能测试:检查负载、超时处理和资源清理下的行为
- 错误处理:确保工具通过 MCP 协议正确报告错误并清理资源