> ## Documentation Index
> Fetch the complete documentation index at: https://mcp.developerdoc.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 工具

<div id="enable-section-numbers" />

Model Context Protocol (MCP) 允许服务器公开可由语言模型调用的工具。工具使模型能够与外部系统交互，例如查询数据库、调用 API 或执行计算。每个工具都由名称唯一标识，并包含描述其 schema 的元数据。

## 用户交互模型

MCP 中的工具被设计为**模型控制**，这意味着语言模型可以基于其对上下文和用户提示的理解，自动发现并调用工具。

不过，实现可以自由地通过任何适合自身需求的界面模式公开工具；协议本身并不强制规定任何特定的用户交互模型。

<Warning>
  出于信任与安全及安全性考虑，**SHOULD** 始终让人类参与流程，并能够拒绝工具调用。

  应用 **SHOULD**：

  * 提供清楚说明哪些工具会暴露给 AI 模型的 UI
  * 在工具被调用时插入清晰的视觉指示
  * 针对操作向用户展示确认提示，确保人类参与流程
</Warning>

## 能力

支持工具的服务器 **MUST** 声明 `tools` 能力：

```json theme={null}
{
  "capabilities": {
    "tools": {
      "listChanged": true
    }
  }
}
```

`listChanged` 表示服务器是否会在可用工具列表变化时发出通知。

声明 `tools` 能力的服务器 **MUST** 响应 `tools/list` 请求，并返回当前对请求客户端可用的一组工具。该集合 **MAY** 为空，也 **MAY** 随时间变化（见[列表变化通知](#list-changed-notification)），但 **MUST NOT** 因连接不同或连接上其他请求的副作用而变化。该集合 **MAY** 随请求中提供的授权而变化，例如只返回调用方已授予 scope 允许的工具，因为凭据是逐请求输入，而不是连接状态。

服务器 **SHOULD** 以确定性顺序返回工具（即，当底层工具集合未变化时，请求之间保持相同顺序）。确定性顺序使客户端能够可靠地缓存工具列表，并在工具被纳入模型上下文时提高 LLM 提示缓存命中率。

## 协议消息

### 列出工具

为了发现可用工具，客户端会发送 `tools/list` 请求。此操作支持[分页](/specification/draft/server/utilities/pagination)和[缓存](/specification/draft/server/utilities/caching)。

**请求：**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "cursor": "optional-cursor-value"
  }
}
```

**响应：**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "tools": [
      {
        "name": "get_weather",
        "title": "Weather Information Provider",
        "description": "Get current weather information for a location",
        "inputSchema": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "City name or zip code"
            }
          },
          "required": ["location"]
        },
        "icons": [
          {
            "src": "https://example.com/weather-icon.png",
            "mimeType": "image/png",
            "sizes": ["48x48"]
          }
        ]
      }
    ],
    "nextCursor": "next-page-cursor",
    "ttlMs": 300000,
    "cacheScope": "public"
  }
}
```

<a id="calling-tools" />

### 调用工具

为了调用工具，客户端会发送 `tools/call` 请求：

**请求：**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "location": "New York"
    }
  }
}
```

**响应：**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "content": [
      {
        "type": "text",
        "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
      }
    ],
    "isError": false
  }
}
```

### 需要输入的工具结果

服务器 **MAY** 用 [`InputRequiredResult`](/specification/draft/basic/patterns/mrtr#inputrequiredresult) 响应 `tools/call`，表示在完成工具调用前需要额外输入。这遵循[多轮往返请求](/specification/draft/basic/patterns/mrtr#multi-round-trip-requests)机制。

使用输入响应重试请求时，客户端会在请求参数中包含 `inputResponses`，并在服务器提供时包含 `requestState`：

**需要输入的响应：**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "input_required",
    "inputRequests": {
      "github_login": {
        "method": "elicitation/create",
        "params": {
          "mode": "form",
          "message": "Please provide your GitHub username",
          "requestedSchema": {
            "type": "object",
            "properties": {
              "name": { "type": "string" }
            },
            "required": ["name"]
          }
        }
      }
    },
    "requestState": "eyJsb2NhdGlvbiI6Ik5ldyBZb3JrIn0..."
  }
}
```

**带输入响应重试：**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "location": "New York"
    },
    "inputResponses": {
      "github_login": {
        "action": "accept",
        "content": {
          "name": "octocat"
        }
      }
    },
    "requestState": "eyJsb2NhdGlvbiI6Ik5ldyBZb3JrIn0..."
  }
}
```

请注意，初始请求与重试之间的 JSON-RPC `id` **MUST** 不同。

<a id="list-changed-notification" />

### 列表变化通知

当可用工具列表变化时，已声明 `listChanged` 能力的服务器 **SHOULD** 向已打开 [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) 流且设置了 `toolsListChanged: true` 的客户端发送通知：

```json theme={null}
{
  "jsonrpc": "2.0",
  "method": "notifications/tools/list_changed"
}
```

## 消息流

```mermaid theme={null}
sequenceDiagram
    participant LLM
    participant Client
    participant Server

    Note over Client,Server: Discovery
    Client->>Server: tools/list
    Server-->>Client: List of tools

    Note over Client,LLM: Tool Selection
    LLM->>Client: Select tool to use

    Note over Client,Server: Invocation
    Client->>Server: tools/call
    Server-->>Client: Tool result
    Client->>LLM: Process result

    opt listChanged
      Client->>Server: subscriptions/listen (toolsListChanged: true)
      Server--)Client: notifications/subscriptions/acknowledged
      Note over Client,Server: Updates
      Server--)Client: notifications/tools/list_changed
      Client->>Server: tools/list
      Server-->>Client: Updated tools
    end
```

## 数据类型

### Tool

工具定义包括：

* `name`：工具的唯一标识符
* `title`：用于显示的可选人类可读工具名称。
* `description`：对功能的人类可读描述
* `icons`：用于在用户界面中显示的可选图标数组
* `inputSchema`：定义预期参数的 JSON Schema
  * 遵循 [JSON Schema 使用指南](/specification/draft/basic#json-schema-usage)
  * 如果不存在 `$schema` 字段，则默认为 2020-12
  * **MUST** 是有效的 JSON Schema 对象（不是 `null`）
  * 对于没有参数的工具，请使用以下有效方式之一：
    * `{ "type": "object", "additionalProperties": false }` - **推荐**：明确只接受空对象
    * `{ "type": "object" }` - 接受任何对象（包括带有属性的对象）
  * 属性 **MAY** 包含 [`x-mcp-header`](#x-mcp-header) annotation，用于将参数值公开为 HTTP 标头
* `outputSchema`：定义预期输出结构的可选 JSON Schema
  * 遵循 [JSON Schema 使用指南](/specification/draft/basic#json-schema-usage)
  * 如果不存在 `$schema` 字段，则默认为 2020-12
* `annotations`：描述工具行为的可选属性

<Warning>
  出于信任与安全及安全性考虑，除非工具 annotations 来自受信任服务器，否则客户端 **MUST** 将其视为不可信。
</Warning>

#### 工具名称

* 工具名称长度 **SHOULD** 在 1 到 128 个字符之间（含边界）。
* 工具名称 **SHOULD** 被视为区分大小写。
* **SHOULD** 仅允许以下字符：ASCII 大写和小写字母（A-Z、a-z）、数字（0-9）、下划线（\_）、连字符（-）和点（.）
* 工具名称 **SHOULD NOT** 包含空格、逗号或其他特殊字符。
* 工具名称 **SHOULD** 在服务器内唯一。
* 有效工具名称示例：
  * `getUser`
  * `DATA_EXPORT_v2`
  * `admin.tools.list`

<Note>
  工具名称唯一性限定在单个服务器内。聚合多个服务器工具的客户端或代理 **MAY** 遇到命名冲突（例如，两个服务器各自公开一个 `search` 工具），并且 **SHOULD** 实现消歧策略，例如为工具名称添加服务器标识符前缀。

  服务器 `name`（来自 `serverInfo`）不保证在服务器之间唯一，因此 **SHOULD NOT** 依赖它来消歧。
</Note>

#### x-mcp-header

`x-mcp-header` 扩展属性允许服务器在使用 [Streamable HTTP 传输](/specification/draft/basic/transports/streamable-http#custom-headers-from-tool-parameters)时，指定特定工具参数镜像到 HTTP 标头中。这使网络中间件（负载均衡器、代理、WAF）无需解析请求正文，就能基于参数值路由和处理请求。

`x-mcp-header` 属性直接放置在要镜像的属性的 JSON Schema 中。它的值指定结果 `Mcp-Param-{name}` HTTP 标头的名称部分。

**`x-mcp-header` 值的约束：**

* **MUST NOT** 为空
* **MUST** 匹配 HTTP field-name token 语法（`1*tchar`，[RFC 9110 Section 5.1](https://datatracker.ietf.org/doc/html/rfc9110#section-5.1)）
* **MUST NOT** 包含控制字符，包括回车（CR，`\r`）或换行（LF，`\n`）
* 在 `inputSchema` 中的所有 `x-mcp-header` 值之间，**MUST** 以大小写不敏感方式保持唯一
* **MUST** 仅应用于具有原始类型（integer、string、boolean）的参数。不允许用于类型为 `number` 的参数。Integer 值 **MUST** 位于使用 IEEE754 双精度浮点数表示的整数安全范围内（−2<sup>53</sup>+1 到 2<sup>53</sup>−1）
* **MAY** 应用于 `inputSchema` 中任意嵌套深度的属性，而不仅限于顶层属性

使用 Streamable HTTP 传输的客户端 **MUST** 拒绝任何 `x-mcp-header` 值违反这些约束的工具定义。拒绝意味着客户端 **MUST** 从 `tools/list` 的结果中排除无效工具。客户端在拒绝工具定义时 **SHOULD** 记录警告，并包含工具名称和拒绝原因。这确保单个格式错误的工具定义不会阻止其他有效工具被使用。使用其他传输（例如 stdio）的客户端 **MAY** 完全忽略 `x-mcp-header` annotations。

**带 `x-mcp-header` 的工具定义示例：**

```json theme={null}
{
  "name": "execute_sql",
  "description": "Execute SQL on Google Cloud Spanner",
  "inputSchema": {
    "type": "object",
    "properties": {
      "region": {
        "type": "string",
        "description": "The region to execute the query in",
        "x-mcp-header": "Region"
      },
      "query": {
        "type": "string",
        "description": "The SQL query to execute"
      }
    },
    "required": ["region", "query"]
  }
}
```

在此示例中，当工具以 `"region": "us-west1"` 被调用时，客户端会向 HTTP 请求添加标头 `Mcp-Param-Region: us-west1`。

<Warning>
  服务器开发者 **SHOULD NOT** 使用 `x-mcp-header` 标记敏感参数（密码、API key、token、PII），因为标头值对网络中间件可见。
</Warning>

### Tool Result

工具结果可以包含[**结构化**](#structured-content)内容或**非结构化**内容。

**非结构化**内容会在结果的 `content` 字段中返回，并且可以包含多个不同类型的内容项：

<Note>
  所有内容类型（文本、图像、音频、资源链接和嵌入式资源）都支持可选的
  [annotations](/specification/draft/server/resources#annotations)，用于提供受众、优先级和修改时间等元数据。这与资源和提示使用的 annotation 格式相同。
</Note>

#### 文本内容

```json theme={null}
{
  "type": "text",
  "text": "Tool result text"
}
```

#### 图像内容

```json theme={null}
{
  "type": "image",
  "data": "base64-encoded-data",
  "mimeType": "image/png",
  "annotations": {
    "audience": ["user"],
    "priority": 0.9
  }
}
```

#### 音频内容

```json theme={null}
{
  "type": "audio",
  "data": "base64-encoded-audio-data",
  "mimeType": "audio/wav"
}
```

#### 资源链接

工具 **MAY** 返回指向[资源](/specification/draft/server/resources)的链接，以提供额外上下文或数据。在这种情况下，工具会返回一个可由客户端订阅或获取的 URI：

```json theme={null}
{
  "type": "resource_link",
  "uri": "file:///project/src/main.rs",
  "name": "main.rs",
  "description": "Primary application entry point",
  "mimeType": "text/x-rust"
}
```

资源链接支持与常规资源相同的[资源 annotations](/specification/draft/server/resources#annotations)，以帮助客户端理解如何使用它们。

<Info>
  工具返回的资源链接不保证会出现在 `resources/list` 请求的结果中。
</Info>

#### 嵌入式资源

[资源](/specification/draft/server/resources) **MAY** 使用合适的 [URI scheme](./resources#common-uri-schemes) 以内嵌方式提供额外上下文或数据。使用嵌入式资源的服务器 **SHOULD** 实现 `resources` 能力：

```json theme={null}
{
  "type": "resource",
  "resource": {
    "uri": "file:///project/src/main.rs",
    "mimeType": "text/x-rust",
    "text": "fn main() {\n    println!(\"Hello world!\");\n}",
    "annotations": {
      "audience": ["user", "assistant"],
      "priority": 0.7,
      "lastModified": "2025-05-03T14:30:00Z"
    }
  }
}
```

嵌入式资源支持与常规资源相同的[资源 annotations](/specification/draft/server/resources#annotations)，以帮助客户端理解如何使用它们。

#### Structured Content

**结构化**内容会作为 JSON 值在结果的 `structuredContent` 字段中返回。这可以是任何 JSON 值（对象、数组、字符串、数字、布尔值或 null），并且在定义了工具的 `outputSchema` 时符合该 schema。

为了向后兼容，返回结构化内容的工具 SHOULD 同时在 TextContent 块中返回序列化后的 JSON。

#### 输出 Schema

工具也可以提供输出 schema，用于验证结构化结果。如果提供了输出 schema：

* 服务器 **MUST** 提供符合此 schema 的结构化结果。
* 客户端 **SHOULD** 根据此 schema 验证结构化结果。

带输出 schema 的工具示例：

```json theme={null}
{
  "name": "get_weather_data",
  "title": "Weather Data Retriever",
  "description": "Get current weather data for a location",
  "inputSchema": {
    "type": "object",
    "properties": {
      "location": {
        "type": "string",
        "description": "City name or zip code"
      }
    },
    "required": ["location"]
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "temperature": {
        "type": "number",
        "description": "Temperature in celsius"
      },
      "conditions": {
        "type": "string",
        "description": "Weather conditions description"
      },
      "humidity": {
        "type": "number",
        "description": "Humidity percentage"
      }
    },
    "required": ["temperature", "conditions", "humidity"]
  }
}
```

此工具的有效响应示例：

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"temperature\": 22.5, \"conditions\": \"Partly cloudy\", \"humidity\": 65}"
      }
    ],
    "structuredContent": {
      "temperature": 22.5,
      "conditions": "Partly cloudy",
      "humidity": 65
    }
  }
}
```

带数组输出 schema 的工具示例：

```json theme={null}
{
  "name": "list_users",
  "title": "User List",
  "description": "Returns a list of all users",
  "inputSchema": {
    "type": "object",
    "properties": {}
  },
  "outputSchema": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "name": { "type": "string" },
        "email": { "type": "string" }
      },
      "required": ["id", "name", "email"]
    }
  }
}
```

带数组输出的工具的有效响应示例：

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Found 2 users: Alice (alice@example.com) and Bob (bob@example.com)."
      }
    ],
    "structuredContent": [
      { "id": "1", "name": "Alice", "email": "alice@example.com" },
      { "id": "2", "name": "Bob", "email": "bob@example.com" }
    ]
  }
}
```

提供输出 schema 有助于客户端和 LLM 通过以下方式理解并正确处理结构化工具输出：

* 启用对响应的严格 schema 验证
* 提供类型信息，以便更好地与编程语言集成
* 指导客户端和 LLM 正确解析和使用返回的数据
* 支持更好的文档和开发者体验

### Schema 示例

#### 使用默认 2020-12 schema 的工具：

```json theme={null}
{
  "name": "calculate_sum",
  "description": "Add two numbers",
  "inputSchema": {
    "type": "object",
    "properties": {
      "a": { "type": "number" },
      "b": { "type": "number" }
    },
    "required": ["a", "b"]
  }
}
```

#### 使用显式 draft-07 schema 的工具：

```json theme={null}
{
  "name": "calculate_sum",
  "description": "Add two numbers",
  "inputSchema": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "a": { "type": "number" },
      "b": { "type": "number" }
    },
    "required": ["a", "b"]
  }
}
```

#### 无参数工具：

```json theme={null}
{
  "name": "get_current_time",
  "description": "Returns the current server time",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false
  }
}
```

## 有状态工具

<Note>
  本节是关于工具设计的非规范性指导。协议没有状态句柄的概念；从线上传输视角看，句柄只是工具结果中的普通字符串，也是后续工具调用的普通参数。
</Note>

MCP 没有协议级 session，因此服务器不能依赖隐式的逐连接状态来关联一个工具调用和下一个工具调用。需要跨调用维护状态的服务器（购物车、打开的浏览器上下文、数据库事务等）应通过创建工具返回显式句柄，并在后续调用中接受该句柄作为参数。

例如，管理购物车的服务器可能会公开：

```jsonc theme={null}
// → tools/call
{ "name": "create_basket", "arguments": {} }

// ← result
{
  "content": [{ "type": "text", "text": "Created basket bsk_a1b2c3" }],
  "structuredContent": { "basket_id": "bsk_a1b2c3" }
}

// → tools/call
{
  "name": "add_item",
  "arguments": { "basket_id": "bsk_a1b2c3", "sku": "..." }
}
```

模型负责继续携带 `basket_id`；服务器将购物车内容存储在该键下，并在每次调用时查找。

设计句柄时，服务器应考虑：

* **Authorization。** 对于已认证服务器，句柄是名称而不是能力。服务器应在每次调用时根据句柄验证调用方授权。对于未认证服务器，句柄必然是 bearer token，因此应以足够熵生成（例如 UUIDv4）并设置有界生命周期。
* **Opacity。** 编码内部结构的句柄会诱使解析或猜测；不透明标识符不会。
* **Lifetime。** 由于句柄的生命周期超过任何单个连接，服务器的保留策略应在创建工具的描述中说明（例如，“baskets expire after 24 hours of inactivity”），以便模型在决定创建状态时能够看到。
* **Expiry errors。** 针对已过期或未知句柄的调用应返回说明该情况的工具执行错误，以便模型可以通过创建新句柄来恢复。

## 错误处理

工具使用两种错误报告机制：

1. **协议错误** 表示请求结构本身存在问题，模型通常不太可能修复：

   * 未知工具
   * 格式错误的请求（不满足 [CallToolRequest schema](/specification/draft/schema#calltoolrequest) 的请求）
   * 服务器错误

   它们以标准 JSON-RPC 错误形式返回：

   ```json theme={null}
   {
     "jsonrpc": "2.0",
     "id": 3,
     "error": {
       "code": -32602,
       "message": "Unknown tool: invalid_tool_name"
     }
   }
   ```

2. **工具执行错误** 包含可操作反馈，语言模型可用其自我修正并使用调整后的参数重试：

   * API 失败
   * 输入验证错误（例如日期格式错误、值超出范围）
   * 业务逻辑错误

   它们在工具结果中以 `isError: true` 报告：

   ```json theme={null}
   {
     "jsonrpc": "2.0",
     "id": 4,
     "result": {
       "content": [
         {
           "type": "text",
           "text": "Invalid departure date: must be in the future. Current date is 08/08/2025."
         }
       ],
       "isError": true
     }
   }
   ```

客户端 **MAY** 将协议错误提供给语言模型，但这类错误不太可能成功恢复。客户端 **SHOULD** 将工具执行错误提供给语言模型，以支持自我修正。

## 安全注意事项

1. 服务器 **MUST**：
   * 验证所有工具输入
   * 实现适当的访问控制
   * 对工具调用进行速率限制
   * 清理工具输出

2. 客户端 **SHOULD**：
   * 对敏感操作提示用户确认
   * 在调用服务器前向用户显示工具输入，以避免恶意或意外的数据外泄
   * 在传递给 LLM 前验证工具结果
   * 根据 `inputSchema` 和 `outputSchema` 验证工具输入与输出时，遵循 [`$ref` 解析要求](/specification/draft/basic/index#ref-resolution)
   * 为工具调用实现超时
   * 出于审计目的记录工具使用情况
