[Linux Desktop 0.147.0] Completed v2 subagents retain full stdio MCP runtimes
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
Environment
- Codex Desktop on Linux
- Bundled / local CLI:
codex-cli 0.147.0 - Platform:
Linux 6.8.0-137-generic x86_64(Ubuntu 24.04) - Authentication: ChatGPT subscription
- MCP configuration at the time of reproduction: 8 enabled stdio servers plus 4 Streamable HTTP servers
- Long-lived Desktop
app-server - Multi-agent v2 /
spawn_agentworkflows
What issue are you seeing?
Completed subagents can leave their entire stdio MCP runtime resident under the live Desktop app-server. The processes are not zombies and are not reparented to PID 1: every retained MCP launcher/server is still a direct descendant of the same healthy app-server.
On one real workload, after a subagent-heavy task:
- 15 instances each of
context7,github,gitee,playwright, andcodex-securityremained. - The 15 start clusters aligned across unrelated servers, so the growth unit was one complete MCP stack, not one crashing third-party server.
- A sixth stdio MCP was unusually expensive because of its own development logging, amplifying the Codex lifecycle bug but not causing the stack duplication.
- System used memory grew to about 29 GiB; the Desktop cgroup accounted for about 23.9 GiB RSS.
- Sending SIGTERM only to the stale MCP descendants reduced system used memory to about 11 GiB and the Desktop cgroup to about 5.4 GiB. The live task then recreated one healthy current stack, demonstrating that the old stacks were not required for the current task.
Local logs correlate each new process batch with:
spawn_agent / followup_task
-> thread_spawn
-> session_init
-> session_init.mcp_manager_init
-> mcp.runtime.refresh
-> start_server_task
This is related to #12491 and #17832, but the narrower failure mode here is completed v2 subagents retaining live runtimes while their logical agent identity remains resumable. It is not a request to mark the spawn edge closed, and it is not only the already-fixed manager-replacement leak from #18881.
Steps to reproduce
- Configure several global stdio MCP servers.
- Start Codex Desktop and keep the same
app-serveralive. - Run a task that creates subagents with
spawn_agent; let them finish normally. - Repeat across several tasks and/or use follow-up/resume flows.
- After every child reports a terminal status, count the
app-serverdescendants by MCP command. - Observe complete, timestamp-aligned MCP stacks remaining after the child work has completed and memory increasing monotonically.
The problem becomes especially visible with a high-memory stdio server, but it also reproduces as equal instance counts across small, unrelated servers.
Current-main code observation
The current v2 residency path can unload Completed, Errored, or Interrupted threads, preserving their durable logical identity so they can be reloaded on later delivery. However, that unload path is currently driven by a later residency-slot reservation under capacity pressure. The completion watcher delivers the child result to the parent and returns without proactively releasing the now-idle resident thread/runtime.
This can leave completed children holding stdio MCP processes indefinitely when no later spawn forces eviction. Across multiple Desktop tasks, those resident stacks accumulate under the same long-lived app-server.
Recent lazy startup work reduces how many MCPs a child starts, but any MCP actually started by the child still needs an idle release path.
Expected behavior
After a v2 subagent reaches a terminal status, its result has been delivered, its active turn is cleared, and its mailbox is empty:
- Its resident execution runtime (including stdio MCP children) should be unloaded within a bounded period.
- Its logical agent id/path and open spawn edge should remain durable so
followup_task/send_inputcan transparently reload it. - Active turns and pending mailbox input must never be unloaded.
- Repeating completed subagent runs should return MCP process counts and RSS near the idle baseline instead of growing monotonically.
A regression test should use a PID-recording stdio MCP fixture, verify that the process exits after terminal idle, then send a follow-up and verify that the same logical agent reloads and can start/use MCP again.
Related issues / changes
- #12491 — broad Desktop MCP child cleanup tracking; latest maintainer guidance asks distinct bugs to be filed separately
- #17832 — Playwright stdio processes retained after subagents
- #17574 — subagent MCP helper process trees
- #30408 — closed/archived threads retaining MCP processes
- #33700 — persisted subagent state / rehydration observations (logical edge lifetime is related but should not be conflated with runtime residency)
- #18881 / #19753 — explicit manager/client shutdown fixes
- #26632 and #26997 — durable v2 unload/reload behavior
- #38217 — lazy startup of required cached MCP servers for subagents
I am preparing a minimal patch with tests. I understand external contributions are invitation-only; if maintainers agree that proactively releasing terminal-idle v2 runtimes is the right layer, please explicitly invite the PR and I will open it against main.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the v2 completion watcher, residency-slot unload/reload path, and the spawn_agent, followup_task, and send_input entry points described in the issue. Use a PID-recording stdio MCP fixture to verify terminal-idle runtimes exit, then confirm follow-up reloads the same logical agent and can use MCP again without unloading active turns or pending mailbox input.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux, rust
- Domain
- backend, distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100