MCP 工具列表少了几个:`enabled_tools` 与 `disabled_tools` 的生效顺序
配 MCP server 这件事最烦人的地方,是它出错的时候往往不报错。你在 config.toml 里老老实实写好了一台 server,重启 Codex(OpenAI Codex)之后一看,工具确实来了,但比你预期的少了两三个。没有红字,没有堆栈,就是安安静静地少。
这类”少了几个”有一种很容易被忽略的成因:配置里两张名单打了架。下面按我平时的排查顺序走一遍,先把”整台 server 没来”和”来了但工具不全”分开,再往下定位。
一、先分清是”整台 server 没来”还是”来了但工具不全”
这两种情况的处置完全不同,混在一起查会绕远路。先用只读命令看一眼:
codex mcp list
在 codex-cli 0.147.0(Windows 11)上,这条命令输出的表头是 Name | Command | Args | Env | Cwd | Status | Auth 七列。本机三台 stdio server 的 Status 列都是 enabled、Auth 列都是 Unsupported。
顺带说一个对你有用的细节:Env 列里的环境变量值会被打成 *****,只留键名。也就是说这条命令的输出自带脱敏,贴到工单里或者发给同事看是相对安全的(当然贴之前自己再扫一眼 Command、Args、Cwd 三列有没有暴露目录结构)。
再看一眼整体健康度:
codex doctor --summary
在 codex-cli 0.147.0(Windows 11)上,doctor 的 Configuration 分组里有一行 mcp,格式是 N server (N stdio) · N disabled。这一行直接告诉你 Codex 认下来几台 server、其中几台是禁用状态。
判定分岔就在这里:
- 如果你要的那台 server 根本没出现在
codex mcp list里,或者doctor那一行的disabled计数不是 0 —— 先往 server 这一层查,跳到第三节; - 如果 server 在列表里、
Status是enabled,只是它提供的工具少了几个 —— 那就是第二节这回事。
二、两张名单同时写了,disabled_tools 后生效
官方《Configuration Reference》在 mcp_servers.<id>. 下给了两个控制工具粒度的键:enabled_tools 和 disabled_tools。关键的一句是:disabled_tools 是在 enabled_tools 之后套用的。
顺序摆在这里,结论就很干脆:两个键都配的时候,以 deny 为准。一个工具即使写进了 enabled_tools,只要它同时出现在 disabled_tools 里,最终还是不可用。
这个坑之所以容易踩,是因为直觉上很多人会把 enabled_tools 理解成”最终名单”——我都白纸黑字点名要这个工具了,它凭什么不来?但配置的执行顺序是先过白名单再过黑名单,后面那道工序有最终解释权。跟防火墙规则里 deny 压 allow 是一个套路,只是这里没有任何提示告诉你某条规则被后一条盖掉了。
排查动作也就很直接了:打开 ~/.codex/config.toml,把这台 server 对应的段落整个揪出来,两张名单摆在一起逐个字符比对。特别注意这几种情况:
- 同一个工具名在两张名单里都写了(最典型);
disabled_tools是你几个月前为了临时避坑加的,早就忘了;- 你复制了同事的配置段,他的
disabled_tools里有你需要的工具。
处置方式只有两条路:要么把这个工具从 disabled_tools 里删掉,要么干脆只留一张名单。我个人倾向于同一台 server 只用其中一个键——要么正着列白名单,要么反着列黑名单,不要两边都写。两边都写的配置,半年后你自己也读不懂谁压谁。
一段组合示例:
[mcp_servers.demo]
command = "npx"
args = ["-y", "<你的 MCP server 包名>"]
enabled = true
startup_timeout_sec = 120
enabled_tools = ["<工具名 A>", "<工具名 B>"]
# 同一台 server 别再叠一张 disabled_tools,否则以它为准
以上为按官方文档键位组合的示例,未逐项实测,以官方文档为准。
三、server 这一层的几个常见原因
如果第一节的判定指向”整台 server 没来”,官方配置键里有这么几个地方值得依次看:
| 键 | 官方默认值 | 跟”看不到”的关系 |
|---|---|---|
mcp_servers.<id>.enabled | true | 显式设成 false 就是把这台 server 关掉;doctor 的 mcp 行会给出一个 disabled 计数,官方未说明该计数的具体口径,按字面理解应为被禁用的 server 数 |
mcp_servers.<id>.startup_timeout_sec | 10 | 启动慢的 server 需要显式调大 |
mcp_servers.<id>.required | — | 官方说明是:启用的 server 初始化失败则启动失败 |
mcp_servers.<id>.tool_timeout_sec | 60 | 管的是单次工具调用,不是列表 |
启动超时那一行值得单独说:默认只有 10 秒。一台需要现拉依赖、现起运行时的 server,10 秒经常不够。在 codex-cli 0.147.0(Windows 11)的本机 config.toml 里,就有一台 server 显式写了 startup_timeout_sec = 120。如果你的 server 属于慢启动型,先把这个值调大再排查别的,能省不少时间。
还有一个更基础、也更容易被跳过的可能:配置文件根本没被加载。在 codex-cli 0.147.0(Windows 11)上,我故意用 codex -c 'features=[unclosed' doctor --summary 塞了一段语法不合法的 TOML,结果是 doctor 照常跑完没有崩,但 Notes 区多了一行:
✗ config config could not be loaded - Fix the reported config error, then rerun codex doctor.
这条一手观测的意义在于:配置坏了,命令不一定会拒绝启动,但 doctor 会明确告诉你配置没加载成功。所以只要出现”我明明改了配置但一点反应都没有”,第一步就该跑 codex doctor --summary 看这一行,而不是继续在名单里找错别字——名单写得再对,文件没加载也是白搭。
最后一个容易张冠李戴的点:官方配置键里还有 plugins.<plugin>.mcp_servers.<server>.* 这一族,用于插件自带的 MCP server 的启停与工具审批。也就是说,如果那台 server 是随插件来的,你在顶层 mcp_servers 里怎么改都不会命中它,得去插件那一族键里找。想确认插件侧的情况,可以跑 codex plugin list——在 codex-cli 0.147.0(Windows 11)上它按 marketplace 分组,列出 PLUGIN | STATUS | VERSION | PATH 四列,STATUS 观测到 installed, enabled 与 not installed 两种值。
四、改完怎么验证
别只靠”感觉工具回来了”,走一遍固定动作:
- 跑
codex doctor --summary,先确认 Configuration 分组里的config那一行是 loaded 而不是✗。配置没加载,后面全部免谈。 - 跑
codex mcp list,确认目标 server 在表里且Status是enabled。 - 想单看某一台 server 的配置,
codex mcp还带get子命令(官方 help 里codex mcp的子命令为list/get/add/remove/login/logout)。它的具体输出格式我这边没有逐一核对,你自己跑一次看。 - 再回头对照
doctor里mcp那一行的N disabled计数,看这个数字跟改配置之前比有没有变化。改之前先记下来,改之后再看一眼,两个数一比就知道你这次改动有没有落到 Codex 认下来的配置上。
顺带提一个别踩的坑:--strict-config 不是万能的拼写检查器。在 codex-cli 0.147.0(Windows 11)上,我执行 codex -c model_reasoning_effortt=high --strict-config exec --help(注意键名多了个 t),命令正常打印了 help,没有报未知字段。说明这项校验发生在真正加载配置去跑会话的路径上,--help 这类不进入会话的调用不会触发。所以别指望加个 --strict-config 跑个 help 就能验出配置里的错字。
五、什么情况说明不是这个原因
以下几种迹象出现时,就别在两张名单上死磕了:
- 配置里压根没写过
enabled_tools/disabled_tools。两个键都不存在,就不存在谁盖谁的问题,往第三节的 server 层查。 - 工具在列表里,但调用的时候才出问题。名单是控可见性的;调用环节还有别的键在管,比如
tool_timeout_sec(默认 60)管单次调用时长,default_tools_approval_mode和tools.<tool>.approval_mode这一族名字里带 approval 的键管的是要不要弹审批。工具看得见、点了没反应或者卡住,方向在那边不在这边。 doctor里config那一行是✗。这时候你改名单改到天亮也不会生效,先把 TOML 语法修好。- 那台 server 是插件带来的。顶层
mcp_servers改了不生效很正常,去plugins.<plugin>.mcp_servers.<server>.*那边。 - 同一台机器上不同时间行为不一致。在本机采集时,前后十几分钟内
codex --version从codex-cli 0.131.0变成了codex-cli 0.147.0(which -a codex全程只有一个可执行文件)。Codex 有自更新能力,check_for_update_on_startup默认true。所以排查任何”昨天还好好的”问题之前,先跑一次codex --version拿实时版本号,别用记忆里的版本对着文档看。
最后补一句关于求助的:如果你要把诊断结果贴给别人,codex doctor --json 的官方说明是输出脱敏的机器可读报告,codex mcp list 的 Env 列也做了掩码。这两个是相对安全的对外材料,而直接把 ~/.codex/config.toml 整份贴出去不是——那里面可能有 env_vars、bearer_token_env_var 之类指向凭据的配置线索。
相关阅读
- MCP 服务器配了
required = true,整个 Codex 就起不来了 - 给 Codex 接一个 MCP server 的完整流程:配置、启动超时与工具审批怎么调
- Codex 插件实战:三个 marketplace 怎么读、插件怎么装怎么停
- Codex 的六个使用面:一张图看懂该用哪个
本文依据 Codex 官方文档(learn.chatgpt.com/docs/ 的《Configuration Reference》页面)整理,核对日 2026-08-09;文中标注「本机实测」的部分基于 codex-cli 0.147.0 / Windows 11 环境下的只读命令输出。产品功能、模型与价格以官方最新说明为准。