MCP
CC 支持 8 种 transport、7 种 scope,并默认把 MCP 工具延迟加载(ToolSearch);Codex 只有 stdio + streamable_http 两种 transport,但 per-server/per-tool 管控字段更细(allow/deny list、per-tool approval)
MCP
结论
两家都把 MCP 当一等公民,但设计重心完全不同:CC 重"接入面"——8 种 transport(含 IDE 专用与 claude.ai 代理)、7 种配置 scope、OAuth/XAA 鉴权矩阵,并且默认通过 ToolSearch 把所有 MCP 工具 defer_loading 延迟加载来省上下文;Codex 重"管控面"——transport 只有 stdio 和 streamable_http 两种,但每个 server 有 enabled/required/enabled_tools/disabled_tools/default_tools_approval_mode 以及 per-tool 的 approval_mode,还能声明 environment_id 把 server 跑在远端环境。harness 统一抽象时,交集是 stdio + HTTP 两种 transport;CC 的延迟加载和 Codex 的工具级 allow/deny 是各自必须单独建模的能力。
研究问题
- 各 CLI 的 MCP 配置文件位置与 scope(全局/项目/托管)?
- transport 支持度(stdio / SSE / HTTP / WS)差异?
- OAuth 鉴权与工具暴露的管控粒度?
- 工具发现与延迟加载(deferred loading)机制?
各 Agent 设计与实现
Claude Code
Scope:7 种。 [一手源码] src_2026-03-31/services/mcp/types.ts:10:
z.enum(['local','user','project','dynamic','enterprise','claudeai','managed'])[一手文档] claude-code-docs/docs/mcp.md 给出用户可操作的三种及其存储位置:local(默认,~/.claude.json 按项目路径存)、project(项目根 .mcp.json,可入版本库,需用户审批,pending 状态显示 "Pending approval")、user(~/.claude.json 全局)。managed 配置在 managed-mcp.json([一手源码] services/mcp/config.ts:63);.mcp.json 还会沿父目录向上查找(config.ts:924)。
Transport:8 种。 [一手源码] services/mcp/types.ts:23:stdio / sse / sse-ide / http / ws / ws-ide / sdk / claudeai-proxy(后四种为 IDE 扩展、SDK 进程内与 claude.ai 代理的内部类型;TransportSchema 枚举本身列 6 个,union 里另含 ws-ide 与 claudeai-proxy 两个 config 类型,types.ts:69-122)。stdio 配置为 command/args/env;http/sse 支持 headers、headersHelper(外部命令生成动态 header)与 oauth。
OAuth/XAA。 [一手源码] types.ts:43-56:oauth: { clientId, callbackPort, authServerMetadataUrl(https-only), xaa }。XAA(Cross-App Access / SEP-990)是布尔开关,IdP 细节在 settings.xaaIdp 全局配置一次、多 server 共享。鉴权失败的 server 进入 needs-auth 状态(types.ts:201),连接状态机共 5 态:connected/failed/needs-auth/pending/disabled。
工具发现与延迟加载:默认全量 defer。 [一手源码] utils/toolSearch.ts:155-197:tool search 模式 'tst'(默认)/ 'tst-auto'(超 token 阈值才 defer)/ 关闭;注释明确 "(unset) → tst (default: always defer MCP and shouldDefer tools)"。被 defer 的工具定义带 defer_loading: true 发给 API,模型用 ToolSearch 工具按需取回 schema(tools/ToolSearchTool/ToolSearchTool.ts:26,查询语法 select:<tool_name> 或关键词)。阈值按模型用 token 计数 API 动态算(toolSearch.ts:102-135)。这是 CC 解决 "MCP 工具撑爆上下文" 的核心机制。
审批:项目级 .mcp.json server 首次使用需用户批准(services/mcpServerApproval.tsx);HTTP/SSE 断连自动指数退避重连 5 次([一手文档] mcp.md:175)。
Codex CLI
配置位置与层叠。 MCP server 写在各层 config.toml 的 [mcp_servers.<name>] 下([一手源码] config/src/config_toml.rs:250:mcp_servers: HashMap<String, McpServerConfig>)。层叠优先级即配置层优先级([一手源码] app-server-protocol/src/protocol/v2/config.rs:102):Mdm(0) < System(10) < EnterpriseManaged(15) < User(20,profile 21) < Project .codex/(25) < SessionFlags -c(30)。被 requirements 禁用的 server 带 disabled_reason(config/src/mcp_types.rs:35)。
Transport:2 种。 [一手源码] config/src/mcp_types.rs:424 McpServerTransportConfig:Stdio { command, args, env, env_vars, cwd, ... } 与 StreamableHttp { url, bearer_token_env_var, http_headers, ... }。字段互斥校验在反序列化时强制(如 stdio 不许配 url/bearer_token,mcp_types.rs:321-348)。无 SSE/WS。
Per-server / per-tool 管控(CC 没有的)。 [一手源码] mcp_types.rs:130-192 McpServerConfig:
[mcp_servers.github]
command = "github-mcp"
enabled = true # false 则跳过初始化
required = false # true 时 codex exec 初始化失败直接报错退出
enabled_tools = ["search_issues"] # 白名单
disabled_tools = ["delete_repo"] # 黑名单(白名单之后再剔除)
default_tools_approval_mode = "prompt" # auto | prompt | approve
[mcp_servers.github.tools.create_pr]
approval_mode = "approve" # 工具级覆盖另有 supports_parallel_tool_calls、startup_timeout_sec、tool_timeout_sec,以及 environment_id(默认 "local";remote 环境的 stdio server 要求绝对路径 cwd,mcp_types.rs:398-418——意味着 Codex 支持把 MCP server 跑在远端执行环境里)。
OAuth。 [一手源码] mcp_types.rs:120-127,177-187:oauth.client_id、scopes、oauth_resource(RFC 8707);流程实现在 rmcp-client/src/oauth.rs 与 perform_oauth_login.rs,bearer_token_env_var 支持从环境变量取 token。
无延迟加载。 [一手源码] grep defer 于 codex-rs 的 mcp/config/core 相关 crate 无对应机制;Codex 的瘦身手段是配置期的 enabled_tools 白名单,而非运行期 defer。[推断] 这与 Responses API 暂无 defer_loading 等价物有关。
差异矩阵
| 维度 | Claude Code | Codex CLI |
|---|---|---|
| 配置文件 | ~/.claude.json(local/user)、.mcp.json(project)、managed-mcp.json | 各层 config.toml 的 [mcp_servers.*] |
| Scope 数 | 7(含 dynamic/claudeai) | 6 个配置层(Mdm→SessionFlags) |
| Transport | 8(stdio/sse/http/ws + 4 内部) | 2(stdio / streamable_http) |
| 工具白/黑名单 | 无(靠 permissions 规则间接控制) | enabled_tools / disabled_tools |
| per-tool 审批 | 无 per-tool 字段 | tools.<name>.approval_mode(auto/prompt/approve) |
| server 必需性 | 无 | required = true 失败即退出 |
| 延迟加载 | 默认全量 defer + ToolSearch 取回 | 无 |
| OAuth | clientId/callbackPort/metadataUrl + XAA(SEP-990) | client_id/scopes/oauth_resource(RFC 8707) |
| 远端执行 | 无(server 均本地/URL) | environment_id 支持 remote 环境拉起 stdio server |
| 项目级审批 | .mcp.json server 需用户 approve | 项目层信任随目录 trust 决策 [推断] |
最小复现
# CC:三种 scope 落盘位置
claude mcp add demo -- npx -y @modelcontextprotocol/server-everything # local → ~/.claude.json
claude mcp add demo --scope project -- npx ... # → ./.mcp.json
claude mcp list # 项目级未审批的显示 "Pending approval"(文档 mcp.md:161)
# Codex:工具黑白名单
# ~/.codex/config.toml:
# [mcp_servers.everything]
# command = "npx"; args = ["-y","@modelcontextprotocol/server-everything"]
# enabled_tools = ["echo"]
codex # /mcp 中该 server 应只注册 echo 一个工具(未在本机重测,结论来自 mcp_types.rs 字段语义)Harness 接入建议(Yoda 实践)
Yoda 已在 harness-spec.ts 声明了两家的项目级 MCP 来源({kind:'mcp-json', relativePath:'.mcp.json'} 与 {kind:'codex-toml', relativePath:'.codex/config.toml'})。建议演进:
- 检测要覆盖非项目层:CC 的 local/user scope 都在
~/.claude.json,只扫项目目录会漏掉大半 server;Codex 同理要读$CODEX_HOME/config.toml。 - 校验分两级:语法级(CC 用
McpServerConfigSchema的 union 判别 type 字段;Codex 按RawMcpServerConfig的互斥规则——stdio 配了url直接报错);连通级(真正 spawn/connect 一次,复用 CC 的 5 态状态机语义:connected/failed/needs-auth/pending/disabled)。 - 统一模型取交集:harness 内部 server 模型建议只承诺 stdio + HTTP 两种 transport,CC 专属(sse/ws/oauth-xaa)与 Codex 专属(enabled_tools/approval_mode/environment_id)作为 runtime-specific 扩展字段透传,不要强行抹平。
- 调试入口:CC 引导用户
claude mcp get <name>与/mcp;Codex 用/mcp与disabled_reason字段——后者能直接告诉用户"被哪层 requirements 禁了"。
失效条件
- Codex 增加 SSE/WS transport 或延迟加载机制(
McpServerTransportConfig变体增加时矩阵过期) - CC 把 MCP scope 从
~/.claude.json迁到 settings 体系(services/mcp/config.ts路径变更) - CC tool search 默认模式从
'tst'改回阈值触发(utils/toolSearch.ts的 mode 决策变更) - 两家 per-tool 审批/权限模型互相补齐
参考资料
- CC 源码:
src_2026-03-31/services/mcp/types.ts、services/mcp/config.ts、utils/toolSearch.ts、tools/ToolSearchTool/ - Codex 源码:
codex/codex-rs/config/src/mcp_types.rs、config/src/config_toml.rs:250、app-server-protocol/src/protocol/v2/config.rs、rmcp-client/src/oauth.rs、codex-mcp/src/ - 文档:
claude-code-docs/docs/mcp.md、managed-mcp.md、mcp-quickstart.md;https://developers.openai.com/codex/config-reference(mcp_servers 节) - Yoda:
yoda/src/renderer/features/projects/components/harness-view/harness-spec.ts