a4agent 自 0.2.2 起内置 MCP server 四端管理:把 Claude Code、Codex、dsh(DeepSeek Harness)与 ZCode 四端各自配置文件里的 MCP server 归一为统一视图(name / transport / command / args / env / url / headers),自动发现并聚合标注,支持从零安装与 JSON 批量导入(自 0.2.3 起)、跨端迁移(按传输能力矩阵严格校验)、快照回收站与迁移日志。密钥全程脱敏或用 DPAPI 加密,API 永不回传明文。本文章介绍 MCP 的发现与聚合、安装方式、功能介绍、配置文件位置、传输能力矩阵、跨端迁移与回收站机制。

1. 功能概述

维度 说明
管理对象 四端配置文件中的 MCP server(stdio / sse / http 传输)
统一视图 { name, transport, command, args, env, url, headers, cwd } 归一 schema
适用端 Claude Code、Codex、dsh、ZCode(自 0.2.2 起)
核心能力 发现聚合、从零安装与 JSON 批量导入(0.2.3 起)、跨端迁移、快照回收站、迁移日志、功能介绍
安全特性 env / headers 一律脱敏;回收站快照 DPAPI 加密

1.1 与技能管理的差异

MCP 与 技能管理 管理骨架同构,但配置形态不同:skill 是独立目录,MCP server 是配置文件内的嵌套子结构,因此读写走各端的配置文件适配器,迁移语义为「配置片段复制」,冲突处理为「目标端同名先快照进回收站再写入」。

2. 配置文件位置

端 全局(用户级) 项目级 server 存放位置
Claude Code ~/.claude.json 顶层 mcpServers <项目>/.mcp.json mcpServers 对象
Codex ~/.codex/config.toml <项目>/.codex/config.toml [mcp_servers.*] 子表
dsh ~/.dsh/profiles/<profile>/cordis.patch.yml 不支持(cordis 为全局 profile 层) @deepseek-ai/dsh-mcp-client 插件的 insert 条目
ZCode ~/.zcode/cli/config.json <项目>/.zcode/config.json 嵌套 mcp.servers(严格 schema 只写规范键)

路径全部可通过环境变量覆盖(详见数据目录与日志说明);dsh 的 profile 默认 web,可用 A4AGENT_DSH_MCP_PROFILE 指定。

3. 发现与聚合

「MCP 管理」页签加载时调用 /api/v1/mcp/discover,扫描四端全局与各项目级配置文件,把跨端同名的 server 聚合到一张卡片,并标注「已在 N 端存在」:

graph LR A[扫描四端
全局配置文件] --> D[归一 schema
按 name 聚合] B[扫描项目级
配置文件] --> D D --> E{同名?} E -->|是| F[合并到一张卡片
标注「已在 N 端存在」] E -->|否| G[单独一张卡片] F --> H[渲染卡片列表
env/headers 脱敏] G --> H style A fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style B fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style D fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style E fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style F fill:#d6eaf8,stroke:#1a6b8a,stroke-width:2px style G fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style H fill:#d5f5e3,stroke:#27ae60,stroke-width:2px

几个细节:

  • 传输归一:各家对传输类型的命名不一(如 dsh 的 streamable-http、ZCode 省略 type 时按字段推断),统一归一为 stdio / sse / http 三种。
  • 脱敏:server 详情的 env / headers 只回显键名,API 永不回传明文密钥;迁移读写由后端直接基于配置文件进行,前端全程见不到真实值。
  • 项目级识别:Claude Code 读 <项目>/.mcp.json,Codex 读 <项目>/.codex/config.toml,ZCode 读 <项目>/.zcode/config.json;dsh 无项目级 MCP。

4. 安装 MCP 服务

除迁移已有 server 外,「安装 MCP」还能在任意应用从零新建或批量导入 server(自 0.2.3 起),安装后立即出现在卡片列表并自动匹配功能介绍。

4.1 从零新建

点「安装 MCP」选择目标应用(Claude Code / Codex / dsh / ZCode,写入该应用全局配置)与传输类型(stdio / http / sse,按目标端能力自动过滤,如 Codex 仅 stdio),再填写命令 / 参数 / 环境变量(stdio)或地址 / 请求头(http / sse)即可。安装走各端原生渲染与原子写:目标端同名 server 已存在会明确拒绝(可改用迁移或先删除),既有 server 与其他配置键原样保留。

4.2 JSON 批量导入

把已有的 MCP 配置片段直接粘贴进来一次装多个,兼容三种格式:

  • mcpServers 顶层键的完整配置片段;
  • 名称作键的 server 字典;
  • 单个 server 对象。

批量导入逐条独立:单条失败(同名冲突、目标端不支持该传输等)不中断其余,并逐条报告成功 / 失败结果。

graph LR A[安装 MCP] --> B{安装方式} B -->|从零新建| C[选目标应用+传输类型
填命令或地址] B -->|JSON 批量导入| D[粘贴配置片段
兼容三种格式] C --> E[逐条原生渲染
原子写入全局配置] D --> E E --> F{单条成功?} F -->|是| G[出现在卡片列表
自动匹配功能介绍] F -->|否| H[报告该条失败原因
不影响其余条目] style A fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style B fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style C fill:#d6eaf8,stroke:#1a6b8a,stroke-width:2px style D fill:#d6eaf8,stroke:#1a6b8a,stroke-width:2px style E fill:#ffecd6,stroke:#e67e22,stroke-width:2px style F fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style G fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style H fill:#fadbd8,stroke:#c0392b,stroke-width:2px

5. 功能介绍

每张 server 卡片显示该 server 的功能介绍,三个来源自动兜底(自 0.2.3 起):

来源 说明
内置简介库 常用 server 的预置说明,开箱即用
npm registry 实时查询 npx 形式的 server 读取其 npm 包描述,查询结果有缓存与失败兜底
手工维护 点「介绍」可自定义说明:本地持久化、跨端共享、留空即清除

6. 跨端迁移与传输能力矩阵

点击卡片的「迁移」选择源副本与目标位置(全局 / 项目),执行后把 server 的配置片段写入每个目标端:

  • 源端保留:迁移是复制而非移动,源配置文件不变。
  • 先快照再写入:目标端已有同名 server 时,旧片段先快照进回收站再写入新内容,绝不静默覆盖;写入前自动备份目标配置文件(滚动保留 5 份)。
  • 严格校验:迁移按传输能力矩阵校验源传输类型是否被目标端支持,不兼容的组合整对失败并留日志,不静默降级:
graph LR A[选择源 server
含传输类型] --> B{目标端支持
该传输?} B -->|否| C[整对失败
写入迁移日志] B -->|是| D{目标端已有
同名 server?} D -->|是| E[旧片段快照
进回收站] D -->|否| F[直接写入] E --> G[写入目标配置文件
前先备份] F --> G G --> H[记录迁移日志] C --> H style A fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style B fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style C fill:#fadbd8,stroke:#c0392b,stroke-width:2px style D fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style E fill:#ffecd6,stroke:#e67e22,stroke-width:2px style F fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style G fill:#d6eaf8,stroke:#1a6b8a,stroke-width:2px style H fill:#d5f5e3,stroke:#27ae60,stroke-width:2px

6.1 传输能力矩阵

目标端 支持的传输 配置文件 项目级
Claude Code stdio / sse / http ~/.claude.json 支持 .mcp.json
Codex 仅 stdio ~/.codex/config.toml 支持
dsh stdio / streamable-http cordis.patch.yml 不支持
ZCode stdio / sse / http ~/.zcode/cli/config.json 支持

6.2 各端写入细节

  • dsh:MCP server 挂在 @deepseek-ai/dsh-mcp-client 插件条目下,重写时保留该插件其他非管理条目与其余插件;条目 id 按 server 名安全化(仅保留字母数字与 - / _)。
  • ZCode:官方 schema 严格(未知键会被丢弃),a4agent 只写规范字段(type / command / args / cwd / env / url / headers / enabled / timeoutMs);type 可省略,有 command 推断 stdio、有 url 推断 http/sse。迁移到 ZCode 的 server 会被客户端自动连接。
  • Codex:仅 stdio——把 sse / http 传输的 server 迁到 Codex 会整对失败,改用本地桥接(如 npx 起 stdio 包装)后再迁。

7. 回收站与安全

  • 被替换 / 删除的 server 配置片段快照进回收站:磁盘快照存于数据目录 mcp_recycle\,数据库 mcp_trash 表记录原配置文件路径等恢复信息,30 天内可恢复原位或彻底删除,过期条目访问时惰性清理。
  • 快照中的 env / headers 用 DPAPI 加密落盘,恢复时解密写回——保证回收站这个"垃圾桶"里也没有明文密钥。
  • 每次成功或失败的迁移写入 McpMigration 日志(时间、server、传输类型、源、目标、结果),「迁移日志」弹窗按新到旧查看。
  • 发现、内容预览、回收站接口对敏感字段全程脱敏。

8. 接口一览

接口 方法 用途
/api/v1/mcp/discover GET 全量发现与聚合
/api/v1/mcp/servers POST 从零新建安装 server(自 0.2.3 起)
/api/v1/mcp/servers/import POST JSON 配置片段批量导入(自 0.2.3 起)
/api/v1/mcp/descriptions GET / PUT 读取 / 维护 server 功能介绍(自 0.2.3 起)
/api/v1/mcp/projects GET 项目级配置文件扫描列表
/api/v1/mcp/migrate POST 跨端迁移(源端保留,冲突先入回收站)
/api/v1/mcp/migrations GET 迁移日志(新到旧)
/api/v1/mcp/delete POST 删除某端某 server(配置片段移入回收站)
/api/v1/mcp/content GET 读取 server 详情(脱敏)供预览
/api/v1/mcp/trash GET 回收站列表(含惰性清理提示)
/api/v1/mcp/trash/{id}/restore POST 恢复回收站条目到原位置
/api/v1/mcp/trash/{id} DELETE 彻底删除回收站条目

9. 常见问题

问:迁移会把源端的 MCP server 移走吗?

答:不会。迁移把配置片段复制到目标端,源端配置文件保持不变;目标端已有同名 server 时旧片段先进回收站,不静默覆盖。

问:为什么把 sse 的 server 迁到 Codex 会失败?

答:Codex 的 MCP 客户端仅支持 stdio 传输,sse / http 组合不满足传输能力矩阵,整对失败并写入日志。想给 Codex 用,请在源端改用 stdio 桥接方式。

问:回收站快照里的密钥安全吗?

答:安全。快照由 mcp_recycle\ 目录承载,其中的 env / headers 在落盘前经 Windows DPAPI 加密,恢复时才解密写回;同时所有接口响应只回显键名,不返回任何明文。

问:mcp_trash 里的旧条目会不会一直占用磁盘?

答:不会。回收站条目超过 30 天后在下次访问回收站时惰性清理,并在返回结果中提示本次清理数量;也可随时对单条执行「彻底删除」。

问:批量导入时有一条格式不对会怎样?

答:逐条独立处理——格式正确且无冲突的条目正常安装,失败的那条单独报告原因(同名冲突、目标端不支持该传输等),不会中断或回滚其余条目;修好失败的条目后可以单独再导。

问:卡片上的功能介绍不准怎么办?

答:点卡片上的「介绍」手工维护说明即可,自定义内容本地持久化、跨端共享;清空则恢复自动识别(内置简介库或 npm 包描述)。