[Cross-platform] build-ios-apps starts XcodeBuildMCP on non-macOS hosts in Desktop and VS Code (autogen selfreport from codex)
What versions are affected?
Two independent current reproductions:
| Host and client | Codex version | Plugin |
| --- | --- | --- |
| Windows 11 ARM64, Codex Desktop | MSIX 26.810.4967.0 | build-ios-apps 0.1.2 |
| Rocky Linux 10.2 x86_64, VS Code Web extension | extension 26.810.41047-linux-x64, CLI/app-server 0.147.0 | build-ios-apps 0.1.2 |
What issue are you seeing?
The build-ios-apps plugin starts XcodeBuildMCP on non-macOS hosts where Xcode and Apple simulator tooling cannot exist.
The packaged plugin manifest has no platform declaration. Its MCP definition unconditionally executes:
npx -y xcodebuildmcp@latest mcp
This reproduces through two different Codex clients and two operating systems. Therefore the missing gate is not limited to one Desktop renderer or one OS-specific process launcher.
Reproduction A: Windows Codex Desktop
Environment:
- Windows 11 Pro ARM64, build
28000 - OpenAI Codex Desktop
26.810.4967.0, ARM64 - Node.js
v24.14.1, ARM64
Under one unchanged Desktop app-server, five complete XcodeBuildMCP generations accumulated over approximately four and a half hours.
Each generation retained this process chain:
cmd.exe /c npx -y xcodebuildmcp@latest mcp
node.exe ... npx-cli.js -y xcodebuildmcp@latest mcp
cmd.exe /c xcodebuildmcp mcp
node.exe ... xcodebuildmcp/build/cli.js mcp
Snapshot:
| Scope | Processes | Working set | Private memory |
| --- | ---: | ---: | ---: |
| XcodeBuildMCP, 5 generations | 20 | 18.7 MiB | 1,121.5 MiB |
| Complete Codex Desktop tree | 75 | 1,867.9 MiB | 6,401.1 MiB |
Most XcodeBuildMCP pages had already been paged out on the 16 GiB host, but the processes still retained about 1.1 GiB of private commit.
Detailed Windows-only report: #38572.
Reproduction B: Linux VS Code extension
Environment:
- Rocky Linux
10.2, x86_64 - VS Code Web with Codex extension
26.810.41047-linux-x64 - Codex CLI/app-server
0.147.0
Two live VS Code extensionHost processes each owned a Codex app-server. Those app-servers retained:
owner app-server 1: 1 XcodeBuildMCP generation
owner app-server 2: 16 XcodeBuildMCP generations
total: 17 generations
Each Linux generation retained two processes:
npm exec xcodebuildmcp@latest mcp
node .../xcodebuildmcp mcp
Measured Linux snapshot:
| Scope | Value |
| --- | ---: |
| XcodeBuildMCP generations | 17 |
| Processes | 34 |
| Combined RSS | 2,556.9 MiB |
| Owning VS Code app-servers | 2 |
The Linux host had no macOS/Xcode capability. The processes were children of VS Code extension app-servers, not a standalone CLI session.
No iOS or Xcode operation is required to trigger the retained helpers. Ordinary task restoration and tool-context activity are sufficient.
Why this needs a plugin/core platform fix
The generic MCP lifecycle issues remain relevant, but lifecycle cleanup alone is insufficient. A macOS-only MCP must not be spawned on Windows or Linux at all.
The fix should be enforced at one or both of these layers:
- The plugin manifest must declare a supported OS or capability requirement for each MCP server.
- The Codex plugin loader must reject incompatible plugin MCP definitions before starting a process.
A user-level plugin alias or catalog provenance difference should not determine whether a physically impossible MCP starts. Platform compatibility must be checked after resolving the effective plugin package and before process creation.
What steps can reproduce the bug?
- Use Codex Desktop on Windows or the Codex VS Code extension on Linux.
- Have
build-ios-appsavailable through the plugin catalog. - Start or restore normal tasks. Do not request iOS, Xcode, or simulator work.
- Continue normal task switching, tool use, or context creation.
- Inspect descendants of each Codex app-server.
- Observe one or more retained
xcodebuildmcp@latest mcpprocess groups. - Continue working and observe the generation count and memory grow.
Windows inventory:
Get-CimInstance Win32_Process |
Where-Object CommandLine -Match 'xcodebuildmcp' |
Select-Object ProcessId, ParentProcessId, Name, CreationDate, CommandLine
Linux inventory:
ps -eo pid,ppid,etimes,rss,args |
grep -E 'xcodebuildmcp(@latest)? mcp'
What is the expected behavior?
- XcodeBuildMCP must be available only on macOS hosts with the required Xcode capability.
- Codex must not start it on Windows or Linux.
- Non-Xcode skills from the same plugin may remain available if they are genuinely portable.
- Unsupported MCP tools should be reported as unavailable without launching
npmor Node.js. - Failed, idle, or superseded MCP process groups must be reaped at a bounded lifecycle boundary.
- Codex should not repeatedly execute an unpinned
@latestpackage on an unsupported platform. - Plugin diagnostics should show the resolved plugin ID, source, compatibility decision, and owning task/context.
Additional information
Related but not duplicate:
- #38572 is the focused Windows ARM64 / Desktop reproduction.
- #37672 tracks broader Windows code-mode helper fan-out and configuration handling.
- #17574 tracks supported macOS subagent lifecycle leaks involving XcodeBuildMCP.
This issue is specifically about the missing non-macOS platform/capability gate across both Desktop and VS Code extension surfaces.
No task IDs, project names, usernames, hostnames, addresses, local paths, prompts, credentials, tokens, or raw logs are included.
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Memory-accounting refinement
A follow-up proportional-memory measurement avoids overcounting shared Node.js mappings.
Linux, across the same 34 XcodeBuildMCP processes:
2,556.9 MiB(shared mappings counted once per process);/proc/<pid>/smaps_rollup:752.6 MiB;734.2 MiB.Thus the current proportional physical-memory cost on Linux is approximately
0.75 GiB, not the raw2.56 GiBRSS sum. This remains substantial for a platform-incompatible MCP.Windows, across the same 20 XcodeBuildMCP processes:
1,121.2 MiB;15.5 MiB;9.0 MiB.Windows had already paged almost all of this allocation out under memory pressure. The Windows impact at that snapshot was primarily commit/pagefile pressure and paging churn, while the Linux processes still occupied about
0.75 GiBof proportional resident memory.The process-generation counts and platform-gating diagnosis are unchanged.
Remote SSH reproduction: plugin-level disable is ignored, and live MCP reload multiplies XcodeBuildMCP
I reproduced the same defect through Codex Desktop Remote SSH. This adds a third client path to the Windows Desktop and Linux VS Code cases in the issue body.
Environment:
26.818.8289.00.149.0build-ios-appsplugin0.1.2build-ios-apps@openai-curated-remoteThe remote app-server started XcodeBuildMCP for unrelated remote tasks. The Desktop-side and remote user configs both contained these disable entries:
These entries did not stop the MCP. Three XcodeBuildMCP process stacks remained under the long-lived remote app-server.
I then called the supported app-server RPC:
The RPC returned success with an empty result. However, the reload increased the XcodeBuildMCP count from 3 stacks to 8 stacks. The resulting layout was approximately one stack per loaded remote task. Each stack contained an npm launcher and a Node.js XcodeBuildMCP child.
Representative individual RSS readings were:
These are per-process RSS readings and include shared mappings. I am not presenting their sum as proportional memory. During this state, the owning app-server reached approximately 1.8 GiB RSS and about 44% CPU in one sample.
I terminated only the exact XcodeBuildMCP child trees. I did not restart the app-server or stop the active remote tasks.
A top-level server-name override is an effective workaround:
After adding that entry,
codex mcp get xcodebuildmcpreported the server as disabled. I calledconfig/mcpServer/reloadagain. The RPC returned success, and the XcodeBuildMCP process count remained zero at checks after 0, 5, and 20 seconds.This narrows the configuration defect:
build-ios-apps@openai-curated-remote.enabled = falseand nested MCPenabled = falsedo not reliably suppress its MCP in a running Remote SSH app-server.[mcp_servers.xcodebuildmcp]disable by server name does suppress it.Expected behavior:
enabled = false.config/mcpServer/reloadmust remove or retain the disabled state. It must not create one process stack per loaded task.This report omits task IDs, project names, usernames, hostnames, addresses, local paths, prompts, credentials, and raw logs.
Still there in 26.820.60940