Skip to content

build-ios-apps starts multiple XcodeBuildMCP instances on unsupported Linux hosts, causing severe memory pressure #33343

Closed as not planned

Description

@tnt2ray
### Component

Codex App Server / plugin runtime / MCP lifecycle

### Versions

- Codex CLI / App Server: `0.144.1`
- Codex Desktop client observed in logs: `26.707.72221`
- `build-ios-apps` plugin: `0.1.2`
- `xcodebuildmcp`: `2.6.2`
- Node.js: `24.18.0`
- npm: `11.18.0`

### Environment

- Debian GNU/Linux 13 (trixie), x86_64
- KVM virtual machine
- 1 vCPU
- 1.9 GiB RAM
- Initially 1 GiB swap
- No Xcode or iOS Simulator; neither can run on this host

### Summary

The `build-ios-apps` plugin eagerly starts XcodeBuildMCP on a Debian Linux
host, even when the user request, repository, selected skill, and actual tool
usage have no relationship to iOS, macOS, Swift, Xcode, or Simulator.

A separate XcodeBuildMCP process tree is created for multiple Codex threads and
subagents. Six concurrent instances were initially observed, consuming
approximately 1.2 GiB on a host with only 1.9 GiB RAM.

No XcodeBuildMCP tool was ever called.

The MCP processes were started while Codex initialized the MCP manager and
enumerated the available tool list, before the model selected a skill or tool.

Uninstalling the plugin reported success and briefly removed its cache, but the
running App Server subsequently recreated the plugin cache and started new
XcodeBuildMCP processes.

### Evidence that project code did not start the MCP

Every XcodeBuildMCP process was a direct descendant of Codex App Server:

```text
codex app-server
└─ npm exec xcodebuildmcp@latest mcp
   └─ sh -c xcodebuildmcp mcp
      └─ node .../xcodebuildmcp mcp

The observed process environment included:

npm_config_user_agent=npm/11.18.0 node/v24.18.0 linux x64
XCODEBUILDMCP_ENABLED_WORKFLOWS=simulator,ui-automation,debugging,logging

The project did not contain or execute an xcodebuildmcp command.

The affected threads were working on unrelated tasks, including:

  • Markdown-based examination question import
  • SQL concurrency review
  • Release/delta review
  • Linux SSH and memory-pressure investigation

Evidence that no skill or Xcode tool triggered it

I scanned all available active and archived rollout JSONL files.

Results:

Actual mcp__XcodeBuildMCP__* tool calls: 0
build-ios-apps skill reads/triggers: 0

No iOS/macOS skill was selected or read before these processes started.

Internal startup path shown by Codex logs

Codex logs show that XcodeBuildMCP was started during thread/session
initialization:

thread_spawn
→ session_init
→ session_init.mcp_manager_init
→ new{server_name=xcodebuildmcp}
→ start_server_task

During turn initialization, Codex eagerly enumerated all plugin MCP tools:

run_turn
→ build_skills_and_plugins
→ list_all_tools
→ server_name=xcodebuildmcp
→ tool_count=44

Representative trace messages:

session_init.mcp_manager_init:
new{server_name=xcodebuildmcp}:
start_server_task{server_name=xcodebuildmcp}
text
build_skills_and_plugins:list_all_tools:
listed MCP server tools while building tool list
server_name=xcodebuildmcp
tool_count=44
text
list_all_tools:
waiting for MCP server tools while building tool list
server_name=xcodebuildmcp
has_cached_tools=false
startup_complete=true

This happens before any Xcode tool invocation and independently of task
relevance.

Unbounded per-thread/subagent multiplication

Multiple unrelated root threads and subagent threads each initialized their own
MCP manager and started a separate XcodeBuildMCP process tree.

Three confirmed subagents were performing unrelated review tasks:

/root/final_delta_review
/root/sql_concurrency_review
/root/release_delta_review

Each had:

XcodeBuildMCP tool calls: 0
iOS/macOS skill triggers: 0

Despite that, their creation times aligned with new XcodeBuildMCP process
start times.

The initial observation showed six simultaneous process trees. The wrappers and
Node processes together consumed approximately 1.2 GiB.

Resource impact

Before terminating the duplicate MCP processes:

RAM:        1.9 GiB total
Available:  approximately 300 MiB
Swap used: approximately 450–700 MiB
I/O wait:  observed as high as 57%

systemd-journald repeatedly logged:

Under memory pressure, flushing caches.

The three preceding abnormal boots contained respectively:

78 memory-pressure events
5 memory-pressure events
16 memory-pressure events

The host repeatedly became unresponsive over SSH during high CPU, memory, and
swap pressure. The journal ended abruptly without a normal shutdown sequence.

After terminating six XcodeBuildMCP instances:

Available memory increased to approximately 1.4 GiB
System load dropped substantially
XcodeBuildMCP process count became 0

This strongly correlates the unnecessary MCP instances with the host-wide
resource exhaustion, although there was no explicit kernel OOM kill.

Plugin uninstall does not stop or invalidate the runtime state

I ran:

codex plugin remove build-ios-apps@openai-curated-remote --json

The command reported success:

{
  "pluginId": "build-ios-apps@openai-curated-remote",
  "name": "build-ios-apps",
  "marketplaceName": "openai-curated-remote"
}

Immediately afterward:

  • The plugin cache directory was absent.
  • Plugin references were absent from ~/.codex/config.toml.
  • Four existing XcodeBuildMCP process trees had to be terminated manually.

However, while the same App Server remained running:

  • npm recorded nine additional npm exec xcodebuildmcp@latest mcp starts.
  • The build-ios-apps/0.1.2 plugin cache directory reappeared.
  • New XcodeBuildMCP processes appeared again.
  • During preparation of this report, two XcodeBuildMCP process trees were
    running again.
  • No XcodeBuildMCP tool had been called.

This suggests that the running App Server, Desktop-injected plugin state, or
another active runtime state can re-materialize a locally uninstalled plugin.
The exact ownership of that state is not visible from the client logs.

Steps to reproduce

  1. Run Codex App Server on a Linux host.

  2. Install or enable build-ios-apps@openai-curated-remote.

  3. Open a thread with a task unrelated to iOS/macOS, such as editing Markdown.

  4. Observe the process tree:

    npm exec xcodebuildmcp@latest mcp
    
  5. Inspect Codex logs and observe:

    session_init.mcp_manager_init
    new{server_name=xcodebuildmcp}
    start_server_task
    list_all_tools
    
  6. Confirm that no mcp__XcodeBuildMCP__* tool was invoked.

  7. Spawn or resume several unrelated threads/subagents.

  8. Observe additional independent XcodeBuildMCP process trees.

  9. Run codex plugin remove build-ios-apps@openai-curated-remote.

  10. Keep the existing App Server running and continue unrelated turns.

  11. Observe the plugin cache and XcodeBuildMCP processes reappear.

Expected behavior

  1. build-ios-apps and XcodeBuildMCP should be unavailable on non-macOS hosts,
    or the runtime should verify OS/Xcode compatibility before starting them.
  2. Plugin MCP servers should not start merely because Codex enumerates the
    global tool list when the platform is unsupported.
  3. A plugin MCP should not create an unbounded local process tree for every
    unrelated thread or subagent.
  4. MCP instances should be shared where safe, constrained, lazily started, or
    reclaimed when idle.
  5. Uninstalling a plugin should:
    • invalidate it in the running App Server;
    • terminate its child MCP processes;
    • prevent its cache from being recreated;
    • prevent subsequent turns from restarting it.
  6. Unsupported MCP servers should not consume CPU, RAM, swap, or network
    resources.

Actual behavior

  • XcodeBuildMCP starts on Debian Linux.
  • Startup occurs during MCP manager/tool-list initialization.
  • No related skill or tool call is required.
  • Multiple threads and subagents create multiple process trees.
  • Six instances consumed most of a 2 GiB host.
  • The host experienced severe memory pressure and SSH unresponsiveness.
  • Plugin removal did not terminate existing processes.
  • The running system recreated the plugin cache and started the MCP again.

Severity

High for low-memory local or remote Codex hosts.

An unusable, platform-specific plugin can consume most system memory without
ever being called, and parallel agent work amplifies the issue enough to make
the entire host unresponsive.

Suggested areas to investigate

  • Platform filtering for plugin manifests and MCP servers
  • session_init.mcp_manager_init
  • build_skills_and_plugins:list_all_tools
  • Per-thread MCP connection-manager ownership
  • Plugin MCP process reuse and idle cleanup
  • Plugin uninstall invalidation in a running App Server
  • Desktop/plugin-state synchronization after CLI uninstall
  • Automatic cache re-materialization

Activity

  1. added
    bugSomething isn't working
    app-serverIssues involving app server protocol or interfaces
    mcpIssues related to the use of model context protocol (MCP) servers
    skillsIssues related to skills
    on Jul 15, 2026
  2. github-actions commented on Jul 15, 2026

    @github-actions
    Contributor
  3. tnt2ray commented on Jul 15, 2026

    @tnt2ray
    Author

    Closing this report in favor of #32694, where I added the Linux-specific reproduction evidence, zero-tool-call traces, platform-gating findings, and uninstall lifecycle details: #32694 (comment). This issue is a duplicate of the broader per-runtime MCP subprocess fan-out problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app-serverIssues involving app server protocol or interfacesbugSomething isn't workingmcpIssues related to the use of model context protocol (MCP) serversperformanceskillsIssues related to skills

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions