Skip to content

Windows Desktop app-server repeatedly spawns duplicate MCP stdio process pools (183 node.exe / 13GB private memory) #31499

Open

Description

@xxH7r

Summary

Codex Desktop on Windows repeatedly starts duplicate stdio MCP process pools under codex.exe app-server --analytics-default-enabled. The duplicate cmd -> npx/npx.cmd -> node.exe trees are not consistently reaped, causing large memory growth.

This appears related to:

I am filing a separate report because this reproduces on the current Windows Desktop app installed on my machine, and the process count/memory growth is severe enough to affect normal use.

Environment

  • OS: Microsoft Windows 11 Home Chinese, 64-bit
  • OS version/build: 10.0.22621 / build 22621
  • Codex Desktop package: OpenAI.Codex_26.527.3686.0_x64__2p2nqsd0c76g0
  • Codex Desktop version: 26.527.3686.0
  • ~/.codex/version.json: latest_version is 0.142.5
  • App server command observed:
    • codex.exe app-server --analytics-default-enabled

Global MCP servers configured in ~/.codex/config.toml:

  • reactbits: npx -y reactbits-dev-mcp-server
  • tavily: npx.cmd -y tavily-mcp
  • chrome-devtools: npx chrome-devtools-mcp@latest
  • shadcn: npx.cmd -y shadcn@latest mcp
  • figma: HTTP MCP
  • node_repl: bundled Codex node_repl

No secrets are included here.

Observed Behavior

During normal Codex Desktop usage, Task Manager showed a large number of node.exe processes consuming substantial memory.

Read-only process inspection showed:

  • Peak observed: 183 node.exe processes
  • Peak private memory: 13.2 GB
  • Peak working set: 10.92 GB
  • One old Desktop app-server process tree owned about 170 of the node.exe descendants and about 12.24 GB private memory

The duplicated processes were primarily repeated MCP stdio server trees:

  • tavily-mcp
  • reactbits-dev-mcp-server
  • shadcn@latest mcp
  • chrome-devtools-mcp@latest
  • chrome-devtools-mcp watchdog children

Representative command lines:

"node" "...\\npm-cache\\_npx\\...\\chrome-devtools-mcp\\build\\src\\bin\\chrome-devtools-mcp.js"
node.exe ...\\chrome-devtools-mcp\\build\\src\\telemetry\\watchdog\\main.js --parent-pid=...
"node" "...\\npm-cache\\_npx\\...\\shadcn\\dist\\index.js" mcp
"node" "...\\npm-cache\\_npx\\...\\tavily-mcp\\build\\index.js"
"node" "...\\npm-cache\\_npx\\...\\reactbits-dev-mcp-server\\dist\\index.js"

After I only inspected the process tree, without killing any process and without changing config, the old app-server appears to have exited/restarted and the count dropped to:

  • 19 node.exe processes
  • about 1.5 GB private memory

However, shortly afterward, the count started increasing again:

  • 37 node.exe processes
  • 2.89 GB private memory
  • 2.91 GB working set

Breakdown at that point:

chrome-devtools: 12 processes, 1.22 GB private
shadcn:           8 processes, 0.68 GB private
reactbits:        8 processes, 0.49 GB private
tavily:           8 processes, 0.47 GB private
codex-node:       1 process,  0.02 GB private

This suggests the duplicate MCP pools are still being created after the old high-memory app-server tree is cleaned up.

Expected Behavior

Codex Desktop should not create unbounded duplicate MCP stdio process pools.

At most one active MCP process pool should exist per owning active session/thread, and MCP child processes should be reliably cleaned up when the owning session/thread/app-server lifecycle ends.

Actual Behavior

The Desktop app-server creates multiple full MCP stdio process pools. Those pools accumulate under the app-server and can grow to hundreds of node.exe processes and more than 10 GB of memory.

In my case, the leak/duplication was visible without any project dev server being involved. The repeated processes came from Codex MCP startup, not from application code.

Impact

This makes Codex Desktop risky to keep open for long sessions on Windows when several stdio MCP servers are configured. Memory growth can become large enough to degrade the machine and force users to manually kill processes or restart Codex.

Notes

This looks especially close to #28361 and #30753:

The extra data point here is that I observed both behaviors in one session:

  1. a very large old app-server tree with around 170 duplicate node.exe descendants;
  2. automatic cleanup/restart reducing the count;
  3. new duplicate MCP pools appearing again afterward.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    windows-osIssues related to Codex on Windows systems
    mcpIssues related to the use of model context protocol (MCP) servers
    app-serverIssues involving app server protocol or interfaces
    on Jul 7, 2026
  2. github-actions commented on Jul 7, 2026

    @github-actions
    Contributor
  3. xxH7r commented on Jul 7, 2026

    @xxH7r
    Author

    Warning: a user posted codex_mcp_fix.zip in this thread. My browser/Windows security flagged it as malicious. Please do not download or run it. Maintainers may want to remove that comment/attachment.

  4. mayank6091 commented on Jul 8, 2026

    @mayank6091

    @xxH7r This feels like one of those issues where process metrics alone won't explain the root cause. For long-running agent workflows, it's useful to capture an execution timeline that correlates MCP server lifecycle events, tool invocations, and process creation. That makes it much easier to identify whether duplicate pools are caused by orchestration retries, MCP reconnects, or process management itself.

  5. ken-jo commented on Jul 13, 2026

    @ken-jo

    I reproduced the same process-pool accumulation on a newer Windows Codex Desktop build.

    Environment

    • Codex Desktop package: OpenAI.Codex_26.707.3748.0_x64__2p2nqsd0c76g0
    • Bundled process: codex.exe app-server
    • App-server uptime at inspection: about 40 hours

    Process tree before cleanup

    The single long-lived app-server owned repeated, thread-shaped pools:

    • 29 × context-mode/start.mjs
    • 30 × bundled Sites mcp/server.mjs
    • 30 × Data Analytics mcp/server.cjs --stdio
    • 30 × node_repl.exe
    • 35 × codex-windows-sandbox-setup.exe observed globally

    The three Node MCP groups were direct children of the same app-server PID. Their creation times appeared in repeated clusters from July 11 through July 13, consistent with new thread/task startup.

    Memory snapshot:

    • 99 × node.exe globally: ~14.4 GB aggregate working set
    • 89 of those Node processes were direct app-server children
    • context-mode/start.mjs alone: ~8.7 GB aggregate working set, ~2.45 GB private working set, ~4.57 GB private commit
    • app-server codex.exe: ~1.27 GB working set

    This was process-count accumulation rather than a clearly demonstrated single-process heap leak: process age did not positively correlate with private working set.

    Disk activity

    Before cleanup, Task Manager showed sustained disk writes around 50 MB/s. Local Codex state at the time was:

    • ~/.codex: 10.24 GiB total
    • 6.55 GiB of files modified within the previous hour
    • logs_2.sqlite: 3.53 GiB
    • context-mode storage: 3.20 GiB
    • sessions: 2.08 GiB

    Cleanup result

    I retained the four newest active MCP/REPL pools and terminated 130 older managed child processes, then removed 22 accumulated sandbox-setup helpers.

    Immediately afterward:

    • global node.exe count: 99 → 29
    • aggregate Node working set: ~14.4 GB → ~5.28 GB
    • free physical RAM: 31.2 GB → 33.4 GB
    • disk write counter snapshot: ~50 MB/s observed before cleanup → 0.0 MB/s after cleanup

    The remaining global Node count included unrelated local development processes, so the reduction is not based on killing all Node processes indiscriminately.

    This strongly matches the per-thread MCP pool retention described here. It also indicates that the problem remains reproducible on Windows package 26.707.3748.0, after the earlier explicit MCP shutdown work in #19753.

  6. wherewolf87 commented on Jul 13, 2026

    @wherewolf87

    Reproduced on the newer Windows package 26.707.8479.0. I filed #32797 with a sanitized current-version process snapshot.

    Key measurements from one Codex Desktop app-server tree:

    • 193 total descendants
    • 83 node.exe
    • 3 node_repl.exe
    • 54 cmd.exe launcher wrappers
    • Node family: 7.742 GiB working set and 6.837 GiB private memory
    • three creation batches of 26, 28, and 32 Node-family processes within about three and a half minutes of app-server startup

    The processes were attributed through the full parent chain to codex.exe app-server. Seven Claude Code-owned Node processes and 19 already-orphaned/unattributable Node processes were explicitly excluded. This confirms current-build recurrence of Codex-owned MCP/Node process-batch accumulation and is not an artifact of counting every machine-wide Node process. Process evidence alone does not identify the internal manager, refresh, or session event that owned each batch.

    Follow-up from the same app-server at 2026-07-13T09:50:42.6070046-04:00: the retained tree had grown to 147 node.exe, 5 node_repl.exe, 94 cmd.exe, 13.902 GiB Node-family working set, and 12.084 GiB private memory. Two additional batches of 33 Node-family processes each began at 09:42 and 09:43. Their specific internal trigger remains unverified.

  7. lixunqi12 commented on Jul 18, 2026

    @lixunqi12

    Still reproduces on 26.707.9981 and, after today's auto-update, on 26.715.3651 (Windows 11 Pro, Store package OpenAI.Codex_26.715.3651.0_x64__2p2nqsd0c76g0). Adding some evidence that narrows the root cause to the client side.

    Setup

    6 stdio MCP servers in ~/.codex/config.toml (npx-based: @mskalski/lightroom-mcp, @playwright/mcp; uvx-based: paper-search-mcp, photoshop-mcp-server; one plain node script; bundled node_repl), 3–4 conversations open in the Desktop app.

    Measured behavior

    • The app-server re-spawns the full set of configured servers roughly every 60–90 s per conversation (≈ one new set every ~15 s with 4 conversations). 90-second sample: +20 processes. After ~5 h unattended: 172 node.exe + 104 python/uv/uvx processes, ≈ 11 GB working set, 877 total system processes.
    • Abandoned sets are never killed and their pipe handles are never closed: the orphaned cmd → npx → node wrapper chains stay alive indefinitely, i.e. the stdio servers never receive stdin EOF, so a spec-compliant server cannot exit on its own.
    • uvx-based (python) servers accumulate identically to npx-based ones, so it is not npm-specific.

    The servers themselves are healthy

    Manual stdio probe (spawn the exact configured command, write an MCP initialize request, time the response):

    • @mskalski/lightroom-mcp: valid initialize response in 1.27 s — even with its backend app (Lightroom) closed
    • local plain-node server: valid response in 0.58 s
    • npx package resolution itself: ~1 s (warm cache), measured from wrapper spawn → server process spawn timestamps

    So the app-server discards connections to servers that complete a valid handshake within ~1 s, respawns the whole pool, and leaks the old one.

    Control group

    Same machine, same server binaries/configs attached to Claude Code: exactly one set per session, stable for hours, zero accumulation. This rules out the servers, npx/uvx, and the OS — the lifecycle management difference is in the Codex client.

    Workaround

    Scheduled reaper task (every 10 min). Reliable kill criterion under the bug: any same-command MCP process owned by the app-server older than ~10 minutes is necessarily abandoned, because the respawn loop keeps replacing the live set — survivors automatically equal (open conversations) × (one set). Plus unconditional reaping of processes whose parent chain is dead (with PID-reuse check: parent creation time later than child ⇒ real parent is gone).

    Happy to provide the probe script or raw process listings if useful.

  8. abangkis commented on Aug 13, 2026

    @abangkis

    Independent reproduction on Windows build 26.803.10989.0

    I can reproduce this on a newer Windows Codex Desktop build, using two native Rust stdio MCP servers without npm/cmd wrapper chains.

    Environment

    • Windows 11 x64
    • Codex Desktop package: OpenAI.Codex_26.803.10989.0_x64
    • Codex CLI: 0.147.0-alpha.6.6
    • One long-lived Desktop app-server: codex.exe app-server --analytics-default-enabled
    • Project configuration registers two Rust stdio MCP servers:
      • one read-only proxy
      • one human-gated registration server

    Measured process tree

    Snapshot captured on 2026-08-13 at 12:09:53 UTC+07:00:

    • One app-server held 104 direct child processes.
    • The two custom MCP servers had accumulated into 22 live processes:
      • 11 × mcp-proxy
      • 11 × registration-mcp
    • They were created in matching timestamp pairs across multiple waves.
    • Every retained process still had the same live app-server as its direct parent; these were not Windows orphans.
    • The complete set of direct app-server children included:
      • 52 × node.exe MCP processes
      • 26 × node_repl.exe
      • 22 × the custom Rust MCP processes
      • 4 other app-server helper processes

    Aggregate resource use of all 104 direct children:

    • approximately 2.8 GB working set
    • approximately 2.8 GB private memory
    • 19,470 handles

    The 22 Rust MCP processes alone used:

    • 137.5 MB working set
    • 20.8 MB private memory
    • 2,551 handles
    • zero CPU delta during a three-second observation
    • no TCP connections; they were blocked waiting for stdio input

    Useful lifecycle evidence

    Both Rust servers use a bounded read_line() loop and return normally as soon as stdin reaches EOF:

    Earlier generations nevertheless remain alive indefinitely. This strongly suggests that the app-server retains their stdio writer/transport instead of closing the previous generation.

    The processes are also not children of the supervised application. Shutting down that application correctly leaves these Codex-owned MCP processes untouched, confirming that their lifetime is controlled by the Desktop app-server.

    Expected behavior

    When an MCP connection, thread, agent, or replacement generation is no longer active, Codex should close its stdio transport and wait for or terminate that specific child. Repeated generations should not accumulate beneath one app-server.

    This appears consistent with #30408, but adds:

    • reproduction on the newer Windows package 26.803.10989.0;
    • native single-process Rust MCP servers without npm/cmd wrappers;
    • direct evidence that EOF-based shutdown is implemented but never triggered; and
    • measured handle growth in addition to process and memory counts.
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

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingmcpIssues related to the use of model context protocol (MCP) serversperformancewindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions