主题
MCP 配置系统
本文引用的源码文件
本文引用的文件
目录
引言
本文件面向 MCP(Model Context Protocol)配置子系统,聚焦 Agent 端如何持久化、校验、加载和运行 MCP Server 配置,以及扩展端如何通过 HTTP API 管理这些配置。文档覆盖以下目标:
- 配置文件格式:服务器定义、传输协议、认证头、环境变量和工作目录。
- 配置验证机制:必填字段检查、类型校验、依赖关系校验。
- 配置热重载:增量更新、状态同步与连接生命周期。
- 安全策略:命令白名单/黑名单、环境变量注入边界、网络访问控制。
- 配置模板与最佳实践:多环境管理与敏感信息保护。
- 完整示例与排障路径。
本项目为双进程架构:Chrome 扩展端(Manifest V3,src/)与独立本地代理端 Agent(Node.js,agent/src/server.js)。MCP 配置主要位于 Agent 端,扩展端通过 /api/mcp/* 接口进行增删改查和连接控制。
项目结构与定位
MCP 配置相关代码集中在 Agent 端的 agent/src/mcp 目录,并由 agent/src/server.js 暴露 HTTP API;扩展端在设置页中提供 UI 并调用该 API。
graph TB subgraph "扩展端" Options["设置页<br/>src/options/toolbox-config.js"] BackgroundConfig["后台配置读取<br/>src/background/config.js"] LocalesEn["国际化文案<br/>src/shared/locales/en.js"] end subgraph "Agent 端" Server["HTTP 路由与鉴权<br/>agent/src/server.js"] Security["命令安全检查<br/>agent/src/security.js"] McpConfig["MCP 配置持久化<br/>agent/src/mcp/mcp-config.js"] Registry["MCP 注册表与工具发现<br/>agent/src/mcp/registry.js"] Client["MCP 客户端与传输层<br/>agent/src/mcp/client.js"] end Options --> Server BackgroundConfig --> Server LocalesEn --> Options Server --> Security Server --> McpConfig Server --> Registry Registry --> Client
图示来源
- agent/src/server.js#L1846-L1922
- agent/src/mcp/mcp-config.js#L1-L129
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/client.js#L1-L184
- src/options/toolbox-config.js#L27-L40
- src/background/config.js#L1-L90
- src/shared/locales/en.js#L1005-L1032
章节来源
- agent/src/server.js#L1846-L1922
- agent/src/mcp/mcp-config.js#L1-L129
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/client.js#L1-L184
- src/options/toolbox-config.js#L27-L40
- src/background/config.js#L1-L90
- src/shared/locales/en.js#L1005-L1032
核心组件
- MCP 配置持久化模块:负责
mcp_servers.json的读写、内存缓存、写入互斥锁、添加/删除/启用禁用服务器。 - MCP 客户端模块:封装 Model Context Protocol SDK,根据配置创建 stdio/SSE/streamableHttp/websocket 传输层,完成握手、工具列表拉取、工具调用。
- MCP 注册表模块:维护已连接的
McpClient实例,提供初始化、状态查询、工具扁平化、连接/断开、关闭等能力。 - HTTP 路由模块:将扩展端请求映射到 MCP 配置与注册表操作,并在 stdio 模式下对命令执行安全检查。
- 命令安全检查模块:对 MCP stdio 命令做黑白名单与确认级拦截,防止 MCP 成为命令管控后门。
- 扩展端设置页:提供 MCP 服务器管理界面,保存后通知 background 刷新工具列表。
章节来源
- agent/src/mcp/mcp-config.js#L1-L129
- agent/src/mcp/client.js#L1-L184
- agent/src/mcp/registry.js#L1-L181
- agent/src/server.js#L1846-L1922
- agent/src/security.js#L70-L70
- src/options/toolbox-config.js#L27-L40
架构总览
MCP 配置系统的运行时流程如下:
- 扩展端用户在设置页编辑 MCP 服务器配置。
- 设置页调用 Agent 的
/api/mcp/servers接口保存配置。 - Agent 路由层先做参数校验与命令安全检查,再调用 MCP 配置模块持久化。
- 用户点击“连接”时,Agent 通过注册表创建
McpClient,选择传输层并建立连接。 - 连接成功后,注册表拉取工具列表,并向扩展端暴露工具元数据。
- 工具调用经由注册表转发到对应
McpClient,最终由 MCP SDK 与远端服务交互。
sequenceDiagram
participant UI as "扩展端设置页"
participant API as "Agent HTTP 路由"
participant SEC as "命令安全检查"
participant CFG as "MCP 配置模块"
participant REG as "MCP 注册表"
participant CLI as "MCP 客户端"
UI->>API : POST /api/mcp/servers
API->>SEC : 校验 command + argsstdio
SEC-->>API : deny / confirm / allow
API->>CFG : addMcpServer(server)
CFG-->>API : { success }
UI->>API : POST /api/mcp/servers/connect
API->>REG : connectMcpServer(id)
REG->>CLI : new McpClient(server)
CLI->>CLI : _createTransport()
CLI->>CLI : client.connect()
CLI-->>REG : { success, toolCount }
REG-->>API : { success, toolCount }
API-->>UI : 连接结果
图示来源
- agent/src/server.js#L1846-L1922
- agent/src/mcp/mcp-config.js#L82-L98
- agent/src/mcp/registry.js#L130-L154
- agent/src/mcp/client.js#L47-L127
详细组件分析
MCP 配置持久化模块
该模块维护 ~/.ai-helper-agent/mcp_servers.json,结构为 { servers: Array }。每个 server 对象包含:
id:唯一标识。name:显示名称。transport:传输协议,支持stdio、sse、streamableHttp、websocket。url:SSE/streamableHttp/websocket 必需。command、args:stdio 模式启动命令及参数。env:stdio 模式的环境变量注入。cwd:工作目录。headers:HTTP 类传输的请求头。enabled:是否启用。
关键行为:
- 首次加载若文件不存在,会创建默认空配置。
- 解析失败时降级为
{ servers: [] }。 - 所有写操作使用 Promise 链式写锁,避免并发覆盖。
- 提供
addMcpServer、removeMcpServer、toggleMcpServer等原子操作。
flowchart TD
Start(["调用 addMcpServer"]) --> Load["loadMcpConfig()"]
Load --> Find{"是否存在相同 id?"}
Find --> |是| Merge["合并字段:旧值 + 新值"]
Find --> |否| Push["追加新服务器"]
Merge --> Save["saveMcpConfig(config)"]
Push --> Save
Save --> WriteLock["withWriteLock 串行写入"]
WriteLock --> Persist["writeFileSync(mcp_servers.json)"]
Persist --> Cache["更新内存缓存与 mtime"]
Cache --> End(["返回 { success: true }"])
图示来源
章节来源
MCP 客户端与传输层
McpClient 根据 server.transport 选择传输实现:
stdio:需要command,可选args、env、cwd。sse:需要url,可选headers。streamableHttp:需要url,可选headers。websocket:需要url。
连接过程:
- 创建传输层。
- 初始化 MCP SDK Client。
- 调用
client.connect()。 - 获取服务端版本与能力。
- 调用
listTools拉取工具列表。 - 标记
connected = true。
工具调用:
- 若未连接直接返回错误。
- 调用
callTool,提取 text 内容作为统一文本输出。 - 捕获异常并返回结构化错误。
classDiagram
class McpClient {
+string serverId
+string serverName
+object serverConfig
+boolean connected
+array tools
+object serverInfo
+connect() Promise
+callTool(toolName, args) Promise
+disconnect() Promise
+getStatus() object
-_createTransport() object
}
图示来源
章节来源
MCP 注册表
注册表维护 Map<serverId, McpClient>,提供:
initializeMcpRegistry:启动时遍历启用的服务器并连接。getMcpServersStatus:返回服务器状态、工具数量、工具详情。getMcpTools:扁平化工具列表,可按 serverId 过滤。callMcpTool:转发工具调用。connectMcpServer/disconnectMcpServer:单服务器连接生命周期。shutdownMcpRegistry:进程关闭时清理连接。
sequenceDiagram
participant Reg as "注册表"
participant Cfg as "配置模块"
participant Cli as "McpClient"
Reg->>Cfg : loadMcpConfig()
loop 遍历启用的服务器
Reg->>Cli : new McpClient(server)
Cli->>Cli : connect()
alt 连接成功
Reg->>Reg : clients.set(server.id, client)
else 连接失败
Reg->>Reg : failedServers.push(...)
end
end
Reg-->>Caller : { connected, failed }
图示来源
章节来源
HTTP 路由与配置入口
Agent 的 HTTP 路由暴露以下 MCP 相关接口:
POST /api/mcp/servers:添加或更新服务器。DELETE /api/mcp/servers:删除服务器。POST /api/mcp/servers/connect:连接指定服务器。POST /api/mcp/servers/disconnect:断开指定服务器。POST /api/mcp/servers/toggle:启用/禁用服务器。GET /api/mcp/servers:获取服务器状态。GET /api/mcp/tools:获取工具列表。POST /api/mcp/call:调用工具。
其中,添加服务器时对 stdio 模式的 command + args 执行命令安全检查,拒绝危险命令或要求确认。
flowchart TD
Req["HTTP 请求"] --> Route{"匹配 /api/mcp/*"}
Route --> Add["POST /api/mcp/servers"]
Route --> Del["DELETE /api/mcp/servers"]
Route --> Conn["POST /api/mcp/servers/connect"]
Route --> Disconn["POST /api/mcp/servers/disconnect"]
Route --> Toggle["POST /api/mcp/servers/toggle"]
Route --> List["GET /api/mcp/servers"]
Route --> Tools["GET /api/mcp/tools"]
Route --> Call["POST /api/mcp/call"]
Add --> CheckCmd["stdio 命令安全检查"]
CheckCmd --> Allow{"允许?"}
Allow --> |否| Deny["返回 403 或确认提示"]
Allow --> |是| Save["addMcpServer()"]
图示来源
章节来源
扩展端设置页与工具刷新
设置页在保存 MCP 配置后,向 background 发送 RELOAD_MCP_TOOLS 消息以刷新工具列表。同时,设置页会根据 Agent 返回的状态计算启用/总数统计,并渲染 UI。
章节来源
依赖关系分析
server.js依赖security.js对 stdio 命令做安全检查。server.js依赖mcp-config.js做配置持久化。server.js依赖registry.js做连接与工具管理。registry.js依赖client.js做 MCP 协议通信。- 扩展端
toolbox-config.js通过 HTTP API 与 Agent 交互,并通过 background 刷新工具。
graph LR Server["server.js"] --> Security["security.js"] Server --> McpConfig["mcp-config.js"] Server --> Registry["registry.js"] Registry --> Client["client.js"] Options["toolbox-config.js"] --> Server
图示来源
- agent/src/server.js#L1846-L1922
- agent/src/security.js#L70-L70
- agent/src/mcp/mcp-config.js#L1-L129
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/client.js#L1-L184
- src/options/toolbox-config.js#L27-L40
章节来源
- agent/src/server.js#L1846-L1922
- agent/src/security.js#L70-L70
- agent/src/mcp/mcp-config.js#L1-L129
- agent/src/mcp/registry.js#L1-L181
- agent/src/mcp/client.js#L1-L184
- src/options/toolbox-config.js#L27-L40
性能与热重载特性
- 内存缓存:
mcp-config.js使用configCache与configCacheMtime,仅在文件 mtime 变化时重新读取磁盘。 - 写入互斥锁:
withWriteLock保证并发写不会互相覆盖。 - 增量更新:
addMcpServer按id合并字段,避免全量重建。 - 状态同步:
toggleMcpServer在禁用时主动断开连接,确保工具立即可用/不可用。 - 启动初始化:
initializeMcpRegistry在 Agent 启动时批量连接启用的服务器,并记录失败列表。
需要注意:当前 MCP 配置模块没有实现基于文件监听的热重载;热重载主要通过显式连接/断开与重启 Agent 进程生效。Agent 源码修改后必须重启进程,新接口才生效。
章节来源
- agent/src/mcp/mcp-config.js#L14-L31
- agent/src/mcp/mcp-config.js#L66-L80
- agent/src/mcp/mcp-config.js#L114-L126
- agent/src/mcp/registry.js#L22-L55
安全策略
MCP 配置系统的安全策略主要体现在以下方面:
命令白名单与黑名单
- 当
transport为stdio时,Agent 路由层拼接command + args,调用命令安全检查。 - 检查结果可能为:
deny:直接拒绝,返回 403。confirm:要求用户确认,返回确认提示。allow:允许继续添加服务器。
- 命令安全检查逻辑参考 Agent 的命令分级控制策略,包括破坏性命令、权限变更、网络外连等。
章节来源
环境变量注入边界
env仅用于stdio传输模式,传递给子进程。- 扩展端文案提示环境变量仅在 stdio 传输时需要,敏感值建议通过 shell 配置导出。
- 建议在配置中避免硬编码密钥,优先使用外部密钥管理服务或受保护的 shell 环境变量。
章节来源
网络访问控制
- SSE/streamableHttp/websocket 传输通过 URL 发起网络请求。
- 扩展端存在内网地址访问控制开关与白名单,但 MCP 传输层的网络访问控制需结合 Agent 的网络策略与部署环境评估。
- RAG URL 导入的内网访问策略与 MCP 不同,注意区分。
章节来源
配置模板与最佳实践
配置文件结构
mcp_servers.json 的基本结构:
json
{
"servers": [
{
"id": "example-server",
"name": "示例 MCP 服务器",
"transport": "stdio",
"command": "node",
"args": ["./mcp-server.js"],
"env": {},
"cwd": "/path/to/workspace",
"headers": {},
"enabled": true
},
{
"id": "sse-server",
"name": "SSE 服务器",
"transport": "sse",
"url": "https://example.com/mcp",
"headers": {
"Authorization": "Bearer ..."
},
"enabled": true
}
]
}传输协议选择
stdio:适合本地脚本或二进制 MCP Server,支持command、args、env、cwd。sse:适合远程 SSE 服务,支持url与headers。streamableHttp:适合现代 Streamable HTTP 服务,支持url与headers。websocket:非官方标准传输,适合特定实现。
多环境配置管理
- 使用不同
id区分开发、测试、生产环境。 - 通过
enabled控制当前环境启用的服务器。 - 将敏感环境变量放在 shell 配置中,不在 JSON 中明文存储。
敏感信息保护
- 避免在
headers.Authorization中硬编码长期有效密钥。 - 优先使用短期 token 或代理网关鉴权。
- 定期轮换密钥,并限制 MCP Server 的网络访问范围。
章节来源
- agent/src/mcp/mcp-config.js#L82-L98
- agent/src/mcp/client.js#L54-L92
- src/shared/locales/en.js#L1018-L1020
故障排查指南
常见问题与定位
- MCP 服务器未连接:
- 检查
enabled是否为真。 - 检查
transport与必填字段:stdio 需要command,HTTP 类需要url。 - 查看 Agent 日志中的连接失败列表。
- 检查
- 工具列表为空:
- 确认连接成功且
listTools返回非空。 - 检查 MCP Server 是否正确实现工具注册。
- 确认连接成功且
- 命令被拒绝:
- stdio 模式下,命令安全检查可能返回
deny或confirm。 - 调整命令或确认后再添加服务器。
- stdio 模式下,命令安全检查可能返回
- 环境变量未生效:
- 确认使用
stdio传输。 - 检查
env字段是否正确传递。
- 确认使用
- 网络访问失败:
- 检查 URL 可达性与鉴权头。
- 结合 Agent 部署环境的网络策略。
调试步骤
- 打开 Agent 日志,观察
[MCP]与[MCP Registry]输出。 - 使用
GET /api/mcp/servers查看服务器状态。 - 使用
GET /api/mcp/tools查看工具列表。 - 使用
POST /api/mcp/call手动调用工具,观察返回内容。 - 对于 stdio 模式,检查命令安全检查结果。
章节来源
结论
MCP 配置系统在 Agent 端实现了安全的配置持久化、传输层抽象、连接生命周期管理与工具发现能力。扩展端通过简洁的 HTTP API 管理 MCP 服务器,并在设置页中提供直观的配置界面。安全方面,stdio 命令经过严格检查,环境变量注入边界清晰,网络访问需结合部署策略。虽然当前未实现文件监听热重载,但通过显式连接/断开与进程重启可实现稳定更新。建议在生产环境中谨慎配置敏感信息,并使用最小权限原则管理 MCP Server 的能力范围。