Subagents leak stdio MCP helper trees in Codex App; xcodebuildmcp and chrome-devtools-mcp accumulate indefinitely

Open 💬 6 comments Opened Apr 12, 2026 by jaewon-kim-dev
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

26.409.20454 (build 1462)

What subscription do you have?

Pro

What platform is your computer?

Darwin 25.3.0 arm64 arm

What issue are you seeing?

Codex App appears to leak stdio MCP helper process trees when subagents are spawned.

On my machine, every time Codex creates a subagent / thread spawn, it appears to initialize MCP again for the subagent session, including:

  • npm exec xcodebuildmcp@latest mcp
  • npm exec chrome-devtools-mcp@latest --isolated --no-usage-statistics --no-performance-crux

Those helpers are not being cleaned up reliably after the subagent/session closes. Over time they accumulate and drive memory pressure and swap usage extremely high.

Current process state I captured while Codex App was still running:

  • Codex app-server PID: 67522
  • stale/accumulated npm exec ... parents: 394
  • node ... xcodebuildmcp mcp children: 198
  • chrome-devtools-mcp children: 199
  • total related processes: 791
  • combined RSS of those related processes: about 13.5 GB

Breakdown:

  • npm exec ... parents: about 6.9 GB RSS
  • xcodebuildmcp children: about 3.2 GB RSS
  • chrome-devtools-mcp children: about 3.4 GB RSS

This is large enough that macOS starts consuming tens of GB of swap.

The pattern I see in logs is:

  • spawn_agent
  • thread_spawn
  • session_init.mcp_manager_init
  • Codex session closes almost immediately
  • but the spawned MCP helper processes remain alive for tens of minutes or longer

So the issue looks like a lifecycle / teardown bug in Codex App rather than a bug inside xcodebuildmcp itself.

What steps can reproduce the bug?

I do not yet have a minimal deterministic repro, but this reproduces repeatedly during normal use in Codex App.

My environment includes:

  • Codex App on macOS
  • build-ios-apps plugin enabled
  • global chrome-devtools MCP enabled
  • frequent use of subagents / spawn_agent

Rough repro pattern:

  1. Start Codex App.
  2. Work in a thread that uses subagents repeatedly.
  3. Have plugins / MCP-backed tools available, especially:
  • xcodebuildmcp
  • chrome-devtools-mcp
  1. Continue using the app for a while, spawning multiple subagents over time.
  2. Inspect processes with ps / Activity Monitor.

Observed result:

  • each subagent/thread spawn appears to trigger a fresh MCP manager init
  • new npm exec ... MCP parents and helper children are spawned
  • old helper trees are not cleaned up
  • process count and memory usage keep growing

Relevant local observations:

  • app-server parent PID was 67522
  • I saw log sequences like:
  • spawn_agent
  • thread_spawn
  • session_init.mcp_manager_init
  • immediate codex: close
  • but corresponding xcodebuildmcp / chrome-devtools-mcp processes remained alive

This may be related to or a regression adjacent to earlier MCP leak issues, but I am still seeing it on:

  • Codex App 26.409.20454
  • Codex CLI/core version family corresponding to current 0.120.0

I can provide logs, process snapshots, or uploaded thread/session details if needed.

What is the expected behavior?

Codex App should not leave stdio MCP helper trees running after a subagent or spawned session is finished.

Expected behavior:

  • MCP helper processes should be reused safely or torn down reliably
  • ending a subagent/session should clean up its entire MCP subprocess tree
  • repeated spawn_agent usage should not grow the number of xcodebuildmcp / chrome-devtools-mcp helpers without bound
  • long-running Codex App usage should not consume tens of GB of swap because of stale MCP helpers

Additional information

Related symptoms seem close to issues #16895, #14950, and #17448, but I am reporting a current Codex App repro with concrete process counts and memory usage.

<img width="920" height="615" alt="Image" src="https://github.com/user-attachments/assets/1b13acb8-514c-49cb-bdfa-c8dffb03524c" />

View original on GitHub ↗

6 Comments

github-actions[bot] contributor · 3 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #16895
  • #17115
  • #16256
  • #16660

Powered by Codex Action

RedesignedRobot · 3 months ago

Same bug, different MCP server. We observed 213 leaked @playwright/mcp process pairs (13.6 GB RSS) on v0.120.0. Filed as #17832.

Your description of the spawn_agent -> thread_spawn -> session_init.mcp_manager_init -> close lifecycle is accurate. We traced it through the source: each Session::new() creates its own McpConnectionManager::new() with fresh child processes, but handlers::shutdown() never calls cleanup on MCP. McpConnectionManager has no Drop impl, no shutdown(), no close().

Root cause analysis with proposed fix: #17832 (comment)
https://github.com/openai/codex/issues/17832#issuecomment-4247026597

Keesan12 · 2 months ago

The big clue here is that the leak is tied to session_init.mcp_manager_init on subagent spawn, not just raw process count. That suggests the missing lifecycle primitive is probably a session-scoped MCP ownership model: either helpers are shared and reference-counted across child sessions, or child-specific helpers get a guaranteed teardown receipt when the child closes. Right now it sounds like Codex has spawn receipts but not reliable close receipts for the helper tree. We have been hitting a similar boundary in MartinLoop whenever tool runtimes outlive the attempt they were admitted for. If helpful, happy to compare notes against the OSS run-record shape we are using for terminal halt and teardown accounting.

dimasyankauskas · 1 month ago

Adding one more reproduction signal from Codex Desktop while working in a real iOS product repo.

Observed behavior:

  • build-ios-apps@openai-curated was enabled in ~/.codex/config.toml.
  • The curated plugin MCP config launches xcodebuildmcp through:

``json
{
"command": "npx",
"args": ["-y", "xcodebuildmcp@latest", "mcp"]
}
``

  • Runtime process checks showed multiple live helper pairs:

``text
npm exec xcodebuildmcp@latest mcp
node .../.bin/xcodebuildmcp mcp
``

  • The npm exec xcodebuildmcp@latest mcp parents were direct children of the Codex app-server process.
  • At one point this correlated with active Swift compiler heat from swift-frontend; later verification showed the MCP helpers remained as idle leaked residue after build workers were gone.
  • Disabling the plugin and running pkill -f 'xcodebuildmcp' cleared the leak. After cleanup, xcodebuildmcp, xcodebuild, and swift-frontend were all absent from ps.

Impact:

  • Long-running Codex Desktop sessions can accumulate plugin-provided stdio MCP helper trees.
  • For xcodebuildmcp, the failure mode is especially expensive because a leaked/duplicated server can fan out into xcodebuild and swift-frontend workers.
  • Practical workaround for now: keep build-ios-apps@openai-curated disabled unless actively using the iOS MCP workflow.

This looks like a Codex Desktop/plugin MCP lifecycle issue rather than an app-project issue. Sharing because predictable MCP process cleanup matters for longer-running Codex sessions.

robin-liquidium · 10 days ago

I can confirm closely related behavior, including on a remote Linux execution environment controlled from Codex Desktop on macOS.

Environment

  • Codex Desktop host: macOS, app version 26.707.31428 (build 5059), bundled Codex 0.144.0-alpha.4
  • Remote execution environment: Ubuntu 24.04 x86_64, connected through Codex's SSH/Connection feature
  • Remote Codex app-server/CLI: 0.144.1
  • Plugin: build-ios-apps@openai-curated-remote, version 0.1.2
  • MCP server: xcodebuildmcp 2.6.2

Original user-visible failure

With plugins enabled, Codex tasks running on my remote Linux machine would eventually stop responding completely. The live process table showed:

  • npm exec xcodebuildmcp@latest mcp
  • sh -c xcodebuildmcp mcp
  • node .../xcodebuildmcp mcp

This happened even though XcodeBuildMCP is not useful on that Linux machine and I had explicit local disable entries for both the local and remote Build iOS plugin IDs.

codex mcp list could look clean while the processes were still running. Returning the remote machine to plugins = false, killing the XcodeBuildMCP process trees, and starting a fresh task restored normal operation.

Controlled reproduction

I reproduced the Desktop-selected plugin path directly through app-server using a real selectedCapabilityRoots entry for Build iOS Apps.

A single isolated thread behaved normally:

  • thread/start completed in approximately 0.33s
  • XcodeBuildMCP successfully completed its MCP handshake on Linux
  • Two consecutive model turns completed in 4.70s and 4.01s
  • App-server remained responsive

So this does not appear to require XcodeBuildMCP itself to fail during initialization. A single instance can initialize successfully on Linux.

The problem appeared when I repeated the selected-root lifecycle in one long-running app-server:

  1. Start an ephemeral thread with the Build iOS Apps selected capability root.
  2. Query mcpServerStatus/list for that thread.
  3. Repeat with additional threads.
  4. Inspect the process table after each iteration.

Observed process growth:

  • After the first thread: 3 XcodeBuildMCP-related processes (npm -> sh -> node)
  • After the second thread: 6 processes
  • During the third iteration: 12 processes were observed
  • The third mcpServerStatus/list request timed out after 60s

In normal Desktop usage, the corresponding user-visible symptom was that my remote Codex tasks stopped responding.

When I terminated the isolated app-server itself, all XcodeBuildMCP process trees disappeared. That points to lifetime management within the long-running app-server/thread lifecycle rather than an unkillable child process.

Reproduction caveat

The controlled test used ephemeral threads. thread/delete returned:

thread is not persisted and cannot be deleted

Therefore those ephemeral threads remained loaded during the test. This does not by itself prove that every process was orphaned after a successful thread deletion, but it does demonstrate that repeated loaded/spawned threads create independent MCP process trees and can make the app-server unresponsive very quickly.

This seems consistent with the issue's broader lifecycle problem: MCP subprocess ownership is tied to individual thread/session initialization, while teardown or reuse is not reliably preventing process accumulation in a long-running Codex app-server.

Related selected-plugin behavior

In my remote setup, Desktop-selected capability roots also bypassed ordinary per-plugin enabled = false configuration. If the Build iOS plugin root was selected for the Linux environment, its MCP declaration was launched there regardless of the local disable entry.

My current stable mitigation is:

  • apps = true
  • plugins = false
  • terminate existing XcodeBuildMCP process trees
  • validate recovery with a fresh remote task

I can provide the JSONL app-server reproduction harness or additional process snapshots if useful.

jokwa135 · 3 days ago

Windows confirmation on a current 26.707 build: completed subagent stacks still remain alive after the earlier shutdown fix.

Environment

  • Microsoft Windows 10 Pro 22H2, build 19045, x64
  • Codex Desktop package: OpenAI.Codex 26.707.3748.0
  • Bundled CLI: codex-cli 0.144.0-alpha.4
  • Long-running packaged codex.exe app-server
  • Per-session stdio tools included node_repl, AgentMemory MCP, and three plugin MCP servers

Controlled completion-versus-process proof

I correlated one subagent rollout with the process burst created beneath the packaged codex.exe app-server:

  1. The subagent session_meta timestamp was 2026-07-17T06:17:13.549Z.
  2. Its unique process burst began about 99 ms later and contained six external processes: one node_repl, one AgentMemory launcher plus child, and three plugin MCP Node servers.
  3. The latest subagent turn recorded task_complete at 2026-07-17T06:22:22.760Z, and the collaboration UI/registry reported the subagent as completed.
  4. The exact timestamp-matched process tree remained alive afterward. The corresponding spawn edge also remained open.
  5. That retained stack used approximately 250.9 MiB working set, 152.7 MiB private memory, 67 threads, and 893 handles while idle.

This makes the lifecycle boundary explicit: the model/subagent turn completes, but the subagent's stdio MCP client/process group is not drained.

Accumulated impact

Before restarting the app, the packaged ChatGPT/Codex tree had accumulated:

  • 83 descendants
  • 11 node_repl processes / persistent runtime stacks
  • 44 plugin MCP Node processes
  • approximately 4.24 GB working set and 3.64 GB private bytes
  • 1,241 threads and 17,607 handles

Windows Error Reporting also contained recent ChatGPT hang and resource-leak events. System RAM, pagefile, disk activity/free space, network response, and GPU memory were not saturated.

A normal app restart immediately collapsed the runtime count from 11 stacks to one active stack. In a separate spawn, one subagent timestamp also produced two complete MCP stacks, suggesting duplicate initialization can amplify the leak.

Reproduction pattern

  1. Start Codex Desktop with stdio MCP-backed tools/plugins available.
  2. Spawn a subagent.
  3. Wait until its rollout records task_complete and the UI reports it done.
  4. Inspect direct runtime children of the packaged codex.exe app-server.
  5. The subagent's timestamp-matched node_repl / MCP process burst remains alive.
  6. Repeat with more subagents; process, memory, thread, and handle counts grow until the desktop UI becomes very slow or hangs.

Regression detail

The installed bundled CLI is newer than the merge of #19753, which added explicit MCP client shutdown/draining and process-group termination. The issue therefore appears to be a remaining Windows Desktop collaboration/subagent close path or a regression adjacent to that fix, rather than simply an older build missing it.

Normal inactive owner-thread unsubscribe is present and observable in the desktop logs, but it does not appear to close these completed subagent sessions. There is also no supported MCP idle lifetime, shutdown timeout, or process-limit configuration that prevents the accumulation.

Expected behavior

When the latest subagent turn reaches task_complete, Codex should close/drain that subagent's MCP manager and terminate its owned stdio process group. Repeated completed subagents should not increase the persistent process count.

I have retained sanitized process snapshots and timing evidence and can provide them privately if a maintainer needs additional details. I have intentionally not attached raw session transcripts, account data, or local paths to this public comment.