工具
工具是 LLM 可以调用的函数,用于执行操作。它们是服务端暴露可执行功能的主要机制。
注册工具
server->RegisterTool("get_weather",
ToolOptions{}.Description("获取某个位置的当前天气"),
[](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
std::string location;
if (ctx.Params().arguments) {
auto* v = ctx.Params().arguments->Find("location");
if (v) location = v->GetString();
}
CallToolResult result;
result.content.push_back(
TextContent{"text", location + "的天气是晴天。"});
return result;
});带注解的工具
ToolOptions opts;
opts.title = "删除文件";
opts.description = "按路径永久删除文件";
opts.destructive = true; // 标记为 destructive_hint
opts.idempotent = false;
server->RegisterTool("delete_file", opts,
[](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
// ...
});McpServerTool(可复用工具)
对于可复用的工具逻辑,可以显式创建 McpServerTool 对象:
auto tool = McpServerTool::Create("get_weather",
[](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
// ...
},
ToolOptions{}.Description("获取当前天气"));
server->RegisterTool(tool);基于 lambda 的 RegisterTool 重载是此方式的简写——两种形式等价。
ToolOptions 字段
所有 ToolOptions 字段:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name | optional<string> | — | 工具的注册名以 RegisterTool 的第一个参数(或 McpServerTool::Create 的 name 参数)为准,此字段当前未被消费 |
title | optional<string> | — | 人类可读的标题 |
description | optional<string> | — | 工具描述 |
input_schema | optional<JsonValue> | {"type":"object","properties":{}} | 输入参数的 JSON Schema |
output_schema | optional<JsonValue> | — | 结构化输出的 JSON Schema |
use_structured_content | bool | false | 选择启用结构化输出(将 output_schema 设为 {"type":"object"}) |
icons | vector<Icon> | — | 工具图标 |
meta | optional<JsonValue> | — | 附加元数据 |
execution | optional<ToolExecution> | — | 执行元数据(mode:Auto 等;可选 human_use 说明) |
注解字段(传播到 ToolAnnotations):
| 字段 | 类型 | 说明 |
|---|---|---|
destructive | optional<bool> | 标记工具为破坏性操作 |
idempotent | optional<bool> | 多次调用效果等同于一次 |
read_only_hint | optional<bool> | 工具不修改状态 |
open_world_hint | optional<bool> | 工具可能和外部系统交互 |
结构化内容
工具可以返回结构化 JSON 数据而非文本:
CallToolResult result;
result.content.push_back(TextContent{"text", "已处理。"});
result.structured_content = JsonValue::Parse(R"({
"records_updated": 42,
"duration_ms": 153
})");structured_content 字段是 2026-07-28 协议特性。在 ToolOptions 上设置 use_structured_content = true 以选择启用(将 output_schema 设为 {"type": "object"})。也可以直接设置 output_schema 以实现更精细的模式控制。
输入模式
通过 ToolOptions::InputSchema() 或直接设置工具的 input_schema:
auto schema = JsonValue::Parse(R"({
"type": "object",
"properties": {
"location": {"type": "string"},
"units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
})");
server->RegisterTool("get_weather",
ToolOptions{}.InputSchema(std::move(schema)),
[](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
// ...
});多轮工具请求(input_required)
工具处理程序可以在 CallToolResult 上设置 input_required,向客户端发起 MRTR(多轮往返请求)收集轮次,客户端通过 elicitation 收集输入后携带 requestState 重试调用:
CallToolResult result;
InputRequiredResult ir;
ElicitRequestParams params;
params.message = "请提供 API 密钥";
ir.input_requests["api_key"] = MakeInputRequestForElicitation(params);
result.input_required = std::move(ir);
return result; // 服务端自动签名 requestState(需配置 request_state_key)配置 ServerOptions::request_state_key 后,服务端在返回前自动为 input_required 结果签名 request_state;重试时篡改或过期的状态会在进入处理程序前被拒绝(-32602,data.reason="invalid_request_state")。完整协议流程见 MRTR。
任务化执行
将工具声明为任务模式后,tools/call 立即返回任务句柄(taskId),后台异步执行,客户端用 GetTask / PollTaskToCompletion 跟进(2025 与 2026 时代均可;2026 时代下任务状态通知按订阅路由,无订阅者时丢弃,客户端靠轮询取终态):
ToolExecution execution;
execution.mode = ToolExecutionMode::Task;
ToolOptions opts;
opts.execution = execution;
opts.description = "耗时较长的计算";
server->RegisterTool("slow_compute", opts,
[](const RequestContext<CallToolRequestParams>& ctx) -> CallToolResult {
// 轮询 ctx.IsCancellationRequested() 实现协作取消
// ...
});前提是 ServerOptions::task_store 已配置(任务持久化后端)。tasks/update 支持携带 inputResponses 回应任务执行中的输入请求(与 result 互斥)。任务句柄形态按时代区分:2026 时代扁平直写顶层 taskId/status,2025 时代保留嵌套 task 对象兼容(客户端双形态接受)。后台落终态语义:处理程序正常返回(含 is_error 结果)落 Completed,抛异常落 Failed 并以内联 error 透传错误载荷。扩展声明与 wire 语义见 扩展。