Codex MCP server 启动超时:默认只有 10 秒
有一类问题特别容易被误判成”配置写错了”:MCP server 在你自己机器上跑得好好的,换一台机器、或者刚开机第一次启动 Codex(OpenAI Codex)时就是接不上;有时候重开一次又正常了。这种”时好时坏、跟机器状态有关”的表现,配置文件本身往往一个字都没错——真正卡住你的是一条默认值:MCP server 的启动超时,官方给的默认只有 10 秒。
下面按排查顺序走一遍。文中所有配置键都取自官方《Configuration Reference》页,标注「本机实测」的部分来自 codex-cli 0.147.0(Windows 11)上执行的只读命令。
先把两个超时分清楚
在 Codex 的配置里,mcp_servers.<id> 这一层底下有两个长得很像的超时键,含义完全不同:
| 键 | 默认值 | 管什么 |
|---|---|---|
startup_timeout_sec | 10 | server 启动(初始化)阶段的等待上限 |
tool_timeout_sec | 60 | 单次工具调用的等待上限 |
同一层还有一个 startup_timeout_ms。官方配置参考里列了这个键,但没有给它的默认值,也没有说明它和 startup_timeout_sec 同时出现时谁优先——我不打算替官方推断这件事,所以下面的例子统一只写 startup_timeout_sec。
10 秒这个数字是本篇的关键。一个 stdio 型的 MCP server,启动时要做的事情可能包括:拉起运行时进程、加载依赖、读取环境变量、建立第一次握手。这些在温机状态下也许两三秒就完事,但冷启动、磁盘忙、杀毒软件扫描新进程、或者依赖包第一次解包的时候,超过 10 秒一点都不稀奇。这就解释了为什么它”时好时坏”:你不是在跟一个必然失败的配置打交道,你是在跟一条卡在临界线上的耗时打交道。
配置参考里还有一个相关的开关:features.skill_mcp_dependency_install,默认 true,官方说明是”允许提示并安装 MCP 依赖”。如果某次启动恰好触发了依赖安装,耗时会跟平时完全不是一个量级——这也是同一台机器上第一次特别慢、后面就正常的一种可能来源。
怎么确认是启动超时,而不是别的毛病
先做一件事:确认你当前跑的是哪个版本。本机实测过一个很有意思的现象——同一台机器上,采集开头 codex --version 输出 codex-cli 0.131.0,十几分钟后再执行同一条命令变成了 codex-cli 0.147.0,而 which -a codex 全程只有一个可执行文件。配置项的默认值是会随版本变的,所以排查任何”默认行为”问题,都得以当次的实时输出为准,别用记忆里的版本号。
codex --version
第二步,看 Codex 到底认到了几个 MCP server:
codex mcp list
在 codex-cli 0.147.0(Windows 11)上,这条命令输出的表头逐字是 Name | Command | Args | Env | Cwd | Status | Auth。本机三个 stdio server 的 Status 列都是 enabled、Auth 列都是 Unsupported。这里要说清楚一个容易误读的点:Status 列反映的是这个 server 有没有被启用,不能直接当成”启动成功了”来读——本机只观测到 enabled 这一个取值,我没有构造过超时场景,所以不知道超时之后这一列会显示成什么,也不会替它编一个。
顺带一个实用信息:codex mcp list 的 Env 列会把环境变量的值打成 *****,只显示键名。也就是说这条命令的输出自带脱敏,贴到工单或群里问人是安全的(当然,命令行本身和 Cwd 列仍可能带出你的目录结构,贴之前扫一眼)。
第三步,跑一次总体体检:
codex doctor --summary
本机实测这条命令的 Configuration 分组里有一行专门给 MCP,格式是 mcp 后面跟着 N server (N stdio) · N disabled 这样的计数。把这个计数和你 config.toml 里实际写了几个 server 对一下——如果数目对得上,说明配置是被读进去了,问题出在”读进去之后启动不起来”这一段,往启动超时这个方向查是合理的。
codex mcp 还有 get 子命令(本机只核对过子命令清单,没有逐一取过它的输出),可以用来看单个 server 的配置。另外 codex doctor --json 的官方说明是 “Emit a redacted machine-readable report”,是脱敏过的报告,需要交给别人分析时用这个更稳妥。
处置:把启动超时显式调大
官方配置参考里给出的做法就是在对应 server 下把 startup_timeout_sec 写大。配置文件位置是 $CODEX_HOME/config.toml,默认 ~/.codex/config.toml。
[mcp_servers.slow_server]
command = "<启动这个 server 的可执行文件>"
args = ["<参数1>", "<参数2>"]
startup_timeout_sec = 120
以上为按官方文档键位组合的示例,未逐项实测,以官方文档为准。本机的 config.toml 里确实有一个 stdio server 把这个值设成了 120——这不是官方推荐值,只是一个”重的 server 需要远超默认值”的实际例证。
调多大合适?我没有耗时数据可以给你(本机没有跑过任何模型对话请求,也没有采集过 server 的实际启动耗时),所以只能给方法:先设一个明显宽松的值确认问题确实消失,再往回收。这么做的意义在于先证伪——如果设到很宽松还是接不上,那就不是超时的锅,可以马上转向别的方向,别在这个键上继续磨。
这里顺带澄清一个容易被想当然的做法:Codex CLI 确实有 -c, --config <key=value>,支持点号路径表示嵌套(官方给的例子之一就是 -c shell_environment_policy.inherit=all),value 按 TOML 解析,解析失败则按字面字符串处理。看上去很像可以”临时覆盖一下超时值试试”,但我要把话说明白:本机没有验证过用这种方式覆盖 MCP 启动超时的实际效果,而且 codex mcp list 的表头里压根没有跟超时相关的列,你也没法靠它看出这次覆盖有没有起作用。所以这条选项只当作”配置覆盖能力”来了解,别把它当成验证超时值的手段——要验证,还是老老实实改 config.toml 再走下面那套流程。
required 决定这次故障有多严重
同一层还有一个键值得单独说:required。官方说明是”启用的服务器初始化失败则启动失败”。
这条决定了同样一次启动超时,你看到的症状完全不同:
required没开:这个 server 挂掉,Codex 本身照常可用,你只是发现某些工具”不见了”。required开着:这个 server 初始化失败会把整个启动一起拖垮。
所以如果你的症状是”Codex 整个起不来”而不是”某个工具没了”,就顺手看一眼有没有哪个 server 设了 required。反过来,如果某个 server 你近期根本不用,比调超时更干脆的处置是把它的 enabled 设成 false(这个键默认 true),先让主流程恢复,回头再单独收拾它。
改完怎么验证
别改完就直接开会话赌一把,按下面顺序验证,每一步都是只读命令:
codex doctor --summary,先在 doctor 输出里找config这一项。本机实测过一个很有价值的边界:故意用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 这一行告诉你。你手改 TOML 之后第一件事就该看它。- 同一份 doctor 输出里看
mcp那一行的计数有没有变化。 codex mcp list,确认目标 server 还在表里、Status列没有变差。- 最后才是开一次真实会话,看那个 server 提供的工具是不是回来了。
顺带说一下 --strict-config 这个选项:它的作用是”config.toml 里出现本版本不认识的字段时直接报错退出”,听起来像是拼写检查神器,但本机实测有边界——执行 codex -c model_reasoning_effortt=high --strict-config exec --help(注意 effortt 是故意拼错的),命令正常打印了 help,没有报未知字段错误。说明这个校验发生在真正加载配置去跑会话的时候,--help 这类不进入会话的路径不触发。所以别指望用 --strict-config 加 --help 来”快速检查配置有没有拼错”,那样什么都检查不出来。
什么情况说明不是启动超时
这一节比上面几节更重要——排查最怕的是一条道走到黑。出现下面这些迹象,说明你该换方向了:
doctor 报 config could not be loaded。 那你改的那些键根本没被加载,超时值写多大都不起作用。先把 TOML 语法修好。
工具”少了几个”而不是”整个 server 没了”。 这更像是工具级的开关在起作用。配置参考里 enabled_tools 和 disabled_tools 都在 mcp_servers.<id> 这一层,并且官方明确说明 disabled_tools 是在 enabled_tools 之后生效的——两个都配的时候以 deny 为准。这条挺反直觉,很容易写完之后奇怪”我明明在白名单里放了它”。
你的 server 是 url 型(streamable HTTP)而不是 stdio 型。 这类 server 走的是另一套配置:auth(默认 oauth,可设 chatgpt)、bearer_token_env_var、http_headers、scopes、oauth_resource,另外顶层还有 mcp_oauth_credentials_store、mcp_oauth_callback_port、mcp_oauth_callback_url。接不上的时候先排查认证与回调,而不是启动耗时。密钥一律走 bearer_token_env_var 指向的环境变量,别把 <YOUR_API_KEY> 直接写进 config.toml。
卡在了某个需要你确认的弹窗上。 配置参考里 approval_policy.granular.mcp_elicitations 这个键的说明是”MCP elicitation 弹窗允许还是自动拒绝”。如果这类交互被自动拒绝,你看到的表现可能是”这个 server 就是不干活”,跟超时是两码事。
你其实在找 codex mcp-server。 本机 codex --help 里这两个子命令同时存在,说明也完全不同:mcp 是 “Manage external MCP servers for Codex”(管理你接进 Codex 的外部 server),mcp-server 是 “Start Codex as an MCP server (stdio)“(把 Codex 自己当成一个 MCP server 起起来)。想接第三方工具却敲了后者,怎么调超时都不会有结果。
最后提一句 experimental_environment 这个键,取值 local / remote。名字里带 experimental,属于实验阶段的配置项,排查阶段不建议顺手把它开起来当解法——把变量控制住,一次只动一个键,才知道到底是哪一下起的作用。
相关阅读
- MCP 工具列表少了几个:
enabled_tools与disabled_tools的生效顺序 - MCP 服务器配了
required = true,整个 Codex 就起不来了 - 给 Codex 接一个 MCP server 的完整流程:配置、启动超时与工具审批怎么调
- Codex 的六个使用面:一张图看懂该用哪个
本文依据 Codex 官方文档(learn.chatgpt.com/docs/ 的《Configuration Reference》页面)整理,核对日 2026-08-09;文中标注「本机实测」的部分基于 codex-cli 0.147.0 / Windows 11 环境下的只读命令输出。产品功能、模型与价格以官方最新说明为准。