主题
集成示例与最佳实践
本文引用的源码文件
本文引用的文件
- agent/src/server.js
- agent/src/mcp/client.js
- agent/src/mcp/registry.js
- agent/src/mcp/mcp-config.js
- src/background/local-agent-client.js
- src/background/tool-executor.js
- src/options/toolbox-mcp.js
- agent/test/mcp-test-server.cjs
- agent/test/mcp-client-test.js
- agent/docs/MCP-UPGRADE-ANALYSIS.md
- agent/README.zh-CN.md
目录
引言
本文件面向希望将外部工具接入 AI Helper 的开发者,聚焦 MCP(Model Context Protocol)在该项目中的集成方式、客户端调用流程、错误处理、安全策略、性能优化与调试方法。文档同时给出 Python 与 Node.js 两种 MCP Server 的实现模式参考,帮助读者快速搭建可被 Agent 调用的工具服务。
本项目采用双进程架构:Chrome 扩展端(Manifest V3,src/)与独立本地代理端 Agent(Node.js,agent/src/server.js)。两端版本号保持同步,当前以 2.3.1 为准。Agent 通过 HTTP/WebSocket 暴露接口,扩展端通过本地 Agent Client 调用;MCP 工具由 Agent 自动发现并注入到扩展端的工具列表中,供 ReAct 执行循环使用。
项目结构
围绕 MCP 的关键代码分布在以下位置:
- Agent 服务端与路由:agent/src/server.js
- MCP 客户端封装:agent/src/mcp/client.js
- MCP 注册表与多服务器管理:agent/src/mcp/registry.js
- MCP 配置持久化:agent/src/mcp/mcp-config.js
- 扩展端 Agent 客户端封装:src/background/local-agent-client.js
- 扩展端工具加载与注入:src/background/tool-executor.js
- 选项页 MCP 服务器管理 UI:src/options/toolbox-mcp.js
- MCP 测试服务器与客户端测试:agent/test/mcp-test-server.cjs、agent/test/mcp-client-test.js
- MCP 协议升级说明:agent/docs/MCP-UPGRADE-ANALYSIS.md
graph TB subgraph "扩展端" A["side_panel<br/>聊天与工具选择"] B["background/local-agent-client.js<br/>本地 Agent 客户端"] C["background/tool-executor.js<br/>工具加载与注入"] D["options/toolbox-mcp.js<br/>MCP 服务器管理 UI"] end subgraph "Agent 端" E["server.js<br/>HTTP 路由 + WebSocket"] F["mcp/registry.js<br/>MCP 注册表"] G["mcp/client.js<br/>MCP 客户端封装"] H["mcp/mcp-config.js<br/>MCP 配置持久化"] end I["外部 MCP Server<br/>Python / Node.js / CLI"] A --> B B --> E C --> B D --> B E --> F F --> G G --> I
图示来源
- agent/src/server.js#L1840-L2039
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/client.js#L1-L184
- agent/src/mcp/mcp-config.js#L1-L129
- src/background/local-agent-client.js#L730-L774
- src/background/tool-executor.js#L547-L588
- src/options/toolbox-mcp.js#L1-L43
章节来源
- agent/src/server.js#L1840-L2039
- agent/src/mcp/client.js#L1-L184
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/mcp-config.js#L1-L129
- src/background/local-agent-client.js#L730-L774
- src/background/tool-executor.js#L547-L588
- src/options/toolbox-mcp.js#L1-L43
核心组件
- MCP 客户端封装(client.js):负责根据传输类型创建连接、建立会话、列出工具、调用工具、断开连接。
- MCP 注册表(registry.js):维护已连接的多个 MCP Server,提供统一工具发现与调用入口。
- MCP 配置(mcp-config.js):持久化 MCP Server 列表,支持增删改查与启用状态切换。
- Agent 路由(server.js):暴露 MCP 管理 API(添加/删除/连接/断开/启用/禁用/工具列表/工具调用),并对 stdio 命令进行安全检查。
- 扩展端 Agent 客户端(local-agent-client.js):封装对 Agent 的 MCP 相关 HTTP 请求。
- 工具加载器(tool-executor.js):从 Agent 拉取 MCP 工具列表,合并到扩展端工具集,参与预筛选与执行。
章节来源
- agent/src/mcp/client.js#L35-L184
- agent/src/mcp/registry.js#L19-L181
- agent/src/mcp/mcp-config.js#L11-L129
- agent/src/server.js#L1840-L2039
- src/background/local-agent-client.js#L730-L774
- src/background/tool-executor.js#L547-L588
架构总览
下图展示一次 MCP 工具调用的端到端流程:扩展侧发起调用 → Agent 路由校验 → 注册表定位目标 Server → MCP 客户端转发至外部 MCP Server → 结果回传并注入扩展端工具体系。
sequenceDiagram
participant Ext as "扩展端"
participant LAC as "LocalAgentClient"
participant Srv as "Agent server.js"
participant Reg as "MCP registry.js"
participant Cli as "MCP client.js"
participant Svr as "外部 MCP Server"
Ext->>LAC : "调用 MCP 工具"
LAC->>Srv : "POST /api/mcp/call {serverId, toolName, args}"
Srv->>Reg : "callMcpTool(serverId, toolName, args)"
Reg->>Cli : "client.callTool(toolName, args)"
Cli->>Svr : "JSON-RPC tools/call"
Svr-->>Cli : "返回内容或错误"
Cli-->>Reg : "{success, content, raw}"
Reg-->>Srv : "结果"
Srv-->>LAC : "JSON 响应"
LAC-->>Ext : "工具结果"
图示来源
- src/background/local-agent-client.js#L744-L746
- agent/src/server.js#L1916-L1923
- agent/src/mcp/registry.js#L116-L128
- agent/src/mcp/client.js#L129-L158
- agent/test/mcp-test-server.cjs#L165-L186
详细组件分析
MCP 客户端封装(client.js)
- 传输层抽象:支持 stdio、SSE、Streamable HTTP、WebSocket 四种传输。
- 连接生命周期:connect() 创建传输、初始化 SDK Client、获取版本与能力、列出工具、标记 connected。
- 工具调用:callTool() 封装 JSON-RPC 调用,过滤 text 类型内容,统一 success/content/raw 返回结构。
- 断开与状态:disconnect() 关闭 SDK 与传输;getStatus() 返回连接状态与工具数量。
classDiagram
class McpClient {
+string serverId
+string serverName
+object serverConfig
+object client
+object transport
+boolean connected
+array tools
+object serverInfo
+constructor(serverConfig)
+_createTransport() object
+connect() Promise~object~
+callTool(toolName, args) Promise~object~
+disconnect() Promise~void~
+getStatus() object
}
图示来源
章节来源
MCP 注册表(registry.js)
- 启动时初始化:initializeMcpRegistry() 遍历配置中启用的 Server,逐个连接并缓存。
- 工具发现:getMcpTools() 扁平化所有已连接 Server 的工具,附带 serverId、serverName、inputSchema。
- 工具调用:callMcpTool() 校验 Server 存在且已连接,转发到对应 client.callTool。
- 连接管理:connectMcpServer()/disconnectMcpServer() 支持单 Server 重连与断开。
- 生命周期:shutdownMcpRegistry() 清理所有连接。
flowchart TD
Start(["注册表初始化"]) --> LoadCfg["加载 MCP 配置"]
LoadCfg --> ForEach["遍历启用的 Server"]
ForEach --> Connect["创建 McpClient 并 connect()"]
Connect --> Connected{"连接成功?"}
Connected --> |是| Cache["缓存 client 实例"]
Connected --> |否| Fail["记录失败信息"]
Cache --> Done(["完成"])
Fail --> Done
图示来源
章节来源
MCP 配置管理(mcp-config.js)
- 文件路径:~/.ai-helper-agent/mcp_servers.json。
- 内存缓存:按 mtime 缓存,避免频繁 IO。
- 写锁串行:withWriteLock() 保证并发写入安全。
- 操作接口:addMcpServer/removeMcpServer/toggleMcpServer/saveMcpConfig/loadMcpConfig。
flowchart TD
Read["读取 mcp_servers.json"] --> Parse["解析 JSON"]
Parse --> Valid{"包含 servers 字段?"}
Valid --> |否| Default["默认 {servers: []}"]
Valid --> |是| Return["返回配置对象"]
Save["保存配置"] --> Lock["加写锁"]
Lock --> Write["写入文件"]
Write --> UpdateCache["更新内存缓存与 mtime"]
图示来源
章节来源
Agent 路由与 MCP API(server.js)
- MCP 管理接口:
- POST /api/mcp/servers:添加 Server,校验 id/url/command,stdio 命令走 checkCommand 安全分级。
- DELETE /api/mcp/servers:删除 Server。
- POST /api/mcp/servers/connect:连接指定 Server。
- POST /api/mcp/servers/disconnect:断开指定 Server。
- POST /api/mcp/servers/toggle:启用/禁用 Server,禁用时先断开。
- POST /api/mcp/call:调用工具,校验 serverId/toolName,转发到 registry.callMcpTool。
- GET 接口:
- GET /api/mcp/servers:返回所有 Server 状态与工具数。
- GET /api/mcp/tools:返回扁平化工具列表,可选 serverId 过滤。
flowchart TD
Req["收到 /api/mcp/* 请求"] --> Validate["校验 body 参数"]
Validate --> Security{"stdio 命令需安全检查?"}
Security --> |是| CheckCmd["checkCommand(fullCmd)"]
CheckCmd --> Level{"deny/confirm/pass"}
Level --> |deny| Deny["拒绝并记录日志"]
Level --> |confirm| Confirm["返回确认提示"]
Level --> |pass| Next["继续处理"]
Security --> |否| Next
Next --> Route["分发到 add/remove/connect/disconnect/toggle/call"]
Route --> Result["返回 JSON 响应"]
图示来源
章节来源
扩展端工具加载与注入(tool-executor.js)
- loadMcpTools():检查全局 MCP 开关,清理旧工具,并行拉取工具列表与服务器状态,构建禁用 Server ID 集合,过滤无效工具。
- mergeForcedMcpTools():当用户通过“/”触发器强制下发某些 MCP Server 的工具时,补回被预筛选丢弃的工具。
- 工具可见性:mcp_* 工具按服务级开关判定,不受 enabledTools 勾选影响;Agent 未连通或 MCP 全局关闭时隐藏。
flowchart TD Start(["loadMcpTools"]) --> CheckGlobal["检查 mcpEnabled 开关"] CheckGlobal --> |关闭| Skip["跳过加载"] CheckGlobal --> |开启| Clean["清理旧 MCP 工具"] Clean --> Fetch["并行获取 tools 与 servers"] Fetch --> Filter["过滤禁用 Server 的工具"] Filter --> Inject["注入 RAW_TOOLS 与 TOOL_HANDLERS"] Inject --> End(["完成"])
图示来源
- src/background/tool-executor.js#L547-L588
- src/background/tool-executor.js#L742-L758
- src/background/tool-executor.js#L1216-L1240
章节来源
- src/background/tool-executor.js#L547-L588
- src/background/tool-executor.js#L742-L758
- src/background/tool-executor.js#L1216-L1240
选项页 MCP 服务器管理(toolbox-mcp.js)
- loadMcpServers():确保 Agent 连接后调用 /api/mcp/servers。
- renderMcpServers():渲染空态提示与服务器列表,支持连接/断开/启用/禁用等操作。
章节来源
依赖关系分析
- 扩展端依赖 Agent 提供的 MCP API,通过 local-agent-client.js 封装。
- Agent 端依赖 MCP SDK 与自定义 client.js/registry.js/mcp-config.js。
- 外部 MCP Server 通过 JSON-RPC 2.0 与 Agent 通信,支持多种传输。
graph LR Ext["扩展端 tool-executor.js"] --> LAC["local-agent-client.js"] LAC --> Srv["server.js"] Srv --> Reg["registry.js"] Reg --> Cli["client.js"] Cli --> Svr["外部 MCP Server"]
图示来源
- src/background/tool-executor.js#L547-L588
- src/background/local-agent-client.js#L730-L774
- agent/src/server.js#L1840-L2039
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/client.js#L1-L184
章节来源
- src/background/tool-executor.js#L547-L588
- src/background/local-agent-client.js#L730-L774
- agent/src/server.js#L1840-L2039
- agent/src/mcp/registry.js#L1-L128
- agent/src/mcp/client.js#L1-L184
性能考虑
- 连接池管理:registry.js 维护 Map<serverId, McpClient>,避免重复连接;toggle 时先断开再启用,减少资源泄漏。
- 批量调用:registry.getMcpTools() 扁平化工具列表,扩展端一次性注入,减少多次网络往返。
- 缓存策略:mcp-config.js 使用 mtime 缓存配置;tool-executor.js 在加载前清理旧工具,避免冗余计算。
- 传输选择:优先使用官方推荐的 Streamable HTTP,降低长连接复杂度;stdio 适合本地 CLI 场景。
- 超时与限流:server.js 对重启/更新等敏感操作设置冷却时间,防止 DoS;npm 安装带超时保护。
[本节为通用指导,不直接分析具体文件]
调试与监控
- 测试服务器:agent/test/mcp-test-server.cjs 提供最小可用 MCP Server,支持 add/multiply/echo/get_time/random_number 工具,便于端到端验证。
- 客户端测试:agent/test/mcp-client-test.js 演示连接、状态查询、工具调用与断开的完整流程。
- 日志与国际化:server.js 在请求入口处同步各子模块语言;MCP 相关日志通过 logSystem/logSecurity 输出。
- 协议升级:agent/docs/MCP-UPGRADE-ANALYSIS.md 说明 Legacy/Dual-era/Modern 兼容矩阵与探测机制,建议迁移到 Streamable HTTP。
章节来源
- agent/test/mcp-test-server.cjs#L1-L234
- agent/test/mcp-client-test.js#L1-L52
- agent/src/server.js#L427-L443
- agent/docs/MCP-UPGRADE-ANALYSIS.md#L113-L147
安全与合规
- 命令安全检查:stdio 传输的 command+args 经 checkCommand 分级(deny/confirm/pass),防止 MCP 成为命令管控后门。
- CORS 与来源限制:仅放行 chrome-extension:// 来源,恶意网页无法跨域读取无认证端点。
- 认证与令牌:除 /api/status 与 /api/pair 外,其他接口需 Bearer Token;/api/shutdown 远程来源仍需认证。
- 输入大小限制:parseBody/parseMultipartBody 限制 MAX_BODY_SIZE,防止大体积请求。
- 输出过滤:client.js 仅提取 text 类型内容,避免富文本或二进制直接透传。
章节来源
- agent/src/server.js#L242-L266
- agent/src/server.js#L271-L303
- agent/src/server.js#L310-L383
- agent/src/server.js#L537-L548
- agent/src/server.js#L1846-L1871
- agent/src/mcp/client.js#L144-L154
常见问题与故障排除
- MCP 工具未出现在工具列表:
- 检查全局 MCP 开关是否开启。
- 确认 Agent 已连接且 Server 已连接。
- 查看 Server 是否被禁用或被排除。
- 工具调用失败:
- 检查 serverId 与 toolName 是否正确。
- 查看 MCP Server 是否返回 error 或 isError。
- 确认传输配置(url/command/headers/env)正确。
- stdio 命令被拒绝:
- 检查 command+args 是否命中 deny 规则。
- 若需要确认,前端应引导用户确认后再提交。
- 连接不稳定:
- 优先使用 Streamable HTTP 或 WebSocket。
- 检查网络可达性与证书(HTTPS/WSS)。
- 配置未生效:
- 修改 Agent 源码或配置后需重启 Agent 进程。
- 确认 mcp_servers.json 权限与路径正确。
章节来源
- src/background/tool-executor.js#L547-L588
- agent/src/mcp/client.js#L129-L158
- agent/src/server.js#L1846-L1923
- agent/README.zh-CN.md#L386-L392
结论
本项目通过 Agent 端集中管理 MCP Server 连接与工具发现,扩展端按需注入工具并参与预筛选与执行。MCP 客户端封装支持多种传输,注册表提供统一工具调用入口,配置持久化与安全校验保障稳定性与安全性。结合测试服务器与客户端测试脚本,开发者可快速验证集成效果。建议在生产环境优先使用 Streamable HTTP,配合连接池、缓存与限流策略,提升整体性能与可靠性。
[本节为总结性内容,不直接分析具体文件]
附录:Python 与 Node.js MCP Server 实现模式
以下为两类常见 MCP Server 实现模式的参考思路,帮助读者快速搭建可被 Agent 调用的工具服务。注意:这些模式为概念性说明,实际实现需遵循 MCP 协议规范与本项目使用的 SDK 行为。
同步工具(Node.js)
- 使用 @modelcontextprotocol/sdk/server 创建 Server。
- 定义 tools/list 返回工具 schema。
- 在 tools/call 中同步执行业务逻辑,返回 text 内容。
- 通过 stdio 传输与 Agent 通信。
异步工具(Python)
- 使用 MCP Python SDK 定义异步 handler。
- 在 tools/call 中执行异步任务(如数据库查询、API 调用)。
- 返回结构化 content,Agent 端会提取 text 片段。
流式工具(Node.js/Python)
- 使用 SSE 或 Streamable HTTP 传输。
- 在 tools/call 中逐步推送增量内容,最终 finalize。
- 注意控制流式输出的大小与速率,避免阻塞。
文件操作工具(Python)
- 在 tools/call 中执行安全的文件读写(受限于工作目录与白名单)。
- 返回文件摘要、路径、大小等信息,避免直接返回大文件内容。
- 结合 Agent 的文件上传/下载接口,实现大文件分块处理。
[本节为概念性说明,不直接分析具体文件]