What it takes off you is the describe-then-guess loop. The accessibility tree returns the elements a tap is aimed at, so the coordinates come from the screen rather than from an assumption — and a screenshot or a recording is one call away when a run has to be shown rather than described.
A simulator control server built on Facebook's IDB. It finds the booted simulator, describes what is on screen through the accessibility tree, drives the UI by coordinate, and captures the run as a screenshot or a video.
- The booted simulator's id, and the Simulator application opened (`get_booted_sim_id`, `open_simulator`)
- The whole screen described through its accessibility tree, one point described, or elements found by search criteria and match mode (`ui_describe_all`, `ui_describe_point`, `ui_find_element`, `ui_view`)
- Taps, typing and swipes at coordinates, with duration control (`ui_tap`, `ui_type`, `ui_swipe`)
- A screenshot for the model to look at, and video recorded and stopped on demand (`screenshot`, `record_video`, `stop_recording`)
- Apps installed from a bundle, launched, terminated, and the installed ones listed (`install_app`, `launch_app`, `terminate_app`, `list_apps`)
- A URL opened on the simulator, which is how you deep-link straight to the screen under test (`open_url`)
macOS — iOS simulators exist nowhere else — with Xcode and its simulators installed, Node.js 20 or later, and Facebook's IDB tool. Every UI call takes a udid, which the booted-simulator call supplies. Three environment variables shape it: `IOS_SIMULATOR_MCP_IDB_PATH` when idb is not on the PATH, `IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR` for screenshots and recordings (`~/Downloads` otherwise, which matters when the agent's file access is restricted), and `IOS_SIMULATOR_MCP_FILTERED_TOOLS` to keep named tools out of the registered list entirely.
One command — npx -y ios-simulator-mcp
