Codex App 中 MCP 进程重复启动与无法回收问题排查

太阳作者太阳
原创内容采用 CC-4.0 协议发布,转载请注明出处

我在 Windows 任务管理器里发现了很多 Node.js 进程。它们都来自 chrome-devtools-mcp,数量还会随着 Codex 对话增加。

奇怪的是,当时只打开了一个可见对话,也没有调用 Chrome DevTools MCP。继续检查后,我确认这不是 Chrome 页面没有关闭,而是 Codex App 为内部 thread 重复初始化 STDIO MCP,thread 结束后又没有及时回收子进程。

这篇文章用于持续记录这个问题。2026 年 8 月,我先在 CodeGraph 上遇到进程累积,后来又看到 Codex 自带的 node_repl.exe 从 6 个增加到 31 个。继续核对后发现,node_repl.exe 不是用户安装的第三方 MCP,但它本身是 Codex Desktop 内置的本地工具服务,不能再简单归为“与 MCP 无关”。Chrome DevTools MCP 的安装和浏览器连接方法仍放在在 Codex 中接入 Chrome DevTools MCP

当前结论

截至 2026 年 8 月 20 日,我的判断是:

  • MCP 配置语法没有写错。
  • Codex 会在 thread/startthread/resume 时初始化已启用的 STDIO MCP,不需要等到真正调用工具。
  • 可见对话之外,还有旧任务恢复、空白任务预创建、自动标题生成等内部 thread。
  • 每个 thread 都会得到一套独立的 MCP 进程。
  • thread 不可见或内部任务完成后,相关 MCP 进程没有可靠退出。
  • 当前 Codex 版本没有公开的按需启动 MCP 或 thread cleanup 配置。
  • node_repl.exe 是 Codex Desktop 随 cua_node 一起下发的内置本地工具服务,用于受限 JavaScript 执行、Code Mode、插件和 Computer Use 一类能力。
  • 它不是 Chrome DevTools、CodeGraph 这类用户配置的第三方 MCP,但在 Codex 内部按本地 STDIO 工具/MCP 服务管理。
  • 当前版本会把这类进程扩张到几十个,并且只缓慢回收;这已经不是原先观察到的 6 个稳定实例。

为每个活动 thread 创建独立 MCP,可以视为当前实现方式。已经结束的 thread 一直保留第三方 MCP 或内置 node_repl.exe,则是生命周期和回收问题。两类进程的用途不同,但都受 Codex app-server 管理。

本机复现

复现时的版本是:

Codex App 26.721.4979.0
codex-cli 0.145.0
Windows

按照 Codex MCP 配置文档,用户配置中启用了 Chrome DevTools MCP:

[mcp_servers.chrome-devtools]
command = "npx"
args = ["-y", "chrome-devtools-mcp@latest", "--autoConnect"]

@latest--autoConnect 会影响启动的版本以及连接哪一个 Chrome,但它们不是重复创建 MCP 的触发条件。触发来自 Codex 的 thread 初始化。

我先查询了进程命令行和父进程:

$chromeMcpProcesses = Get-CimInstance Win32_Process |
  Where-Object {
    $_.Name -eq "node.exe" -and
    $_.CommandLine -match "chrome-devtools-mcp"
  }

$chromeMcpProcesses |
  Select-Object ProcessId, ParentProcessId, CreationDate, CommandLine

$chromeMcpProcesses.Count

第一次检查有 5 套 Chrome DevTools MCP,共 15 个 Node.js 进程。稍后 Codex 又恢复了一个旧 thread,数量变成 6 套、18 个进程。

每套包含:

1 × npx-cli.js
1 × chrome-devtools-mcp 主进程
1 × telemetry watchdog

父进程最终都指向同一个 Codex app-server:

ChatGPT.exe
└─ codex.exe app-server
   └─ cmd.exe
      └─ node.exe npx-cli.js
         └─ node.exe chrome-devtools-mcp.js
            └─ node.exe telemetry/watchdog/main.js

这排除了“其他终端碰巧启动了相同服务”的可能。

一个可见对话为什么出现 6 套 MCP

Codex 桌面日志给出了对应的时间线:

13:18:06  thread/resume
13:18:08  thread/resume
13:18:47  thread/start
13:19:19  thread/start,创建当前可见对话
13:19:20  启动一个界面不认识的内部 conversation
13:21:48  thread/resume

这些时间与 6 组 MCP 进程的创建时间一一对应。三个 thread/resume 来自旧 thread;两个 thread/start 分别对应空白任务初始化和当前任务。

第六组更值得注意。日志先报告:

Received turn/started for unknown conversation

约 30 秒后出现:

ThreadMetadataGenerationService
Failed to generate thread title
Timed out waiting for structured result.
Received turn/completed for unknown conversation

这说明 Codex 为自动生成标题创建了内部 thread。标题任务已经结束,但它启动的 MCP 进程仍然存活。

在这次检查中,没有 Chrome DevTools MCP 工具调用,也没有子代理。进程增长发生在 thread/startthread/resume 和标题生成阶段。

怎么查看 Codex 的 thread 事件

Windows 版日志通常在:

C:\Users\TARGET_USER\AppData\Local\Packages\OpenAI.Codex_2p2nqsd0c76g0\
LocalCache\Local\Codex\Logs\YYYY\MM\DD\

可以搜索这些事件:

$codexLogRoot = Join-Path $env:LOCALAPPDATA `
  "Packages\OpenAI.Codex_2p2nqsd0c76g0\LocalCache\Local\Codex\Logs"

rg -n "method=thread/(start|resume)|ThreadMetadataGenerationService|unknown conversation" `
  $codexLogRoot

判断是否为同一个问题时,我会同时满足三个条件:

  • MCP 进程的父进程最终是 codex.exe app-server
  • 创建时间紧跟 thread/startthread/resume
  • thread 完成、切换或隐藏后,进程数没有回到之前的基线。

只看到多个 Node.js 进程还不够。npx、MCP 主程序和 watchdog 本来就会让一个实例显示成多个进程。

CodeGraph 一次累积了 13 套进程

2026 年 8 月 19 日,我发现 CodeGraph 查询不仅返回了大量无关源码,后台进程也一直没有回到基线。脱敏统计后,同一个 codex.exe 下有 13 个 CodeGraph 进程树,共 39 个相关进程。每套大致是:

codex.exe
└─ cmd.exe
   └─ node.exe
      └─ node.exe

这些进程在十几分钟内陆续创建,旧实例没有随着查询结束退出。对文档和已知路径进行简单定位时,CodeGraph 带来的调用链信息并没有抵消进程与上下文成本,使用 rg 反而更直接。

执行 codegraph uninstall 后,我重新检查了三项:

codegraph command: not found
codegraph cmd/node processes: 0
.codegraph directory exists: True

这说明卸载已经移除了命令和运行中的 MCP 进程,但项目索引目录仍然保留。索引文件本身不会继续启动服务,可以留待后续判断,不必为了停止 MCP 一并删除。

同类问题可以用下面的方式先做脱敏统计。不要直接输出完整命令行,其中可能包含内部路径或凭据:

$processes = Get-CimInstance Win32_Process |
  Where-Object {
    $_.CommandLine -match "(?i)codegraph" -and
    $_.Name -in @("cmd.exe", "node.exe")
  }

$processes.Count
$processes |
  Group-Object Name |
  Select-Object Name, Count

node_repl.exe 到底是什么服务

它来自 Codex Desktop 自动下载的 cua_node 运行时:

C:\Users\OWNER\AppData\Local\OpenAI\Codex\runtimes\cua_node\BUILD\bin\node_repl.exe

我在 2026 年 8 月 20 日检查到的 runtime manifest 是:

cua-node 0.0.8
Node.js 24.19.0
Windows x64

这个程序不是普通的交互式 Node.js 命令行,也不是用户安装的 Chrome DevTools 或 CodeGraph。它提供受限制的 JavaScript 执行环境,让 Codex 可以在一次程序中调用多个工具、处理结果,再把较小的结果交还给模型。Codex 的 Code Mode、插件、内置 Browser、Computer Use 和自动化会用到这条执行链。

从进程形态看,它同时具备两个身份:

  • 对用户来说,它是 Codex 随应用下发的内部运行时。
  • 对 app-server 来说,它是通过 STDIO 连接的内置本地工具服务,在部分配置和 issue 中直接登记为 mcp_servers.node_repl

因此,“它不是 MCP”这个说法不准确。更合适的表述是:它不是用户配置的第三方 MCP,但 Codex 确实按内置 MCP/工具服务使用它。

OpenAI Programmatic Tool Calling 文档也使用 JavaScript 编排多个工具,但写的是 hosted runtime。它能解释这种工具为什么需要程序化执行能力,不能证明云端 PTC 和 Codex Desktop 的 cua_node 是同一套实现。node_repl.exe 的具体协议、池大小和回收策略仍没有公开说明。

当前版本已经增加到几十个进程

2026 年 8 月 20 日重新检查时,版本已经变为:

Codex App 26.814.5517.0
codex-cli 0.148.0-alpha.15
Windows

同一个 codex.exe app-server 下出现了 31 个 node_repl.exe

ChatGPT.exe
└─ codex.exe app-server
   ├─ node_repl.exe
   ├─ node_repl.exe
   └─ ... 共 31 个

这 31 个进程的命令行指纹相同,没有参数,也没有子进程。合计工作集约 313 MB、私有内存约 89 MB,共 626 个线程,累计 CPU 时间只有约 1 秒。它们不是正在繁忙计算,而是大量空闲 worker 留在 app-server 下。

五分钟内,数量从 31 个降到 28 个,工作集降到约 283 MB,说明当前版本并非完全不回收。但最早的实例已经存活约 34 分钟,28 个进程仍有 560 个线程,不能再把它描述为固定的 6 个运行时池。

当前更像是运行时池扩张到高水位后延迟、部分回收。它是否最终会全部回到低位,还需要更长时间的空闲观察;现有证据已经足够确认回收速度和保留数量不合理。

这次检查还有一个限制:当前 Codex Desktop 进程对应的三个日志文件都是空文件,无法像 7 月那次一样把每个进程与 thread/startthread/resume 对齐。任务 session 记录显示同期存在大量本地工具调用,但进程数小于调用次数,因此不能断言“每次工具调用永久创建一个进程”。更可能的情况是 worker 会复用,同时在 thread、自动化或工具会话之间不断扩容。

判断这类进程是否异常,应继续看:

  • 数量是否随着 thread、自动化或工具活动增长。
  • 空闲后能否回到一个有明确上限的基线。
  • 完全退出 Codex 后是否归零。
  • 是否出现持续 CPU、私有内存或线程增长。

配置有没有问题

配置本身有效,但放在用户级 config.toml 意味着所有本地 Codex thread 都会继承它。对于 Chrome DevTools 这类常驻成本较高的 STDIO MCP,这个范围偏大。

把配置移到可信项目的 .codex/config.toml 可以缩小生效范围,但同一项目内的多个 thread 仍会分别启动。它不能修复回收问题。

当前手册公开的 MCP 配置包括 enabled、工具白名单、启动超时和工具超时等选项,没有“第一次调用工具时再启动”的 lazy 配置。我本机的 codex features list 也没有可用的 thread_listener_cleanup 或类似开关。

因此,这不是修改 startup_timeout_secrequiredenabled_tools 能解决的问题。

目前可用的规避方法

node_repl.exe 只能通过完整退出暂时回收

目前没有公开配置可以限制 node_repl.exe 池大小,也没有 code_mode_host 的用户开关。相关 issue 的实测结果一致:完全退出 Codex/ChatGPT 后,app-server 和它的 node_repl.exe 子进程会一起消失;只关闭任务、标签页或窗口不可靠。

我会先从系统托盘完整退出 Codex,再确认:

Get-CimInstance Win32_Process |
  Where-Object Name -eq "node_repl.exe" |
  Select-Object ProcessId, ParentProcessId, CreationDate

预期结果是 0 个。如果 codex.exe 已经退出,node_repl.exe 仍然存在,才属于真正脱离父进程的孤儿进程。当前观察到的几十个实例都还有存活的 app-server 父进程,问题发生在应用运行期间的池管理和回收,不是退出后的孤儿残留。

不要在 Codex 运行时逐个结束 node_repl.exe。其他用户的受控测试中,仍然存活的 app-server 会重新拉起 worker。需要止损时,完整退出应用比批量杀子进程可靠。

减少同时打开和恢复的任务、暂停高频自动化、暂时不用 Browser 或 Computer Use,可以降低触发频率,但不是修复。node_repl.exe 是内置服务,删除 cua_node 目录也没有意义,应用仍可能重新下载运行时。

不使用时禁用

对于 Chrome DevTools 这类用户配置的第三方 MCP,最稳妥的做法仍是在现有配置块中关闭:

[mcp_servers.chrome-devtools]
enabled = false
command = "npx"
args = ["-y", "chrome-devtools-mcp@latest", "--autoConnect"]

需要浏览器调试时再改为:

enabled = true

修改后要重新加载 MCP 配置或重启 Codex。仅仅不调用工具,不能阻止服务启动。这个办法只针对相应的第三方 MCP,不会关闭 Codex 内置的 node_repl.exe

退出 Codex 后清理残留

先禁用 MCP,再从系统托盘完全退出 Codex。Windows 上只关闭窗口,应用可能仍留在后台。

如果 app-server 已经退出,但 Chrome DevTools MCP 仍在,可以先列出精确目标:

Get-CimInstance Win32_Process |
  Where-Object {
    $_.Name -eq "node.exe" -and
    $_.CommandLine -match "chrome-devtools-mcp"
  } |
  Select-Object ProcessId, ParentProcessId, CommandLine

确认后再清理:

Get-CimInstance Win32_Process |
  Where-Object {
    $_.Name -eq "node.exe" -and
    $_.CommandLine -match "chrome-devtools-mcp"
  } |
  ForEach-Object {
    Stop-Process -Id $_.ProcessId -Force
  }

不要执行 taskkill /IM node.exe。机器上可能还有开发服务器、构建工具和其他 Node.js 程序。

关闭使用统计

Chrome DevTools MCP 支持:

args = [
  "-y",
  "chrome-devtools-mcp@latest",
  "--autoConnect",
  "--no-usage-statistics",
]

这会关闭 Chrome DevTools MCP 的使用统计,但不能阻止 Codex 为每个 thread 启动 MCP,也不能代替进程回收。

上游问题

OpenAI Codex 仓库中已经有多份同类报告。

#11324 记录了多任务场景中 MCP 内存持续增长,以及归档 conversation 后进程仍然保留。#12491 更集中地描述 Codex App 在任务结束后没有回收 MCP 子进程,目前仍是 open。

#17574 直接记录了 chrome-devtools-mcp 随 subagent 和 thread spawn 持续累积,判断是 Codex App 的 lifecycle/teardown 问题。它目前也是 open。

#18881 处理的是替换 McpConnectionManager 时泄漏子进程,已经由 #19753 关闭。不过我在更新后的 codex-cli 0.145.0 和 Codex App 26.721.4979.0 上仍能通过 thread 恢复和标题生成复现,说明那个修复没有覆盖当前桌面端路径。

#25015 在 Linux app-server 上给出了受控复现:子代理完全不调用 MCP 工具,创建和关闭后仍会留下新的 MCP 进程栈。这个结果与我在 Windows 上看到的现象一致。

node_repl.exe 本身也已经有更直接的报告。#35485 记录 Windows Codex Desktop 为 thread 启动内置 node_repl.exe 后不及时回收,进程一直由同一个 app-server 持有,完全退出应用后才归零。它和我的进程路径、父进程、空闲 CPU、增长方式都一致。

#35582 在 macOS 自动化中观察到 284 个 cua_node/bin/node_repl worker。报告还确认,公开的 openai/codex 仓库没有 cua_nodenode_repl 的具体源码;仓库里的通用 code-mode host 已有连接复用和子进程 killwait 逻辑,真正决定 Desktop 如何选择和启动 cua_node 的代码位于私有 Desktop runtime。

#37672 描述了更严重的 Windows 启动扩张:127 个 node_repl.exe 与大量插件 helper 同时存活。该报告发现 features.code_mode_host=true 由 Desktop 启动参数注入,没有公开的用户配置开关;在那个版本中,禁用插件也没有降低 helper 数量。这个结果不能证明每个版本都有同样的插件枚举问题,但说明删除 runtime、逐个杀进程或随意修改 MCP 超时都不是可靠方案。

截至 2026 年 8 月 20 日,#35485 和 #35582 都仍是 open,没有负责人、milestone 或关联修复 PR。仓库里有人把问题记录得很清楚,但暂时没有维护者给出已发布修复或 node_repl 池大小的正式说明。

后续怎么验证修复

以后升级 Codex,我会按同一组步骤复查:

  1. 记录 Codex App 和 CLI 版本。
  2. 从系统托盘完全退出 Codex,确认第三方 MCP 和 node_repl.exe 都归零。
  3. 重新启动,只打开一个任务,不调用工具,记录基线。
  4. 分别执行普通本地工具调用、Programmatic Tool Calling、Browser 或 Computer Use,再记录进程数。
  5. 关闭任务或等它完成,分别等待 2 分钟、10 分钟和 30 分钟。
  6. 检查进程数、私有内存、线程数以及最早实例的存活时间。

第三方 MCP 应在对应 thread 结束后退出;内置 node_repl.exe 即使采用共享池,也应回到有明确上限的稳定基线。只看到重启后暂时归零,或者某个 issue 被关闭,都不能证明运行期间的回收问题已经修好。

跟进记录

2026-08-20

  • Codex App 已更新到 26.814.5517.0,codex-cli 为 0.148.0-alpha.15,内置 runtime 为 cua-node 0.0.8 和 Node.js 24.19.0
  • 同一个 app-server 下的 node_repl.exe 峰值达到 31 个;五分钟后降到 28 个,说明存在部分回收,但仍保留 560 个线程和约 80 MB 私有内存。
  • 所有实例都是 app-server 的直接子进程,命令行指纹相同,没有子进程,CPU 基本空闲。
  • 当前 Desktop 日志文件为空,无法复用 7 月的日志时间线;进程树和 session 工具调用记录仍能确认它属于 Codex 内置运行时。
  • 旧文“稳定在 6 个、不是 MCP”的结论已修正:它不是第三方 MCP,但确实是 Codex 内置的 STDIO 工具/MCP 服务。
  • 上游 #35485、#35582 与本机现象直接对应,目前仍未见已发布修复。现阶段最可靠的止损方式是从系统托盘完整退出应用,不逐个结束 worker,也不删除 runtime。

2026-08-19

  • CodeGraph 在同一个 codex.exe 下累积了 13 套进程树,共 39 个相关进程。
  • codegraph uninstall 后命令不可用,相关 cmd.exenode.exe 进程归零,.codegraph 索引目录保持不变。
  • 使用定点 rg 查询替代 CodeGraph 后,路由、数据库事务和文档链接都能用少量输出完成定位。
  • 当时 Codex 自带的 node_repl.exe 稳定在 6 个实例,合计约 61 MB,没有子进程;一次额外工具调用没有让数量继续增加。
  • 8 月 19 日的证据只支持把 CodeGraph 判定为已确认的第三方 MCP 进程残留;node_repl.exe 当时尚未观察到增长,后续结论以 8 月 20 日记录为准。

2026-07-29

  • 在 Windows Codex App 26.721.4979.0codex-cli 0.145.0 上复现。
  • 一个可见对话期间出现 6 套 Chrome DevTools MCP,共 18 个 Node.js 进程。
  • 进程创建时间与三个 thread/resume、两个 thread/start 和一个自动标题生成 thread 对齐。
  • 自动标题生成超时完成后,对应 MCP 进程没有退出。
  • 当前未发现按需启动或 thread cleanup 配置,继续使用 enabled = false 作为日常规避。