ECC 的 MCP Connector Policy 解读:默认 MCP 服务器的准入铁律与跨 Harness 瘦身实践
导读
本文围绕开源仓库 ECC(The agent harness performance optimization system,面向 Claude Code、Codex、Opencode、Cursor 等编码 Agent 的 Harness 性能优化系统)中的 MCP-CONNECTOR-POLICY.md 展开,系统讲解 ECC 治理"默认 MCP 连接器(connector)"所依赖的准入双门槛、单一默认集的决策过程,以及如何通过 ECC_DISABLED_MCPS 在安装/同步期按需剔除 MCP 服务器。读完本文,你将掌握一套可迁移到任何 Agent 工作区的 MCP 选型判断框架,以及 ECC 仓库中该策略从策略文档到配置目录、再到安装脚本和测试用例的完整落地链路。
背景:为什么默认 MCP 服务器需要一条"准入铁律"
MCP(Model Context Protocol)服务器能给 Agent 带来工具能力,但每一种能力都有隐藏成本。正如 MCP 策略文档开篇所言:工具 schema 会被加载到每一次会话中,每一个默认连接器无论用户是否真正使用,都会占用每位用户的上下文窗口(context window)。对于一个需要同时面向多种 Harness(Claude Code、Codex、Opencode、Cursor……)发布配置的系统来说,每多带一个默认 MCP 服务器,就是对所有用户的一次持续的上下文"征税"。
因此 ECC 的核心立场是极简且强约束的:
ECC ships exactly one default MCP connector. Everything else is a skill wrapping a CLI or REST API, or an opt-in entry in
mcp-configs/mcp-servers.json.
即:ECC 默认只随附 一个 MCP 连接器;除此之外的能力,要么是"包装 CLI / REST API 的 skill",要么是 mcp-configs/mcp-servers.json 中需要用户**主动选择启用(opt-in)**的目录条目。这一原则从策略文档、README、安装脚本到测试用例,全链路一致(见 README.md 对默认连接器集的说明,以及下文源码佐证)。
核心规则:默认连接器必须同时满足两个条件
在 MCP-CONNECTOR-POLICY.md 中,一个默认连接器要获得席位,必须同时满足两条判据(both hold):
- 通用性(Universal):它必须适用于 ECC 所覆盖的每种 Harness 上的、几乎所有编码 Agent 用户。也就是说,能力本身具有普适价值,而不是少数人的特定诉求。
- MCP 确实优于"用 skill 包装 CLI/API"(MCP beats a CLI/API wrapped in a skill):这项任务真正需要 MCP 才能提供的东西——交互式会话状态(interactive session state)、流式输出(streaming)、认证握手(auth handshake)或结构化浏览(structured browsing)。反之,无状态(stateless)的请求/响应型工作属于 skill,而不是服务器。
第二条是本策略的"分水岭":MCP 的价值在于它托住了长期存活的会话状态,而不是"发一条命令拿一个结果"。一次性的、无状态的调用,用 skill 内部封装一个 CLI 或 REST API 反而更省 token、更好组合、更易被模型理解。
数量纪律:默认集上限与 2026 年的行业现实
策略文档同时给出了一个数量约束:默认集必须远低于 10 个(The default set stays well under ten)。并援引行业观测——2026 年严肃 Harness 的默认配置现实是 0 到 2 个连接器 + Harness 原生内置能力(native built-ins)。这一纪律同样沉淀进了配置目录与代码注释:
- mcp-configs/mcp-servers.json 的
_comments字段明确写着"context_warning": "Keep under 10 MCPs enabled to preserve context window"(启用上限保持 10 个以内以保护上下文窗口); - scripts/codex/merge-mcp-config.js 中
ECC_SERVERS定义处也注明:当前默认连接器集恰好一个,2026 年 6 月审计裁撤的前默认项绝不能再被重新生成。
当前默认集:为什么只有 chrome-devtools
| Server | 为什么它能通过准入 |
|---|---|
chrome-devtools |
Google 官方 DevTools MCP。提供交互式 CDP 会话——在有状态浏览器上进行实时调试、性能追踪(performance traces)、控制台与网络检查。这是"MCP 胜过 CLI"的教科书式场景:价值在于保持打开的会话,而非一次性命令。无需 API Key(Keyless)。 |
从源码实现可以进一步印证它的工程形态。在 scripts/codex/merge-mcp-config.js 中,默认连接器集被硬编码为仅此一个:
const ECC_SERVERS = {
'chrome-devtools': dlxServer(
'chrome-devtools',
'chrome-devtools-mcp@latest',
{ startup_timeout_sec: DEFAULT_MCP_STARTUP_TIMEOUT_SEC },
DEFAULT_MCP_STARTUP_TIMEOUT_TOML
)
};
其中:
dlxServer(name, pkg, extraFields, extraToml)会根据探测到的包管理器(npx/pnpm dlx/bunx等)生成 stdio 服务器定义;- 落地到 Codex 的
config.toml时写成[mcp_servers.chrome-devtools],含command = "npx"、args = ["chrome-devtools-mcp@latest"],并带startup_timeout_sec = 30的启动超时保护; - 该文件的注释特别强调:Codex 的
[mcp_servers.*]TOML schema 只支持 stdio(command/args),绝不能生成url键,http/url形式仅对 Claude Code 的.mcp.json有效(对应 issue #2224 的修复逻辑)。
这些生成行为都有测试锁定:在 tests/scripts/codex-hooks.test.js 中可以找到对 command == 'npx'、args == ['chrome-devtools-mcp@latest']、startup_timeout_sec == 30 以及合并输出含 [mcp_servers.chrome-devtools] 的断言。
2026 年 6 月审计:被它替换掉的六个默认连接器
在成为"唯一默认"之前,ECC 的默认集曾多达 7 个(README 与合并脚本的历史记录中可看到 GitHub、Context7、Exa、Memory、Playwright、Sequential Thinking 乃至 Supabase)。2026 年 6 月审计基于上述两条判据逐一裁决,将其全部移出默认集:
| 原默认连接器 | 裁决 | 替代方案 |
|---|---|---|
github |
降级为 skill | 通过 github-ops skill 调用 gh CLI。gh 出现在每个模型的训练数据里,能以最低 token 开销组合一次性命令,且只需 gh auth login 认证一次;原 MCP 服务器约 30 个工具 schema 反而拖累每次会话 |
context7 |
降级为 skill | documentation-lookup skill 直接调用 Context7 公开 REST API(/api/v2/libs/search、/api/v2/context)。两次无状态调用 + bearer key,没有会话状态需要维持,不构成服务器的理由 |
exa |
降级为 skill | 默认改用 Harness 原生搜索(Claude Code WebSearch、Codex web_search、Cursor @Web);持有 API Key 的用户仍可使用 exa-search skill。原服务器需要 API Key,本身就不满足"默认连接器的通用性" |
memory |
直接移除 | Harness 原生记忆(Claude Code 的 auto-memory 目录、Cursor memories、AGENTS.md 约定)+ ECC 自有的 instinct / continuous-learning 体系。知识图谱服务器解决的是 2024 年、如今 Harness 已内置吸收的问题 |
playwright |
降级为 skill | 微软自己的 @playwright/cli Agent 表面——厂商自身都把 Agent 工作流移出了 MCP,因为每步返回完整可访问性树会烧掉大量上下文。ECC 的 e2e 类 skill 已经在驱动 CLI;而浏览器调试(交互式场景)由 chrome-devtools 覆盖 |
sequential-thinking |
直接移除 | 每个现代 Harness 都具备原生扩展思维(extended thinking)。该服务器没有包装任何外部系统——本质上是"被包装成连接器的提示词模式" |
注意每一项裁决都精确对应两条判据之一:github、context7、exa、playwright 是因为"任务无状态、用 skill 更优"(判据 2 不成立),memory、sequential-thinking 是因为"问题已被 Harness 原生能力吸收、不再有独立的普遍价值"(判据 1 松动)。
被裁撤并不意味着消失:opt-in 目录仍在
策略文档明确:上述六个连接器全部保留在 mcp-configs/mcp-servers.json 中作为 opt-in 条目,想要它们的用户可以自行启用。查看 mcp-configs/mcp-servers.json 可以验证这一点——github、context7、exa-web-search、memory、sequential-thinking、playwright 等条目依然存在。
该文件结构上有三个值得注意的设计:
- 顶层是
mcpServers对象,每个条目形如:"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "YOUR_GITHUB_PAT_HERE" }, "description": "GitHub operations - PRs, issues, repos" } - 大量条目使用
YOUR_*_HERE占位符(如JIRA_URL、FIRECRAWL_API_KEY、EXA_API_KEY),配合description字段说明用途与注意事项——它是一个"模板目录"而非"开箱即用清单"。 - 文件内嵌
_comments字段规定了使用方式:把需要的服务器复制到你的~/.claude.json的mcpServers段(usage)、替换占位符为真实值(env_vars)、用ECC_DISABLED_MCPS在安装/同步期屏蔽随附 MCP、每项目可用disabledMcpServers覆盖(disabling),并保持启用数低于 10(context_warning)。
目录中还可看到本地化生态的 opt-in 例子,例如 ecc-memory-vault(描述中注明"not enabled by default"、仅当 operator 显式设置 ECC_MEMORY_ALLOW_USER_SCOPE=1 才放行用户作用域)、codehealth-mcp(codescene 条目标注 "Not enabled by default——copy only if you opt in")。这些都与"默认集瘦身、能力全部 opt-in"的总策略自洽。
Opt-out:用 ECC_DISABLED_MCPS 在安装/同步期剔除服务器
即便默认集只剩一个,ECC 仍然提供了显式退出开关。策略文档给出的用法是:
export ECC_DISABLED_MCPS="chrome-devtools"
要准确理解它的语义,必须看注释与文档的一再澄清:ECC_DISABLED_MCPS 是一个 ECC 安装/同步(install/sync)过滤器,而不是 Claude Code 的运行时开关。它只作用于 ECC 生成的 MCP 配置输出,涉及 install.sh、npx ecc-universal install 以及 Codex MCP 合并等流程(详见 docs/token-optimization.md)。变量值使用逗号分隔的服务器名列表,例如 ECC_DISABLED_MCPS="github,context7,exa,playwright,sequential-thinking,memory"。
这一行为在源码中有三层实现支撑:
- 解析层 scripts/lib/mcp-config.js 的
parseDisabledMcpServers()负责把环境变量切分为去重、去空白的服务器名集合;filterMcpConfig(config, disabledServerNames)则遍历config.mcpServers,命中禁用名的条目被移除,并返回{ config, removed }供调用方记录日志。 - 安装层 scripts/lib/install/apply.js 在执行 merge-json 类操作时,会先判断目标路径是否为 MCP 配置路径(
isMcpConfigPath),若是且disabledServers非空,就用filterMcpConfig过滤后再合并写入。 - Codex 合并层 scripts/codex/merge-mcp-config.js 启动时即读取该环境变量(
process.env.ECC_DISABLED_MCPS)并打印Disabled via ECC_DISABLED_MCPS: ...,随后对对应条目执行跳过(skip)/ 移除(remove)/ 更新(update disabled)三类动作,且遵守"add-only、绝不改动用户自建条目"的合并纪律。
测试层对禁用语义有细颗粒度的锁定,见 tests/scripts/codex-hooks.test.js:以 ECC_DISABLED_MCPS: 'chrome-devtools' 运行时断言输出包含 Disabled via ECC_DISABLED_MCPS、[skip] mcp_servers.chrome-devtools (disabled) / [update] mcp_servers.chrome-devtools (disabled),并且最终合并结果中不再出现 chrome-devtools 片段(assert.doesNotMatch(updated, /chrome-devtools/))。
如何新增一个默认连接器:PR 必须论证两条判据
策略文档对"想往默认集里加东西"的人给出了唯一路径——开一个 PR,并且显式论证两条判据:
Open a PR that argues both prongs of the rule explicitly. "Popular" is not an argument; "the job is stateful and universal" is.
翻译过来即:
- 流行不是理由("Popular" is not an argument)——用户多、热度高、GitHub Star 多都不能构成准入证据;
- "任务有状态且通用"才是理由("the job is stateful and universal" is)——必须说明:这项任务 (a) 对几乎所有 Harness 用户普遍成立;(b) 依赖 MCP 才能提供的会话状态/流式/认证/结构化浏览,无法被一个 skill 内封装的 CLI/REST 调用等价替代。
反过来,这份 PR 论证模板同样可以当"自查清单"用:如果任务是无状态的请求/响应,那它应该做成 skill;如果任务状态已被 Harness 原生能力覆盖,那它连 skill 都不需要;只有两者都站得住,才值得占用每一次会话的上下文窗口。
给自建 Agent 工作区的迁移建议
结合 ECC 的策略与仓库实现,这套原则可以直接迁移到任何团队自建的 Agent 配置中:
- 把默认 MCP 当预算而非资产:每个默认服务器都在给全体用户上"上下文税",默认集应从"能力越多越好"转为"能不放就不放",并给默认集设硬上限。
- 先做 skill 方案再谈 MCP:凡是"发一条命令拿一个结果"的(PR 查询、文档检索、搜索、截图对比……),先用 skill 封装 CLI/REST,参考 skills/github-ops/SKILL.md(内含对不可信仓库内容的处理规范)与 skills/documentation-lookup/SKILL.md(限定每次最多 3 次工具调用的使用预算)的写法。
- 把"被裁撤"的服务器放进 opt-in 目录:不给默认集增负,但保留
command/args/env/description齐全的模板条目,让有需要的人一键复制。 - 给禁用行为提供"安装期过滤"语义:用一个环境变量在配置生成阶段做剔除,而不是让用户在每次运行后再手工删,可避免同步流程把用户删掉的服务器又加回来(这正是 scripts/codex/merge-mcp-config.js "add-only + disabled 过滤"要解决的问题)。
- 用测试锁定策略:把"默认集只有 X 个""禁用后不重新生成"写成断言,防止后续版本悄悄把默认集改回去(参考 tests/scripts/codex-hooks.test.js 与 tests/docs/mcp-management-docs.test.js 对文档措辞的约束)。
结语
ECC 的 MCP Connector Policy 用一份不到 50 行的策略文档,定义了一套可审计、可执行的默认连接器治理模型:准入双门槛 + 默认集上限 + 定期审计裁撤 + opt-in 目录兜底 + 安装期禁用开关。从 mcp-configs/mcp-servers.json 的目录形态、scripts/lib/mcp-config.js 的过滤实现、scripts/codex/merge-mcp-config.js 的合并纪律到测试套件的断言,仓库里的每一层都在为"少即是多"这一上下文效率原则服务。对任何被 MCP 服务器数量困扰的 Agent 使用者而言,这份策略文档和它的落地代码本身就是一份可参照的最佳实践样本。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00