Files
NotesAgentic/docs/development/独立MCP-Server配置中心开发说明.md
T
admin 2f7066aa92 添加MCP客户端超时配置和连接管理改进
添加了MCP客户端的超时配置功能,包括启动超时和工具调用超时参数。
改进了HTTP客户端和标准IO客户端的超时处理机制,确保请求在指定时间内完成或取消。
增加了对MCP服务器数量的限制,防止配置过多服务器导致系统不稳定。
增强了错误处理机制,当连接异常时能够正确清理资源并移除桥接主机。
添加了对大型MCP消息的大小验证,防止过大的请求导致系统问题。
优化了密钥更改后的处理流程,确保在修改密钥时停用服务器并要求重新测试。
2026-09-03 16:16:58 +08:00

6.0 KiB
Raw Blame History

独立 MCP Server 配置中心开发说明

更新日期:2026-09-03。本文记录第二阶段 C.1 的完整实现;独立 MCP Server Registry 与 Plugin 自带 MCP Host 是两个并列入口。

1. 已实现范围

  • 独立 Server 的创建、读取、版本化编辑、删除和 Tool 摘要查询;
  • stdio、Streamable HTTP 和旧版 HTTP+SSE 三种 Transport
  • stdio 可执行文件、参数、普通/加密环境变量,以及 HTTP URL、普通/加密 Header
  • 配置摘要确认、连接测试、启停、异常状态与最近一次测试结果;
  • MCP initialize、tools/listtools/call、取消与动态 Tool 注册,名称为 mcp.{server_id}.{tool}
  • Streamable HTTP Session、协议版本 Header、JSON/SSE POST 响应、可选 GET 事件流和 Last-Event-ID 重连;
  • 旧 HTTP+SSE 的 endpoint 事件与消息 POST,并强制消息地址和配置地址同源;
  • 前端表单/JSON 双模式、三种模板、高风险变更确认及请求期 Secret 输入。

Streamable HTTP 按 MCP 当前规范实现;SSE 仅用于兼容旧 Server,不应作为新部署首选。

2. 配置、版本与 Secret

普通配置原子写入 APP_DATA_DIR/mcp/servers.json。更新请求必须携带读取到的 version;版本过期返回 409 MCP_SERVER_VERSION_CONFLICT,避免多个页面互相覆盖。改变 Transport、命令、URL、Header、环境变量或权限后,旧授权和测试结果立即失效。

Secret 使用带类型和键名哈希的 mcp.* 内部 ID 写入 Fernet 凭据存储。API 只返回环境变量或 Header 是否配置,绝不返回明文。删除 Server 或移除 Secret 键会同步清理密文。前端密码框提交后立即清空,不写入 JSON 编辑器、localStorage、普通配置或日志。

跨 Registry 与凭据存储的删除以“失败后可重试”为顺序约束:先原子清理密文,再提交新版本或删除 Registry 记录。凭据存储失败时保留原版本和 Server 记录,避免出现返回 500 但配置已提交、版本无法重试或密文失去清理入口的状态。

写入或删除 Secret 会先停用正在运行的连接、注销动态 Tool,并撤销当前配置的测试通过状态;必须使用新凭据重新测试后才能启用。这样页面展示的凭据状态不会与运行中进程实际持有的旧凭据不一致。

3. 启用与运行时规则

一次连接按以下顺序执行:

  1. 用户检查服务端生成的连接摘要并确认当前摘要;
  2. 后端临时连接,完成 initialize 和 tools/list 后关闭连接;
  3. 只有当前摘要测试成功,启用操作才会启动长期连接并注册 Tool;
  4. 停用、删除、超时或异常退出会注销 Tool 并关闭连接。

运行期连接异常或 Tool 列表变化时,Registry 会在同一生命周期临界区内标记不可用、注销 Tool,并从 Bridge 移除 Host,不保留后台事件线程或 HTTP Client。Secret 写入和删除可能触发该停用流程,因此对应 API 通过工作线程执行,不阻塞 FastAPI 事件循环。

HTTP Header 中 HostContent-TypeMCP-Session-Id 等协议保留项不可由配置覆盖。URL 不允许内嵌凭据或 Fragment。旧 SSE 返回的 POST endpoint 必须与初始 URL 同源,防止认证 Header 被转发到其他站点。

启动与 Tool 请求超时会同时应用于业务等待和底层 HTTP 请求;旧 SSE 的 endpoint 等待也使用启动超时。非主动结束的旧 SSE 事件流视为 Host 不可用,宿主随后注销 Tool。注册表加载时逐条校验 Server ID、配置字段、Transport 组合和摘要格式,损坏记录统一返回 MCP_REGISTRY_INVALID

stdio 命令不经过 Shell,管道、重定向和命令拼接不会被解释。Windows 使用新进程组并通过 taskkill /T 回收子树;POSIX 使用独立 session/process group 并向进程组发信号。Python 阶段仍无法提供文件、网络、系统调用或操作系统版本差异下的绝对隔离保证。

uvx 模板使用 --isolated、明确的 --from 和固定包版本。它只能隔离依赖,不能替代安全沙箱。非开发环境仍拒绝启动 stdio Server,并返回 403 MCP_SANDBOX_REQUIRED;远程 HTTP Transport 不创建本机子进程,但仍要求摘要确认和成功测试。第三阶段前的 C.5 将冻结 Tauri/Rust 沙箱设计。

4. 接口

GET    /api/mcp/servers
POST   /api/mcp/servers
GET    /api/mcp/servers/{server_id}
PUT    /api/mcp/servers/{server_id}
DELETE /api/mcp/servers/{server_id}
GET    /api/mcp/servers/{server_id}/tools
POST   /api/mcp/servers/{server_id}/trust
POST   /api/mcp/servers/{server_id}/test
POST   /api/mcp/servers/{server_id}/enable
POST   /api/mcp/servers/{server_id}/disable
PUT    /api/mcp/servers/{server_id}/secrets/{key}?kind=environment|header
DELETE /api/mcp/servers/{server_id}/secrets/{key}?kind=environment|header

完整字段、状态和错误码见《第二阶段接口契约-开发版》。协议实现参考 MCP 官方的 TransportsLifecycle

5. 验证

cd backend
uv run pytest -q tests/test_mcp_registry.py tests/test_extension_core.py

cd ../frontend
npm run type-check
npm test
npm run build

后端测试使用无需网络或密钥的 stdio Fixture,以及 httpx.MockTransport 驱动的确定性 HTTP/SSE Server Fixture。覆盖摘要授权、Secret 不回显、版本冲突、生产门禁、重启恢复、Streamable HTTP Session/Header/工具调用及旧 SSE 同源校验。前端覆盖模板切换、JSON 校验、Secret 请求期输入、测试失败和删除确认。

6. 后续边界

  • 增加真实第三方 Server 的兼容矩阵;确定性 Fixture 只能证明宿主协议行为,不能代表所有实现兼容;
  • C.5 在第二阶段开发与测试完成后、第三阶段桌面端实现前冻结沙箱 Contract;
  • 第三阶段将 stdio 进程创建和 Secret 托管迁移至 Tauri/Rust Host 与 Stronghold/系统 Keychain。