Skip to content

工具

使 LLM 能够通过您的服务器执行作

工具是模型上下文协议 (MCP) 中一个强大的原语,它使服务器能够向客户端公开可执行功能。通过工具,LLM 可以与外部系统交互、执行计算并在现实世界中采取行动。

image-20250306210530524

一、概述

MCP 中的工具允许服务器公开可执行函数,这些函数可由客户端调用,并由 LLM 用于执行作。工具的关键方面包括:

  • 发现:客户端可以通过终端节点列出可用工具tools/list
  • 调用:使用终端节点调用工具,其中服务器执行请求的作并返回结果tools/call
  • 灵活性:工具范围从简单的计算到复杂的 API 交互

资源一样,工具由唯一名称标识,并且可以包含说明以指导其使用。但是,与资源不同的是,工具表示可以修改状态或与外部系统交互的动态操作。

特别注释

《模型上下文协议中文网》附注:工具在业务上的本质,就是你对外所提供的核心价值点之一(业务功能),最终计算之后以结果数据形式返回。理论上,完全可以统一成大“资源”概念,减少一级概念的复杂的。之所以明确区分,是希望业务表达清晰

  • 资源 → 我是“读取静态数据”的能力。
  • 工具 → 我是“执行动态功能”的能力。

如果将 MCP 形象比如成一个工厂:

image-20250306212621945

二、工具定义结构

每个工具都使用以下结构定义:

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、最佳实践

实施工具时:

  1. 提供清晰的描述性名称和说明
  2. 对参数使用详细的 JSON 架构定义
  3. 在工具描述中包含示例,以演示模型应如何使用它们
  4. 实施适当的错误处理和验证
  5. 使用进度报告进行长时间作
  6. 保持工具作的重点和原子性
  7. 记录预期返回值结构
  8. 实施适当的超时
  9. 考虑对资源密集型作进行速率限制
  10. 用于调试和监控的日志工具使用情况

2、安全注意事项

公开工具时:

输入验证

  • 根据架构验证所有参数
  • 清理文件路径和系统命令
  • 验证 URL 和外部标识符
  • 检查参数大小和范围
  • 防止命令注入

存取控制

  • 根据需要实施身份验证
  • 使用适当的授权检查
  • 审计工具使用情况
  • 速率限制请求
  • 监控滥用情况

错误处理

  • 不要向客户端公开内部错误
  • 记录与安全相关的错误
  • 适当地处理超时
  • 出错后清理资源
  • 验证返回值

3、工具发现和更新

MCP 支持动态工具发现:

  1. 客户可以随时列出可用的工具
  2. 服务器可以在工具更改时使用notifications/tools/list_changed
  3. 可以在运行时添加或删除工具
  4. 工具定义可以更新(但应谨慎进行)

4、错误处理

工具错误应在结果对象中报告,而不是作为 MCP 协议级错误报告。这允许 LLM 查看并可能处理错误。当工具遇到错误时:

  1. 在结果中设置为isError``true
  2. 在数组中包含错误详细信息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 协议正确报告错误并清理资源