iOS Simulator MCP: Setup Guide (2026)
The iOS Simulator MCP server lets an AI agent open your app in the iOS Simulator, tap a button, type into a field, read the accessibility tree, and screenshot the result — the manual QA loop you used to run by hand after every change. This guide covers what it does, how to install it for Claude Code, the full tool set, the recipes worth keeping, and the one security fix you cannot skip.

On this page · 17 sections▾
TL;DR + what you actually need
Everything you need to get the iOS Simulator MCP server running, in four lines:
- npm package:
ios-simulator-mcp— stdio only, run vianpx -y ios-simulator-mcp. No remote endpoint; it must run locally on macOS. - Claude Code install:
claude mcp add ios-simulator npx ios-simulator-mcp - Prerequisites: Node.js, macOS, Xcode with an iOS Simulator, and Facebook’s IDB tool on your PATH.
- Security: pin
>=1.3.3. Anything older carries a command-injection CVE (more below). This is non-negotiable.
The server is open-source (MIT) and maintained by Joshua Yoes. It was name-checked in Anthropic’s Claude Code best practices as part of the “write code, screenshot result, iterate” loop. The rest of this guide explains the pieces, the tools, and the gotchas.
What it is, in one line
iOS Simulator MCP is a Model Context Protocol server that exposes the iOS Simulator’s controls — tap, type, swipe, screenshot, record, and accessibility inspection — as tools an AI agent can call. MCP is the JSON-RPC wire format that lets any LLM client talk to any tool server; if that’s new, start with our What is MCP guide.
Concretely: you tell Claude “tap the login button and check the error state,” and the agent calls ui_tap and ui_describe_all against the running simulator, then reports what it saw. No hand on the trackpad.
Why it exists
The agentic dev loop has a blind spot on mobile. An agent can write a SwiftUI view or a React Native screen, but it cannot see whether the button it just wired up actually renders, fires, or lands in the right place. Before this server, the loop broke at the worst moment: the agent finished the code and then waited for a human to build, launch the simulator, click around, and paste back what happened.
iOS Simulator MCP closes that loop. The agent drives the simulator itself — it taps, reads the accessibility tree to confirm the right element appeared, screenshots the result, and iterates. One Reddit developer building Expo React Native apps described exactly this gap: they wanted the agent “controlling iOS simulator… clicking through my app, testing features.” That is the problem this server solves.
Apple ships the primitives — simctl for device control, the Accessibility API for the element tree — but they are CLI verbs and private frameworks, not agent tools. This project wraps them (plus Facebook’s IDB) behind clean MCP tool definitions so the agent doesn’t have to know any of that.
The named pieces
Four moving parts. Understanding them makes every install error and tool failure obvious instead of mysterious.
The MCP server
ios-simulator-mcp — the Node process your client spawns. It registers the tools and translates tool calls into IDB / simctl commands.
IDB (Facebook)
The bridge for UI interaction and accessibility inspection. If idb isn’t on your PATH, the tap / type / describe tools fail. This is the #1 setup snag.
simctl (Xcode)
Ships with Xcode. Handles the booted-device lookup, screenshots, and video recording. No separate install — but you need Xcode and a simulator runtime present.
The accessibility tree
How the agent “reads” the screen without OCR. Each element exposes an AXLabel and type, so the agent can find and verify a control by name, not pixel guessing.
The takeaway: the server is thin glue. The real work is done by IDB and simctl, which is why most failures trace back to one of those two not being installed or not on the PATH.
Install (Claude Code & every client)
Prerequisites first, because the server is useless without them. On a Mac: install Xcode and at least one iOS Simulator, then install Facebook’s IDB. Confirm IDB is reachable:
# verify the bridge is installed and on PATH
idb --version
# boot a simulator if you don't have one open
open -a SimulatorThe fastest path for the most-searched client, Claude Code, is one command:
claude mcp add ios-simulator npx ios-simulator-mcpRestart any running Claude Code session so it picks up the new tool catalogue. The install panel below has the exact config for every other client — Cursor, VS Code, Windsurf, Claude Desktop, and the manual JSON fallback. Tap your client’s row, copy the snippet, restart, done. The panel pulls its config straight from our catalog, so it stays in sync with the published package.
One-line install · iOS Simulator
Open server pageInstall
The raw JSON, if you prefer editing config by hand (this is what the Cursor / Claude Desktop entry looks like):
{
"mcpServers": {
"ios-simulator": {
"command": "npx",
"args": ["-y", "ios-simulator-mcp"]
}
}
}Three environment variables are worth knowing. They’re optional but each solves a real problem:
IOS_SIMULATOR_MCP_FILTERED_TOOLS— a comma-separated list of tools to not register (e.g.screenshot,record_video,stop_recording). Trim the tool surface the agent sees.IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR— where screenshots and recordings land. Defaults to~/Downloads; point it inside your repo if your agent has restricted filesystem access.IOS_SIMULATOR_MCP_IDB_PATH— a custom path to theidbbinary, for when IDB lives somewhere non-standard and isn’t on PATH.
Running Claude Code specifically? Our Claude Code client page covers scopes and config file locations. Browse every client and its config path at mcp.directory/clients.
Smallest end-to-end loop
Here’s the whole value in one exchange. Your app is running in the simulator. You type into Claude Code:
You: The login screen is open in the simulator. Tap the
"Sign In" button without filling anything, then tell me what
validation error shows up.
Claude:
→ get_booted_sim_id (finds the running simulator)
→ ui_describe_all (reads the accessibility tree)
→ ui_find_element (locates "Sign In" by AXLabel)
→ ui_tap x=196 y=612 (taps it)
→ ui_describe_all (re-reads the screen)
Claude: I tapped "Sign In" with empty fields. A red
"Email is required" label appeared below the email field,
and the button stayed disabled until I cleared it. The
password field showed no error — you may want to validate
both on submit, not just email.That last sentence is the point. The agent didn’t just click — it read the result back from the accessibility tree and gave you a finding. No screenshot to eyeball, no manual repro. That is the loop iOS Simulator MCP unlocks.
The tools, grouped
The server exposes a focused set of tools. Grouping them by job makes the surface easy to hold in your head.
Device & app lifecycle
get_booted_sim_id— returns the UDID of the currently booted simulator. Most other tools accept an optionaludid; this is how the agent finds the default.open_simulator— launches the Simulator app.install_app— installs an.appor.ipabundle onto the simulator.launch_app— launches an installed app by bundle identifier, with optionalterminate_runningand child environment variables.
UI interaction
ui_tap— tap atx,ywith an optional press duration.ui_type— input text (ASCII printable characters).ui_swipe— swipe from a start point to an end point, with a step size and duration.
Inspection (how the agent “sees”)
ui_describe_all— dumps accessibility info for the entire screen. The agent’s primary way to understand state.ui_describe_point— returns the element at a specific coordinate.ui_find_element— searches the accessibility tree for elements matching label or ID strings, with substring/exact match and type filters. Added in a later release; it’s the cleanest way to target a control by name instead of guessing pixels.ui_view— returns a compressed screenshot as image content the agent can look at directly, useful for vision-capable models.
Capture
screenshot— saves a full-resolution screenshot (png, jpeg, and other formats) to a path.record_video/stop_recording— record the simulator screen to a file, then stop. Handy for capturing a repro of a flaky interaction.
Opinionated takeaway: lean on ui_find_element and ui_describe_all over raw coordinate taps. Coordinates drift across device sizes and layout changes; matching by accessibility label survives a redesign. If a control has no label, that’s a real accessibility bug the agent just surfaced for free.
What we got wrong
Three things bit us when we first wired this into a React Native QA loop. They’re all avoidable once you know.
1. We ran whatever version npx grabbed — that was the dangerous default. Early on we pinned nothing and let npx resolve the package. That’s fine now, but if you’d done it during the window when a vulnerable release was current, you’d have shipped a command-injection hole into your dev machine (see the next section). The lesson: for any MCP server that shells out to a binary, pin a known-good version and read its security history before you trust it with your shell.
2. We blamed the server when the real problem was IDB. The first “tap” call failed with an opaque error and we spent twenty minutes re-reading the server config. The actual cause: idb wasn’t on the PATH. The interaction and inspection tools are thin wrappers over IDB; if IDB isn’t reachable, they all die. Check idb --version first, every time.
3. We let the agent tap by coordinates and it broke on the next screen size. Hardcoded x/y taps worked on the device we tested and silently missed on a different simulator. Switching the prompt to “find the element labeled X and tap it” — which routes through ui_find_element — made the flow stable across devices.
The CVE you must pin past
CVE-2025-52573 · command injection · fixed in v1.3.3
Pin ios-simulator-mcp@latest (or >=1.3.3). Do not run any release below 1.3.3.
This is the most important section in the guide, so here’s the full story. Versions of ios-simulator-mcp below 1.3.3 were vulnerable to OS command injection (GHSA-6f6r-m9pv-67jw, CWE-78). The ui_tap tool built its IDB command by string-concatenating tool arguments — duration, udid, x, y — straight into a shell exec call. An argument containing shell metacharacters like ; or && would break out of the intended idb command and run arbitrary commands on the host.
Why this matters more than a normal library CVE: the arguments come from the LLM. A prompt-injection attack — a malicious string in a webpage, a file, or a test fixture the agent reads — could steer the model into calling ui_tap with a payload, and the injection would execute on your machine. The reporter, Liran Tal of Snyk, demonstrated exactly this class of attack against MCP servers that build shell commands from untrusted input. Severity was rated medium (CVSS 6.0), but the blast radius is your local shell.
The maintainer patched it in v1.3.3 (“Cmd Injection Security Hardening”) by moving off unsafe shell concatenation, and the README now carries a security notice up top. The fix is real and the current releases are clean. The action for you is simply: pin >=1.3.3, and treat this as a reminder that any MCP server which shells out deserves a look at its security history before you grant it your shell.
Real workflows
Four loops where this server earns its place in the toolchain. Each assumes the server is installed and a simulator is booted.
Recipe 1 — QA a feature right after building it
The canonical use, and the one Anthropic highlighted. After the agent implements a screen, prompt: “Open the new settings screen, toggle dark mode, and confirm every label is still readable.” The agent launches the app, navigates, taps the toggle, and reads back the accessibility tree to verify the controls. Build, exercise, report — without you leaving the chat.
Recipe 2 — Reproduce and record a bug
A user reports a crash on a specific tap sequence. Tell the agent the steps and ask it to record_video while it reproduces them. You get a screen recording of the exact repro saved to your output directory, with the agent’s description of where it diverged from expected behaviour.
Recipe 3 — Accessibility audit
Ask: “Walk the main flow and list every interactive element that has no accessibility label.” Because ui_describe_all exposes the AXLabel of each element, unlabeled controls stand out immediately. This turns a tedious manual audit into one prompt — and it’s a use case the keyboard- and-screen-reader crowd genuinely benefits from.
Recipe 4 — React Native / Expo iteration loop
For RN and Expo apps, pair this server with a fast refresh dev build. The agent edits a component, the bundler hot-reloads, and the agent taps through the changed screen to confirm the fix landed — all in one turn. One developer even demoed Claude Code driving an iOS simulator and an Android emulator side by side; the simulator half is exactly this server’s job.
Common mistakes
Tools fail with an opaque error
Root cause: idb isn’t installed or isn’t on PATH. The interaction and inspection tools wrap IDB. Run idb --version; if it fails, follow the IDB install guide or set IOS_SIMULATOR_MCP_IDB_PATH.
“No booted simulator”
Root cause: nothing is running. The tools target a booted simulator. Run open -a Simulator and boot a device first, or have the agent call open_simulator before anything else.
Taps land in the wrong place
Root cause: hardcoded coordinates from a different device size. Prompt the agent to find elements by label via ui_find_element rather than tapping fixed x/y points.
Running an old version
Root cause: an unpinned or stale install below 1.3.3. That release line carries the command-injection CVE. Reinstall to pull @latest and pin >=1.3.3.
Community signal
The clearest demand signal is the volume of developers trying to wire Claude Code into a mobile simulator loop — often before discovering a purpose-built server exists.
“I'm vibe-coding multiple Expo React Native iPhone apps… testing newly implemented features in iOS simulator, controlling iOS simulator… clicking through my app, testing features.”
r/ClaudeCowork · Reddit
A developer describing the exact manual loop this server automates — and asking how to hand it to the agent.
On the React Native side, a widely-upvoted thread showed Claude Code driving an iOS simulator and an Android emulator at the same time — the simulator half is this server’s territory, and the reception was strongly positive.
“Claude Code controlling both iOS simulator & Android emulator at the same time.”
r/reactnative · Reddit
A popular demo thread; the cross-platform agent QA loop is clearly resonating with mobile developers.
The contrarian view comes from developers who’ve gone deeper. A separate r/iOSProgramming project, “Pepper,” argues that simulator-control MCPs only see the UI surface — and that real agent-driven iOS work wants runtime inspection: live view hierarchies, network traffic, heap, and variable mutation inside the app process. It’s a fair critique. iOS Simulator MCP is deliberately scoped to the simulator’s external controls and the accessibility tree; if you need to reach inside the running process, that’s a different and heavier tool.
“I don't open Xcode anymore… It's a dynamic library injected into the sim at runtime, giving your agent full access to the app process. SwiftUI/UIKit view hierarchies, live network traffic, heap inspection…”
r/iOSProgramming · Reddit
The deeper-runtime counterpoint: useful framing for what a UI-control server like iOS Simulator MCP does and does not cover.
iOS Simulator MCP vs XcodeBuildMCP
These two come up together constantly, and they’re complementary, not competing. The split is build vs. interact.
iOS Simulator MCP
Drives a running simulator: tap, type, swipe, screenshot, record, inspect the accessibility tree. The QA-and-exercise half of the loop.
XcodeBuildMCP
Drives the build: compile schemes, run tests, manage projects and simulators from Xcode’s tooling. The make-it-exist half of the loop.
Many teams install both: XcodeBuildMCP builds and launches, iOS Simulator MCP exercises the result. We wrote a full XcodeBuildMCP complete guide if the build side is what you need. For everything else in the catalog, browse all MCP servers.
The verdict
Our take
Install it if you build iOS, React Native, or Expo apps with an AI agent and want it to QA its own work on macOS. It’s the cleanest way to close the write-then-verify loop on mobile, it’s MIT and free, and Anthropic itself points to it. Pin >=1.3.3 and confirm IDB is installed — those are the only two things that go wrong. Skip it if you’re not on macOS, if you need physical-device automation, or if you need to inspect the app’s runtime internals rather than its UI surface.
Use it if
- You ship iOS / RN / Expo apps on a Mac
- You want the agent to tap-test its own changes
- You need screenshots, recordings, or a11y audits
Skip it if
- You’re not on macOS
- You need physical-device automation
- You need in-process runtime inspection
Frequently asked questions
What is the iOS Simulator MCP server?
iOS Simulator MCP is an open-source Model Context Protocol server by Joshua Yoes that lets an AI agent drive the iOS Simulator — tap, type, swipe, screenshot, record video, and read the accessibility tree. It wraps Apple's simctl and Facebook's IDB so agents like Claude Code can QA a running app without a human touching the screen.
What is the iOS Simulator MCP npm package name?
The package is `ios-simulator-mcp`, published on npm. The canonical install is `npx -y ios-simulator-mcp`, run as a stdio subprocess of your MCP client. There is no hosted remote endpoint — it must run locally on macOS because the iOS Simulator only exists there.
How do I add iOS Simulator MCP to Claude Code?
Run `claude mcp add ios-simulator npx ios-simulator-mcp` in your terminal, then restart any running Claude Code session. You also need Xcode, an installed iOS Simulator, and Facebook's IDB tool on your PATH first. After that, ask Claude to view the simulator screen and it will call the server.
Is iOS Simulator MCP safe to use?
Yes, on version 1.3.3 or later. Versions below 1.3.3 carried a command-injection vulnerability (CVE-2025-52573) in the `ui_tap` tool, where shell metacharacters in tool arguments could run arbitrary commands on your machine. It was patched in v1.3.3. Pin `ios-simulator-mcp@latest` or `>=1.3.3` and never run an older release.
What does the iOS Simulator MCP server need to run?
Four things: Node.js, macOS, Xcode with at least one iOS Simulator installed, and Facebook's IDB tool (fbidb.io) on your PATH. IDB is the bridge the server uses for UI interaction and element inspection. simctl, which ships with Xcode, handles screenshots and video recording.
What is the difference between iOS Simulator MCP and XcodeBuildMCP?
iOS Simulator MCP drives a running simulator — tapping, typing, and inspecting the UI for QA. XcodeBuildMCP focuses on the build side: compiling schemes, running tests, and managing Xcode projects. They are complementary; many teams install both so one agent can build the app and then exercise it.
Can iOS Simulator MCP control a physical iPhone?
The project targets the iOS Simulator, not physical devices. IDB can talk to real devices in general, but this server's tools are written and documented for simulators. For device automation you would reach for a different stack; for the agent-driven dev loop on macOS, the simulator is the supported target.
Does iOS Simulator MCP work with Cursor and other clients?
Yes. It is a standard stdio MCP server, so any client that supports MCP can run it — Cursor, Claude Code, VS Code, Windsurf, and others. The README ships one-click Cursor and Claude Code instructions. Point the client at `npx -y ios-simulator-mcp` and restart it.
Glossary
- MCP
- Model Context Protocol — the JSON-RPC wire format that lets any LLM client talk to any tool server.
- IDB
- Facebook’s iOS Development Bridge — the CLI this server uses for UI interaction and accessibility inspection. Must be on your PATH.
- simctl
- Xcode’s simulator control CLI. Ships with Xcode; handles screenshots, video recording, and device lookup here.
- Accessibility tree
- The structured representation of on-screen elements and their labels — how the agent reads the screen without OCR.
- AXLabel
- The accessibility label on an element. The agent matches controls by this string via
ui_find_element. - UDID
- Unique device identifier for a simulator instance. Tools accept an optional
udid; the agent finds the default viaget_booted_sim_id. - stdio transport
- The MCP transport where the client spawns the server as a child process and talks over stdin/stdout. This server is stdio-only — no remote URL.
- Command injection (CWE-78)
- A flaw where untrusted input is concatenated into a shell command, letting an attacker run arbitrary commands. The pre-1.3.3 bug here; fixed in v1.3.3.
Sources & links
Primary
- Repository & README: github.com/joshuayoes/ios-simulator-mcp (MIT, by Joshua Yoes)
- npm package: ios-simulator-mcp
- Security advisory: GHSA-6f6r-m9pv-67jw / CVE-2025-52573
- Facebook IDB: fbidb.io
- Anthropic, Claude Code best practices (mentions this server): anthropic.com/engineering/claude-code-best-practices
Community
- r/reactnative — Claude Code controlling iOS simulator & Android emulator
- r/ClaudeCowork — How-to: iOS app dev — testing in simulator
- r/iOSProgramming — Pepper, an MCP for iOS runtime inspection (contrarian view)
- r/ClaudeAI — Complete Claude Code setup guide for iOS/Swift development
Internal
Apple-dev tooling
XcodeBuildMCP Complete Guide (2026)
ReadServer
iOS Simulator — install & tools
OpenPrimer
What is the Model Context Protocol?
ReadFound an issue?
If something here is out of date — a renamed tool, a new install path, a changed prerequisite — email [email protected] or read more on our about page. We keep these guides current.