A side-by-side look at the Expo Android MCP and Ios Sim MCP MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Expo Android MCP for os automation work as a local process; choose Ios Sim MCP for os automation as a local process. You can also run both side by side in one mcpServers block.
ADB_PATH, ADB_SERIAL, ADB_TIMEOUT_MS, ADB_MAX_BUFFER_MB, ADB_DEBUG, MCP_TRANSPORT, PORT.devices, doctor, setDevice.list_simulators, use_simulator, snapshot.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | OS Automation | OS Automation |
| Quality signal | 52/100 · Good | 52/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | Not declared | Not declared |
| Pricing | Not declared | Not declared |
| Required env vars | ADB_PATHADB_SERIALADB_TIMEOUT_MSADB_MAX_BUFFER_MBADB_DEBUGMCP_TRANSPORTPORT | None listed |
| Verified owner | Community listing | Community listing |
| GitHub stars | 4 | 0 |
| Directory activity | 0 views 0 installs 0 upvotes | 2 views 0 installs 0 upvotes |
| Tools | 17 | 26 |
| Full listing | View Expo Android MCP | View Ios Sim MCP |
deviceslist connected devices and emulators.doctorvalidate adb availability and show connected devices.setDeviceoverride the active device serial for this MCP process.inspectUI dump parsed into elements with a summary (screenshot optional).screenshotcapture a screenshot only (base64 or file path).findElementreturn elements that match search criteria.tapElementfind an element and tap its center.waitForElementwait until an element appears (optionally with state checks).assertElementverify element existence and state.taptap at x/y coordinates.swipeswipe between coordinates.longPresspress and hold at coordinates.list_simulatorsList simulators with UDID, state, OS versionuse_simulatorPick a specific UDID (auto-selected if only one is booted)snapshotCapture the AX tree, assign refs `e1..eN`, return compact text rendering. Filters: `interactive` (default), `actionable`, `allfindSearch the snapshot by `id` (AXUniqueId), `label`, `labelContains`, `role`, `actionabletapTap by `{ref}`, `{id}`, or `{x,y}`. Optional `duration` makes it a long-presstype_textType into the focused field. Optional `{ref}` or `{id}` taps-then-types. Auto-routes through paste when the dylib is loaded for byte-perfect input — no iOS autocorrect, no first-letter capitalization. `via: "keystroke"` forces the typing path; `via: "paste"` forces the paste pathpaste_textByte-perfect text via `UIPasteboard` + first-responder `paste:`. Requires the dylib injected. The right answer for emails, passwords, OAuth tokens, anything case-sensitiveview_treeWalk the running app's `UIView` hierarchy on the main thread. Reports class names, frames in window coords, alpha/hidden/interactive, text content, and annotates view-controller boundaries. Strictly richer than `snapshot` — sees custom-drawn views, transient overlays, SwiftUI internals. Filter by `…view_hit_test"What view actually receives a tap at (x,y)?" Returns the topmost view plus the full responder chain up to `UIApplication`. The right debugging tool when a `tap` isn't doing what you expect. Requires dylib injectednetwork_startInstall/remove an `URLProtocol` interceptor + swizzle `URLSessionConfiguration` so every `URLSession`-based HTTP request flowing through the app is recorded. Options: `max_records`, `max_body_bytes`, `filter_url_substring`. Requires dylib injectednetwork_tailReturn the most recent N captured records. Default: one line per request (id, method, status, timing, sizes, URL). `full=true` includes headers + body previews inline. Page forward via `since_idnetwork_get_bodyFetch the full request or response body (up to `max_body_bytes`, default 256KB) for a specific record id. Returns base64 + UTF-8 decode for text bodiesPaste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"expo-android-mcp": {
"command": "npx",
"args": [
"-y",
"@fndchagas/expo-android"
],
"env": {
"ADB_PATH": "YOUR_ADB_PATH_HERE",
"ADB_SERIAL": "YOUR_ADB_SERIAL_HERE",
"ADB_TIMEOUT_MS": "YOUR_ADB_TIMEOUT_MS_HERE",
"ADB_MAX_BUFFER_MB": "YOUR_ADB_MAX_BUFFER_MB_HERE",
"ADB_DEBUG": "YOUR_ADB_DEBUG_HERE",
"MCP_TRANSPORT": "YOUR_MCP_TRANSPORT_HERE",
"PORT": "YOUR_PORT_HERE"
}
}
}
}
{
"mcpServers": {
"ios-sim-mcp": {
"command": "npx",
"args": [
"-y",
"ios-sim-mcp"
]
}
}
}