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

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

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:

  • #28361
  • #30408
  • #30753
  • #29079

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:

  • #28361 describes Windows app-server/MCP children not being reaped and accumulating to hundreds.
  • #30753 describes Windows Desktop creating duplicate MCP pools after RefreshMcpServers on a hidden thread.

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.

View original on GitHub ↗

6 Comments

github-actions[bot] contributor · 13 days ago

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

  • #30753
  • #30408

Powered by Codex Action

xxH7r · 13 days ago

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.

mayank6091 · 12 days ago

@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.

ken-jo · 7 days ago

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.

wherewolf87 · 7 days ago

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.

lixunqi12 · 3 days ago

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.