iOS Simulator MCP: no way to pass launch arguments to the app (control action:"launch" runs bare simctl launch; `text` is silently ignored)

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 0 comments · opened Aug 19, 2026

Summary

The bundled iOS Simulator MCP server (mcp__Claude_Code_iOS_Simulator__control) has no way
to pass launch arguments to the app. action: "launch" shells out to a bare
xcrun simctl launch <udid> <bundle-id> with no argv, and the tool's input schema has no
args / launch_args property (and is additionalProperties: false, so one cannot be
smuggled in). The text property is documented and implemented for action: "text" only.

This makes the tool unusable for any app that is driven by launch flags -- test fixtures,
seeded demo state, feature toggles, --uitesting-style modes. It fails silently: the launch
succeeds, the app opens, and nothing else happens, so the caller has no signal that the
arguments were dropped.

Where it happens

From /Applications/Claude.app/Contents/Resources/app.asar (Claude desktop 2.1.x, macOS 15.6):

.vite/build/index2.chunk-Du6S5ioL.js

async function wn(e, n) {
await t.zx(xcrun, [simctl, install, e, n], D);
}
async function Tn(e, n) {
await t.zx(xcrun, [simctl, launch, e, n], D);
}

.vite/build/index2.chunk-CAbZtCTS.js -- the launch case only forwards
{udid, appPath, bundleId, kind}, and the schema's only free-text field is:

text: { type: string, description: For 'text': the string to type. }

Minimal repro

  1. Boot any simulator, build any app that branches on ProcessInfo.processInfo.arguments.
  2. Call the tool:

control(action: "launch",
app_path: ".../Build/Products/Debug-iphonesimulator/MyApp.app",
bundle_id: "com.example.myapp",
text: "--my-flag")

  1. Expected: the app sees --my-flag. Actual: launch succeeds, arguments contains no flag.

Verified against a real app on iPhone 17 Pro (iOS 26.5, UDID 5E193C9A-...): the flag's
os.Logger line never appears. The identical flag passed via xcrun simctl launch directly
produces the log line every time.

Workaround (works today)

Call action: "attach" once to open the panel, then launch from the shell:

xcrun simctl terminate <udid> com.example.myapp
xcrun simctl launch <udid> com.example.myapp --my-flag --another-flag

The terminate is required -- simctl launch on an already-running app just foregrounds it.
The live panel keeps streaming, and MCP screenshot / tap / swipe keep working against
the externally launched process.

Requested fix

Add an optional args (array of strings) property to the control schema, used by
action: "launch", appended to the simctl launch argv. Same for the Android control tool
(am start ... --es/-e extras) if that is in scope.

Failing that, please make the mismatch loud: reject text on action: "launch" with an error
naming the simctl workaround, rather than accepting and ignoring it.

Environment

  • Claude desktop app 2.1.x (claude CLI 2.1.220), macOS 15.6 (Darwin 25.6.0), Apple Silicon
  • Xcode simulator: iPhone 17 Pro, iOS 26.5

View original on GitHub ↗