Codex App 中 MCP 进程重复启动与无法回收问题排查
太阳作者太阳
原创内容采用 CC-4.0 协议发布,转载请注明出处

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

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

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

这篇文章用于持续记录这个问题。当前结论、上游 issue 状态和验证结果以后有变化,会直接更新在这里。Chrome DevTools MCP 的安装和浏览器连接方法仍放在在 Codex 中接入 Chrome DevTools MCP

当前结论

截至 2026 年 7 月 29 日,我的判断是:

  • MCP 配置语法没有写错。
  • Codex 会在 thread/startthread/resume 时初始化已启用的 STDIO MCP,不需要等到真正调用工具。
  • 可见对话之外,还有旧任务恢复、空白任务预创建、自动标题生成等内部 thread。
  • 每个 thread 都会得到一套独立的 MCP 进程。
  • thread 不可见或内部任务完成后,相关 MCP 进程没有可靠退出。
  • 当前 Codex 版本没有公开的按需启动 MCP 或 thread cleanup 配置。

为每个活动 thread 创建独立 MCP,可以视为当前实现方式。已经结束的 thread 一直保留 MCP 子进程,则是生命周期和回收问题。

本机复现

复现时的版本是:

Codex App 26.721.4979.0
codex-cli 0.145.0
Windows

用户配置中启用了 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 本来就会让一个实例显示成多个进程。

配置有没有问题

配置本身有效,但放在用户级 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 能解决的问题。

目前可用的规避方法

不使用时禁用

最稳妥的做法是在现有配置块中关闭:

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

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

enabled = true

修改后要重新加载 MCP 配置或重启 Codex。仅仅不调用工具,不能阻止服务启动。

退出 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 上看到的现象一致。

后续怎么验证修复

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

  1. 记录 Codex App 和 CLI 版本。
  2. 完全退出 Codex,清理旧进程,得到基线。
  3. 启用一个 STDIO MCP,启动一个新对话。
  4. 不调用任何 MCP 工具,等待自动标题生成结束。
  5. 切换到旧对话再返回。
  6. 等待两分钟,重新统计 MCP 进程。

如果当前可见 thread 保留一套 MCP,而标题生成和已经卸载的 thread 都能退出,进程数应回到稳定基线。仅仅关闭某个 issue,或者重启后暂时看不到旧进程,不能证明问题已经修好。

跟进记录

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 作为日常规避。

参考资料