Skip to content

工具注册与发现机制 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构与职责划分
  3. 核心组件总览
  4. 架构总览:扩展端、Agent 与 MCP Server 的关系
  5. 动态工具注册流程
  6. 工具自动发现机制
  7. 配置管理系统
  8. 工具生命周期管理
  9. 工具冲突解决策略
  10. 版本兼容性与能力检查
  11. API 契约与使用示例
  12. 性能与可靠性特征
  13. 故障排查指南
  14. 结论

引言 ​

本文件聚焦 AI Helper 的 MCP 工具注册与发现机制。该机制由两部分组成:

  • Agent 端(Node.js):负责加载 MCP Server 配置、建立连接、拉取工具列表、维护已连接客户端,并暴露 HTTP API。
  • 扩展端(Chrome 扩展 Background):负责从 Agent 拉取工具定义,将其转换为内部工具模型,注入执行器,并在运行时转发调用。

整体目标是让任意实现 MCP 协议的第三方服务,都能以“零集成代码”的方式成为 AI 助手可调用的工具。

项目结构与职责划分 ​

模块路径主要职责
MCP 注册表agent/src/mcp/registry.js启动时连接所有启用的 MCP Server;提供工具查询、工具调用、连接管理、语言同步和优雅关闭。
MCP 客户端agent/src/mcp/client.js封装单个 MCP Server 的连接、传输层选择、工具枚举、工具调用和资源释放。
MCP 配置管理agent/src/mcp/mcp-config.js管理 ~/.ai-helper-agent/mcp_servers.json,提供缓存、写锁、增删改查接口。
HTTP 路由入口agent/src/server.js初始化语言、启动 MCP/Skill 子系统、暴露 /api/mcp/* 接口、处理优雅关闭。
扩展端工具加载src/background/tool-executor.js拉取 Agent 的工具列表,去重、过滤禁用服务,注册到全局工具表,并持久化 UI 元数据。
选项页 MCP 管理src/options/toolbox-mcp.js用户界面侧添加 MCP Server 的配置入口。
本地 Agent 客户端src/background/local-agent-client.js扩展端对 Agent HTTP API 的封装,包括添加 MCP Server 等请求。
graph TB
subgraph "Chrome 扩展"
BG["Background<br/>tool-executor.js"]
OPT["Options 页面<br/>toolbox-mcp.js"]
LAC["Local Agent Client<br/>local-agent-client.js"]
end
subgraph "Agent 进程"
SRV["HTTP 服务器<br/>server.js"]
REG["MCP 注册表<br/>registry.js"]
CLI["MCP 客户端<br/>client.js"]
CFG["MCP 配置<br/>mcp-config.js"]
end
subgraph "外部 MCP Server"
EXT["任意 MCP Server"]
end
OPT --> LAC
LAC --> SRV
BG --> SRV
SRV --> REG
REG --> CLI
CLI --> EXT
CFG --> REG

图表来源

章节来源

核心组件总览 ​

MCP 客户端类 ​

McpClient 是单个 MCP Server 的生命周期抽象。它负责:

  • 根据配置创建传输层:stdio、SSE、Streamable HTTP、WebSocket。
  • 建立 MCP 连接。
  • 获取服务端版本和能力。
  • 拉取工具列表。
  • 调用工具并标准化返回结果。
  • 断开连接并清理资源。
classDiagram
class McpClient {
+string serverId
+string serverName
+object serverConfig
+object client
+object transport
+boolean connected
+array tools
+object serverInfo
+connect() Promise
+callTool(toolName, args) Promise
+disconnect() Promise
+getStatus() object
-_createTransport() object
}

图表来源

章节来源

MCP 注册表 ​

注册表维护一个 Map,键为 serverId,值为 McpClient。它对外暴露:

  • initializeMcpRegistry:启动时连接所有启用 Server。
  • getMcpServersStatus:查询 Server 状态、工具数量、工具详情。
  • getMcpTools:扁平化工具列表,支持按 Server 过滤。
  • callMcpTool:通过 Server ID 和工具名调用远程工具。
  • connectMcpServer / disconnectMcpServer:运行时连接管理。
  • shutdownMcpRegistry:Agent 关闭时统一释放连接。
  • setMcpRegistryLang:同步当前语言。
flowchart TD
Start["启动注册表"] --> LoadConfig["读取 mcp_servers.json"]
LoadConfig --> Iterate["遍历 servers 数组"]
Iterate --> Enabled{"是否启用?"}
Enabled --> |否| Next["跳过"]
Enabled --> |是| CreateClient["创建 McpClient"]
CreateClient --> Connect["连接 MCP Server"]
Connect --> Success{"连接成功?"}
Success --> |是| Register["注册到 clients Map"]
Success --> |否| RecordFail["记录失败信息"]
Register --> Done["完成"]
RecordFail --> Done
Next --> Done

图表来源

章节来源

MCP 配置管理 ​

配置管理基于 ~/.ai-helper-agent/mcp_servers.json,提供:

  • 带 mtime 的内存缓存。
  • 写入互斥锁,避免并发写破坏 JSON。
  • 默认创建空配置。
  • 解析失败时降级为空服务器列表。
  • 添加、删除、切换启用状态的原子操作。
flowchart TD
Read["loadMcpConfig"] --> CheckCache{"缓存有效?"}
CheckCache --> |是| ReturnCache["返回缓存"]
CheckCache --> |否| Exists{"文件存在?"}
Exists --> |否| CreateDefault["创建默认配置"]
Exists --> |是| Parse["JSON 解析"]
Parse --> Valid{"解析成功?"}
Valid --> |是| CacheStore["更新缓存"]
Valid --> |否| Fallback["返回空服务器列表"]
CreateDefault --> CacheStore
CacheStore --> ReturnResult["返回配置"]
Fallback --> ReturnResult

图表来源

章节来源

架构总览:扩展端、Agent 与 MCP Server 的关系 ​

AI Helper 采用双进程架构:

  • 扩展端:Manifest V3 Service Worker,负责 UI、会话、提示词、工具选择和本地执行逻辑。
  • Agent 端:独立 Node.js 进程,提供文件、命令、记忆、RAG、Skill 和 MCP 工具能力。
  • MCP Server:第三方服务,实现 MCP 协议,向外暴露工具。
sequenceDiagram
participant User as "用户"
participant Options as "选项页 toolbox-mcp.js"
participant LocalClient as "Local Agent Client"
participant Server as "Agent server.js"
participant Registry as "MCP registry.js"
participant Client as "MCP client.js"
participant External as "外部 MCP Server"
User->>Options : "添加 MCP Server"
Options->>LocalClient : "addMcpServer(serverData)"
LocalClient->>Server : "POST /api/mcp/servers"
Server->>Registry : "addMcpServer(body)"
Registry->>Registry : "保存 mcp_servers.json"
Registry-->>Server : "{ success }"
Server-->>LocalClient : "{ success }"
LocalClient-->>Options : "成功"
Note over Server,External : "Agent 启动后异步连接已启用 Server"
Server->>Registry : "initializeMcpRegistry()"
Registry->>Client : "new McpClient(server)"
Client->>External : "建立 MCP 连接"
External-->>Client : "tools, capabilities"
Client-->>Registry : "connected, tools"

图表来源

动态工具注册流程 ​

动态工具注册发生在两个阶段:

  1. Agent 启动阶段:加载配置并连接 MCP Server,拉取工具列表。
  2. 扩展端运行阶段:从 Agent 拉取工具定义,转换为内部工具模型,注册到执行器。

Agent 端工具发现 ​

Agent 启动后,在 HTTP 服务器监听成功后,异步初始化 MCP 注册表。注册表会:

  • 读取 mcp_servers.json。
  • 跳过未启用的 Server。
  • 为每个启用 Server 创建 McpClient。
  • 调用 connect() 建立连接。
  • 通过 listTools 拉取工具。
  • 将成功连接的客户端存入 clients Map。
sequenceDiagram
participant Server as "server.js"
participant Registry as "registry.js"
participant Config as "mcp-config.js"
participant Client as "client.js"
participant MCP as "MCP Server"
Server->>Registry : "initializeMcpRegistry()"
Registry->>Config : "loadMcpConfig()"
Config-->>Registry : "{ servers }"
loop 遍历启用的服务器
Registry->>Client : "new McpClient(server)"
Client->>Client : "_createTransport()"
Client->>MCP : "connect()"
MCP-->>Client : "serverInfo, capabilities"
Client->>MCP : "listTools({})"
MCP-->>Client : "tools"
Client-->>Registry : "{ success, toolCount }"
Registry->>Registry : "clients.set(server.id, client)"
end

图表来源

扩展端工具注入 ​

扩展端 Background 的 loadMcpTools 负责把 Agent 提供的工具映射到内部工具系统:

  • 检查全局 mcpEnabled 开关。
  • 清理之前注册的 MCP 工具。
  • 并行获取工具列表和服务端状态。
  • 过滤掉被禁用的 Server。
  • 生成唯一工具 ID:mcp_{serverId}_{toolName}。
  • 去重防止重复注册。
  • 构造内部工具定义,包含分类、执行位置、参数 Schema。
  • 注册处理器,实际调用走 AgentClient.callMcpTool。
  • 持久化 mcpTools 供 UI 显示。
flowchart TD
Start["loadMcpTools"] --> CheckGlobal["检查 mcpEnabled"]
CheckGlobal --> |关闭| Exit["返回 0"]
CheckGlobal --> |开启| Clear["unloadMcpToolsInternal"]
Clear --> Fetch["并行获取工具列表与服务端状态"]
Fetch --> HasTools{"有可用工具?"}
HasTools --> |否| Exit
HasTools --> |是| FilterDisabled["过滤禁用 Server"]
FilterDisabled --> BuildId["生成工具 ID"]
BuildId --> Dedup{"是否已注册?"}
Dedup --> |是| NextTool["下一个工具"]
Dedup --> |否| RegisterTool["注册 RAW_TOOLS / BUILTIN_TOOLS / TOOL_HANDLERS"]
RegisterTool --> Persist["写入 chrome.storage.local.mcpTools"]
Persist --> Count["统计已注册数量"]
Count --> End["返回注册数"]

图表来源

章节来源

工具自动发现机制 ​

配置文件解析 ​

MCP 工具自动发现的起点是 ~/.ai-helper-agent/mcp_servers.json。该文件结构由 mcp-config.js 定义,核心字段包括:

字段类型说明
servers数组MCP Server 配置列表
id字符串Server 唯一标识
name字符串显示名称
transport字符串传输方式:stdio、sse、streamableHttp、websocket
command字符串或数组stdio 模式下启动命令
args数组命令参数
env对象stdio 子进程环境变量
cwd字符串stdio 子进程工作目录
url字符串SSE、Streamable HTTP、WebSocket 的目标地址
headers对象HTTP 请求头
enabled布尔值是否启用

当文件不存在时,系统会自动创建默认空配置;当文件损坏时,系统会降级为空服务器列表并记录错误日志。

插件扫描 ​

当前实现中,MCP Server 不是通过文件系统扫描自动发现的,而是通过显式配置管理。也就是说,“插件扫描”在当前代码中表现为 配置驱动的 Server 列表,而不是目录扫描。

如果需要未来扩展为插件扫描,可考虑以下方向:

  • 扫描固定目录下的 MCP Server 包。
  • 解析包元数据中的 MCP 入口。
  • 自动生成 mcp_servers.json 条目。
  • 增加依赖安装和版本校验。

但当前仓库并未实现该能力,因此文档应明确:MCP 工具发现是配置驱动,而非文件系统扫描驱动。

依赖解析 ​

MCP 客户端依赖 @modelcontextprotocol/sdk 提供的 Client 和多种 Transport。这些依赖由 Agent 包的 package.json 管理。扩展端不直接依赖 MCP SDK,只通过 HTTP API 与 Agent 交互。

章节来源

配置管理系统 ​

配置文件位置 ​

MCP 配置存储在用户主目录下的 .ai-helper-agent/mcp_servers.json。该路径由 homedir() 拼接得到,跨平台安全。

配置结构 ​

配置根对象包含 servers 数组。每个 Server 至少需要:

  • id:唯一标识。
  • transport:传输类型。
  • 根据传输类型必填:
    • stdio:command。
    • sse、streamableHttp、websocket:url。

可选字段包括 name、args、env、cwd、headers、enabled。

环境变量支持 ​

对于 stdio 传输,env 字段会被透传到子进程环境。这意味着敏感值可以通过 MCP Server 配置传入,而不必写入 Shell 配置。

对于 HTTP 类传输,headers 字段可用于携带认证头或其他请求头。

写保护与并发控制 ​

配置写入使用链式 Promise 实现的写锁,保证多次写入串行化。这避免了多个请求同时写 JSON 文件导致内容损坏。

缓存策略 ​

配置加载使用 mtime 缓存:

  • 如果文件修改时间未变,直接返回内存缓存。
  • 如果文件不存在,创建默认配置。
  • 如果解析失败,返回空服务器列表。
flowchart TD
Request["addMcpServer / removeMcpServer / toggleMcpServer"] --> Load["loadMcpConfig"]
Load --> Modify["修改 servers 数组"]
Modify --> Save["saveMcpConfig"]
Save --> Lock["withWriteLock 串行化"]
Lock --> Write["writeFileSync"]
Write --> UpdateCache["深拷贝更新内存缓存"]
UpdateCache --> Result["返回成功"]

图表来源

章节来源

工具生命周期管理 ​

启动时初始化 ​

Agent 启动流程如下:

  1. 创建 HTTP 服务器。
  2. 设置各子模块的语言。
  3. 启动配对码轮换。
  4. 启动回收站定期清理。
  5. 异步初始化 MCP 注册表和 Skill 注册表。
  6. 启动 Skill 目录监听。

MCP 初始化不会阻塞 HTTP 服务启动,即使 MCP 连接失败也不会阻止 Agent 正常运行。

运行时更新 ​

运行时可通过 HTTP API 动态管理 MCP Server:

  • 添加 Server。
  • 删除 Server。
  • 连接 Server。
  • 断开 Server。
  • 切换启用状态。
  • 调用工具。

当 Server 被禁用时,注册表会先断开已有连接,确保工具立即不可用。

优雅关闭 ​

Agent 的 shutdown 函数负责:

  • 停止配对码轮换。
  • 停止回收站清理。
  • 中止 RAG 依赖安装。
  • 终止运行中的进程。
  • 关闭所有 MCP 连接。
  • 强制断开 WebSocket 客户端。
  • 销毁活跃 HTTP Socket。
  • 等待服务器关闭。
  • 清理 PID 文件。
  • 退出进程。
stateDiagram-v2
[*] --> 启动
启动 --> 监听HTTP : "server.listen"
监听HTTP --> 异步初始化 : "initializeMcpRegistry"
异步初始化 --> 就绪 : "MCP 连接完成或失败"
就绪 --> 运行中 : "接收 API 请求"
运行中 --> 关闭中 : "shutdown"
关闭中 --> 已关闭 : "释放资源并退出"

图表来源

章节来源

工具冲突解决策略 ​

当前实现通过以下机制避免工具冲突:

冲突场景解决方式
同一 Server 下同名工具MCP Server 自身需保证工具名唯一;Agent 不做二次去重。
不同 Server 下同名工具扩展端使用 mcp_{serverId}_{toolName} 作为最终工具 ID,避免冲突。
重复注册扩展端使用 mcpToolIds Set 去重,已注册工具跳过。
禁用 Server 的工具扩展端构建禁用 Server ID 集合,跳过对应工具。
重复加载loadMcpTools 使用 mcpLoadLock 串行化,避免并发加载覆盖。
卸载旧工具unloadMcpToolsInternal 清理 RAW_TOOLS、BUILTIN_TOOLS、执行映射和处理器。
flowchart TD
Tool["收到工具定义"] --> Normalize["规范化工具 ID"]
Normalize --> Unique{"ID 唯一?"}
Unique --> |否| Skip["跳过重复工具"]
Unique --> |是| Disabled{"Server 是否禁用?"}
Disabled --> |是| Skip
Disabled --> |否| Inject["注入工具定义和处理器"]
Inject --> Track["记录到 mcpToolIds 和 mcpToolMetaMap"]

图表来源

章节来源

版本兼容性与能力检查 ​

MCP 客户端版本 ​

MCP 客户端声明自身版本为 1.3.4,用于向 MCP Server 报告客户端身份。

服务端能力探测 ​

连接成功后,客户端会获取:

  • getServerVersion()
  • getServerCapabilities()

这些信息保存在 serverInfo 中,可用于后续扩展能力判断。当前实现没有对能力做严格断言,而是假设支持标准工具枚举和调用。

工具列表容错 ​

如果 listTools 返回空或无效结构,客户端会将 tools 设为空数组,而不是抛出异常。这样即使某个 MCP Server 行为不规范,也不会阻断整个注册表。

扩展端兼容性 ​

扩展端对 Agent 的 MCP 能力做了容错处理:

  • 如果 Agent 不支持 MCP 或返回空工具列表,扩展端跳过注册。
  • 如果 Agent 不可达,扩展端记录警告日志。
  • 全局 mcpEnabled 开关可完全关闭 MCP 工具加载。
flowchart TD
Connect["连接 MCP Server"] --> Version["获取服务端版本"]
Version --> Capabilities["获取服务端能力"]
Capabilities --> ListTools["listTools"]
ListTools --> Valid{"返回有效工具?"}
Valid --> |是| UseTools["使用工具列表"]
Valid --> |否| EmptyTools["使用空工具列表"]
UseTools --> Connected["标记连接成功"]
EmptyTools --> Connected

图表来源

章节来源

API 契约与使用示例 ​

Agent 端 MCP API ​

方法路径认证要求功能
POST/api/mcp/servers需要添加或更新 MCP Server
DELETE/api/mcp/servers需要删除 MCP Server
POST/api/mcp/servers/connect需要连接指定 MCP Server
POST/api/mcp/servers/disconnect需要断开指定 MCP Server
POST/api/mcp/servers/toggle需要切换 MCP Server 启用状态
GET/api/mcp/servers需要获取所有 MCP Server 状态
GET/api/mcp/tools需要获取所有 MCP 工具列表
POST/api/mcp/call需要调用 MCP 工具

添加 MCP Server 的请求结构 ​

字段必填说明
id是Server 唯一标识
name否显示名称
transport否默认 stdio
command条件必填stdio 模式必填
args否命令参数
env否子进程环境变量
cwd否子进程工作目录
url条件必填HTTP 类传输必填
headers否HTTP 请求头
enabled否默认启用

调用 MCP 工具的流程 ​

sequenceDiagram
participant BG as "Background tool-executor.js"
participant Agent as "Agent server.js"
participant Registry as "registry.js"
participant Client as "client.js"
participant MCP as "MCP Server"
BG->>Agent : "POST /api/mcp/call"
Agent->>Registry : "callMcpTool(serverId, toolName, args)"
Registry->>Client : "client.callTool(toolName, args)"
Client->>MCP : "callTool(name, arguments)"
MCP-->>Client : "result"
Client-->>Registry : "{ success, content, raw }"
Registry-->>Agent : "{ success, content, error }"
Agent-->>BG : "{ success, content, error }"

图表来源

使用示例参考 ​

章节来源

性能与可靠性特征 ​

性能特征 ​

  • MCP 连接在 Agent 启动后异步初始化,不阻塞 HTTP 服务。
  • 扩展端加载工具时使用互斥锁,避免并发加载。
  • 配置加载使用 mtime 缓存,减少磁盘 IO。
  • 配置写入使用链式 Promise 锁,避免并发写竞争。
  • 工具调用走 Agent 单进程,扩展端不直接管理 MCP 子进程。

可靠性特征 ​

  • MCP 连接失败不会中断 Agent 启动。
  • 工具列表为空时扩展端静默跳过。
  • 配置解析失败时降级为空服务器列表。
  • 断开连接时捕获异常,避免清理过程抛错。
  • 关闭流程有 10 秒超时保护,防止进程挂起。

潜在优化点 ​

  • 当前注册表没有主动重连机制,Server 断开后不会自动恢复。
  • 工具 Schema 压缩逻辑不在本文件中,但扩展端会对描述和参数进行压缩,可能影响调试可读性。
  • 如果 MCP Server 数量很大,每次 getMcpTools 都会遍历所有已连接客户端,可考虑缓存扁平化工具列表。

章节来源

故障排查指南 ​

常见问题 ​

现象可能原因排查建议
MCP Server 未连接配置错误、命令不可执行、URL 不可达检查 mcp_servers.json,确认 command 或 url 正确
工具列表为空MCP Server 未暴露工具或连接失败查看 Agent 日志,确认 listTools 是否返回工具
工具调用失败工具名错误、参数不匹配、Server 断开检查 serverId、toolName、args
添加 Server 被拒绝缺少 id、HTTP 传输缺少 url、stdio 缺少 command检查请求体字段
stdio 命令被拦截安全策略判定为 deny 或 confirm检查命令白名单和黑名单规则
配置写入失败权限不足、磁盘空间不足检查 .ai-helper-agent 目录权限
Agent 关闭卡住某些资源未释放检查 MCP 连接、WebSocket、HTTP Socket 关闭逻辑

关键日志位置 ​

  • MCP 初始化失败:[Agent] mcpInitFailed
  • MCP Server 连接状态:[MCP] 前缀日志
  • 工具调用日志:[MCP Registry] callingTool
  • 配置解析失败:[MCP Config] Config file parse failed
  • 配置保存失败:[MCP Config] Save config failed

安全注意事项 ​

  • stdio 模式的 command 和 args 会经过命令安全检查。
  • 高危命令可能被拒绝或要求确认。
  • MCP 不应被视为绕过命令管控的后门。
  • 仅信任可信的 MCP Server。

章节来源

结论 ​

AI Helper 的 MCP 工具注册与发现机制以 配置驱动 为核心,通过 Agent 端统一管理 MCP Server 连接,并通过扩展端动态注入工具定义,实现了浏览器边界之外的能力扩展。

其设计优点包括:

  • 多传输协议支持。
  • 多 Server 并行连接。
  • 工具 ID 隔离避免冲突。
  • 配置缓存与写锁保证一致性。
  • 启动非阻塞、关闭优雅。
  • 扩展端与 Agent 解耦,通过 HTTP API 通信。

需要注意的限制包括:

  • 当前无自动插件扫描。
  • 无自动重连机制。
  • 无严格的 MCP 能力版本断言。
  • 工具 Schema 压缩可能影响调试体验。

未来若需要增强,可优先考虑:

  • 增加 MCP Server 自动发现。
  • 增加连接健康检查和自动重连。
  • 增加能力协商和版本兼容性检查。
  • 增加工具调用限流和超时控制。
  • 增加 MCP 工具调用审计日志。