Skip to content

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

Open

Description

@jaewon-kim-dev

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
  4. Continue using the app for a while, spawning multiple subagents over time.
  5. 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.

Image

Activity

  1. added
    bugSomething isn't working
    subagentIssues involving subagents or multi-agent features
    mcpIssues related to the use of model context protocol (MCP) servers
    on Apr 12, 2026
  2. removed
    appIssues related to the Codex desktop app
    on Apr 12, 2026
  3. RedesignedRobot commented on Apr 14, 2026

    @RedesignedRobot

    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)
    #17832 (comment)

  4. Keesan12 commented on May 18, 2026

    @Keesan12

    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.

  5. dimasyankauskas commented on Jun 18, 2026

    @dimasyankauskas

    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:

      {
        "command": "npx",
        "args": ["-y", "xcodebuildmcp@latest", "mcp"]
      }
    • Runtime process checks showed multiple live helper pairs:

      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.

  6. robin-liquidium commented on Jul 10, 2026

    @robin-liquidium

    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.

  7. jokwa135 commented on Jul 17, 2026

    @jokwa135

    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.

  8. Mavumavu commented on Jul 21, 2026

    @Mavumavu

    Current Windows reproduction on Codex Desktop 26.715.7063.0:

    • Windows 10 Pro 22H2, build 19045, x64.
    • One long-lived codex.exe app-server process had 95 direct node.exe MCP children still alive after the subagent work had completed.
    • Sanitized entrypoint grouping: 49 x mcp/server.bundle.mjs, 46 x mcp/server.mjs.
    • Combined working set of those Node children: approximately 6.24 GiB.
    • The app-server itself used approximately 1.38 GiB.
    • The MCP children were created in repeated batches across the long-lived session and their start times aligned with subagent sessions.
    • All visible subagents were already in terminal completed states when this process snapshot was taken.
    • The machine still had approximately 42.6 GiB physical memory free, so this had not yet reached OOM, but it is an unbounded process/RSS leak and makes a long-running Desktop session progressively heavier.
    • All 95 MCP children had the same live app-server parent and Normal process 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.

  9. Mavumavu commented on Jul 21, 2026

    @Mavumavu

    Additional controlled Windows reproduction on Codex Desktop 26.715.7063.0:

    • After an earlier guarded cleanup, four verified baseline MCP node.exe children remained.
    • I then launched exactly one fresh read-only subagent/reviewer.
    • At the subagent launch timestamp, exactly two new direct children of the same long-lived codex.exe appeared: one mcp/server.bundle.mjs process and one mcp/server.mjs process.
    • The reviewer completed and returned its terminal result, but both MCP processes remained alive.
    • A guarded cleanup matched only those two new processes by executable, parent, command-line family and launch-time cohort, stopped them, and returned the MCP count from six to the protected baseline of four.

    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.

  10. Mavumavu commented on Jul 21, 2026

    @Mavumavu

    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.

  11. psydigital commented on Jul 21, 2026

    @psydigital

    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:

    • one root agent thread plus exactly three resident direct subagents;
    • exactly four live npm exec chrome-devtools-mcp@1.5.0 --isolated ... roots beneath that Codex parent;
    • only one global chrome-devtools MCP server is configured, so this was not duplicate configuration.

    The lifecycle correlation is deterministic:

    • the root thread MCP process started four seconds after the Codex parent;
    • each of the three subagent started events matched creation of one additional Chrome MCP root within zero to one second;
    • the subagent tasks did not require browser work, so the MCP server appears to initialize eagerly with the subagent session;
    • at the later observation point, two subagents were terminal completed and one was terminal interrupted, 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.

  12. andreinknv commented on Jul 22, 2026

    @andreinknv

    Confirming the same lifecycle defect with a native, non-Node stdio MCP server.

    Sanitized environment

    • Codex CLI 0.144.6
    • macOS on arm64
    • Cartograph 1.1.31
    • stdio transport with a PostgreSQL backend

    Observed

    • A long-lived root session had one expected MCP server process.
    • Three spawned subagents each created one additional MCP server process.
    • MCP process start timestamps matched the three subagent rollout starts within one second.
    • Each subagent emitted its final answer and reached task_complete after roughly 6-7 minutes.
    • The three extra MCP processes were still alive 20-31 hours later.
    • The live Codex parent still held the peer ends of all nine stdin/stdout/stderr pipes.
    • Each retained MCP process still held a backend connection and nontrivial RSS; periodic CPU activity was also observed.
    • These were not OS-orphaned processes. They remained descendants of the active Codex process.

    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.

  13. daniel-graham commented on Jul 22, 2026

    @daniel-graham

    macOS reproduction on ChatGPT/Codex Desktop 26.715.70719 (build 5650).

    I correlated subagent creation with process start times under one long-lived codex app-server process:

    • Starting three subagents created three new, separate helper batches within seconds of their respective thread starts.
    • Each batch included node_repl, Chrome DevTools MCP, and the configured stdio MCP helper roots.
    • All three subagents reached completed state, but all three helper batches remained alive afterward.
    • Post-completion snapshot: 247 direct app-server children, more than 700 total descendants, 35 node_repl roots, and 35 Chrome DevTools MCP roots.
    • The full descendant tree reached approximately 14.6 GiB summed RSS. A language-server-backed MCP was the largest amplifier: 27 retained language-server children accounted for approximately 7.7 GiB summed RSS, with three newly created instances each reaching roughly 2.3 GiB while indexing.

    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:

  14. HAOHANZHOU commented on Jul 26, 2026

    @HAOHANZHOU

    I can reproduce this on Codex CLI 0.145.0 under WSL2/Linux.

    Environment:

    • Codex CLI 0.145.0, installed globally with npm
    • WSL2 Ubuntu 24.04
    • Linux kernel 6.6.87.2-microsoft-standard-WSL2
    • Node.js 20.20.2
    • Started with codex resume <session-id> from a VS Code WSL terminal
    • stdio MCP servers include chrome-devtools, Playwright, and the GitHub plugin MCP

    During approximately 1 hour and 43 minutes, one Codex CLI process accumulated six complete MCP process groups:

    • 24 processes in total
    • approximately 2.17 GB combined RSS
    • all old processes remained sleeping
    • all were still direct descendants of the same Codex PID

    Each group contained approximately:

    • chrome-devtools-mcp
    • @playwright/mcp
    • the GitHub plugin stdio MCP server
    • the chrome-devtools telemetry watchdog

    Three groups were created within 13 seconds. Inspection of ~/.codex/logs_2.sqlite showed 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_init

    A later group also aligned exactly with an explicit model-triggered spawn_agent call. 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.refresh event 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_agent was 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.

  15. FE-ALEX-WEI commented on Aug 2, 2026

    @FE-ALEX-WEI

    Current-version data point: full MCP stacks remain after subagent lifecycle

    Environment:

    • Codex desktop build: 26.727.51351 (build 6119)
    • Bundled CLI: 0.146.0-alpha.9.2
    • Platform: macOS
    • Multi-agent mode enabled; max_depth = 3

    I 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:

    • The local thread database contains historical/open subagent metadata, but that metadata is not proof that every historical subagent is a live process.
    • The strong evidence here is process ancestry plus exact timestamp correlation for newly created subagents.
    • The helper command lines did not expose an owning thread/agent identifier, so lifecycle ownership should be tracked internally rather than inferred externally.
    • No credentials, prompts, thread IDs, local usernames, process IDs, repository paths, or raw command lines are included in this report.

    Expected behavior / suggested direction:

    1. A subagent's session-owned MCP/helper processes are disposed when it reaches a terminal lifecycle state or is explicitly closed.
    2. Disposal is bounded and idempotent; helper shutdown cannot leave close_agent hanging forever.
    3. A session-owned resource manager records each helper process group and invokes bounded cleanup from every terminal path (completed, errored, interrupted, shutdown, and explicit close), with TERM → timeout → KILL fallback for owned stdio helpers.
    4. Logical close_agent is decoupled from potentially hanging helper shutdown, while cleanup failures are surfaced separately.
    5. Lazy initialization or correctly reference-counted sharing prevents every short-lived subagent from eagerly duplicating the complete configured MCP suite.

    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.

  16. saerda8 commented on Aug 3, 2026

    @saerda8

    Additional current Windows Desktop data point and bounded containment

    Reproduced on Windows x64 with the Microsoft Store Codex Desktop build 26.727.6591.0 on 2026-08-04.

    • One long-lived signed codex.exe app-server had 100 direct node.exe / node_repl.exe MCP helper children.
    • Grouping by exact, redacted command line produced 10 signatures with 10 live copies each.
    • Their combined working set was approximately 5.50 GiB.
    • A user-level external guard (the signed Codex core was not modified) considered only direct children of that exact Store core, required a minimum age of 15 minutes plus two stable scans 60 seconds apart, and revalidated PID/parent/command/creation time before cleanup.
    • Removing only the older excess copies reduced the tree to 40 helpers, at most four per signature, and approximately 2.20 GiB. Multiple later scans remained at zero excess.

    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/main at 78306a32afe99ce88fbc3616f8ef325baae91cd0 and built a local source prototype for the missing idle boundary:

    • after subagent turn completion or abort, gate on SessionSource::SubAgent and active_turn.is_none();
    • serialize through the existing MCP refresh lock;
    • mark the runtime dirty and shut down that subagent's MCP runtime;
    • lazily reconnect it on the next MCP/tool use, preserving resident logical subagent identity;
    • include an integration regression case where the completed subagent's MCP PID exits and a subsequent tool call starts a fresh PID.

    The prototype is an 8-file, 198-insertion/1-deletion change and currently applies to that main snapshot without merge conflicts; git diff --check is clean. I did not open an unsolicited PR because docs/contributing.md says 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.

  17. ColumbusLabs commented on Aug 31, 2026

    @ColumbusLabs

    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

    • Codex Desktop: 26.825.51511, build 7377.
    • Bundled Codex core currently: 0.151.0-alpha.7.2; an earlier observation during this investigation used 0.151.0-alpha.7.1.
    • macOS 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:

    Helper Processes Combined RSS at this snapshot
    XcodeBuildMCP 40 (20 npm wrappers + 20 Node children) 2,011.6 MiB
    Codex Security stdio server 18 314.8 MiB
    Bundled Codex app-tools server 23 353.4 MiB

    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_level was 2. After terminating only these verified helper process groups, all 81 were gone and the pressure level was 1. 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:

    [plugins."build-ios-apps@openai-curated".mcp_servers.xcodebuildmcp]
    enabled = false
    
    [plugins."codex-security@openai-curated".mcp_servers.codex-security]
    enabled = false

    The bundled CLI, when run with the diagnostic-only --disable remote_plugin mcp list --json, reported both servers disabled. A fresh standalone app-server config/read also 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 the openai-curated-remote cache. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    browserbugSomething isn't workingmcpIssues related to the use of model context protocol (MCP) serverssubagentIssues involving subagents or multi-agent features

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions