Windows Desktop 26.623 starts duplicate MCP pools after RefreshMcpServers on hidden thread

Open 💬 4 comments Opened Jun 30, 2026 by aidawilliam41-ops

Summary

On Windows Codex Desktop, a clean app start spawned four near-complete MCP helper pools within the first minute. Local logs show four RefreshMcpServers submissions in the startup window: three were sent to a non-visible/hidden session loop, and one to a visible pinned thread.

This looks related to the MCP refresh lifecycle area fixed/covered by #29608, but this report adds a Windows Desktop case where duplicate MCP stdio helper pools appear immediately after startup, not after a long-running session.

Environment

  • Product: Codex Desktop App on Windows
  • App package: OpenAI.Codex 26.623.9142.0
  • Bundled/local CLI observed from the Desktop runtime path: codex-cli 0.142.4
  • OS: Windows 11 x64
  • Shell in Codex thread: PowerShell
  • App server command shape:
  • codex.exe app-server --analytics-default-enabled
  • MCP configuration location:
  • %USERPROFILE%\.codex\config.toml

Observed behavior

After a clean Windows restart and launching Codex Desktop, before running any deliberate user workload in that session, the app server spawned multiple MCP helper sets.

Process creation timestamps showed four MCP batches around:

20:59:09
20:59:20
20:59:28
20:59:35

The repeated pools included local stdio MCP helpers such as:

node_repl.exe
node.exe ./mcp/server.mjs --stdio       # codex-security
github-mcp-server.exe
morph-mcp
firecrawl-mcp
tavily-mcp
playwright-mcp
shadcn mcp
figma-developer-mcp
valyu

A later process snapshot still showed multiple instances of the same MCP helper classes, including four node_repl and four codex-security stdio server processes.

RefreshMcpServers evidence

In the startup window 20:58:00..21:01:30 local logs_2.sqlite contained exactly four RefreshMcpServers submissions:

RefreshMcpServers rows in startup window: 4
by_thread:
  hidden/non-visible thread 019f19af-... : 3
  visible pinned WiaiKit thread          : 1

46537615 20:59:14 DEBUG codex_core::session::handlers hidden-thread sub=019f19af-6a38-...
46537765 20:59:15 DEBUG codex_core::session::handlers hidden-thread sub=019f19af-702c-...
46538447 20:59:23 DEBUG codex_core::session::handlers hidden-thread sub=019f19af-8ea8-...
46538450 20:59:23 DEBUG codex_core::session::handlers visible-thread sub=019f19af-8eb9-...

The hidden/non-visible thread had only four exact-thread log rows in the checked DB:

20:59:09 shell_snapshot for hidden thread
20:59:14 RefreshMcpServers
20:59:15 RefreshMcpServers
20:59:23 RefreshMcpServers

The hidden thread did not appear through the app thread-list API, did not appear in the persisted Desktop global state file, and did not have a matching session file under %USERPROFILE%\.codex\sessions.

A separate hidden thread seen later was identified as a Memory Writing Agent and is not the cause of the startup MCP batches.

Things ruled out locally

  • The user's config.toml does not contain duplicated MCP server definitions. It has one configured set of local MCP servers.
  • Desktop saved-project/pinned-thread state validated cleanly:
  • ShapeOk=True
  • SavedRootsOk=True
  • ProjectOrderOk=True
  • PinnedOk=True
  • The duplicate MCP process groups were spawned by the main Desktop app-server parent process, not by a user shell script.
  • The repeated RefreshMcpServers submissions are visible in logs_2.sqlite, so this is not only a Task Manager display issue.
  • No secrets or token values were printed or included in this report.

Expected behavior

After a clean Desktop startup, Codex should not launch several full duplicate pools of stdio MCP helper processes for the same MCP configuration.

If MCP refresh is triggered for loaded threads during startup, old/superseded managers should be shut down and their stdio helper processes should exit. Hidden/internal threads should also not cause repeated full MCP pool creation unless those pools are actually needed and lifecycle-owned.

Actual behavior

Codex Desktop launched multiple MCP helper pools shortly after startup. The local evidence points to repeated RefreshMcpServers submissions, mostly targeting a hidden/non-visible thread, with the stdio MCP helpers remaining alive.

Related issues / PRs

  • #25744: macOS report for accumulated MCP/Computer Use helper processes and unreaped children. This Windows case looks related in symptom class but differs in platform and trigger timing.
  • #26560: Remote Control / thread MCP launch environment issue. Possibly related to per-thread MCP config/session identity, but not the same reproduction.
  • #29608: Shut down superseded MCP managers on refresh. The local Windows Desktop build still exhibits the stdio MCP processes stayed alive and accumulated across refreshes class, or the Desktop build may not yet include the fix.
  • #21055: MCP refresh orchestration moved into app-server / per-thread refresh path.
  • #8957: introduced MCP hot refresh command/path.

Impact

  • Large process count immediately after startup.
  • Extra memory/process overhead from duplicate stdio MCP helpers.
  • Confusing diagnostics: the visible UI shows only normal threads, while the refreshes target at least one hidden/non-listable session loop.
  • Potentially affects Browser/Chrome/Computer Use workflows because node_repl is one of the duplicated MCP helpers.

Suggested investigation area

  • App-server startup MCP refresh scheduling.
  • Hidden/internal thread registration in ThreadManager and whether it participates in queue_best_effort_refresh.
  • Whether RefreshMcpServers can be queued multiple times for the same hidden thread during startup/plugin/account reconciliation.
  • Whether the Desktop build includes the #29608 cleanup behavior and whether cleanup covers the hidden/internal session case.

Notes

I can provide a more detailed sanitized evidence pack privately if needed. The raw local evidence includes logs_2.sqlite excerpts, process parent/child snapshots, and a sanitized list of MCP server names, but I did not attach raw logs publicly because they may contain local paths and unrelated thread metadata.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗