openai / openai/codex

stdio MCP servers accumulate under a live app-server on 26.810.52044, after the #18881 / #19753 shutdown fix

Open
#38,925 10 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug mcp performance
Dominant language
Rust
Stars
125k
Forks
19.5k
PR merge metrics
PR metrics pending

Description

Filing separately from the closed #18881 because the shutdown path that PR #19753
fixed now works on this build, while accumulation during a live session does
not. Cross-referencing #12491 (open, GUI), #20349, #25015, #26984.

Environment

Codex (ChatGPT.app) 26.810.52044, bundle 6662
codex-cli 0.148.0-alpha.9
macOS 26.6.1 (25G76), arm64
Surface Codex desktop app, codex ... app-server

Two stdio MCP servers configured in ~/.codex/config.toml, both launched via a
wrapper script that execs (so the wrapper leaves no process of its own):

[mcp_servers.fin]
command = "/Users/<user>/.ai_ops/bin/mcp-launch.sh"
args = ["fin"]          # execs a python stdio server

[mcp_servers.email]
command = "/Users/<user>/.ai_ops/bin/mcp-launch.sh"
args = ["email"]        # execs `npx -y @codefuturist/email-mcp stdio`

What happens

A long-lived app-server spawns a fresh stdio MCP server roughly every three
minutes and never closes the previous one. The old servers stay parented to the
app-server with their stdio pipes still held open (lsof shows fds 0/1/2 as
PIPE), at 0.0% CPU and ~1s of accumulated CPU time. They are idle but retained.

This is the same shape as #18881, but that issue was closed by PR #19753
(merged 2026-04-28) and this build postdates it.

What PR #19753 did fix, verified here

Shutdown draining works. When the app-server exits, its MCP children go with it.
Observed directly: app-server PID 43065 was restarted, and all ~33 of its
accumulated MCP children terminated along with it, requiring no manual cleanup.

So this is not a regression of the shutdown path. It is the in-session path,
where servers are replaced but the superseded ones are never shut down.

Measurements

Two independent windows, one app-server each, machine otherwise idle:

Rate ~1 new stdio server per 3 minutes, sustained
Single app-server (PID 14353), 71 min uptime 24 fin_mcp children
Across both configured servers, ~1 hour after a manual clear from 11 processes 137 processes
RSS at that point ~5.4 GB
Free system memory at that point 141 MB
After killing the superseded children 4480 MB free

Reproduced twice, hours apart, across an app-server restart in between.

Reproduction

  1. Configure one or more stdio MCP servers in ~/.codex/config.toml.
  2. Start the Codex desktop app and leave a project session open.
  3. Watch the children of the app-server process:
APPSRV=$(pgrep -f "Resources/codex .*app-server" | head -1)
watch -n 30 "pgrep -P $APPSRV -f mcp | wc -l"

The count climbs monotonically and never decreases while the app-server lives.

Expected

When a stdio MCP server is replaced, the superseded one is shut down and its
process reaped, so the count tracks the number of configured servers rather than
session age.

Notes

Each server is cheap alone (~28 to 90 MB here) and the fault is only visible over
hours. With two servers configured it took roughly one hour to consume several GB
and drive the machine to 141 MB free. #12491 reports the same end state at much
larger scale (1319 processes, 37 GB), which suggests the ceiling is however long
the app stays open.

The three fix directions proposed in #12491 (process groups, startup reaping of
stale trees, heartbeat self-termination) would each cover this case too. The
narrowest fix specific to what is seen here is shutting down the superseded
server at the point of replacement, rather than only at session shutdown, which
is what #19753 addressed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the app-server's stdio MCP server replacement and lifecycle handling, then compare the in-session path with the shutdown behavior fixed by PR #19753. Reproduce with configured stdio servers and monitor app-server children as described; done means superseded servers are shut down and reaped so the process count tracks configured servers during a live session.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.