主题
MCP 协议规范
本文引用的源码文件
本文引用的文件
目录
引言
本规范面向 AI Helper Agent 的 MCP(Model Context Protocol)扩展能力,说明当前实现如何发现、连接、调用第三方 MCP Server,并把其工具注入到统一工具列表中。文档同时给出协议版本兼容性策略、工具定义格式、消息与错误处理约定、工具注册机制、以及 Python/Node.js 客户端集成参考路径。
项目结构
Agent 端的 MCP 功能集中在 agent/src/mcp 三个模块中:
client.js:封装单个 MCP Server 的连接、传输层选择、工具列表获取与工具调用。registry.js:维护多个 MCP Client 实例,提供启动时自动连接、状态查询、扁平化工具列表和工具调用路由。mcp-config.js:持久化 MCP Server 配置(~/.ai-helper-agent/mcp_servers.json),提供增删改查与写锁保护。
graph TB subgraph "Agent 进程" REG["registry.js<br/>多 Server 注册表"] CFG["mcp-config.js<br/>配置管理"] CLI["client.js<br/>单 Server 客户端"] end EXT["Chrome 扩展<br/>选项页 / 侧边栏"] API["Agent HTTP API<br/>/api/mcp/*"] S1["MCP Server A<br/>stdio/SSE/HTTP/WebSocket"] S2["MCP Server B<br/>stdio/SSE/HTTP/WebSocket"] EXT --> API API --> REG REG --> CFG REG --> CLI CLI --> S1 CLI --> S2
图表来源
章节来源
核心组件
- McpClient:负责单一 MCP Server 的生命周期,包括传输层创建、连接、工具发现、工具调用与断开。
- Registry:集中管理所有已连接的 McpClient,暴露初始化、状态查询、工具列表聚合、工具调用入口。
- Config:负责 MCP Server 配置的加载、保存、添加、删除、启用/禁用,并提供内存缓存与写入互斥锁。
关键职责边界:
- 协议细节由 SDK 与
client.js承担; - 多 Server 并发与工具聚合由
registry.js承担; - 配置持久化与权限校验由
mcp-config.js与上层 server 路由承担。
章节来源
- agent/src/mcp/client.js#L35-L184
- agent/src/mcp/registry.js#L19-L181
- agent/src/mcp/mcp-config.js#L11-L129
架构总览
Agent 作为 MCP 客户端,通过 JSON-RPC 2.0 与外部 MCP Server 通信。Agent 启动时自动连接所有启用的 MCP Server,拉取工具列表并合并为全局工具集;当扩展端需要执行某个 MCP 工具时,Agent 将请求转发给对应 Server,再把结果返回给扩展端。
sequenceDiagram
participant Ext as "扩展端"
participant Api as "Agent HTTP API"
participant Reg as "MCP 注册表"
participant Cli as "MCP 客户端"
participant Srv as "MCP Server"
Ext->>Api : "GET /api/mcp/tools"
Api->>Reg : "getMcpTools()"
Reg->>Cli : "读取已连接 Server 的工具列表"
Cli-->>Reg : "tools[]"
Reg-->>Api : "{success, tools}"
Api-->>Ext : "工具清单"
Ext->>Api : "POST /api/mcp/ : serverId/connect"
Api->>Reg : "connectMcpServer(serverId)"
Reg->>Cli : "connect()"
Cli->>Srv : "建立连接 + listTools"
Srv-->>Cli : "工具列表"
Cli-->>Reg : "连接成功"
Reg-->>Api : "连接结果"
Api-->>Ext : "连接状态"
图表来源
详细组件分析
组件一:McpClient
McpClient 是单个 MCP Server 的抽象,封装了以下能力:
- 根据配置选择传输层:stdio、SSE、Streamable HTTP、WebSocket。
- 使用 SDK 的
Client进行连接,获取服务端版本、能力与工具列表。 - 调用工具时把 SDK 返回的结构转换为统一的
{success, content, raw}或失败对象。 - 提供
getStatus()用于对外展示连接状态、工具数量与服务端信息。
classDiagram
class McpClient {
+string serverId
+string serverName
+object serverConfig
+object client
+object transport
+boolean connected
+array tools
+object serverInfo
+connect() Promise~object~
+callTool(toolName, args) Promise~object~
+disconnect() Promise~void~
+getStatus() object
-_createTransport() object
}
图表来源
关键行为说明:
- 连接成功后会调用
listTools({})获取工具列表,并缓存到this.tools。 - 工具调用失败时,优先使用 SDK 返回的
error.message,否则回退到本地翻译的错误提示。 - 工具返回内容按
type === 'text'过滤后拼接成文本字符串,便于模型消费。
章节来源
组件二:MCP 工具注册表 Registry
Registry 维护一个 Map<serverId, McpClient>,提供:
- 启动时自动连接所有
enabled: true的 MCP Server。 - 查询所有已连接 Server 的状态与工具。
- 扁平化输出工具列表,包含
serverId、serverName、name、description、inputSchema。 - 路由工具调用到具体 Server。
flowchart TD
Start(["初始化"]) --> LoadCfg["加载 mcp_servers.json"]
LoadCfg --> ForEach["遍历 servers"]
ForEach --> Enabled{"是否启用?"}
Enabled --> |否| Next["下一个 Server"]
Enabled --> |是| Connect["创建 McpClient 并 connect"]
Connect --> Connected{"连接成功?"}
Connected --> |是| Register["注册到 clients Map"]
Connected --> |否| RecordFail["记录失败 Server"]
Register --> Next
RecordFail --> Next
Next --> Done(["完成"])
图表来源
章节来源
组件三:MCP 配置管理
配置存储在 ~/.ai-helper-agent/mcp_servers.json,默认结构为 { servers: [] }。模块提供:
- 带 mtime 缓存的
loadMcpConfig()。 - 带 Promise 写锁的
saveMcpConfig()。 addMcpServer()、removeMcpServer()、toggleMcpServer()。
flowchart TD
Read["读取 mcp_servers.json"] --> CacheCheck{"mtime 未变化?"}
CacheCheck --> |是| ReturnCache["返回内存缓存"]
CacheCheck --> |否| Parse["解析 JSON"]
Parse --> Valid{"servers 字段存在?"}
Valid --> |否| InitDefault["初始化 servers=[]"]
Valid --> |是| UpdateCache["更新缓存与 mtime"]
InitDefault --> UpdateCache
UpdateCache --> Return["返回配置"]
图表来源
章节来源
依赖关系分析
registry.js依赖client.js与mcp-config.js。client.js依赖官方 SDK:@modelcontextprotocol/sdk及其传输层模块。- 扩展端通过 Agent HTTP API 访问 MCP 能力,UI 在选项页中管理 Server 配置。
graph LR REG["registry.js"] --> CLI["client.js"] REG --> CFG["mcp-config.js"] CLI --> SDK["@modelcontextprotocol/sdk"] EXT["options/toolbox-mcp.js"] --> API["Agent HTTP API"]
图表来源
章节来源
性能与可靠性
- 配置读写采用内存缓存与文件 mtime 判断,避免频繁磁盘 I/O。
- 配置写入使用 Promise 链式写锁,防止并发写导致数据损坏。
- 每个 HTTP 请求处理器有异常捕获,避免单个错误拖垮服务。
- MCP 子进程与命令执行共享 Agent 的安全分级与审计日志体系。
章节来源
故障排查指南
常见现象与定位建议:
- 新增 MCP Server 后无法连接:
- 检查
mcp_servers.json中id、command或url是否填写正确。 - stdio 模式需确保命令可执行;HTTP 模式需确保 URL 可达。
- 查看 Agent 控制台日志中的
[MCP]前缀信息。
- 检查
- 工具列表为空:
- 确认 Server 已成功连接;
getMcpServersStatus()会返回connected与toolCount。 - 检查 MCP Server 是否正确实现
tools/list。
- 确认 Server 已成功连接;
- 工具调用失败:
- 查看
callTool返回的error字段;SDK 层错误会被透传。 - 若 MCP Server 返回结构化错误,优先使用其
message。
- 查看
- 配置修改不生效:
- 确认文件已保存且 mtime 发生变化;必要时重启 Agent 以重新加载配置。
章节来源
- agent/src/mcp/client.js#L129-L157
- agent/src/mcp/registry.js#L60-L108
- agent/src/mcp/mcp-config.js#L37-L79
结论
当前 Agent 对 MCP 的实现以 SDK 为核心,围绕 client.js、registry.js、mcp-config.js 形成“单 Server 客户端 + 多 Server 注册表 + 配置持久化”的稳定结构。它支持多种传输方式,具备自动发现工具、统一工具聚合、安全校验与 i18n 能力,适合扩展第三方工具生态。未来升级方向聚焦于协议 Modern 模式的 Dual-era 兼容与无状态化迁移。
附录:协议版本、工具定义与集成示例
协议版本兼容性
- 当前 SDK 版本为
@modelcontextprotocol/sdk@^1.29.0,运行在 Legacy 模式。 - 协议演进时间线包括 2024-11-05、2025-03-26、2025-06-18、2025-11-25,以及 2026-07-28 的无状态化版本。
- 当前实现通过 SDK 内部协商完成版本选择;尚未实现显式的 Dual-era 探测逻辑。
- 官方建议在未来引入
server/discover与_meta无状态请求,并对弃用特性保留 12 个月窗口。
章节来源
- agent/docs/MCP-UPGRADE-ANALYSIS.md#L1-L23
- agent/docs/MCP-UPGRADE-ANALYSIS.md#L26-L75
- agent/docs/MCP-UPGRADE-ANALYSIS.md#L78-L109
工具定义格式
Agent 从 MCP Server 拉取的每个工具至少包含:
name:工具名称。description:工具描述。inputSchema:参数 JSON Schema;若缺失则回退为{ type: 'object', properties: {} }。
Agent 向外暴露的工具元数据包含:
serverId:来源 Server 标识。serverName:显示名称。name、description、inputSchema:来自 MCP Server 的工具定义。
返回值方面,Agent 对 MCP 工具调用的统一包装为:
- 成功:
{ success: true, content: string, raw: object }。 - 失败:
{ success: false, error: string }。
章节来源
消息格式与错误处理
- MCP 客户端与服务端之间使用 JSON-RPC 2.0。
- 连接阶段:
connect()→getServerVersion()→getServerCapabilities()→listTools({})。 - 调用阶段:
callTool({ name, arguments })。 - 错误处理:
- 连接失败:返回
{ success: false, error }。 - 工具调用失败:优先使用 SDK 返回的
error.message,否则使用本地翻译错误。 - 未连接时调用工具:直接返回未连接错误。
- 连接失败:返回
flowchart TD
Entry["调用工具入口"] --> CheckConn{"Server 已连接?"}
CheckConn --> |否| ErrNotConnected["返回未连接错误"]
CheckConn --> |是| CallSdk["调用 SDK callTool"]
CallSdk --> HasError{"SDK 返回 error?"}
HasError --> |是| ErrSdk["返回 success=false + error.message"]
HasError --> |否| BuildResult["提取 text 内容并构建结果"]
BuildResult --> Ok["返回 success=true + content"]
图表来源
章节来源
工具注册机制
- 动态发现:启动时自动连接所有启用的 MCP Server,并调用
listTools获取工具。 - 自动加载:
initializeMcpRegistry()遍历配置,逐个连接并注册到clientsMap。 - 配置管理:
mcp_servers.json支持添加、删除、启用/禁用 Server;UI 通过/api/mcp/servers等接口操作。 - 安全校验:stdio 模式下会对
command + args做命令安全分级检查,高危命令直接拒绝,灰名单命令要求确认。
sequenceDiagram participant UI as "选项页" participant API as "Agent API" participant CFG as "mcp-config.js" participant REG as "registry.js" UI->>API : "POST /api/mcp/servers" API->>CFG : "addMcpServer(server)" CFG-->>API : "保存成功" API->>REG : "可选:触发重连或刷新工具列表" REG-->>UI : "操作结果"
图表来源
章节来源
MCP 服务器集成示例
Node.js 测试服务器
仓库提供一个最小化的 MCP 测试服务器,用于验证协议实现:
- 支持的 RPC:
initialize、notifications/initialized、tools/list、tools/call。 - 提供的测试工具:
add、multiply、echo、get_time、random_number。 - 可通过
node agent/test/mcp-test-server.cjs启动,并在 Agent 配置中使用该脚本作为 stdio 传输的命令。
章节来源
Python 客户端集成参考
虽然仓库未内置 Python MCP Server 示例,但 Agent 的 MCP 客户端支持 stdio 传输,因此可以在 Python 中实现一个遵循 MCP 协议的命令行程序,并通过 Agent 配置中的 command 与 args 启动。典型步骤:
- 安装官方 MCP SDK。
- 实现
initialize、tools/list、tools/call。 - 通过标准输入输出发送 JSON-RPC 2.0 消息。
- 在 Agent 配置中将
command设为python,args设为-m your_mcp_server。
注意:Agent 会对 stdio 命令执行安全分级检查,避免 MCP 成为命令管控后门。
章节来源
Node.js 客户端集成参考
Agent 自身就是 MCP 客户端,可直接复用其 McpClient 类:
- 构造
serverConfig,包含id、name、command或url、transport、env、headers。 - 调用
connect()建立连接并拉取工具列表。 - 调用
callTool(name, args)执行工具。 - 调用
disconnect()释放资源。
章节来源
最佳实践
- 为每个 MCP Server 设置唯一
id与可读name,便于区分来源。 - 优先使用 stdio 传输开发调试,生产环境可使用 Streamable HTTP 或 WebSocket。
- 敏感 Token 通过环境变量传入,不要硬编码在配置文件中。
- 工具描述应清晰说明用途、触发条件与参数含义,有助于模型预筛选。
- 对长耗时工具,建议在 MCP Server 侧做好超时与重试控制。
- 定期清理不再使用的 MCP Server,减少子进程与工具上下文开销。
章节来源