主题
工具定义格式规范
本文引用的源码文件
本文引用的文件
目录
引言
本规范面向 MCP(Model Context Protocol)工具的开发者与维护者,说明在 AI Helper Agent 与扩展端协作体系中,MCP 工具的定义格式、参数校验规则、返回结构、注册发现流程以及生命周期管理方式。文档以仓库中已实现的 MCP Client、MCP Registry、测试服务器和背景工具执行器为依据,避免臆造协议字段;对尚未实现的能力仅给出建议性说明,并明确标注来源。
项目结构定位
MCP 工具相关代码主要分布在以下位置:
- Agent 端 MCP 客户端与注册表:
agent/src/mcp/client.js、agent/src/mcp/registry.js、agent/src/mcp/mcp-config.js - MCP 测试服务器与工具定义样例:
agent/test/mcp-test-server.cjs - 扩展端背景脚本中的 MCP 工具注入与调用桥接:
src/background/tool-executor.js - Skill 参数校验参考实现:
agent/src/skill/executor.js - Skill 参数 Schema 示例:
agent/test/hello-world.skill.json、agent/test/project-report.skill.json - Agent 端 MCP API 文档摘要:
agent/README.md
graph TB subgraph "扩展端" BG["background/tool-executor.js<br/>动态注册 MCP 工具"] end subgraph "Agent 端" REG["mcp/registry.js<br/>工具注册与调用入口"] CLI["mcp/client.js<br/>MCP 客户端连接与工具调用"] CFG["mcp/mcp-config.js<br/>MCP Server 配置管理"] TEST["test/mcp-test-server.cjs<br/>MCP 测试服务器"] end BG --> REG REG --> CLI CLI --> TEST REG --> CFG
图表来源
- src/background/tool-executor.js#L590-L640
- agent/src/mcp/registry.js#L89-L127
- agent/src/mcp/client.js#L96-L157
- agent/src/mcp/mcp-config.js#L37-L64
- agent/test/mcp-test-server.cjs#L27-L85
章节来源
- agent/src/mcp/client.js#L1-L184
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/mcp-config.js#L1-L129
- agent/test/mcp-test-server.cjs#L1-L234
- src/background/tool-executor.js#L580-L779
核心概念与术语
- MCP Server:提供工具的外部服务,可通过 stdio、SSE、Streamable HTTP 或 WebSocket 与 Agent 通信。
- MCP Client:Agent 内部封装的 MCP 客户端实例,负责建立连接、获取工具列表、转发工具调用。
- MCP Registry:维护所有已连接 MCP Server 的工具集合,并提供统一查询与调用接口。
- Tool Definition:MCP Server 暴露的工具描述,包含名称、描述、输入参数 Schema。
- Tool Call:通过 MCP 协议调用的具体工具执行过程。
- Background Tool:扩展端将 MCP 工具包装为本地可执行函数,供 ReAct 推理循环使用。
章节来源
- agent/src/mcp/client.js#L35-L45
- agent/src/mcp/registry.js#L19-L20
- src/background/tool-executor.js#L597-L621
工具元数据定义
MCP 工具元数据由 MCP Server 通过 tools/list 返回,Agent 侧将其扁平化为统一结构后注入扩展端工具系统。
必需字段
| 字段 | 类型 | 是否必需 | 含义 | 备注 |
|---|---|---|---|---|
name | 字符串 | 是 | 工具唯一名称 | 用于 tools/call 指定目标工具 |
description | 字符串 | 否 | 工具用途说明 | 若为空,扩展端会降级使用工具名 |
inputSchema | 对象 | 否 | 输入参数的 JSON Schema | 未提供时默认视为空对象 |
扩展端映射字段
Agent 侧在 getMcpTools 中会为每个工具补充以下字段,便于扩展端展示与路由:
| 字段 | 类型 | 含义 |
|---|---|---|
serverId | 字符串 | 所属 MCP Server 标识 |
serverName | 字符串 | 所属 MCP Server 显示名称 |
name | 字符串 | 工具名称 |
description | 字符串 | 工具描述 |
inputSchema | 对象 | 输入参数 Schema |
classDiagram
class McpClient {
+string serverId
+string serverName
+boolean connected
+Array tools
+connect()
+callTool(toolName, args)
+disconnect()
}
class Registry {
+Map clients
+initializeMcpRegistry()
+getMcpTools(serverId)
+callMcpTool(serverId, toolName, args)
+shutdownMcpRegistry()
}
class TestServer {
+Array TOOLS
+handleRequest(request)
}
Registry --> McpClient : "管理多个实例"
McpClient --> TestServer : "通过 MCP 协议调用"
图表来源
- agent/src/mcp/client.js#L35-L45
- agent/src/mcp/registry.js#L89-L127
- agent/test/mcp-test-server.cjs#L27-L85
章节来源
参数 Schema 规范
MCP 工具的输入参数采用 JSON Schema 风格定义。当前实现中,Agent 侧对 inputSchema 的处理偏保守:如果 MCP Server 未返回 inputSchema,则默认使用 { type: 'object', properties: {} }。
推荐的最小结构
| 字段 | 类型 | 是否必需 | 说明 |
|---|---|---|---|
type | 字符串 | 否 | 通常为 object |
properties | 对象 | 否 | 参数键到属性定义的映射 |
required | 字符串数组 | 否 | 必填参数列表 |
description | 字符串 | 否 | 参数整体说明 |
属性定义常用字段
| 字段 | 类型 | 说明 |
|---|---|---|
type | 字符串 | 如 string、number、boolean、object |
description | 字符串 | 参数用途说明 |
enum | 数组 | 可选值枚举 |
default | 任意类型 | 默认值(Agent 侧未强制校验,建议由 MCP Server 处理) |
验证行为
- Agent 侧不会在 MCP 调用前对参数做严格 JSON Schema 校验。
- 参数校验主要由 MCP Server 自行实现;Agent 侧只负责转发
arguments。 - Skill 系统的参数校验可作为参考:它支持
type、required、基础类型转换,但不等同于 MCP 参数校验器。
flowchart TD
Start(["收到工具调用"]) --> HasSchema{"是否存在 inputSchema?"}
HasSchema --> |否| UseDefault["使用默认空对象 Schema"]
HasSchema --> |是| UseProvided["使用 MCP Server 提供的 Schema"]
UseDefault --> ForwardArgs["向 MCP Server 转发 arguments"]
UseProvided --> ForwardArgs
ForwardArgs --> ServerValidate{"MCP Server 是否校验参数?"}
ServerValidate --> |是| ServerResult["返回成功或错误结果"]
ServerValidate --> |否| RawResult["直接执行业务逻辑"]
ServerResult --> Normalize["转换为统一返回结构"]
RawResult --> Normalize
Normalize --> End(["返回给扩展端"])
图表来源
- agent/src/mcp/registry.js#L100-L103
- agent/src/mcp/client.js#L129-L157
- agent/src/skill/executor.js#L320-L342
章节来源
返回值格式规范
MCP 工具调用最终由扩展端统一包装为工具执行结果。其核心契约如下:
成功响应
| 字段 | 类型 | 含义 |
|---|---|---|
success | 布尔值 | 表示调用是否成功 |
content | 字符串 | 文本化后的工具输出 |
tool_call_id | 字符串 | 工具调用标识,由扩展端传入 |
Agent 侧从 MCP Server 返回的 content 中提取 type === 'text' 的内容并拼接为字符串。
失败响应
| 字段 | 类型 | 含义 |
|---|---|---|
success | 布尔值 | 通常为 false |
error | 字符串 | 错误信息,可能来自 MCP Server 或 Agent 层 |
MCP Server 原始返回结构
MCP Server 应遵循 MCP SDK 约定:
- 成功时返回
result.content,其中至少包含一个type: 'text'的内容项。 - 失败时可返回
result.error,Agent 侧会读取error.message。
sequenceDiagram
participant BG as "扩展端 Background"
participant REG as "Agent MCP Registry"
participant CLI as "Agent MCP Client"
participant SRV as "MCP Server"
BG->>REG : "调用工具(serverId, toolName, args)"
REG->>CLI : "转发 callTool"
CLI->>SRV : "tools/call(name, arguments)"
SRV-->>CLI : "result.content 或 result.error"
CLI-->>REG : "{ success, content, raw }"
REG-->>BG : "{ success, content, error }"
BG-->>BG : "包装为 { success, content, tool_call_id }"
图表来源
- src/background/tool-executor.js#L616-L618
- agent/src/mcp/registry.js#L116-L127
- agent/src/mcp/client.js#L129-L157
- agent/test/mcp-test-server.cjs#L165-L186
章节来源
- agent/src/mcp/client.js#L129-L157
- src/background/tool-executor.js#L616-L618
- agent/test/mcp-test-server.cjs#L165-L186
完整工具定义示例
以下示例基于仓库中的测试服务器与 Skill 参数定义,展示不同类型工具的实现模式。
数值计算类工具
- 典型特征:参数为数字,返回计算结果。
- 示例参考:
文本处理类工具
- 典型特征:参数为字符串,返回处理后的文本或结构化结果。
- 示例参考:
枚举选择类工具
- 典型特征:参数使用
enum限制可选值。 - 示例参考:
范围约束类工具
- 典型特征:参数为数值范围,需要服务端进行边界校验。
- 示例参考:
Skill 参数 Schema 参考
Skill 的 parameters 结构与 MCP inputSchema 类似,可用于理解 JSON Schema 风格参数定义:
章节来源
- agent/test/mcp-test-server.cjs#L27-L84
- agent/test/hello-world.skill.json#L1-L33
- agent/test/project-report.skill.json#L1-L56
工具生命周期管理
MCP 工具的生命周期包括:配置加载、连接建立、工具发现、动态注册、调用、断开与销毁。
启动阶段
- Agent 启动时加载 MCP 配置。
- 遍历启用的 MCP Server。
- 创建
McpClient并连接。 - 调用
listTools获取工具列表。 - 将工具注册到全局状态。
运行阶段
- 扩展端请求 MCP 工具列表。
- Agent 返回扁平化工具定义。
- 扩展端将 MCP 工具包装为本地工具处理器。
- 调用时经
AgentClient.callMcpTool转发至对应 Server。
关闭阶段
- 显式断开某个 MCP Server。
- 清理客户端实例与工具缓存。
- Agent 关闭时批量断开所有连接。
stateDiagram-v2 [*] --> 未连接 未连接 --> 连接中 : "初始化 / 手动连接" 连接中 --> 已连接 : "连接成功" 连接中 --> 未连接 : "连接失败" 已连接 --> 已断开 : "断开连接" 已断开 --> 未连接 : "清理完成" 已连接 --> 已断开 : "Agent 关闭"
图表来源
- agent/src/mcp/registry.js#L26-L55
- agent/src/mcp/client.js#L96-L127
- agent/src/mcp/registry.js#L133-L177
章节来源
- agent/src/mcp/registry.js#L26-L55
- agent/src/mcp/client.js#L96-L127
- agent/src/mcp/registry.js#L133-L177
依赖关系分析
MCP 工具链路的依赖关系如下:
graph LR A["src/background/tool-executor.js"] --> B["agent/src/mcp/registry.js"] B --> C["agent/src/mcp/client.js"] C --> D["@modelcontextprotocol/sdk/client"] C --> E["stdio/sse/streamableHttp/websocket 传输"] B --> F["agent/src/mcp/mcp-config.js"] C --> G["agent/test/mcp-test-server.cjs"]
图表来源
- src/background/tool-executor.js#L590-L640
- agent/src/mcp/registry.js#L1-L5
- agent/src/mcp/client.js#L1-L6
- agent/src/mcp/mcp-config.js#L1-L6
- agent/test/mcp-test-server.cjs#L1-L21
章节来源
- agent/src/mcp/client.js#L1-L6
- agent/src/mcp/registry.js#L1-L5
- agent/src/mcp/mcp-config.js#L1-L6
- src/background/tool-executor.js#L590-L640
性能与上下文压缩
扩展端会对 MCP 工具的 inputSchema 进行压缩,防止工具元数据撑爆上下文窗口。压缩策略包括:
- 移除
$schema、$ref、definitions、additionalProperties等冗余字段。 - 截断过长的描述。
- 限制嵌套深度。
- 当参数数量超过上限时,保留前若干参数,并将剩余参数合并为
additionalParams。
flowchart TD
Start(["接收 inputSchema"]) --> CheckEmpty{"是否为空或非对象?"}
CheckEmpty --> |是| ReturnDefault["返回空对象 Schema"]
CheckEmpty --> |否| StripFields["移除冗余字段"]
StripFields --> SetType["确保 type 为 object"]
SetType --> CompressDesc["压缩 description"]
CompressDesc --> CompressProps["压缩 properties"]
CompressProps --> CountProps{"参数数量是否超限?"}
CountProps --> |是| MergeExtra["合并多余参数为 additionalParams"]
CountProps --> |否| KeepProps["保留原 properties"]
MergeExtra --> ReturnCompressed["返回压缩后的 Schema"]
KeepProps --> ReturnCompressed
ReturnDefault --> End(["结束"])
ReturnCompressed --> End
图表来源
章节来源
开发最佳实践
- 明确工具职责:每个 MCP 工具应聚焦单一能力,避免把复杂业务拆成模糊的大工具。
- 使用 JSON Schema 描述参数:即使 Agent 不强制校验,清晰的
inputSchema也能帮助 LLM 正确传参。 - 优先返回文本内容:MCP Client 会提取
type: 'text'的内容,因此建议将结构化结果序列化为可读文本。 - 区分成功与失败语义:成功时返回
result.content,失败时返回result.error.message,便于 Agent 层统一包装。 - 控制参数数量:避免暴露过多参数;必要时拆分工具或使用枚举减少组合爆炸。
- 保持工具名稳定:
name是工具识别关键字段,频繁变更会影响历史调用与调试。 - 利用测试服务器验证:使用仓库中的 MCP 测试服务器快速验证
tools/list与tools/call行为。 - 注意 Agent 进程重启约束:Agent 源码修改后必须重启进程,新接口才生效。
章节来源
常见陷阱与排错指南
- 未连接就调用工具:Agent 会在
callTool前检查连接状态,返回success: false与错误消息。 - MCP Server 未返回工具列表:Agent 会将
tools置为空数组,扩展端不会注册任何 MCP 工具。 - MCP Server 返回非文本内容:Agent 只拼接
type === 'text'的内容,其他类型会被忽略。 - 参数缺失或类型错误:Agent 不做强校验,需由 MCP Server 自行处理;建议在 Server 层返回明确的错误信息。
- 配置写入冲突:MCP 配置保存使用写锁,避免并发写入导致损坏。
- 扩展端上下文被撑爆:注意
compressMcpSchema的参数截断行为,避免暴露超大 Schema。 - Agent 端口占用或服务异常:Agent 启动时会检测端口占用并记录日志,排查时应关注服务启动日志。
flowchart TD
Problem["工具调用异常"] --> CheckConnected{"MCP Server 是否连接?"}
CheckConnected --> |否| FixConnect["检查配置与连接状态"]
CheckConnected --> |是| CheckResponse{"MCP Server 是否返回 content?"}
CheckResponse --> |否| FixContent["确保返回 text 类型内容"]
CheckResponse --> |是| CheckError{"是否返回 error?"}
CheckError --> |是| FixError["检查 Server 业务错误"]
CheckError --> |否| CheckSchema{"参数是否符合预期?"}
CheckSchema --> |否| FixSchema["完善 inputSchema 与参数校验"]
CheckSchema --> |是| CheckCompression{"Schema 是否被压缩?"}
CheckCompression --> |是| ReviewCompression["审查参数数量与描述长度"]
CheckCompression --> |否| DebugCall["查看 Agent 日志与调用链路"]
图表来源
- agent/src/mcp/client.js#L129-L157
- agent/src/mcp/registry.js#L116-L127
- src/background/tool-executor.js#L521-L543
章节来源
- agent/src/mcp/client.js#L129-L157
- agent/src/mcp/registry.js#L116-L127
- agent/src/mcp/mcp-config.js#L69-L79
- src/background/tool-executor.js#L521-L543
结论
本规范总结了 AI Helper 项目中 MCP 工具的定义格式、参数 Schema 约定、返回值结构、生命周期管理与常见问题处理方式。实际实现中,Agent 侧对 MCP 工具的定义较为轻量:重点在于 name、description、inputSchema 与 content 文本输出。开发者应优先保证工具语义清晰、参数描述准确、返回内容可读,并通过测试服务器与 Agent 日志完成端到端验证。对于更严格的 JSON Schema 校验、默认值处理与复杂返回结构,建议由 MCP Server 自行实现,并在 Agent 层做好错误包装与上下文压缩。