Repository navigation
Subagents leak stdio MCP helper trees in Codex App; xcodebuildmcp and chrome-devtools-mcp accumulate indefinitely #17574
Description
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 mcpnpm 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 mcpchildren:198chrome-devtools-mcpchildren:199- total related processes:
791 - combined RSS of those related processes: about
13.5 GB
Breakdown:
npm exec ...parents: about6.9 GB RSSxcodebuildmcpchildren: about3.2 GB RSSchrome-devtools-mcpchildren: about3.4 GB RSS
This is large enough that macOS starts consuming tens of GB of swap.
The pattern I see in logs is:
spawn_agentthread_spawnsession_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-appsplugin enabled- global
chrome-devtoolsMCP enabled - frequent use of subagents /
spawn_agent
Rough repro pattern:
- Start Codex App.
- Work in a thread that uses subagents repeatedly.
- Have plugins / MCP-backed tools available, especially:
xcodebuildmcpchrome-devtools-mcp
- Continue using the app for a while, spawning multiple subagents over time.
- 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_agentthread_spawnsession_init.mcp_manager_init- immediate
codex: close - but corresponding
xcodebuildmcp/chrome-devtools-mcpprocesses 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_agentusage should not grow the number ofxcodebuildmcp/chrome-devtools-mcphelpers 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.

Activity
github-actions commentedon Apr 12, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
RedesignedRobot commentedon Apr 14, 2026
Same bug, different MCP server. We observed 213 leaked
@playwright/mcpprocess 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 -> closelifecycle is accurate. We traced it through the source: eachSession::new()creates its ownMcpConnectionManager::new()with fresh child processes, buthandlers::shutdown()never calls cleanup on MCP.McpConnectionManagerhas noDropimpl, noshutdown(), noclose().Root cause analysis with proposed fix: #17832 (comment)
#17832 (comment)
Keesan12 commentedon May 18, 2026
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 commentedon Jun 18, 2026
Adding one more reproduction signal from Codex Desktop while working in a real iOS product repo.
Observed behavior:
build-ios-apps@openai-curatedwas enabled in~/.codex/config.toml.The curated plugin MCP config launches
xcodebuildmcpthrough:{ "command": "npx", "args": ["-y", "xcodebuildmcp@latest", "mcp"] }Runtime process checks showed multiple live helper pairs:
The
npm exec xcodebuildmcp@latest mcpparents 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, andswift-frontendwere all absent fromps.Impact:
xcodebuildmcp, the failure mode is especially expensive because a leaked/duplicated server can fan out intoxcodebuildandswift-frontendworkers.build-ios-apps@openai-curateddisabled 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 commentedon Jul 10, 2026
I can confirm closely related behavior, including on a remote Linux execution environment controlled from Codex Desktop on macOS.
Environment
26.707.31428(build5059), bundled Codex0.144.0-alpha.40.144.1build-ios-apps@openai-curated-remote, version0.1.2xcodebuildmcp2.6.2Original 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 mcpsh -c xcodebuildmcp mcpnode .../xcodebuildmcp mcpThis 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 listcould look clean while the processes were still running. Returning the remote machine toplugins = 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
selectedCapabilityRootsentry for Build iOS Apps.A single isolated thread behaved normally:
thread/startcompleted in approximately0.33s4.70sand4.01sSo 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:
mcpServerStatus/listfor that thread.Observed process growth:
3XcodeBuildMCP-related processes (npm->sh->node)6processes12processes were observedmcpServerStatus/listrequest timed out after60sIn 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/deletereturned:thread is not persisted and cannot be deletedTherefore 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 = falseconfiguration. 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 = trueplugins = falseI can provide the JSONL app-server reproduction harness or additional process snapshots if useful.
jokwa135 commentedon Jul 17, 2026
Windows confirmation on a current
26.707build: completed subagent stacks still remain alive after the earlier shutdown fix.Environment
19045, x64OpenAI.Codex 26.707.3748.0codex-cli 0.144.0-alpha.4codex.exe app-servernode_repl, AgentMemory MCP, and three plugin MCP serversControlled completion-versus-process proof
I correlated one subagent rollout with the process burst created beneath the packaged
codex.exe app-server:session_metatimestamp was2026-07-17T06:17:13.549Z.node_repl, one AgentMemory launcher plus child, and three plugin MCP Node servers.task_completeat2026-07-17T06:22:22.760Z, and the collaboration UI/registry reported the subagent as completed.open.250.9 MiBworking set,152.7 MiBprivate memory,67threads, and893handles 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:
83descendants11node_replprocesses / persistent runtime stacks44plugin MCP Node processes4.24 GBworking set and3.64 GBprivate bytes1,241threads and17,607handlesWindows 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
task_completeand the UI reports it done.codex.exe app-server.node_repl/ MCP process burst remains alive.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.
Mavumavu commentedon Jul 21, 2026
Current Windows reproduction on Codex Desktop
26.715.7063.0:19045, x64.codex.exeapp-server process had 95 directnode.exeMCP children still alive after the subagent work had completed.mcp/server.bundle.mjs, 46 xmcp/server.mjs.completedstates when this process snapshot was taken.Normalprocess priority.This looks like the same lifecycle family as this issue, now confirmed on a current Windows Desktop build with bundled Node MCP servers rather than the original macOS helpers.
I am not posting raw command lines, project paths, thread IDs, or logs. I can provide a redacted process/timestamp table privately if useful.
Mavumavu commentedon Jul 21, 2026
Additional controlled Windows reproduction on Codex Desktop
26.715.7063.0:node.exechildren remained.codex.exeappeared: onemcp/server.bundle.mjsprocess and onemcp/server.mjsprocess.This is a narrower reproduction than the earlier accumulation report: one completed subagent lifecycle left one bundle/server pair behind. The machine had ample free memory, so this was observed as a lifecycle/cleanup failure rather than an out-of-memory condition. No private task IDs, prompts, repository paths, usernames, project content, secrets or raw logs are included.
Mavumavu commentedon Jul 21, 2026
Follow-up: this is now reproducible across three consecutive fresh read-only subagent/reviewer lifecycles in the same long-lived Windows Desktop session. Each completed reviewer added exactly one mcp/server.bundle.mjs child and one mcp/server.mjs child under the same codex.exe, and both remained alive after the terminal result. After each completion, an identity/time/parent/command-family guarded cleanup returned the MCP count from 6 to the protected baseline of 4. This repeated 2-process-per-completed-subagent pattern strengthens the lifecycle-leak diagnosis; no task content, private paths, IDs, secrets or raw logs are included.
psydigital commentedon Jul 21, 2026
Independent macOS confirmation with a one-to-one subagent/process timestamp correlation on current stable
codex-cli 0.144.6.Observed in one long-lived Codex parent process:
npm exec chrome-devtools-mcp@1.5.0 --isolated ...roots beneath that Codex parent;chrome-devtoolsMCP server is configured, so this was not duplicate configuration.The lifecycle correlation is deterministic:
startedevents matched creation of one additional Chrome MCP root within zero to one second;completedand one was terminalinterrupted, but all three timestamp-matched MCP roots were still alive, alongside the root thread MCP process.This is operationally significant even at a small count: a run-scoped browser cleanup verifier cannot distinguish these retained per-thread servers because the process command lines expose no owning thread/session ID. It must either treat them as unregistered contamination or risk attributing another thread's browser runtime incorrectly. No processes were signalled during this investigation.
This also connects cleanly to #33777: terminal subagents remain resident with their MCP subprocesses, and eviction of an interrupted resident can then block indefinitely in
shutdown_and_wait. The evidence here supports both guaranteed MCP teardown for terminal agent threads and explicit MCP PID-to-thread ownership telemetry.I have retained the redacted timestamp/process table and can provide it privately. No project paths, task names, prompts, account data, raw logs, PIDs, or thread IDs are included here.
andreinknv commentedon Jul 22, 2026
Confirming the same lifecycle defect with a native, non-Node stdio MCP server.
Sanitized environment
0.144.61.1.31Observed
task_completeafter roughly 6-7 minutes.This is useful for attribution because it reproduces without
npx, Node.js, a browser MCP, or a helper subprocess tree. The MCP server cannot infer that its owning subagent completed while Codex deliberately keeps stdio open. The lifecycle boundary appears to be owned by Codex.Expected
When a subagent reaches a terminal state, Codex should release that subagent's MCP runtime and backend connections, or suspend/reap it and recreate the runtime lazily if a follow-up turn later resumes the subagent. Pooling MCP clients with a bounded lifetime would also prevent linear growth.
This report intentionally omits local usernames, filesystem paths, project/repository names, process IDs, ports, session/thread identifiers, subagent names/tasks, database URLs/schemas, and raw logs.
daniel-graham commentedon Jul 22, 2026
macOS reproduction on ChatGPT/Codex Desktop
26.715.70719(build5650).I correlated subagent creation with process start times under one long-lived
codex app-serverprocess:node_repl, Chrome DevTools MCP, and the configured stdio MCP helper roots.node_replroots, and 35 Chrome DevTools MCP roots.Summed RSS is an upper bound because shared pages can be counted more than once, but process counts, parentage, timestamps, and continued residency after subagent completion are unambiguous. This was collected read-only; no processes were terminated and no configuration or local state was modified. The one-to-one timestamp correlation supports the same per-subagent MCP initialization without corresponding teardown described here.
Related reports
These appear to describe overlapping MCP/session lifecycle symptoms:
HAOHANZHOU commentedon Jul 26, 2026
I can reproduce this on Codex CLI 0.145.0 under WSL2/Linux.
Environment:
codex resume <session-id>from a VS Code WSL terminalDuring approximately 1 hour and 43 minutes, one Codex CLI process accumulated six complete MCP process groups:
Each group contained approximately:
chrome-devtools-mcp@playwright/mcpThree groups were created within 13 seconds. Inspection of
~/.codex/logs_2.sqliteshowed that these times aligned with separate subagent/thread initialization rather than an MCP reconnect loop.The relevant log sequence was:
spawn_agent -> thread_spawn -> session_init -> session_init.mcp_manager_initA later group also aligned exactly with an explicit model-triggered
spawn_agentcall. The subagent returned its final result, but its MCP processes remained alive under the long-running parent Codex process.I did not find a corresponding
mcp.runtime.refreshevent around that later process-group creation, so this does not appear to be a regular health-check or reconnect restart.When the top-level Codex process eventually shut down normally, the logs showed MCP services being cancelled and current stdio children receiving SIGTERM. The accumulation therefore occurs while the long-running parent remains active and completed subagent sessions are retained.
I cannot confirm from this capture that
close_agentwas explicitly called, so this report demonstrates retention after subagent completion, but not necessarily the stronger case of leakage after a successful explicit close.This appears to be the same lifecycle issue described here, now reproduced on Codex CLI 0.145.0 on WSL2/Linux rather than the macOS Codex App.
FE-ALEX-WEI commentedon Aug 2, 2026
Current-version data point: full MCP stacks remain after subagent lifecycle
Environment:
26.727.51351(build 6119)0.146.0-alpha.9.2max_depth = 3I can reproduce the lifecycle pattern in this issue on the current desktop build. Two explorer subagents were created six seconds apart. For each creation timestamp, the desktop app-server acquired a new batch of direct-child MCP launchers at the same second. A conservative classifier recognized 11 launcher roots in each timestamp cohort, including package-based MCP servers, Python-based MCP launchers, and
node_repl; those launchers then created their own descendants.After both explorers had completed, those helper trees remained under the long-lived app-server. A later snapshot showed roughly twelve duplicated launcher groups for several configured MCP families. The app process tree contained about 317 processes, around 308 below the primary app-server, and about 503 open pipe descriptors in that app-server tree.
The summed RSS sample for the app tree was about 22.6 GB (about 21.4 GB below the primary app-server). This is an upper-bound-style diagnostic because summed RSS double-counts shared pages; it should not be interpreted as unique physical memory. Even with that caveat, individual retained MCP descendants reached more than 1 GB RSS, and the repeated per-subagent launcher groups were directly visible.
Important distinctions:
Expected behavior / suggested direction:
close_agenthanging forever.completed,errored,interrupted,shutdown, and explicit close), with TERM → timeout → KILL fallback for owned stdio helpers.close_agentis decoupled from potentially hanging helper shutdown, while cleanup failures are surfaced separately.This is a current-build confirmation of the same per-subagent initialization without corresponding teardown. It also appears operationally related to #17832, #19197, #25015, and #25426.
saerda8 commentedon Aug 3, 2026
Additional current Windows Desktop data point and bounded containment
Reproduced on Windows x64 with the Microsoft Store Codex Desktop build
26.727.6591.0on 2026-08-04.codex.exeapp-server had 100 directnode.exe/node_repl.exeMCP helper children.That guard is only bounded containment, not an upstream fix, but the stable before/after result supports repeated retained session-owned MCP stacks as the source of the growth.
I also audited current
origin/mainat78306a32afe99ce88fbc3616f8ef325baae91cd0and built a local source prototype for the missing idle boundary:SessionSource::SubAgentandactive_turn.is_none();The prototype is an 8-file, 198-insertion/1-deletion change and currently applies to that
mainsnapshot without merge conflicts;git diff --checkis clean. I did not open an unsolicited PR becausedocs/contributing.mdsays external PRs are by invitation. I can provide the patch or test it against a maintainer-preferred approach if useful.No prompts, task IDs, account data, local paths, raw command lines, credentials, or logs are included here.
ColumbusLabs commentedon Aug 31, 2026
Additional macOS reproduction with XcodeBuildMCP, Codex Security, and bundled Codex app-tools helpers. This appears consistent with the accumulation reported here, although I have not established that the exact lifecycle defect is identical.
Environment checked August 31, 2026
26.825.51511, build7377.0.151.0-alpha.7.2; an earlier observation during this investigation used0.151.0-alpha.7.1.26.6.2, arm64, 16 GiB RAM.Observed repeatedly during normal multi-task use
Optional MCP helpers appear even in tasks that do not invoke the corresponding iOS/security skills. Repeated targeted termination clears them temporarily, but further sets accumulate. I have not isolated a minimal deterministic reproduction or instrumented each process back to a specific task/subagent.
One August 31 snapshot contained 81 helper processes, all descended from the same Codex root app-server:
Some helpers were newly spawned; some Security/app-tools processes had been alive for roughly 6–10 hours. An earlier snapshot reached 88 processes across the same three categories.
At the 81-process snapshot, CPU was approximately 90% idle, the memory compressor held roughly 6 GiB, swap usage was about 2 GiB, and
kern.memorystatus_vm_pressure_levelwas2. After terminating only these verified helper process groups, all 81 were gone and the pressure level was1. No unrelated builds/tests were terminated. These are observational before/after readings, not a claim that summed RSS equals reclaimed physical RAM.Disabling optional servers and restarting did not prevent recurrence
The following settings were added to user
config.toml, retaining the plugins/skills while disabling their MCP servers:The bundled CLI, when run with the diagnostic-only
--disable remote_plugin mcp list --json, reported both servers disabled. A fresh standalone app-serverconfig/readalso returned these values. However, after a genuine Desktop restart (old root app-server exited, new root PID verified), fresh helpers appeared under the new root and later accumulated to the 81-process snapshot above. The settings remained false.Potentially relevant distinction: the logical plugin IDs reported by local-plugin inventory use
@openai-curated, whereas the running plugin scripts reside in theopenai-curated-remotecache. I have not verified that these settings govern Desktop's remote-plugin startup path. This may overlap with #28443 and #32942.XcodeBuildMCP also had
XCODEBUILDMCP_MCP_IDLE_TIMEOUT_MS=600000, verified in a sampled child's environment. That timeout did not prevent repeated startup. Security/app-tools helpers also accumulated, so Xcode-only cleanup is insufficient.Expected: optional helpers should start when needed, disabled-server configuration should be honored consistently, and task/session completion should reliably release owned helper trees without disrupting active calls. Restarting or repeatedly killing helpers should not be necessary to keep memory pressure under control.
Private paths, project names, session identifiers, and raw logs have been omitted.