Give Claude Code a real iPhone
Claude Code can write a SwiftUI screen but can't see it. Mobster's MCP server lets it read each screen by name, drive it, and prove it works with a verdict.
Claude Code can write a SwiftUI screen, build it with xcodebuild and still have no idea what the screen looks like, so it hands you the result to check by hand. Mobster’s MCP server gives it the screen. Claude Code reads every control by name, taps, types and swipes, and gets back a pass or fail it can’t talk its way around. Nothing goes through a relay: the server runs on your Mac, next to the simulator or the phone.
Connect it in one command
On a Mac with Apple silicon, macOS 15 or later, and Xcode with an iOS Simulator runtime:
curl -fsSL https://mobster.dev/install.sh | sh
mobster mcp install claude-codeThe second line runs claude mcp add --scope user mobster -- /Users/you/.local/bin/mobster mcp for you, with the absolute path, so the server also starts from apps opened from the Dock. To share it with your team, mobster mcp install claude-code --project . writes the project’s .mcp.json. Or install the plugin, which adds the server, the mobster skill and a /mobster:verify command:
claude plugin marketplace add RadishSoftware/mobster
claude plugin install mobster@mobster/mobster:verify the paywall shows three plans then builds the app, runs the verify loop and reports the verdict. Mobster in Claude Code keeps the setup current, including the key for Smart mode.
What Claude Code sees
The screen comes back as an outline built from the accessibility tree, the labelled controls VoiceOver reads. Daybreak’s paywall, the sample app in the CLI’s repository, as screen returned it on 28 September 2026 (abridged):
Screen dev.mobster.daybreak 402×874 pt keyboard: none alert: none
e2 text "Choose your plan" id=paywall_title
e7 button "Weekly" value="$2.99 / week" id=plan_weekly
e13 button "Monthly" value="$7.99 / month" id=plan_monthly
e20 button "Annual" value="$39.99 / year" id=plan_annual selected
e27 button "Start free trial" id=paywall_ctaClaude Code taps by ref or by selector: tap with {"target": {"id": "plan_monthly"}} answered Tapped “Monthly”; the screen changed., and the next outline had selected on Monthly. Prices arrive as text and switch states as values, so the agent never guesses them from pixels. A ref is good until the screen changes, and a tap on an old ref says so.
Start on a simulator
A simulator costs nothing to break, and it needs no Developer Mode, Apple ID or signing. Prepare it once:
mobster sim doctor --fixDoctor checks Xcode, the runtime and free disk space, creates Mobster’s own simulator, boots it headless and builds WebDriverAgent once per Xcode version. Mobster never opens Simulator.app and never touches the simulators you made yourself. On an M5 Max with Xcode 26.4 (28 September 2026, n = 2), a first run that did all of that took 77.7 s and 103.6 s, and warm runs of the same check took 6.8 s and 8.6 s.
The server never makes Claude Code wait on a long call. Every tool returns within 45 seconds, and wait within 50. While a call waits, the server sends a progress notification every 5 seconds, which keeps Claude Code’s idle timer from firing.
The verify loop
Claude Code states what must be true before it touches the app, then drives, then gets a verdict it didn’t write.
- Build.
xcodebuild -scheme <Scheme> -destination 'generic/platform=iOS Simulator' -derivedDataPath .mobster/build CODE_SIGNING_ALLOWED=NO build. No signing team is needed. - Start.
verify_starttakes the absoluteapp_path, the steps in plain English, andexpect: the assertions the verdict is decided by. They’re fixed now. - Drive. Claude Code reads the outline and acts. Each action returns the new screen.
- Finish.
verify_finishchecks the assertions on a settled screen and returns the verdict, the report path and an overlay frame. - Fix and repeat. On
failed, Claude Code fixes the code, rebuilds and verifies again.
A real key-less session on Daybreak’s onboarding, from scripts/mcp_smoke.py on 28 September 2026, with the simulator already up. Each line is a tool call, how long it took, and the first line it returned:
verify_start 3.94 s Run 20260928-151841-816e is ready. Drive the app with the refs below, then call verify_finish.
tap 1.86 s Tapped “Continue”; the screen changed.
tap 2.13 s Tapped “Continue”; the screen changed.
tap 1.89 s Tapped “Turn on reminders”; the screen didn't change.
screen 0.46 s Screen dev.mobster.daybreak 402×874 pt keyboard: none alert: "“Daybreak” Would Like to Send You Notifications …"
alert 2.13 s Dismissed the alert "“Daybreak” Would Like to Send You Notifications …".
tap 4.13 s Tapped “Get started”; the screen changed.
wait_for 4.50 s All 1 hold (4.5 s).
verify_finish 3.07 s Verdict: passed Complete onboarding. Don't allow notifications. (24.1 s)A failed run says what was on screen instead. With Daybreak’s planted missing-plan bug, which drops the Annual card:
✗ failed The paywall shows three plans with Annual at $39.99 a year (18.2 s)
✓ text "Choose your plan"
✗ count id=/^plan_/ == 3: found 2: plan_weekly, plan_monthly
✗ value id=plan_annual == "$39.99 / year": not found; closest: "plan_monthly"
✓ visible label=Restore Purchases role=button
✓ no_text "Loading"The verdict comes from the assertions, never from a model. AI end-to-end tests for iOS explains the rules. To make Claude Code do this after every UI change, put this in CLAUDE.md, with your scheme and app names:
## Verifying UI changesAfter you change a screen in this iOS app, verify it before you say it works.1. Build for the simulator: xcodebuild -scheme <Scheme> -destination 'generic/platform=iOS Simulator' -derivedDataPath .mobster/build CODE_SIGNING_ALLOWED=NO build2. Call mobster's verify_start with app_path set to the absolute path of .mobster/build/Build/Products/Debug-iphonesimulator/<App>.app, the steps in plain English, and expect: what must be true when the steps are done.3. Drive with screen, tap, type_text and swipe, then call verify_finish.4. If the verdict is failed, fix the code and verify again. Report the verdict and the report path.A check worth running once is worth keeping: save_check writes the run’s check to .mobster/checks as plain YAML, and mobster verify --check reruns it.
Then your iPhone
A simulator gets layout and logic right. The real keyboard and the build as your users have it need the phone. Mobster drives an iPhone over USB through WebDriverAgent, an XCTest runner, so the iPhone needs Developer Mode on, the Mac needs Xcode signed in to an Apple ID, and the runner must be signed for that phone. A free Apple ID works. Mobster for Mac builds, signs and renews the runner for you, and with the CLI alone mobster serve --manage-device walks the same steps (Device setup).
The phone tools take a device for a USB iPhone, as the MCP reference documents. Mobster’s own agent already runs tasks on your iPhone and asks before it sends: Automate your own iPhone from a Mac.
Every tool carries an MCP annotation that marks it as read-only or acting, so a client that asks before acting calls asks before taps and typing.
Give Claude Code the screen
Mobster CLI is free and open source under MIT:
curl -fsSL https://mobster.dev/install.sh | sh
mobster sim doctor --fix
mobster mcp install claude-codeMobster for Mac adds guided setup for your iPhone, a live view and approvals, for $34.99 one time.
Other MCP clients are set up the same way: the integrations page has each one, and the Developers page has the CLI’s other commands.
Questions
Can Claude Code control an iPhone?
Yes, through an MCP server. With Mobster's server added (mobster mcp install claude-code), Claude Code reads each screen's accessibility tree and taps, types and swipes on an iOS simulator Mobster manages. The same tools are documented for an iPhone plugged into your Mac.
Does Claude Code need a model key to use Mobster?
No. In the key-less loop Claude Code drives with its own model and Mobster calls no model at all. A key is only needed for the verify tool, where Mobster runs the steps itself on your OpenAI or Anthropic key.
Do I need Developer Mode to try it?
Not on a simulator. Mobster builds its simulator runner without an Apple ID or signing team. A real iPhone needs Developer Mode on the phone, Xcode signed in to an Apple ID, and a signed WebDriverAgent runner, which Mobster for Mac sets up for you.
Can Claude Code test UI?
For an iOS app, yes, with an MCP server. Through Mobster, Claude Code runs your app on a simulator, taps through the screens by element name, and gets passed or failed from assertions on the accessibility tree, with the frames that show it. The verdict never comes from Claude.
Sources
We read each of these on 8 October 2026. Reviewed by Andy Guo on . Corrections are welcome at the GitHub repo.
- Claude Code docs: connect Claude Code to tools via MCP
- Claude Code docs: discover and install plugins
- Claude Code docs: how Claude remembers your project (CLAUDE.md)
- MCP specification: ToolAnnotations (readOnlyHint)
- Mobster docs: MCP server
- Mobster docs: plugin and skill
- Mobster docs: simulators
- Mobster docs: device setup
- Apple: enabling Developer Mode on a device
- WebDriverAgent on GitHub