iOS Simulator MCP Server

Drives and inspects iOS simulators on a Mac: taps, typing, screenshots, video and app installs

By Joshua Yoes (individual) TypeScript Local · stdio TestingDeveloper tools

79 popularity score ★ 2.2k ↓ 11k/wk

Connect your client

Local (npm)

Add in one click

Opens the app, which asks before it adds the server.

Or add it by command or config

Claude CodeTerminal
claude mcp add ios-simulator -- npx -y ios-simulator-mcp
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "ios-simulator": {
      "command": "npx",
      "args": [
        "-y",
        "ios-simulator-mcp"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "ios-simulator": {
      "command": "npx",
      "args": [
        "-y",
        "ios-simulator-mcp"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "ios-simulator": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "ios-simulator-mcp"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.ios-simulator]
command = "npx"
args = ["-y", "ios-simulator-mcp"]
Gemini CLITerminal
gemini mcp add --scope user ios-simulator npx -- -y ios-simulator-mcp
Local (from source)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

FirstTerminal
git clone https://github.com/joshuayoes/ios-simulator-mcp
cd ios-simulator-mcp
npm install
npm run build
Claude CodeTerminal
claude mcp add ios-simulator -- node '<ABSOLUTE_PATH_TO_CLONE>/build/index.js'
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "ios-simulator": {
      "command": "node",
      "args": [
        "<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
      ]
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "ios-simulator": {
      "command": "node",
      "args": [
        "<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
      ]
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "ios-simulator": {
      "type": "stdio",
      "command": "node",
      "args": [
        "<ABSOLUTE_PATH_TO_CLONE>/build/index.js"
      ]
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.ios-simulator]
command = "node"
args = ["<ABSOLUTE_PATH_TO_CLONE>/build/index.js"]
Gemini CLITerminal
gemini mcp add --scope user ios-simulator node -- '<ABSOLUTE_PATH_TO_CLONE>/build/index.js'

Settings 3

IOS_SIMULATOR_MCP_FILTERED_TOOLS Optional: Comma-separated tool names to leave unregistered.
IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR Optional: Folder for screenshots and videos given a relative or no path. Default ~/Downloads. For screenshot, record_video.
IOS_SIMULATOR_MCP_IDB_PATH Optional: Path to the idb executable when it is not on PATH. The server errors if the path does not exist. Default idb.

What it does

iOS Simulator MCP Server gives an assistant hands and eyes on an iOS simulator running on the developer's own Mac. It can find the booted simulator, open the Simulator app, read the accessibility tree of the whole screen or of one point, search that tree for elements by label or id, and act on the screen with taps, swipes and typed text. Text can also be pasted through the simulator clipboard, which is the mode to pick for non-US keyboard layouts or non-ASCII text.

It also captures what is on screen: a compressed image returned straight to the assistant, a screenshot saved to disk in several formats, or a video recording that can be started and stopped. App-level tools install a .app or .ipa bundle, list installed apps with their bundle ids, launch or terminate an app (optionally passing environment variables to it), and open web URLs, custom schemes or universal links.

The typical use is a quick QA pass after building a feature: the assistant opens the screen under test, checks labels and layout, interacts with it and records the result. Under the hood it calls Apple's simctl and Facebook's IDB command-line tools. Note that stop_recording takes no arguments and sends SIGINT to every process matching simctl recordVideo, so it also ends recordings started outside the server.

What it needs

RuntimeNode.js 20+
Runs onmacOS
Also
  • Xcode with at least one iOS simulator installed
  • Facebook IDB: idb_companion plus the fb-idb Python client on PATH
  • fb-idb 1.5.1+ and a recent idb_companion for ui_type paste mode

Install IDB as the repository's TROUBLESHOOTING.md describes: idb_companion through Homebrew and the fb-idb client (for example `uv tool install --python 3.12 fb-idb@latest`). If idb is not on PATH, give its location in IOS_SIMULATOR_MCP_IDB_PATH. Paste mode fails on idb_companion 1.1.8, which lacks the axbridge reader. Run `brew upgrade idb-companion` and then `idb kill`. No account or sign-in.

Limits

  • Platform Runs only on macOS, where iOS simulators exist
  • Not covered Works on simulators only, not physical iPhones or Android emulators
  • Size cap ui_type accepts at most 500 characters per call and no newlines
  • Limit ui_type's default method "type" takes printable ASCII only and assumes a US keyboard layout, so other layouts get wrong characters
  • Limit Paste mode needs the target field focused first and takes about 2 to 11 seconds a call. Non-text clipboard content is not restored
  • Limit Taps and swipes take screen coordinates, so the assistant reads the accessibility tree or a screenshot first
  • Limit Versions before 1.3.3 had command-injection flaws, and its makers ask users to run 1.3.3 or later

Works only on macOS, since iOS simulators exist only there; it does not reach physical iPhones or Android emulators. Typed text is limited to printable ASCII characters. Taps and swipes take screen coordinates, so the assistant must first read the accessibility tree or a screenshot. Versions before 1.3.3 had command-injection flaws; its makers ask users to run 1.3.3 or later.

Who it suits

Suits iOS and React Native developers on a Mac who want an assistant to check its own UI work in the simulator: reading accessibility labels, tapping through flows, testing deep links and keeping screenshots or videos as evidence. It runs entirely locally and needs no account. Testers on non-US keyboard layouts should use the paste mode of ui_type, which needs an up-to-date IDB. It is not for Windows or Linux users, for real devices, or for Android. Teams that only need code or build help rather than on-screen checks need none of this.

Tools 17

6 only read, 11 change things. A ? marks an optional parameter.

get_booted_sim_id
Returns the id and name of the simulator that is currently booted
open_simulator changes
Starts the Simulator app
ui_describe_all
Reads accessibility details for everything on the current screenudid?: string
ui_tap changes
Taps at given screen coordinates, with an optional press lengthx: numbery: numberduration?: stringudid?: string
ui_type changes
Enters up to 500 characters into the simulator by key presses or by pastingtext: stringmethod?: enumreplace?: booleanudid?: string
ui_swipe changes
Swipes from one point to another over a set durationx_start: numbery_start: numberx_end: numbery_end: numberduration?: stringdelta?: numberudid?: string
ui_describe_point
Reports the accessibility element found at one coordinatex: numbery: numberudid?: string
ui_find_element
Searches the accessibility tree by label or id, optionally filtered by element typesearch: arraytype?: stringmatchMode?: enumcaseSensitive?: booleanudid?: string
ui_view
Returns a compressed image of the current screen to the assistantudid?: string
screenshot changes
Saves a screenshot to a file in png, jpeg, tiff, bmp or gifoutput_path: stringtype?: enumdisplay?: enummask?: enumudid?: string
record_video changes
Starts recording the simulator screen to a video fileoutput_path?: stringcodec?: enumdisplay?: enummask?: enumforce?: booleanudid?: string
stop_recording changes
Ends every running simctl screen recording
install_app changes
Installs a .app or .ipa bundle on the simulatorapp_path: stringudid?: string
launch_app changes
Starts an app by bundle id, optionally restarting it and passing env variablesbundle_id: stringterminate_running?: booleanenv?: objectudid?: string
terminate_app changes
Stops a running app by bundle idbundle_id: stringudid?: string
open_url changes
Opens a web address, custom scheme or universal link in the simulatorurl: stringudid?: string
list_apps
Lists installed apps with bundle ids and display namesudid?: string

Similar servers