Skip to content

MCP 工具集成 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与并发特性
  8. 故障排查指南
  9. 结论
  10. 附录:配置与调用示例路径

引言 ​

本文件系统性梳理 AI Helper 的 MCP(Model Context Protocol)工具集成方案,覆盖客户端实现、远程工具发现、协议适配、错误处理、服务分组与开关控制、deny-list 模型、缓存同步与竞态处理、用户界面展示与安全控制等关键主题。文档面向开发者与高级用户,既提供高层架构图,也给出代码级流程与关键路径引用,便于定位与二次扩展。

项目结构 ​

本项目采用双进程架构:Chrome 扩展端(Manifest V3,位于 src/)与独立本地代理端 Agent(Node.js,位于 agent/)。MCP 能力由 Agent 端负责连接外部 MCP Server,并通过 HTTP API 暴露给扩展端;扩展端在 Background 中动态注册 MCP 工具,并在侧边栏与选项页提供管理与展示能力。

graph TB
subgraph "扩展端Chrome 扩展"
BG["Background<br/>tool-executor.js"]
SP["Side Panel<br/>tool-panel.js / skill-selector.js / agent-manager.js"]
OPT["Options 页面<br/>toolbox-mcp.js / toolbox-config.js"]
end
subgraph "Agent 端Node.js"
SRV["HTTP 路由<br/>server.js"]
REG["注册表<br/>registry.js"]
CFG["配置管理<br/>mcp-config.js"]
CLI["MCP 客户端<br/>client.js"]
end
EXT["外部 MCP Server"]
OPT --> SRV
SP --> BG
BG --> SRV
SRV --> REG
REG --> CLI
CLI --> EXT

图表来源

章节来源

核心组件 ​

  • Agent 端 MCP 客户端:封装多种传输层(stdio/SSE/streamableHttp/websocket),统一 connect/listTools/callTool/disconnect 生命周期。
  • Agent 端 MCP 注册表:维护已连接 Client 实例,提供工具扁平化查询、按 serverId 过滤、工具调用、连接/断开、启停状态查询。
  • Agent 端 MCP 配置:持久化 mcp_servers.json,支持增删改查、启用/禁用、写锁保护与内存缓存。
  • 扩展端 Background 工具注入:拉取 MCP 工具列表,构建 RAW_TOOLS/BUILTIN_TOOLS/TOOL_HANDLERS,并写入 chrome.storage.local.mcpTools。
  • 扩展端 Side Panel 工具面板:从 storage 读取缓存,监听变更实时刷新,渲染服务分组、展开收起、工具详情与状态指示器。
  • 扩展端 Options 页面:MCP 服务器增删改查、连接/断开、启用/禁用、环境变量与请求头编辑。

章节来源

架构总览 ​

MCP 工具链路的端到端流程如下:用户在 Options 页面配置 MCP 服务器 → Agent 端通过 HTTP API 持久化配置并建立连接 → Registry 维护 Client 实例并暴露工具列表 → Background 拉取工具并动态注册为内置工具 → Side Panel 从 storage 读取缓存并渲染分组 UI。

sequenceDiagram
participant User as "用户"
participant Options as "Options 页面<br/>toolbox-mcp.js"
participant Server as "Agent HTTP 路由<br/>server.js"
participant Registry as "MCP 注册表<br/>registry.js"
participant Client as "MCP 客户端<br/>client.js"
participant ExtBG as "Background<br/>tool-executor.js"
participant Storage as "chrome.storage.local"
participant SidePanel as "Side Panel<br/>tool-panel.js"
User->>Options : 添加/编辑/连接 MCP 服务器
Options->>Server : POST /api/mcp/servers / connect / toggle
Server->>Registry : add/connect/toggle
Registry->>Client : connect()
Client-->>Registry : {success, toolCount}
Registry-->>Server : {success, servers/tools}
Server-->>Options : 返回结果
ExtBG->>Server : GET /api/mcp/tools + /servers
Server-->>ExtBG : tools[] + servers[]
ExtBG->>Storage : set({mcpTools})
SidePanel->>Storage : get(mcpTools) + onChanged
SidePanel-->>User : 渲染服务分组与工具详情

图表来源

详细组件分析 ​

Agent 端 MCP 客户端(协议适配与错误处理) ​

  • 传输适配:根据 transport 字段选择 stdio/sse/streamableHttp/websocket,校验必要参数(command/url),支持 headers/env/cwd/args。
  • 连接流程:创建 Client,connect 后获取 serverInfo/capabilities,listTools 填充 tools,设置 connected=true。
  • 工具调用:callTool 将 name/arguments 转发至远端,解析 content.text 拼接文本内容,统一返回 success/content/raw 或 error。
  • 错误处理:连接失败时 disconnect 清理资源;调用失败时返回结构化错误信息;disconnect/close 均做 try/catch 保护。
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
}

图表来源

章节来源

Agent 端 MCP 注册表(工具发现与调用) ​

  • 初始化:启动时遍历 enabled 的服务器,逐个 connect,统计成功/失败数量并输出日志。
  • 工具查询:getMcpTools 扁平化所有已连接 Client 的工具,支持按 serverId 过滤。
  • 工具调用:callMcpTool 校验 serverId 存在且 connected,转发到对应 Client.callTool。
  • 连接管理:connectMcpServer 先断开旧连接再新建;disconnectMcpServer 清理 Map 条目;shutdownMcpRegistry 关闭全部。
flowchart TD
Start(["调用 callMcpTool(serverId, toolName, args)"]) --> Lookup["查找 clients.get(serverId)"]
Lookup --> Exists{"是否存在?"}
Exists --> |否| Err1["返回 serverNotFound"]
Exists --> |是| Connected{"是否已连接?"}
Connected --> |否| Err2["返回 serverNotConnected"]
Connected --> |是| Call["client.callTool(toolName, args)"]
Call --> Return["返回 {success, content/raw/error}"]

图表来源

章节来源

Agent 端 MCP 配置(持久化与写锁) ​

  • 存储位置:~/.ai-helper-agent/mcp_servers.json。
  • 读写策略:内存缓存 + mtime 失效;写操作使用 withWriteLock 串行化,避免并发写损坏。
  • 功能接口:load/save/add/remove/toggle,统一返回 success 或带 i18n 的错误消息。
flowchart TD
A["addMcpServer(server)"] --> B["loadMcpConfig()"]
B --> C{"id 已存在?"}
C --> |是| D["合并更新"]
C --> |否| E["push 新项"]
D --> F["saveMcpConfig(config)"]
E --> F
F --> G["withWriteLock 串行写入 + 更新缓存"]

图表来源

章节来源

扩展端 Background 工具注入与调度 ​

  • 全局开关:检查 mcpEnabled,未开启则跳过加载。
  • 互斥加载:mcpLoadLock 保证多次 load/unload 串行执行,避免竞态。
  • 并行拉取:Promise.all 同时获取 tools 与 servers,构建 disabledServerIds 集合。
  • 动态注册:为每个工具生成 id=mcp_{serverId}_{name},注入 RAW_TOOLS/BUILTIN_TOOLS/TOOL_HANDLERS,并记录元信息映射。
  • 缓存同步:将过滤后的工具列表写入 chrome.storage.local.mcpTools,供 Side Panel 消费。
  • 会话强制下发:sessionForcedMcpServers 保存“/”触发器指定的服务,绕过关闭/排除列表。
flowchart TD
S(["loadMcpTools()"]) --> Lock["等待 mcpLoadLock"]
Lock --> CheckGlobal{"mcpEnabled === true ?"}
CheckGlobal --> |否| End1["返回 0"]
CheckGlobal --> |是| Clean["unloadMcpToolsInternal()"]
Clean --> Fetch["Promise.all(getMcpTools(), getMcpServers())"]
Fetch --> Filter["过滤 disabledServerIds"]
Filter --> Register["注册 RAW_TOOLS/BUILTIN_TOOLS/HANDLERS"]
Register --> Cache["set(chrome.storage.local.mcpTools)"]
Cache --> Release["释放 mcpLoadLock"]

图表来源

章节来源

服务分组与 deny-list 模型 ​

  • 分组维度:按 serverId 聚合工具,形成服务级行,显示 serverName、工具数、ID 与展开按钮。
  • 三层判定:
    • closed:用户在工具配置弹窗关闭的服务(agentMcpClosedServers_${agentId})。
    • excluded:助手编辑器排除的服务(agent.mcpExcludedServerIds)。
    • forced:/ 触发器手动指定的服务,强制下发并绕过前两者。
  • 生效规则:forced > 非 closed/excluded;closed/excluded 为 deny-list,不在列表中即视为开放。
flowchart TD
T["工具过滤"] --> CheckMcp{"是否为 MCP 工具?"}
CheckMcp --> |否| Keep["保留"]
CheckMcp --> |是| Global{"mcpEnabled && agentConnected && registered ?"}
Global --> |否| Drop["丢弃"]
Global --> Forced{"forcedMcpServerIds 包含?"}
Forced --> |是| Keep
Forced --> |否| Closed{"closed 包含?"}
Closed --> |是| Drop
Closed --> |否| Excluded{"excluded 包含?"}
Excluded --> |是| Drop
Excluded --> |否| Keep

图表来源

章节来源

扩展端 Side Panel 工具展示与交互 ​

  • 数据源:优先通过 runtime.sendMessage('GET_MCP_TOOLS') 直接从 Background 获取,否则回退到 chrome.storage.local.mcpTools。
  • 实时更新:监听 storage.onChanged,当 mcpTools/mcpEnabled 变化时刷新分类计数、标题与工具栏状态点。
  • 服务分组渲染:按 serverId 分组,计算 effectiveOpen(未被 closed 且未被 excluded),未开放的服务排在后面并附角标。
  • 交互行为:
    • 服务行 checkbox:切换服务级开关(denied/open)。
    • 展开按钮:展开只读工具列表(名称+描述)。
    • 全选/取消全选:仅对当前可见且可操作的项生效。
    • 计数与角标:按服务粒度统计 open/total,区分被助手排除的行不计入 open。
sequenceDiagram
participant SP as "Side Panel"
participant BG as "Background"
participant Store as "chrome.storage.local"
SP->>BG : sendMessage('GET_MCP_TOOLS')
BG-->>SP : {success, tools}
alt 获取失败
SP->>Store : get(['mcpTools'])
Store-->>SP : mcpTools[]
end
SP->>Store : onChanged 监听 mcpTools/mcpEnabled
SP-->>User : 渲染服务分组/工具详情/状态指示器

图表来源

章节来源

扩展端 Options 页面:MCP 服务器管理 ​

  • 列表渲染:显示连接状态、启用状态、transport、命令/URL、工具列表折叠区。
  • 表单编辑:支持 stdio/SSE/streamableHttp/websocket 四种传输方式,按需显示 command/args/url,以及 env/headers 多行键值对。
  • 操作接口:add/remove/connect/disconnect/toggle,统一通过 agentApi 调用后端路由。
  • 搜索与筛选:支持按 name/id/command/url/args 模糊搜索,以及 enabled/disabled 状态筛选。

章节来源

Agent 端 HTTP 路由(API 契约) ​

  • 服务器管理:POST /api/mcp/servers(新增)、DELETE /api/mcp/servers(删除)。
  • 连接控制:POST /api/mcp/servers/connect、/disconnect、/toggle(enabled 切换时若禁用会先断开)。
  • 工具调用:POST /api/mcp/call(serverId + toolName + args)。
  • 审计日志:所有关键操作均调用 logSystem 记录 serverId、success 等上下文。

章节来源

依赖关系分析 ​

  • Agent 端:
    • registry.js 依赖 client.js(连接与调用)、mcp-config.js(配置读写)、i18n(多语言错误提示)。
    • server.js 作为 HTTP 入口,依赖 registry.js 提供的工具与连接能力。
  • 扩展端:
    • background/tool-executor.js 依赖 AgentClient(HTTP 调用)、chrome.storage.local(缓存)、内部工具注册表。
    • side_panel/tool-panel.js 与 skill-selector.js 依赖 chrome.storage.local 与 runtime message 机制。
    • options/toolbox-mcp.js 依赖 toolbox-shared.agentApi 与 i18n。
graph LR
REG["registry.js"] --> CLI["client.js"]
REG --> CFG["mcp-config.js"]
SRV["server.js"] --> REG
BG["tool-executor.js"] --> SRV
SP["tool-panel.js"] --> BG
OPT["toolbox-mcp.js"] --> SRV

图表来源

章节来源

性能与并发特性 ​

  • 互斥锁:
    • Background 侧 mcpLoadLock 串行化 load/unload,避免重复注册与缓存不一致。
    • Agent 侧 mcp-config.js 使用 withWriteLock 串行化写操作,防止并发写损坏配置文件。
  • 并行拉取:Background 侧 Promise.all 并行获取 tools 与 servers,减少首屏延迟。
  • 缓存策略:
    • Background 将工具列表写入 chrome.storage.local.mcpTools,Side Panel 优先走 runtime message 直取,失败再回退 storage。
    • Agent 侧 mcp-config.js 使用内存缓存 + mtime 失效,降低频繁 IO。
  • 工具定义压缩:description 与 inputSchema 经过压缩函数处理,减少发送给模型的负载。

[本节为通用性能建议,不直接分析具体文件]

故障排查指南 ​

  • 无法加载 MCP 工具:
    • 检查全局开关 mcpEnabled 是否为 true。
    • 确认 Agent 已连接且支持 MCP。
    • 查看 Background 日志:[Background] load MCP tool failed...
  • 工具未出现在侧边栏:
    • 确认该工具所属服务未被 disabledServerIds 过滤。
    • 检查服务是否在 closed/excluded 列表中,或被助手排除。
    • 验证 chrome.storage.local.mcpTools 是否已写入。
  • 连接失败:
    • 检查 transport 必填参数(stdio 需要 command,SSE/streamableHttp/websocket 需要 url)。
    • 查看 Agent 端日志与 i18n 错误消息(如 mcp.sseRequiresUrl、mcp.stdioRequiresCommand)。
  • 工具调用失败:
    • 确认 serverId 存在且 connected。
    • 检查 callTool 返回的 error.message,必要时重试或降级。

章节来源

结论 ​

本方案以 Agent 端为核心,统一封装 MCP 协议客户端与注册表,通过 HTTP API 向扩展端暴露工具发现与调用能力;扩展端在 Background 动态注册工具并缓存,Side Panel 与 Options 提供直观的管理与展示界面。通过 deny-list 模型与三层判定(closed/excluded/forced),在保证安全可控的前提下,灵活支持服务级开关与会话级强制下发。整体设计兼顾可扩展性、可观测性与用户体验。

[本节为总结性内容,不直接分析具体文件]

附录:配置与调用示例路径 ​