# iOS Simulator MCP An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that provides tools to interact with the iOS Simulator. Take screenshots, inspect UI hierarchy, tap, swipe, type, set GPS location, and more. Works with any MCP-compatible client, including [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Claude Desktop](https://claude.ai/download), and [others](https://modelcontextprotocol.io/clients). ## Quick Start ```bash # 1. Install prerequisites xcode-select --install brew tap facebook/fb brew install idb-companion uv pipx pipx ensurepath pipx install fb-idb --python python3.11 # 2. Clone and install the MCP git clone https://github.com/whitesmith/ios-simulator-mcp.git ~/ios-simulator-mcp cd ~/ios-simulator-mcp uv sync # 3. Add to Claude Code settings (see Configuration section below) claude mcp add ios-simulator \ -- uv run --directory ~/ios-simulator-mcp ios-simulator-mcp # 4. Restart Claude Code ``` ## Architecture This MCP uses two underlying tools: | Tool | Source | Used For | |------|--------|----------| | `xcrun simctl` | Built into Xcode | Simulator management, screenshots, location, URLs | | `idb` | Facebook IDB | UI interactions (tap, swipe, type), UI hierarchy, app management | ## Prerequisites ### 1. Xcode Command Line Tools ```bash xcode-select --install ``` ### 2. Facebook IDB (iOS Development Bridge) IDB is required for UI interactions (tap, swipe, type, UI hierarchy). It has **two components** that must both be installed: #### a) idb-companion (the backend service) ```bash brew tap facebook/fb brew install idb-companion ``` #### b) idb CLI (the command-line interface) The `idb` command comes from the `fb-idb` Python package. Install it globally with pipx: ```bash # Install pipx if you don't have it brew install pipx pipx ensurepath # Install fb-idb globally (use Python 3.11 for compatibility) pipx install fb-idb --python python3.11 ``` > **Note**: The `fb-idb` package has compatibility issues with Python 3.14. Use Python 3.11 or 3.12. #### Verify IDB installation ```bash # Check idb-companion which idb_companion # Should output: /opt/homebrew/bin/idb_companion # Check idb CLI which idb # Should output: ~/.local/bin/idb # Test connectivity idb list-targets # Should list all available simulators ``` ### 3. uv (Python package manager) ```bash brew install uv ``` ## Installation Clone the repository and install dependencies: ```bash git clone https://github.com/whitesmith/ios-simulator-mcp.git ~/ios-simulator-mcp cd ~/ios-simulator-mcp uv sync ``` ## Configuration ### Claude Code The quickest way is using the CLI: ```bash claude mcp add ios-simulator -- uv run --directory /Users/yourname/ios-simulator-mcp ios-simulator-mcp ``` Or manually add to `~/.claude/settings.json` (global) or `.mcp.json` in your project root (project-specific): ```json { "mcpServers": { "ios-simulator": { "command": "uv", "args": ["run", "--directory", "/Users/yourname/ios-simulator-mcp", "ios-simulator-mcp"] } } } ``` Replace `/Users/yourname/ios-simulator-mcp` with the absolute path where you cloned the repository. > **Note**: Use an absolute path (e.g., `/Users/yourname/ios-simulator-mcp`), not `~`, since JSON values are not processed by a shell. Then restart Claude Code or run `/mcp` to reload MCP servers. ### Claude Desktop Add to your Claude Desktop config file (`~/Library/Application Support/Claude/claude_desktop_config.json`): ```json { "mcpServers": { "ios-simulator": { "command": "uv", "args": ["run", "--directory", "/Users/yourname/ios-simulator-mcp", "ios-simulator-mcp"] } } } ``` Then restart Claude Desktop. ## Available Tools ### Simulator Management | Tool | Description | |------|-------------| | `list_simulators` | List all available simulators with state and UDID | | `boot_simulator` | Boot a simulator (auto-selects if none specified) | | `get_device_info` | Get info about connected simulator | ### Screenshots & UI Inspection | Tool | Description | |------|-------------| | `screenshot` | Capture screenshot (returns image for visual inspection) | | `get_ui_hierarchy` | Get UI element tree with positions and labels | ### User Interactions | Tool | Description | |------|-------------| | `tap` | Tap at x,y coordinates | | `long_press` | Long press at coordinates | | `swipe` | Swipe from one point to another | | `type_text` | Type text into focused field | | `tap_and_type` | Tap on field then type | | `press_button` | Press hardware button (home, lock, siri, volume) | | `shake` | Trigger shake gesture | ### App Management | Tool | Description | |------|-------------| | `launch_app` | Launch app by bundle ID | | `terminate_app` | Kill running app | | `install_app` | Install .app bundle | | `uninstall_app` | Uninstall app by bundle ID | | `open_url` | Open URL (great for deep links) | ### Location | Tool | Description | |------|-------------| | `set_location` | Set GPS coordinates | | `clear_location` | Clear simulated location | ### Utility | Tool | Description | |------|-------------| | `wait` | Wait for specified seconds | ## Usage Examples Once configured, your MCP client can use these tools automatically. Here are some examples with Claude Code: ### Visual verification after implementing a feature ``` Claude: Let me check how the new balance screen looks. [Uses screenshot tool] Claude: I can see the balance card is displaying correctly with the $50.00 amount. However, the "Add Funds" button appears to be cut off on the right edge. Let me fix the padding... ``` ### Testing a flow ``` Claude: I'll test the login flow. [Uses launch_app with bundle_id "com.example.myapp"] [Uses screenshot to see current state] [Uses get_ui_hierarchy to find the email field coordinates] [Uses tap_and_type to enter email] [Uses tap to press login button] [Uses wait for 2 seconds] [Uses screenshot to verify login succeeded] ``` ### Testing location-based features ``` Claude: Let me test the pickup location feature in San Francisco. [Uses set_location with lat=37.7749, lng=-122.4194] [Uses screenshot to verify map updated] ``` ## Troubleshooting ### MCP tools not appearing in Claude Code 1. Check that the MCP is configured in `~/.claude/settings.json` or `.mcp.json` 2. Restart Claude Code or run `/mcp` to reload servers 3. Check for errors in the MCP server startup ### "idb: command not found" This is the most common issue. The `fb-idb` Python package must be installed globally, not just in the MCP's virtual environment: ```bash # Install pipx if needed brew install pipx pipx ensurepath # Install fb-idb globally with Python 3.11 (3.14 has compatibility issues) pipx install fb-idb --python python3.11 # Verify which idb # Should show ~/.local/bin/idb ``` ### "No simulator connected" The MCP will auto-connect to a booted simulator. If none is booted, use: ``` boot_simulator with device_name="iPhone 15 Pro" ``` Or boot one manually: ```bash xcrun simctl boot "iPhone 16" ``` ### IDB connection issues Restart the idb companion: ```bash idb kill idb_companion --udid ``` Or connect manually: ```bash idb connect ``` ### UI hierarchy returns empty Make sure the simulator has an app open. The accessibility tree may be empty on the home screen or system dialogs. ### Screenshots fail Ensure the simulator is fully booted and visible. Test with: ```bash xcrun simctl io booted screenshot /tmp/test.png ``` ### Python version issues with fb-idb If you see errors like `RuntimeError: There is no current event loop`, you're likely using Python 3.14 which has asyncio changes incompatible with fb-idb. Reinstall with an older Python: ```bash pipx uninstall fb-idb pipx install fb-idb --python python3.11 ``` ## Development ```bash cd ~/ios-simulator-mcp uv sync uv run ios-simulator-mcp # runs the server directly (for testing) ``` ## How It Works When the MCP client calls a tool: 1. **Simulator management** (`list_simulators`, `boot_simulator`) uses `xcrun simctl` 2. **Screenshots** use `xcrun simctl io screenshot` 3. **UI interactions** (`tap`, `swipe`, `type_text`) use `idb ui` commands 4. **UI hierarchy** uses `idb ui describe-all` to get the accessibility tree 5. **App management** (`launch_app`, `terminate_app`) uses `idb` commands 6. **Location** uses `xcrun simctl location` The MCP automatically connects to an already-booted simulator, or boots the latest iPhone if none is running. ## Limitations - **macOS only** - iOS Simulator only runs on macOS - **Simulator only** - Does not support physical iOS devices (idb does, but this MCP is configured for simulators) - **UI hierarchy on app screens** - The accessibility tree may be empty or limited on the home screen, system dialogs, or apps without accessibility labels - **Coordinate-based interactions** - Taps and swipes use absolute coordinates; you'll need to use `get_ui_hierarchy` to find element positions - **No gesture recording** - Complex multi-touch gestures are not supported - **Screenshot size** - Screenshots are compressed to JPEG and capped at ~2MB for efficient transmission ## License [MIT](LICENSE)