You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Windows Desktop 26.810.41047] Local STDIO MCP process groups accumulate and consume ~7 GB RAM #38526
Title: [Windows Desktop 26.810.41047] Local STDIO MCP process groups accumulate and consume ~7 GB RAM
Environment:
Windows
ChatGPT/Codex desktop app 26.810.41047
Local STDIO MCP servers: Playwright, todo-query, node_repl
Actual behavior:
After starting/resuming multiple Codex threads, local MCP process groups accumulate and are not reclaimed when most threads become idle or unloaded.
Observed:
26 identical MCP process groups
183 processes total
Approximately 7 GB RAM and 1,200 threads
Each group contains:
1 node_repl.exe
2 Python processes for todo-query
2 cmd.exe and 2 node.exe processes for Playwright MCP
The app listed only 1 active and approximately 4 idle threads at the time
System became noticeably unresponsive
Logs show each thread/start initializing a new MCP manager and launching the configured STDIO servers. Some temporary groups exit gracefully, but many remain attached to the main Codex process.
Expected behavior:
MCP processes belonging to closed, unloaded, or expired thread runtimes should be terminated or reused instead of accumulating.
Workaround:
Restarting the app or disabling local MCP servers releases/prevents the accumulated processes.
237 descendants of the single current codex.exe app-server
approximately 7.14 GB working set / 7.28 GB private memory
approximately 2,100 threads
approximately 42,848 handles
At the system level this coincided with:
639 processes
12,331 threads
276,432 handles
approximately 115,000 context switches/sec
severe system-wide lag
The arithmetic was consistent with the tree: 29 retained contexts * 8 MCP processes = 232, plus a few app/tool helper processes.
These were not leftovers from an older app-server instance. They were descendants of the current app-server and had been started after the current Desktop launch. Some MCP groups remained alive for roughly 68–97 minutes. Counts occasionally dropped as individual contexts were eventually cleaned up, which looks like delayed/partial cleanup rather than permanent OS orphans.
Mitigation and confirming evidence
I changed the four task-specific STDIO MCP servers to enabled = false, kept only the bundled node_repl enabled, and fully restarted Codex Desktop.
After restart:
16 Codex descendants total
13 node_repl.exe processes, stable across repeated samples
0 unityMCP processes
0 comfyui processes
0 jcodemunch / uv / uvx / Python processes
all node_repl instances together: about 133 MB working set / 44 MB private memory
system process count dropped from 639 to approximately 371
This strongly suggests that per-context STDIO startup is multiplying the cost of every globally enabled server. Disabling the heavy servers removes the severe resource impact, but it does not eliminate the underlying retention: 13 node_repl workers still remained while only a small number of tasks were active.
Expected behavior
STDIO MCP process trees should be terminated when their owning task/runtime becomes idle, unloaded, closed, or otherwise disposable.
Restored historical tasks should not eagerly start every globally enabled STDIO MCP unless the runtime is actually active.
Alternatively, eligible MCP servers should be pooled/shared or the number of retained tool runtimes should be bounded.
The UI-visible task count and the number of live tool/MCP runtimes should not diverge enough to create hundreds of background processes.
The configuration-only workaround is effective but removes tools globally. I can provide sanitized PowerShell process-tree collection logic if useful.
I traced the current main lifecycle for the Windows process accumulation reported here.
The remaining leak is at MCP runtime publication/shutdown boundaries:
McpRuntime::publish replaces the published McpConnectionSet, while bindings and prepared calls can still hold the previous set.
McpRuntime::shutdown only shut down the latest published set, so a superseded stdio generation could remain alive when an older binding was still in flight.
A lazy, dormant connection must not be shut down by awaiting its client: that would start the process during cleanup.
I prepared a focused local patch that:
Identifies connections removed by a refresh but not shared by the successor.
Retires each old connection after its last Arc lease is released, preserving in-flight call semantics.
Tracks retired generations weakly and force-shuts all live retired generations plus the current generation during final session shutdown; cleanup is kept alive if the initiating caller is cancelled.
Cancels dormant lazy startup without polling/starting the child.
Adds regressions for twenty repeated pending-server refreshes and for final session shutdown while an external in-flight call still holds the superseded stdio connection.
This is ownership-based cleanup; it does not scan or kill processes by name/PID. Formatting and diff checks pass locally. Full Rust compilation is currently blocked on my Windows checkout because link.exe/MSVC Build Tools are not installed, so I am not claiming the test suite passed.
The repository's contributing guide says external PRs require maintainer invitation. If this direction matches the intended fix, I can provide the focused branch/PR after an invitation.
Activity
github-actions commentedon Aug 14, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
yzh522163-prog commentedon Aug 16, 2026
Additional reproduction on a newer Windows Desktop build, with a full process-tree breakdown and before/after mitigation.
Environment
26.810.7004.0x64codex-cli 0.148.0-alpha.9node_replunityMCPcomfyuijcodemunchObserved process fan-out
Although only two tasks were intentionally active, the app-server retained/restored approximately 29 execution contexts.
Each retained context started this process set:
node_replunityMCPcomfyuijcodemunchuvx -> uv -> python -> jcodemunch-mcp -> python)A process-tree snapshot showed:
codex.exe app-serverAt the system level this coincided with:
The arithmetic was consistent with the tree:
29 retained contexts * 8 MCP processes = 232, plus a few app/tool helper processes.These were not leftovers from an older app-server instance. They were descendants of the current app-server and had been started after the current Desktop launch. Some MCP groups remained alive for roughly 68–97 minutes. Counts occasionally dropped as individual contexts were eventually cleaned up, which looks like delayed/partial cleanup rather than permanent OS orphans.
Mitigation and confirming evidence
I changed the four task-specific STDIO MCP servers to
enabled = false, kept only the bundlednode_replenabled, and fully restarted Codex Desktop.After restart:
node_repl.exeprocesses, stable across repeated samplesunityMCPprocessescomfyuiprocessesjcodemunch/uv/uvx/ Python processesnode_replinstances together: about 133 MB working set / 44 MB private memoryThis strongly suggests that per-context STDIO startup is multiplying the cost of every globally enabled server. Disabling the heavy servers removes the severe resource impact, but it does not eliminate the underlying retention: 13
node_replworkers still remained while only a small number of tasks were active.Expected behavior
The configuration-only workaround is effective but removes tools globally. I can provide sanitized PowerShell process-tree collection logic if useful.
yzh522163-prog commentedon Aug 16, 2026
I traced the current
mainlifecycle for the Windows process accumulation reported here.The remaining leak is at MCP runtime publication/shutdown boundaries:
McpRuntime::publishreplaces the publishedMcpConnectionSet, while bindings and prepared calls can still hold the previous set.McpRuntime::shutdownonly shut down the latest published set, so a superseded stdio generation could remain alive when an older binding was still in flight.I prepared a focused local patch that:
This is ownership-based cleanup; it does not scan or kill processes by name/PID. Formatting and diff checks pass locally. Full Rust compilation is currently blocked on my Windows checkout because
link.exe/MSVC Build Tools are not installed, so I am not claiming the test suite passed.The repository's contributing guide says external PRs require maintainer invitation. If this direction matches the intended fix, I can provide the focused branch/PR after an invitation.