ios-multi-simulator-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +219 -0
  3. package/build/index.js +1179 -0
  4. package/package.json +52 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Joshua Yoes
4
+ Copyright (c) 2026 Nick Clifford (later additions)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,219 @@
1
+ # iOS Multi-Simulator MCP Server
2
+
3
+ Forked from [joshuayoes/ios-simulator-mcp](https://github.com/joshuayoes/ios-simulator-mcp) — all foundational work by Joshua Yoes.
4
+
5
+ An MCP server that lets AI agents create, control, and destroy iOS simulators through session-based lifecycle management. Each session owns its own simulator, enabling multiple agents to work in parallel on separate simulators without conflicts.
6
+
7
+ ```
8
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
9
+ │ Agent A │ │ Agent B │ │ Agent C │
10
+ │ (id: "qa1") │ │ (id: "qa2") │ │ (id: "dev") │
11
+ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
12
+ │ │ │
13
+ └────────────┬────┴────┬────────────┘
14
+ │ │
15
+ ┌─────┴─────────┴──────┐
16
+ │ MCP Server │
17
+ │ (single process) │
18
+ └──┬─────────┬──────┬──┘
19
+ │ │ │
20
+ ┌──────┴──┐ ┌────┴───┐ ┌┴────────┐
21
+ │ iPhone │ │ iPad │ │ iPhone │
22
+ │ 16 Pro │ │ Air │ │ 16 Pro │
23
+ │ (qa1) │ │ (qa2) │ │ (dev) │
24
+ └─────────┘ └────────┘ └─────────┘
25
+ ```
26
+
27
+ **What this fork adds:**
28
+ - **Session-based lifecycle** — `start_simulator` / `destroy_simulator` create and tear down simulators on demand, with automatic cleanup on server exit
29
+ - **Multi-agent support** — each session gets an isolated simulator, so parallel agents don't collide
30
+ - **Attach to existing simulators** — `attach_simulator` lets you control a simulator that was created externally (e.g. by Xcode)
31
+ - Removed `get_booted_sim_id` / `open_simulator` / `IDB_UDID` — the session model replaces all of these
32
+
33
+ ## Tools
34
+
35
+ All tools take a required `id` (session identifier) parameter.
36
+
37
+ | Tool | Additional Parameters | Description |
38
+ |------|----------------------|-------------|
39
+ | `start_simulator` | `type?` (e.g. "iPhone", "iPad", "iPhone 16 Pro") | Creates, boots, and opens a simulator for the session |
40
+ | `destroy_simulator` | — | Shuts down and deletes the session's simulator |
41
+ | `attach_simulator` | `udid` | Attaches to an existing booted simulator by UDID |
42
+ | `detect_rotation` | — | Detects device rotation and updates coordinate mapping |
43
+ | `ui_describe_all` | — | Returns accessibility tree for the entire screen (JSON) |
44
+ | `ui_tap` | `x`, `y`, `duration?` | Tap at coordinates |
45
+ | `ui_type` | `text` | Type text into the focused field |
46
+ | `ui_swipe` | `x_start`, `y_start`, `x_end`, `y_end`, `duration?`, `delta?` | Swipe gesture |
47
+ | `ui_describe_point` | `x`, `y` | Returns the accessibility element at a point |
48
+ | `ui_view` | — | Returns a compressed screenshot as base64 JPEG |
49
+ | `screenshot` | `output_path`, `type?`, `display?`, `mask?` | Saves a screenshot to a file |
50
+ | `record_video` | `output_path?`, `codec?`, `display?`, `mask?`, `force?` | Starts video recording |
51
+ | `stop_recording` | — | Stops the current recording |
52
+ | `install_app` | `app_path` | Installs a .app or .ipa on the simulator |
53
+ | `launch_app` | `bundle_id`, `terminate_running?` | Launches an app by bundle identifier |
54
+
55
+ ## `ui_describe_all` — the key navigation tool
56
+
57
+ `ui_view` lets the agent visually see the screen with a compressed jpg image. While this is sufficient for the agent to determine where to click, it will not work if the screen is rotated. But `ui_describe_all` uses logical coordinates and will work fine for finding buttons to tap. Unless there is a good reason to do otherwise, I'd suggest telling agents to use `ui_describe_all` for navigation (though `ui_view` will work so long as the screen is in portrait)
58
+
59
+ `ui_describe_all` returns a nested JSON accessibility tree. This is another way the agent can "see" the screen to decide what to tap. Example (abbreviated):
60
+
61
+ ```json
62
+ [
63
+ {
64
+ "type": "Application",
65
+ "frame": { "x": 0, "y": 0, "width": 393, "height": 852 },
66
+ "role_description": "application",
67
+ "title": "Settings",
68
+ "children": [
69
+ {
70
+ "type": "NavigationBar",
71
+ "frame": { "x": 0, "y": 59, "width": 393, "height": 96 },
72
+ "children": [
73
+ {
74
+ "type": "StaticText",
75
+ "frame": { "x": 152, "y": 75, "width": 89, "height": 25 },
76
+ "title": "Settings"
77
+ }
78
+ ]
79
+ },
80
+ {
81
+ "type": "Cell",
82
+ "frame": { "x": 0, "y": 200, "width": 393, "height": 44 },
83
+ "title": "General",
84
+ "AXAccessibilityElement": true
85
+ }
86
+ ]
87
+ }
88
+ ]
89
+ ```
90
+
91
+ The `frame` coordinates map directly to `ui_tap` coordinates — to tap "General", use the centre of its frame.
92
+
93
+ ## Example usage
94
+
95
+ **Hot Tip:**
96
+
97
+ You can use cheap agents like Haiku to do navigation and even visual comparison. You do not need Opus to navigate around your app, saving you tons of money and time. Haiku is _almost_ fast enough that you can record demo videos without speeding up ;)
98
+
99
+ **Launch an app and navigate:**
100
+
101
+ > Start an iPhone 16 Pro simulator, open Settings, and navigate to General > About.
102
+
103
+ **Compare a screenshot against expected state:**
104
+
105
+ > Take a screenshot of the simulator and check whether the login screen is showing
106
+ > the "Welcome back" message.
107
+
108
+
109
+ **Multi-step agent workflow (great for Haiku subagents):**
110
+
111
+ > You are a QA agent. Start a simulator, install the app at ./build/MyApp.app,
112
+ > launch it (com.example.myapp), then:
113
+ > 1. Tap "Sign Up"
114
+ > 2. Fill in the email field with "test@example.com" and password with "password123"
115
+ > 3. Tap "Submit"
116
+ > 4. Take a screenshot and verify the success message appears
117
+
118
+ ## Prerequisites
119
+
120
+ - **Node.js** (v18+)
121
+ - **macOS** (iOS simulators are macOS-only)
122
+ - **Xcode** with iOS simulators installed
123
+ - **Facebook IDB** —
124
+
125
+ ### Facebook IDB (Important)
126
+
127
+ This dependency is a little more involved. The official [install guide](https://fbidb.io/docs/installation) can be a little difficult, the easiest way to install it (imo) is to use `pipx`.
128
+
129
+ **MacOS:**
130
+ ```
131
+ # Install pipx to make installing python packages easier
132
+ brew install pipx
133
+ pipx ensurepath
134
+
135
+ brew tap facebook/fb
136
+ brew install idb-companion
137
+ pipx install fb-idb
138
+ ```
139
+
140
+ ## Installation
141
+
142
+ Please note the `fb-idb` dependecy above!
143
+
144
+ ### Cursor
145
+
146
+ Add to `~/.cursor/mcp.json`:
147
+
148
+ ```json
149
+ {
150
+ "mcpServers": {
151
+ "ios-multi-simulator": {
152
+ "command": "npx",
153
+ "args": ["-y", "github:zafnz/ios-multi-simulator-mcp"]
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ For local development, build from source and point to the built file:
160
+
161
+ ```json
162
+ {
163
+ "mcpServers": {
164
+ "ios-multi-simulator": {
165
+ "command": "node",
166
+ "args": ["/path/to/ios-multi-simulator-mcp/build/index.js"]
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ ### Claude Code
173
+
174
+ ```bash
175
+ claude mcp add ios-multi-simulator npx -y github:zafnz/ios-multi-simulator-mcp
176
+ ```
177
+
178
+ For local development:
179
+
180
+ ```bash
181
+ claude mcp add ios-multi-simulator -- node /path/to/ios-multi-simulator-mcp/build/index.js
182
+ ```
183
+
184
+ ## Troubleshooting
185
+
186
+ **Rotated screen**
187
+
188
+ The rotated screen is a problem when using `ui_view` due to the tapping and swipping using logical coordinate space, but the ui_view returning the pixel space, which when rotated don't align. Tell the agent to use `ui_describe_all` to navigate -- it uses less tokens anyhow.
189
+
190
+ ## Configuration
191
+
192
+ ### Environment Variables
193
+
194
+ | Variable | Description | Example |
195
+ |----------|-------------|---------|
196
+ | `IOS_SIMULATOR_MCP_FILTERED_TOOLS` | Comma-separated list of tool names to hide | `screenshot,record_video` |
197
+ | `IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR` | Default directory for screenshots and recordings (default: `~/Downloads`) | `~/Code/project/tmp` |
198
+ | `IOS_SIMULATOR_MCP_IDB_PATH` | Custom path to the IDB executable | `/opt/homebrew/bin/idb` |
199
+
200
+ Example with env vars:
201
+
202
+ ```json
203
+ {
204
+ "mcpServers": {
205
+ "ios-multi-simulator": {
206
+ "command": "npx",
207
+ "args": ["-y", "ios-multi-simulator-mcp"],
208
+ "env": {
209
+ "IOS_SIMULATOR_MCP_DEFAULT_OUTPUT_DIR": "~/Code/project/tmp",
210
+ "IOS_SIMULATOR_MCP_IDB_PATH": "/opt/homebrew/bin/idb"
211
+ }
212
+ }
213
+ }
214
+ }
215
+ ```
216
+
217
+ ## License
218
+
219
+ MIT