The most token-efficient iOS Simulator tool for agents.
Eight tools signed in to the same app on the same iPhone 17 Pro Simulator, on one Mac, each through its own MCP server (AXe, which has none, through its command line). simulator-use read 194 tokens per sign-in: 3.4x fewer than the next tool, 66x fewer than Xcode MCP and 569x fewer than AXe. It also signed in fastest: 3.50 s step by step and 2.87 s batched. Every call was timed and saved, failures included.
Leaderboard
All on one Mac, one tool at a time. Ranked by what the agent reads back over the whole sign-in (read the screen, type the email, type the password, tap Sign In, read the screen to see "Welcome"), since every token of it goes through the model; ties by time. Median of 10 runs, each on a freshly started app. Sign-in times step by step and batched are in The whole sign-in.
| Tool | Tokens read (est.) | Sign in | Signed in | Read the screen | Tap | Tool list tokens (est.) | |
|---|---|---|---|---|---|---|---|
| 1 | simulator-use 0.15.0 | 194 | 3.50 s | 10 of 10 | 0.19 s | 0.68 s | 2,443 |
| 2 | agent-device 0.21.35 | 664 | 6.85 s | 10 of 10 | 0.05 s | 0.88 s | 47,406 |
| 3 | mobile-mcp 1.0.15 | 981 | 6.97 s | 10 of 10 | 0.42 s | 0.77 s | 7,129 |
| 4 | MobileBuildMCP 2.7.1 | 1,561 | 12.26 s | 10 of 10 | 0.62 s | 2.37 s | 6,193 |
| 5 | Maestro MCP 2.12.0 | 2,987 | 9.19 s | 10 of 10 | 0.13 s | 1.58 s | 3,063 |
| 6 | Argent 0.31.0 | 7,129 | 6.63 s | 10 of 10 | 0.19 s | 0.66 s | 42,531 |
| 7 | Xcode MCP 27.0 (27A266a) | 12,732 | 3.58 s | 10 of 10 | 0.09 s | 0.71 s | 19,620 |
| 8 | AXe 1.8.0 | 110,319 | 9.21 s | 10 of 10 | 0.86 s | 1.72 s | none (CLI) |
The runs went in this order: simulator-use, AXe, MobileBuildMCP, mobile-mcp, agent-device, Argent, Xcode MCP, then the second runs under Not ranked here, then Maestro MCP and AXe's last run: their first tries stopped before any call, with the Simulator found shut down after its reboot. Tokens are estimates: characters / 4 for text (no Anthropic API key was set for this run), width * height / 750 for an image.
simulator-use against each tool, one page each: compare.
Read the screen
The tool's own screen read, 20 times on the unchanged sign-in screen, after one warm-up read.
| Tool | Median | p90 | Tokens (est.) | Showed the screen |
|---|---|---|---|---|
| agent-device 0.21.35 | 0.05 s | 0.05 s | 131 | 20 of 20 |
| Xcode MCP 27.0 (27A266a) | 0.09 s | 0.09 s | 2,410 | 20 of 20 |
| Maestro MCP 2.12.0 | 0.13 s | 0.14 s | 1,116 | 20 of 20 |
| simulator-use 0.15.0 | 0.19 s | 0.25 s | 72 | 20 of 20 |
| Argent 0.31.0 | 0.19 s | 0.21 s | 658 | 20 of 20 |
| mobile-mcp 1.0.15 | 0.42 s | 0.42 s | 375 | 20 of 20 |
| MobileBuildMCP 2.7.1 | 0.62 s | 0.70 s | 386 | 20 of 20 |
| AXe 1.8.0 | 0.86 s | 0.92 s | 44,869 | 20 of 20 |
Tap a button
Sign In with empty fields, 20 times, each after a fresh start of the app and an untimed read. The app's own log confirms each tap. "Shows the result" counts answers that hold the new status text, "Invalid email or password", in the answer itself or in the file it names for the agent to open.
| Tool | Median | p90 | Shows the result | Tokens (est.) | Landed |
|---|---|---|---|---|---|
| Argent 0.31.0 | 0.66 s | 0.74 s | 20 of 20 | 647 | 20 of 20 |
| simulator-use 0.15.0 | 0.68 s | 0.81 s | 20 of 20 | 17 | 20 of 20 |
| Xcode MCP 27.0 (27A266a) | 0.71 s | 0.77 s | 20 of 20 | 2,402 | 20 of 20 |
| mobile-mcp 1.0.15 | 0.77 s | 0.79 s | 0 of 20 | 6 | 20 of 20 |
| agent-device 0.21.35 | 0.88 s | 1.26 s | 20 of 20 | 38 | 20 of 20 |
| Maestro MCP 2.12.0 | 1.58 s | 1.60 s | 0 of 20 | 51 | 20 of 20 |
| AXe 1.8.0 | 1.72 s | 1.88 s | 0 of 20 | 18 | 20 of 20 |
| MobileBuildMCP 2.7.1 | 2.37 s | 2.45 s | 0 of 20 | 88 | 20 of 20 |
Type into a field
gary@example.com into Email, 10 times, each on a fresh app: the tool's fill call, or a tap on the field and a type call where that is its way. The tool's next read must show the text.
| Tool | Median | p90 | Calls | Tokens (est.) | Text shown |
|---|---|---|---|---|---|
| Xcode MCP 27.0 (27A266a) | 1.13 s | 1.15 s | 1 | 2,579 | 10 of 10 |
| simulator-use 0.15.0 | 1.14 s | 1.19 s | 1 | 14 | 10 of 10 |
| AXe 1.8.0 | 1.98 s | 2.10 s | 2 | 18 | 10 of 10 |
| agent-device 0.21.35 | 2.48 s | 2.52 s | 1 | 167 | 10 of 10 |
| mobile-mcp 1.0.15 | 2.52 s | 2.54 s | 2 | 13 | 10 of 10 |
| MobileBuildMCP 2.7.1 | 3.15 s | 3.33 s | 1 | 93 | 10 of 10 |
| Argent 0.31.0 | 3.58 s | 3.62 s | 2 | 2,190 | 10 of 10 |
| Maestro MCP 2.12.0 | 3.62 s | 4.00 s | 1 | 51 | 10 of 10 |
The whole sign-in
Step by step, one call per action; and batched, the three actions in the tool's own batch or sequence call where it has one. Signed in means the final read showed "Welcome, gary@example.com" and the app logged the sign-in.
| Tool | Step by step | Tokens (est.) | Signed in | Batched | Tokens (est.) | Signed in |
|---|---|---|---|---|---|---|
| simulator-use 0.15.0 | 3.50 s | 194 | 10 of 10 | 2.87 s | 179 | 10 of 10 |
| Xcode MCP 27.0 (27A266a) | 3.58 s | 12,732 | 10 of 10 | no batched run | ||
| Argent 0.31.0 | 6.63 s | 7,129 | 10 of 10 | 4.37 s | 2,971 | 10 of 10 |
| agent-device 0.21.35 | 6.85 s | 664 | 10 of 10 | 5.99 s | 327 | 10 of 10 |
| mobile-mcp 1.0.15 | 6.97 s | 981 | 10 of 10 | 6.97 s | 1,030 | 10 of 10 |
| Maestro MCP 2.12.0 | 9.19 s | 2,987 | 10 of 10 | 7.56 s | 2,885 | 10 of 10 |
| AXe 1.8.0 | 9.21 s | 110,319 | 10 of 10 | 4.63 s | 110,273 | 8 of 10 |
| MobileBuildMCP 2.7.1 | 12.26 s | 1,561 | 10 of 10 | no batched run | ||
Not ranked here
The second runs. AXe and MobileBuildMCP ran again with Device Hub open, because AXe's README says: "Xcode 27 simulator automation uses Device Hub; Simulator.app is not required." With Device Hub open, their taps mostly did not reach the app. Run once more at the end, with Device Hub closed, both passed again. So on this Mac the headless runs, which every tool had, are the ones ranked.
| Tool | Condition | What happened |
|---|---|---|
| AXe 1.8.0 | Second run; Device Hub open | signed in 0 of 10; taps that reached the app 6 of 20; typings shown 3 of 10; screen reads 20 of 20 (median 0.85 s); batched sign-ins 1 of 10 |
| MobileBuildMCP 2.7.1 | Second run; Device Hub open | signed in 0 of 10; taps that reached the app 9 of 20; typings shown 7 of 10; screen reads 20 of 20 (median 0.62 s) |
| MobileBuildMCP 2.7.1 | Third run; Simulator headless again | sign-in 17.97 s; signed in 10 of 10; taps that reached the app 20 of 20; typings shown 10 of 10; screen reads 20 of 20 (median 0.84 s) |
| AXe 1.8.0 | Third run; Simulator headless again | sign-in 5.91 s; signed in 10 of 10; taps that reached the app 20 of 20; typings shown 10 of 10; screen reads 20 of 20 (median 0.62 s); batched sign-ins 9 of 10 |
- AXe with Device Hub open. Each
axe tapanswered that it tapped the right point, and 6 of the 20 reached the app. Inaxe batchthe taps landed, but the first letters typed into the email were lost in 9 of 10 runs ("ary@example.com", "ry@example.com"), so the screen never showed "Welcome, gary@example.com". - MobileBuildMCP with Device Hub open, which taps through a bundled AXe: 9 of 20 taps reached the app, each answered as done.
- AXe's two ways of reading. In MobileBuildMCP's ranked run and in AXe's last run, the first read timed out creating the Simulator's remote automation session ("Timed out creating the simulator remote automation session"). Every later call still worked, and faster: AXe read the screen in 0.62 s instead of 0.86 s and tapped in 1.09 s instead of 1.72 s, with a longer tree (55,106 tokens instead of 44,869). MobileBuildMCP's last run, which made the session, signed in in 17.97 s, against 12.26 s in its ranked run.
- simulator-use's own engine is built on AXe's frameworks; these rows are AXe's command line and MobileBuildMCP, as their users run them.
Before the first call
What the server's tool list and instructions cost an agent's context in every session, before it does anything.
| Tool | Tools | Definitions | Instructions | Tokens in all (est.) |
|---|---|---|---|---|
| AXe 1.8.0 | CLI | none | ||
| simulator-use 0.15.0 | 12 | 2,075 | 368 | 2,443 |
| Maestro MCP 2.12.0 | 10 | 2,552 | 511 | 3,063 |
| MobileBuildMCP 2.7.1 | 36 | 5,616 | 577 | 6,193 |
| mobile-mcp 1.0.15 | 35 | 6,852 | 277 | 7,129 |
| Xcode MCP 27.0 (27A266a) | 53 | 19,608 | 12 | 19,620 |
| Argent 0.31.0 | 77 | 42,277 | 254 | 42,531 |
| agent-device 0.21.35 | 62 | 46,998 | 408 | 47,406 |
| Tool | Setup its docs ask for |
|---|---|
| AXe 1.8.0 | none |
| MobileBuildMCP 2.7.1 | none |
| simulator-use 0.15.0 | 0.12 s |
| Maestro MCP 2.12.0 | 0.59 s |
| Xcode MCP 27.0 (27A266a) | 4.21 s |
| mobile-mcp 1.0.15 | 16.33 s |
| agent-device 0.21.35 | 34.72 s |
| Argent 0.31.0 | 83.92 s |
Setup is what a tool's instructions say to do before the first action (open a session, pick or boot the device); its time is not in any number above.
What each tool is
From each tool's own README, license and docs, read on October 31, 2026; the sources are linked in each row.
| Tool | License | Builds the app | Runs tests | Screen as text | Cloud option | Sources |
|---|---|---|---|---|---|---|
| simulator-use | MIT | Yes, Xcode projects (app_run) | XCTest and XCUITest, case by case | One line per element | NoMac's cloud iPhone | README, LICENSE |
| AXe | MIT | No | No | The accessibility tree as JSON | None in its docs | README, LICENSE, docs |
| MobileBuildMCP | MIT | Yes, for the Simulator | Yes, on the Simulator | Tap targets with refs | None in its README | README, LICENSE |
| mobile-mcp | Apache 2.0; built on mobilecli, which is under the Functional Source License 1.1 | No; installs an .app, .ipa, .apk or .zip | None in its README | One line per element, with refs | Mobile Next Cloud, real iOS and Android devices | README, LICENSE, mobilecli LICENSE |
| agent-device | MIT | No; installs a built app | Replays its own .ad scripts | Snapshots with refs, and diffs after actions | A remote proxy, or device clouds (BrowserStack, AWS Device Farm, TestMu AI, Limrun) | README, LICENSE |
| Argent | Apache 2.0 source; its simulator-server and ax-service binaries are proprietary | React Native projects | Records and replays its own e2e tests | An element tree, and a screenshot after each action | Argent Cloud | README, LICENSE, tools |
| Maestro MCP | Apache 2.0 | No | Maestro flows | A compact JSON view hierarchy | Maestro Cloud runs flows | README, MCP docs |
| Xcode MCP | Part of Xcode | Yes (BuildProject) | Yes (RunAllTests, RunSomeTests) | A UI hierarchy file per interaction, by path | None in its docs | Apple docs, Xcode 27 notes, its tool list |
What each tool needs
Every tool here needs a Mac with Xcode and an iOS Simulator runtime for the iOS Simulator. Quoted needs come from the sources above.
| Tool | Version tested | How it was run | Needs besides Xcode |
|---|---|---|---|
| simulator-use | 0.15.0 | simulator-use mcp | Node 20. Its engine is built on AXe's frameworks, bundled; "there is no test runner to build" |
| AXe | 1.8.0 | the axe command, one process per step (it has no MCP server) | macOS 14 or later. "Xcode 27 simulator automation uses Device Hub; Simulator.app is not required" |
| MobileBuildMCP | 2.7.1 | mobilebuildmcp mcp with its ui-automation workflow on (off by default) | macOS 14.5, Xcode 16, Node 18. Reads and taps through its bundled AXe (its docs) |
| mobile-mcp | 1.0.15 | its npm package's server (npx @mobilenext/mobile-mcp in its README) | Node 20 and the Xcode command line tools. On iOS, mobilecli's on-device agent "is required for touch input ... and UI tree inspection" (mobilecli README) |
| agent-device | 0.21.35 | agent-device mcp | Node 22.12. "A local accessibility bridge for iOS Simulator snapshots and XCTest for iOS interactions" |
| Argent | 0.31.0 | argent mcp | Node 20.12 (its docs). Software Mansion's proprietary simulator-server and ax-service binaries |
| Maestro MCP | Maestro 2.12.0 | maestro mcp | Java 17. It "installs and communicates with a small companion driver app on the device" (its docs) |
| Xcode MCP | Xcode 27.0 (27A266a) | xcrun mcpbridge, headless | Xcode 27 with sudo xcrun mcp-server enable (Xcode 27 release notes), or Xcode open with "Allow external agents to use Xcode tools" turned on |
How each tool was driven
Each tool's own calls, chosen from its README, its tool descriptions or the hints in its answers. The code is in bench/tools.
- simulator-use. Read with
ui_look;ui_actwithtap #signInorfill #email .... Batched: oneui_actwith the three steps. - AXe. No MCP server, so one
axeprocess per step:describe-ui,tap --id, andtap --idthentype. Batched: oneaxe batchwith the five steps, as in its help. It ran twice: with the Simulator headless, like every tool, and again with Device Hub open, since its README says "Xcode 27 simulator automation uses Device Hub". - MobileBuildMCP. Run twice, like AXe, which it taps and reads through: headless, and with Device Hub open. Its
ui-automationworkflow turned on.snapshot_ui, thentapandtype_textby elementRef, andsnapshot_uiagain after eachtype_text(its descriptions say to refresh after layout changes, and the keyboard is one). Its read lists only tap targets, so the last step checks "Welcome" with itswait_for_uitextContains, as its tips say. No batched run: itsbatchtakes taps, not typing. - mobile-mcp.
mobile_list_elements_on_screen, thenmobile_click_on_screen_at_coordinatesby @ref, and a click thenmobile_type_keys. Batched:mobile_batch_commands. Its first read starts its on-device agent, which left the Home Screen in front; the setup starts the agent and the app is then started again, as before every step. - agent-device. Setup:
openwithforeground: true, as its instructions say.snapshotwithinteractiveOnly,pressandfillbyid="..."selector withsettle: true. Batched: itsbatch. - Argent. Setup: the Simulator booted by Argent's
boot-device(its firstdescribesaid it needs that for its accessibility settings), thenlaunch-app.describe, thengesture-tapat the centre of the element's frame, and a tap thenkeyboard. Batched:run-sequence. - Maestro MCP.
inspect_screen, thenrunwith inline YAML:tapOnby id, andtapOntheninputTextin one call. Batched: onerunwith every step. - Xcode MCP. Headless (
sudo xcrun mcp-server enable).DeviceInteractionStartSession, thenDeviceInteractionSynthesize: with no command to read (the agent opens the hierarchy file it names),t x yat the element's hitPoint, andt x y sender keyboard kbd ...to tap a field and type, from Xcode's own device-interaction skill. No batched run: typing must come last in a command.
Method
Every run was on one Mac, one tool at a time, with every other tool's processes ended and the Simulator shut down and booted again before it. AXe and MobileBuildMCP ran a second time with Device Hub open. The harness speaks MCP over stdio to the tool's own server, as an agent's client does, and times each call from the request sent to the answer received (AXe has no MCP server, so its command ran once per step, timed from start to exit). Every tool used its own read, its own way to tap and type (by id where it has one, at coordinates where that is its way), its own settle and verify options, and the setup its docs or its own hints ask for. A tap or a sign-in counts only when the app's own log shows it, a check that uses no accessibility; a step that failed is reported, never retried.
Tokens are what the agent reads back: the answer's text as characters / 4 (no Anthropic API key was set for this run; the harness counts with Anthropic's token counting API when one is), an image as width * height / 750, and for Xcode the hierarchy file its answer points to, which its own skill says to read after every interaction. Medians are the middle value; p90 is the 90th percentile by nearest rank.
| Mac | Apple M5 Pro (Virtual), 6 cores, 8 GB of memory (VirtualMac2,1, a NoMac Session Mac) |
| macOS | 26.6.2 (25G83) |
| Xcode | Xcode 27.0 (27A266a) |
| Simulator | iPhone 17 Pro, iOS 27.0 (24A434), booted with simctl; Device Hub closed unless a row says otherwise |
| Node | 24.20.0 |
| Date | 2026-11-01 |
| Tokens | estimates: text as characters / 4 (no Anthropic API key was set for this run), images as width * height / 750 |
The harness and every call it made: bench, with the raw results in bench/results/2026-11-01 (each file records its Mac, Simulator, versions and whether Device Hub was open). bash bench/setup.sh, then bash bench/run-all.sh, runs it again on any Mac with Xcode; node bench/summarize.mjs and node bench/page.mjs turn the results into these tables.