feat(mcp): add standalone server registry
Implement C.1 stdio MCP server CRUD, encrypted environment secrets, command digest approval, connection tests, lifecycle recovery, and dynamic tool registration. Add the standalone frontend configuration center, contracts, regression tests, and development documentation.
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
- [Knowledge 与 Retrieval Core 开发说明](development/Knowledge与Retrieval-Core开发说明.md)
|
||||
- [模型提供商与模型发现开发说明](development/模型提供商与模型发现开发说明.md)
|
||||
- [MCP Bridge 与 Plugin Host 开发说明](development/MCP-Bridge与Plugin-Host开发说明.md)
|
||||
- [独立 MCP Server 配置中心开发说明](development/独立MCP-Server配置中心开发说明.md)
|
||||
- [Plugin Command 与 Settings 开发说明](development/Plugin-Command与Settings开发说明.md)
|
||||
- [前端壳子与接口层开发说明](development/前端壳子与接口层开发说明.md)
|
||||
- [前端写作体验优化开发说明](development/前端写作体验优化开发说明.md)
|
||||
|
||||
@@ -47,6 +47,12 @@
|
||||
| Agent Trace | GET | `/api/agent/runs/{run_id}/trace` | 已实现 | 分页读取可回放 Trace 快照 |
|
||||
| Plugin Host | GET | `/api/plugins/{plugin_id}/host` | 已实现 | 获取 MCP Host 健康状态 |
|
||||
| Plugin Host | POST | `/api/plugins/{plugin_id}/host/restart` | 已实现 | 重启异常 Host 并重新发现 Tool |
|
||||
| MCP Server | GET/POST | `/api/mcp/servers` | 已实现(C.1/P0) | 列出、创建独立 MCP Server 配置 |
|
||||
| MCP Server | GET/PUT/DELETE | `/api/mcp/servers/{server_id}` | 已实现(C.1/P0) | 读取、修改、删除独立配置 |
|
||||
| MCP Server | POST | `/api/mcp/servers/{server_id}/trust` | 已实现(C.1/P0) | 确认当前可执行配置摘要 |
|
||||
| MCP Server | POST | `/api/mcp/servers/{server_id}/test` | 已实现(C.1/P0) | 隔离启动、握手、发现工具后退出 |
|
||||
| MCP Server | POST | `/api/mcp/servers/{server_id}/enable`、`disable` | 已实现(C.1/P0) | 控制 Host 与动态 Tool 生命周期 |
|
||||
| MCP Server | PUT/DELETE | `/api/mcp/servers/{server_id}/secrets/{key}` | 已实现(C.1/P0) | 写入或删除加密环境变量 |
|
||||
| Plugin Command | GET | `/api/plugin-contributions/commands` | 已实现 | 获取前端可展示的 Command |
|
||||
| Plugin Command | POST | `/api/plugin-contributions/commands/{command_id}/execute` | 已实现 | 受控执行 Command |
|
||||
| Plugin Settings | GET | `/api/plugins/{plugin_id}/settings` | 已实现 | 获取 Schema 与非敏感配置 |
|
||||
@@ -647,6 +653,18 @@ MCP_TOOL_SCHEMA_INVALID
|
||||
MCP_TOOL_CALL_FAILED
|
||||
MCP_TOOL_RESULT_TOO_LARGE
|
||||
MCP_TRUST_APPROVAL_REQUIRED
|
||||
MCP_TRUST_DIGEST_STALE
|
||||
MCP_SANDBOX_REQUIRED
|
||||
MCP_TRANSPORT_UNSUPPORTED
|
||||
MCP_SERVER_NOT_FOUND
|
||||
MCP_SERVER_NAME_INVALID
|
||||
MCP_SERVER_ALREADY_ENABLED
|
||||
MCP_REGISTRY_WRITE_FAILED
|
||||
MCP_SECRET_REQUIRED
|
||||
MCP_SECRET_NOT_DECLARED
|
||||
MCP_SECRET_STORE_ERROR
|
||||
MCP_ENVIRONMENT_INVALID
|
||||
MCP_PERMISSION_INVALID
|
||||
PLUGIN_COMMAND_NOT_FOUND
|
||||
PLUGIN_COMMAND_CONFLICT
|
||||
PLUGIN_COMMAND_INVALID
|
||||
@@ -670,6 +688,14 @@ PLUGIN_STORAGE_ERROR
|
||||
CREDENTIAL_NAMESPACE_RESERVED
|
||||
```
|
||||
|
||||
### 7.8 独立 MCP Server Registry(C.1)
|
||||
|
||||
独立 Server 不依附 Plugin Manifest,配置持久化于 `APP_DATA_DIR/mcp/servers.json`,敏感环境变量只以 `mcp.*` 引用进入加密凭据存储。响应仅返回每个 Secret 是否已配置,不返回明文。动态工具使用 `mcp.{server_id}.{remote_tool}` 命名空间,来源标记为 `mcp_server`,仍通过统一 Tool Registry、Permission Manager 与 Agent Trace。
|
||||
|
||||
P0 只真实支持 `stdio`。`streamable_http` 与 `sse` 已作为后续 Contract 枚举保留,但测试或启用会返回 `501 MCP_TRANSPORT_UNSUPPORTED`,前端不可伪装为可用。命令始终以 executable 与 args 数组通过 `shell=False` 启动;普通环境变量和加密 Secret 显式注入,不继承 Provider Key、数据库或 Vault 路径。
|
||||
|
||||
创建或编辑配置后,调用方必须向 `/trust` 回传服务端计算的 `command_digest`。后端只接受与当前 transport、command、args、环境变量键值及权限完全一致的摘要;配置变化会撤销旧信任。测试连接同样会实际启动进程,因此也要求确认。当前 Python Host 仅在 `APP_ENVIRONMENT=development` 时允许启动;其他环境返回 `403 MCP_SANDBOX_REQUIRED`,等待第三阶段桌面端沙箱接管。
|
||||
|
||||
---
|
||||
|
||||
## 8. Provider Adapter 扩展
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# 独立 MCP Server 配置中心开发说明
|
||||
|
||||
> 更新日期:2026-09-03。本文记录第二阶段 C.1 的 P0 实现;它与 Plugin 自带的 MCP Host 是两个并列入口。
|
||||
|
||||
## 1. 已实现范围
|
||||
|
||||
- 独立 Server 的创建、读取、编辑和删除;
|
||||
- stdio 命令、参数、普通环境变量、加密环境变量及超时配置;
|
||||
- 命令摘要确认、测试连接、启用、停用和异常状态展示;
|
||||
- MCP initialize、`tools/list` 与动态 Tool 注册,工具命名为 `mcp.{server_id}.{tool}`;
|
||||
- 启用状态持久化与开发服务重启恢复;
|
||||
- 前端独立“MCP”导航与配置弹窗,提供 stdio/uvx 模板;
|
||||
- Streamable HTTP 与旧 SSE 仅作为后续选项展示为禁用,不属于本次完成范围。
|
||||
|
||||
## 2. 数据与 Secret
|
||||
|
||||
普通配置原子写入 `APP_DATA_DIR/mcp/servers.json`。Secret 使用 `mcp.{server_id}.{key_hash}` 作为内部引用写入现有 Fernet 凭据存储;API 和前端只看到 `configured: true/false`。删除 Server 或移除 Secret 键时同步清理密文。
|
||||
|
||||
前端 Secret 输入使用密码框,提交后立即清空,不写入 localStorage、普通配置 JSON 或日志。`mcp.*` 同 `plugin.*` 一样属于保留凭据命名空间,Provider 配置与通用凭据 API 无权读取。
|
||||
|
||||
## 3. 启动安全边界
|
||||
|
||||
命令不经过 Shell,管道、重定向和拼接字符串不会被解释。Host 只继承启动所需的系统变量,再叠加用户显式配置;`uvx` 可隔离 Python 依赖,但不能限制文件、网络和系统调用。
|
||||
|
||||
后端会对影响执行的配置计算 SHA-256 摘要。测试或启用前,用户必须确认并回传当前摘要;修改配置会立即撤销旧确认。由于 Python Host 尚无 OS 沙箱,非开发环境硬拒绝启动。第三阶段由 Tauri/Rust Host 提供平台级隔离后再替换这道临时门禁。
|
||||
|
||||
## 4. 测试与启动
|
||||
|
||||
```powershell
|
||||
cd backend
|
||||
uv run pytest -q tests/test_mcp_registry.py
|
||||
uv run uvicorn app.main:app --reload
|
||||
|
||||
cd ../frontend
|
||||
npm run type-check
|
||||
npm test
|
||||
npm run dev
|
||||
```
|
||||
|
||||
打开知识库后进入左侧“MCP”。保存配置,按提示确认命令,先执行“测试连接”;成功后再启用。默认模板 `uvx mcp-server-fetch` 仅为配置示例,首次下载是否联网由本机 uv 缓存与网络环境决定。
|
||||
|
||||
## 5. 后续增量
|
||||
|
||||
- P1:Streamable HTTP 连接、认证 Header 与重连策略;
|
||||
- 兼容项:仅在确有旧服务需求时增加 SSE;
|
||||
- 第三阶段前:把命令确认与进程创建迁移至 Tauri/Rust 沙箱;
|
||||
- 增加面向真实第三方 Server 的兼容矩阵,不用单一 Fixture 代表协议全兼容。
|
||||
Reference in New Issue
Block a user