MCP servers eat up memory when multi-tasking in Codex App
What version of the Codex App are you using (From “About Codex” dialog)?
260208.1016
What subscription do you have?
Business
What issue are you seeing?
Hey,
I'm working 100% of the time using the Codex app, working on multiple parallel worktrees overtime multiple days, can get to more than 10 active threads at a time.
I also have 17 MCP servers configured for my app.
Combine these two and you get about 30gb of memory used when the codex app is open on my PC, simply because i have 10 codexes working in parallel, not to mention sub agents and such.
Further more, when I close off/archive conversations in the codex app, it doesn't seem to kill the conversation process as well as MCP server processes, effectively flooding the PC with stale instances that fill up memory overtime.
A few solution I can propose to address this:
- if usage is through the app, share MCP connections across all codex instances. I understand it's very different from how Codex functions today but it's one approach
- Implement tool search so context doesn't bloat + MCP servers are connected at boot up so only the needed MCPs are used with how the conversation progress
- Allow turning off, turning on and restarting MCP servers incase some connections aren't working and the process is stale on the PC
What steps can reproduce the bug?
Work on multiple codex conversations in parallel
What is the expected behavior?
High memory usage on MAC
Additional information
I am using the MacBook Pro M4 Max with 36GB of Ram, so it took a lot of Codex session to reach the limit of my PC, but eventually it did.
10 Comments
With that many MCP servers, I'm surprised codex is even functioning. MCP servers can take up quite a lot of your context window (due to their instructions / meta-data / schema etc). Honestly, in my experience codex is just phenomenal without external assistance. It should not need that many MCP servers unless all of these are custom MCP servers that control gadgets around your house.
@guidedways it works very well. compaction handles context fill up really smoothly in the transition, and i do need some of the MCPs each time, anything i don't need i remove.
when i'm doing research i need to connect a lot of MCPs to gather context.
I've also experienced that codex does not properly clean up the mcp servers it started up when running. That includes mcp servers started up by the sub-agents as well
bump? :)
Related issues that may help narrow root cause and mitigation:
These are CLI-focused, but the underlying lifecycle pattern seems aligned with what this App issue reports (stale MCP/agent processes accumulating over time).
If useful, we can consolidate around:
1) MCP connection sharing/pooling strategy,
2) explicit auto-close lifecycle policy for completed/idle agents,
3) deterministic MCP teardown when no active agent references remain.
I encountered the same problem.
I dug into this locally and can confirm a more specific app-side failure mode that matches the original report.
My setup:
26.311.21342 (build 993)Darwin 25.3.0 arm64 armomx_state,omx_memory,omx_code_intel,omx_trace, and a customclaude_plan_reviewWhat I observed:
Codex.app/Contents/Resources/codex app-serverlaunchd; they stay attached to the still-running app-server and accumulate over timeA representative process snapshot looked like this:
Source-level findings from
openai/codex:ThreadManager::spawn_thread_with_source()goes throughCodex::spawn(), which creates a freshMcpConnectionManagerfor that session.kill_on_drop(true)and a process-group guard that terminates / kills the process group on drop.thread/unsubscribe. If the last subscriber unsubscribes, it shuts down the thread and emitsthread/closed.retaining thread listener after connection disconnect left zero subscribersImportant control experiment:
/dev/nullMy current read is:
McpConnectionManagers never dropThis seems closely related to
#12491, but the narrower root cause here is conversation / thread unload lifecycle in the desktop app, especially aroundthread/unsubscribeand disconnect handling.Same pattern here, plus residue after Cmd+Q
@yahelroro0196 this matches what I saw. @francoisrob on sub-agent cleanup and @RemarkRemedy on the app-server unload path also line up with my side.
My setup
26.311.21342 (build 993)Darwin 25.3.0, Apple Silicon18conversations over~2.5 dayscontext7,playwright,chrome-devtools,webflow mcp-remote, custom Python MCPBefore I quit the app
It looked like each conversation got its own full MCP bundle, and finished/archived conversations were not going back to a sane baseline.
I want to be clear on the same distinction people made in
#12333and#14233: i am not asking for one shared MCP instance for all active conversations. The bug on my machine was teardown after the work was already done.After Cmd+Q
I quit Codex from the Dock on March 17, 2026. Most of the pile died right away:
But cleanup was still not complete. I still had:
The old survivors matched earlier Codex sessions from
March 9, 2026andMarch 14, 2026.So for me this is not only "memory gets high while Codex is open". It is also "a small orphan set can survive the quit and still be there across later sessions".
Same-machine control:
#10710is why this feels like an app lifecycle gap more than a raw stdio cleanup bug. The process-group cleanup seems to exist when drop happens. The desktop app path still looks like it sometimes never reaches that clean drop for every conversation.One architecture split that has helped us on a similar runtime: treat MCP child lifetime as a separate admission problem from thread lifetime.
Concretely:
owner_threads, last tool call timestamp, rss, idle_since)refcount == 0plus a short idle TTL, instead of tying the child to whether the parent app-server is still aliveThat tends to solve two different pain points at once:
If the team does not want global MCP sharing, a narrower fix would still help a lot: deterministic teardown on zero live thread refs, plus a visible
why_alivereceipt in the app so operators can tell stale from intentional.We have been hitting the same class of failure in MartinLoop, and the biggest win was making teardown observable before trying to make it clever.
Reproduced this on the current Codex Desktop build on Apple Silicon.
A secret-safe process inventory found roughly 900 MCP-related Node processes consuming about 10 GB RSS. The repeated groups were proportional to retained task runtimes (approximately 75 copies of each configured stdio server or wrapper). Many processes had been alive for about 20 hours. Migrating compatible remote servers from stdio bridges to native Streamable HTTP prevented new bridge copies, but existing task-owned processes remained alive until Codex was restarted.
This suggests the missing layer is Codex-side lifecycle ownership, not just individual MCP implementation cleanup.
Possible fixes:
mcp-remote-style bridge duplicates a transport Codex can already speak directly.Account identity and state isolation must remain part of pooling eligibility: two separately authenticated MCP registrations must not be merged merely because they use the same implementation.