Skip to main content
Glama
mgcrea

@mgcrea/mcp-ios-simulator

by mgcrea

@mgcrea/mcp-ios-simulator

Model Context Protocol server for driving an iOS Simulator from a model: screenshot the screen, read its accessibility tree, tap, swipe, type, manage the app under test — and stage the device itself, which is the part no physical device can do.

No Apple Developer team. No code signing. No device trust. No tunnel. Nothing to unlock. And screenshots work with nothing installed at all.

Features

  • See the screen, with zero setup. simctl captures it directly, scaled to exactly the device's point size, so a position read off the image is a tap coordinate with no conversion. No WebDriverAgent needed for this.

  • Read the screen. A flattened, pruned accessibility tree — type, label, identifier and the precomputed tap point per element — instead of the tens of KB of nested JSON WebDriverAgent actually returns.

  • Drive the screen. Tap by coordinate or by accessibility label, swipe, type, press Home. Every action returns the resulting screen by default, so a mis-aimed tap is visible on the call that made it.

  • Stage the device. Dark mode, Dynamic Type size, increased contrast, a frozen 9:41 status bar, a simulated location, and app permissions granted or denied without a prompt anyone has to tap. None of this is possible on real hardware.

  • Push without APNs. Deliver a real remote notification with no certificate and no server.

  • Manage the app. Install a build, launch it with fixture arguments, terminate it, uninstall it, open a deep link. An app's data container is an ordinary path on this Mac, so its database or logs are read directly — there is nothing to copy off a device.

  • Read its logs. launch with capture_logs: true writes the app's stdout, stderr and every Logger/os_log message into one file, and read_logs follows it with a cursor, a regex filter and Xcode's thirty-character line prefix cut down to the time.

  • Read its crashes. Simulator crash reports land among this Mac's own in ~/Library/Logs/DiagnosticReports; list_crash_logs keeps only the simulators', says which simulator each came from, and get_crash_log returns the exception and the faulting thread with library names resolved.

Related MCP server: Shotter

Security

Writes are on by default, and that is deliberate. The rest of the fleet is read-only until a flag is set because a mutating tool acts on someone's real account or someone's real phone. A simulator is neither: it holds no person's data, and ios_simulator_erase puts it back to factory in seconds.

What that still costs you, stated honestly:

  • install and launch run code on your Mac. A simulated process is a host process.

  • The app's data container is a plain host path, readable by anything.

  • erase and uninstall are irreversible — they are the two tools behind an explicit confirm.

  • list_crash_logs reads this Mac's DiagnosticReports folder. It keeps only simulator reports and get_crash_log refuses a Mac app's, but the folder is yours and the server reads it as you.

  • IOS_SIMULATOR_ALLOW_WRITES=0 restores the device server's posture in one variable, and then the seventeen driving tools are absent from tools/list rather than refused, because a refusal still lets a model try, retry and reason about a way around it.

Your credentials. There are none. The server holds no tokens and talks to no vendor API. Everything goes through xcrun simctl and a loopback HTTP server.

Supply chain. Three runtime dependencies: @modelcontextprotocol/server, zod, and @mgcrea/mcp-ios-core — our own, and itself dependent on only the first two. Scaling images uses sips and reading property lists uses plutil, both of which ship with macOS, specifically so neither an image library nor a plist parser has to be installed.

How it reaches the simulator

Lane

Carries

Needs

xcrun simctl

simulators, apps, install, launch, deep links, the screenshot, appearance, status bar, location, permissions, push, boot/shutdown/erase

Xcode. Nothing else.

WebDriverAgent over HTTP

the accessibility tree, tap, swipe, type, buttons

a runner started once with scripts/wda.sh

The asymmetry with mcp-ios-device is worth stating plainly: there, every pixel comes through WebDriverAgent, so nothing about the screen works until a signed runner is installed and trusted on the phone. Here simctl captures the screen itself, so eighteen of the twenty-five tools work with no runner at all — only ios_simulator_ui_tree, ios_simulator_wait_for_element and the five input tools need one, and building it takes about two minutes with no Apple account.

ios_simulator_diagnostics reports both lanes separately, so "the simulator is fine but the runner is not up" is a distinguishable answer rather than a generic failure.

Configure

Variable

Default

What it does

IOS_SIMULATOR_ID

the only booted simulator

UDID, name, or booted. Two booted and no value is an error that names them.

IOS_SIMULATOR_ALLOW_WRITES

on

0 drops the seventeen driving tools from tools/list.

IOS_SIMULATOR_LAUNCH_ARGS

none

Launch arguments applied when launch passes none of its own.

IOS_SIMULATOR_WDA_PORT

8100

Must match the runner's USE_PORT. One port per simulator.

IOS_SIMULATOR_WDA_URL

http://127.0.0.1:<port>

Explicit override; rarely needed.

IOS_SIMULATOR_MAX_TREE_BYTES

24000

Byte cap on a ui_tree payload.

IOS_SIMULATOR_TIMEOUT_MS

120000

Budget for one simctl call; a boot is slow.

IOS_SIMULATOR_WDA_TIMEOUT_MS

30000

Budget for one WebDriverAgent call.

IOS_SIMULATOR_OUTPUT_DIR

$TMPDIR/mcp-ios-simulator

Screenshots, launch logs, the runner log.

IOS_SIMULATOR_CRASH_REPORTS_DIR

~/Library/Logs/DiagnosticReports

Where list_crash_logs looks.

IOS_SIMULATOR_DEBUG

off

Log every simctl and WebDriverAgent call to stderr.

The same keys in camelCase can go in ~/.config/ios-simulator-mcp/config.json (IOS_SIMULATOR_CONFIG to move it). The environment wins per field, so a one-off IOS_SIMULATOR_ALLOW_WRITES=0 beats a file that says true. Unknown keys in the file are an error rather than silently ignored — a typo that looks like "that setting had no effect" is the worst way to learn where your configuration came from.

See .env.example for the annotated version.

Quick start

Requires macOS with Xcode and a booted simulator.

A. Everything except the tree and the taps, with no setup

npx -y @mgcrea/mcp-ios-simulator

list, list_apps, screenshot, diagnostics, power, install, launch, open_url, set_environment, push and erase all work immediately.

B. The input lane

ui_tree, tap, tap_element, swipe, type and press_button need a WebDriverAgent runner. Build and start it — no team id, no signing, no prompt:

scripts/wda.sh setup   # ~2 minutes
scripts/wda.sh run     # leave this running
scripts/wda.sh status  # is it answering?

Installed from npm, the same script is the ios-simulator-wda binary:

npx -p @mgcrea/mcp-ios-simulator ios-simulator-wda setup
npx -p @mgcrea/mcp-ios-simulator ios-simulator-wda run

C. Wired into a client

See .mcp.json.example.

Tools

Twenty-five. Eight are read-only; the other seventeen disappear with IOS_SIMULATOR_ALLOW_WRITES=0. read_logs is among those seventeen although it changes nothing: it only reads what launch started capturing, so it goes where launch goes.

Tool

Writes?

What it does

ios_simulator_list

Every simulator, with state and whether its runtime is installed

ios_simulator_diagnostics

Both lanes, the resolved target, the geometry, and who owns the WDA port

ios_simulator_list_apps

Installed apps, with bundle id and host-path data container

ios_simulator_screenshot

The screen, in point space — no runner needed

ios_simulator_ui_tree

Addressable elements with precomputed tap points

ios_simulator_wait_for_element

Poll until something appears, or goes away

ios_simulator_list_crash_logs

Simulator crash reports, newest first, by simulator and process

ios_simulator_get_crash_log

One report: exception, termination, faulting thread

ios_simulator_tap

✓

Tap a point

ios_simulator_tap_element

✓

Tap by identifier, label or predicate

ios_simulator_swipe

✓

Drag between two points

ios_simulator_type

✓

Type into the focused field, or a named one

ios_simulator_press_button

✓

Home

ios_simulator_power

✓

Boot or shut down; never implicit

ios_simulator_erase

✓ confirm

Wipe to factory

ios_simulator_install

✓

Install a simulator .app

ios_simulator_launch

✓

Launch, with fixture arguments and captured output

ios_simulator_read_logs

✓ (gate only)

Follow a capture_logs launch: stdout, stderr and os_log, with a cursor

ios_simulator_uninstall

✓ confirm

Remove one app and its data

ios_simulator_terminate

✓

Kill a running app

ios_simulator_open_url

✓

Deep links and universal links

ios_simulator_set_environment

✓

Appearance, Dynamic Type, contrast, status bar, location, permissions

ios_simulator_add_media

✓

Seed the photo library — the way around the missing camera

ios_simulator_push

✓

A remote notification, with no APNs certificate

ios_simulator_restart_wda

✓

Start or restart the runner, detached

Deliberately absent: create, clone, delete, rename, upgrade and pair (fleet management, not driving, and delete all is a footgun with no upside); get_app_container (list_apps already returns the path); keychain, pbcopy, spawn, diagnose and recordVideo (real capabilities that an agent would use approximately never, and every tool costs listing bytes on every connect).

addmedia was on that list until 0.2.0, and it was the wrong call. A simulator has no camera, so seeding the photo library is not a nice-to-have — it is the only way an app whose first step is "choose a photo" can be driven here at all. Anyone hitting that had to drop out to a shell, which is exactly what these tools exist to avoid.

uninstall was on it too, on the grounds that install overwrites and erase covers a first run. But erase takes every other app's data and a reboot with it, and "this app's first launch, everything else as it was" is the ordinary case. It sits behind confirm like erase.

Traps worth knowing

Measured on Xcode 26.6 (17F113) unless marked Xcode 27, which was checked on Xcode 27.0 (27A266a) with an iOS 27.0 runtime.

  • simctl io … screenshot - does not write to stdout. The help text says it does. It creates a file literally named - in the current working directory and prints Wrote screenshot to: … to stderr, exit 0. This server always passes a real path.

  • simctl io on a simulator whose runtime is missing aborts — SIGABRT, exit 134, an uncaught NSInternalInconsistencyException and a thirty-line stack trace, not an error message. Availability is checked in the resolver, before the call. On a typical machine a large fraction of simulators are in this state.

  • erase, delete and shutdown all accept the literal all. A target of "all" reaching simctl erase wipes every simulator on the machine. Refused in the resolver and again in the adapter.

  • booted is a coin flip. simctl's own help: "If multiple devices are booted … simctl will choose one of them." Resolved to a concrete UDID here first.

  • WebDriverAgent scans ports 8100-8199 when USE_PORT is unset. With two booted simulators, the second runner comes up healthy on 8101 and a server pointed at 8100 drives the first one while every call reports success. scripts/wda.sh always pins USE_PORT, and diagnostics reports the port's real owner via SIMULATOR_UDID from ps -Eww.

  • listapps returns an old-style NeXTSTEP plist, not JSON. --json is a flag on list and nothing else.

  • A status bar override survives a reboot. Clear it or it quietly pollutes every later screenshot.

  • simctl launch environment variables need a SIMCTL_CHILD_ prefix on the calling process, not a flag.

  • An app's Logger output reaches no file unless OS_ACTIVITY_DT_MODE is set (Xcode 27). Settings launched plainly wrote 8 lines to stderr; launched with SIMCTL_CHILD_OS_ACTIVITY_DT_MODE=YES it wrote 77 in the same eight seconds, the unified log mirrored with Xcode's prefix. capture_logs sets it.

  • --stdout and --stderr may be the same file (Xcode 27). A probe app alternating print, stderr and Logger produced one file with all fifteen lines in order and nothing overwritten. The redirect appends, so a relaunch into the same path keeps the previous run's lines — every capture_logs launch gets a fresh file.

  • A launch log under /tmp or $TMPDIR is not where you asked (Xcode 27). The simulator opens the redirect itself, and it has its own /tmp and /var/folders: --stdout=/tmp/x/a.out created <device>/data/tmp/x/a.out, and the path given never existed — which is where this server's default output directory is. launch now looks in both places and returns the real one. A path under /Users is written as given.

  • A simulator crash report says it is one in platform, not is_simulated (Xcode 27). Of 593 reports on one Mac, the 464 from simulators all had header platform: 7 (PLATFORM_IOSSIMULATOR), the Mac's all had 1, and is_simulated: 1 was on 13 Mac reports — Safari, Mail and two helpers. procPath is anonymised, so the simulator's UDID comes from the body's coalitionName (com.apple.CoreSimulator.SimDevice.<UDID>), which sat in the first 1.8 KB of every one.

  • A Swift fatalError message is in the log, not the crash report (Xcode 27). The probe's report had the _assertionFailure frame and no application-specific text; the message was on stderr. get_crash_log says so when it happens.

  • simctl uninstall of an app that is not installed succeeds (Xcode 27), silently, exit 0. Success does not prove it was there.

  • Launching an app that is not installed fails as "The request to open … failed" (Xcode 27), FBSOpenApplicationServiceErrorDomain code 4, with nothing about installation. The error now carries that remedy.

  • A label belongs to the control and to every container around it. WebDriverAgent answers depth-first, so an unqualified label match lands on the navigation bar as readily as on the button — and a tap on a container does nothing while reporting success. tap_element narrows a label to the interactive types first, and says preferredControl when it did.

  • isVisible is not always truthful. A PHPicker presented over Safari reports all nine of its asset cells isVisible: "0" while they are on screen and tappable — a synthesised tap on one opens the preview. The default ui_tree filter drops them, which is why the result carries a filtered tally: a short list that has been filtered and a screen that is genuinely bare are otherwise the same answer.

  • simctl install wants a .app bundle directory built for the simulator — an .ipa or a device build fails with "No such file or directory", which reads like a path typo.

  • simctl boot gives you no window. It runs headless, which is what an agent wants and confusing the first time; power opens a window by default.

  • Xcode 27 ships no Simulator.app. The simulator's window belongs to DeviceHub (com.apple.dt.Devices), and open -a Simulator fails. power tries Simulator.app first and falls back to opening DeviceHub by bundle id; a window that still will not open is a warning on a boot that worked, never an error.

  • DeviceHub cannot be told which device to show. It keeps one device per window, on whatever was last picked in its sidebar. No devices:// URL switches it — device/<UDID>, a bare UDID and simulator/<UDID> were all ignored — and a query-string form it did not recognise made it quit, taking every booted simulator down with it. power therefore opens it by bundle id and says in its note to select the device. Screenshots and the WDA lane do not care which device the window shows.

  • Quitting DeviceHub shuts every booted simulator down. Unlike Simulator.app, whose window could close with the device left running, a plain Quit takes the simulators with it; DeviceHub's separate "Quit and Keep Simulators Running" does not. Since power opens DeviceHub by default, a device that vanishes mid-session usually means someone quit that window. Pass open_window: false to boot headless when nobody needs to watch.

  • Xcode 27 moved the screen geometry out of profile.plist. No device type's profile carries mainScreen* any more, old types included; the same numbers are under capabilities.ScreenDimensionsCapability in capabilities.plist. Reading only the profile defaults the scale to 1 and labels a 1206×2622 pixel capture as points, with nothing looking wrong.

  • Two runtimes can share one identifier, so the key of list devices is not a primary key.

Develop

pnpm install
pnpm lint && pnpm format:check && pnpm typecheck && pnpm test && pnpm build

License

MIT — see LICENSE.

Available Tools

25 tools
ios_simulator_add_mediaiOS Simulator: Add MediaA

Put photos or videos into the simulator's photo library. A simulator has no camera, and this is how you get around that: seed the library first, then drive the app's picker as normal. Without it, every flow that starts with an image is untestable here. Files are copied in, so the originals are untouched and the simulator keeps them until it is erased. Pair it with permission on ios_simulator_set_environment to skip the access prompt entirely.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathsYesAbsolute paths to the images or videos, e.g. ["/Users/me/fixtures/monstera.jpg"]. Formats are the ones Photos itself accepts — JPEG, PNG, HEIC, MOV, MP4.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say non-read-only, non-idempotent, non-destructive. The description adds meaningful behavioral detail beyond those flags: 'Files are copied in, so the originals are untouched and the simulator keeps them until it is erased.' This clarifies persistence, non-destructiveness to source files, and the fact that the simulator's library is mutated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is about five sentences long, but every sentence earns its place: purpose, motivation, workflow, side effects, and integration with a sibling tool. It is front-loaded with the core function and avoids filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with two parameters, no output schema, and only generic annotations, the description plus schema gives an agent everything needed to select and invoke it correctly: what it does, why it exists, how to sequence it in a test flow, what side effects to expect, and how to combine it with permission handling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already has 100% description coverage with clear explanations for both `paths` and `device`, so the baseline is 3. The description does not add parameter-level semantics beyond the schema; it provides useful workflow context, but the schema itself carries the parameter documentation burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and noun: 'Put photos or videos into the simulator's photo library.' This clearly distinguishes it from sibling tools like screenshot, install, or launch, none of which address media seeding. It also gives the motivating problem ('A simulator has no camera'), so an agent understands exactly what unique gap this tool fills.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description is explicit about when and how to use the tool: seed the library first, then drive the app's picker as normal. It states the consequence of not using it ('every flow that starts with an image is untestable here') and even gives complementary guidance by pairing it with `permission` on ios_simulator_set_environment to skip the access prompt.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_diagnosticsiOS Simulator: DiagnosticsA
Read-only

Report both lanes separately and never fail: which simulators exist and which are usable, which one this server would drive, its screen geometry, and whether WebDriverAgent is answering — including which simulator owns its port, which is the one way to catch a second runner quietly taking your taps. Start here when anything else misbehaves.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description adds meaningful behavioral context: it reports 'both lanes separately', 'never fail[s]', and can detect a second runner by identifying which simulator owns the WDA port. This gives the agent useful expectations about reliability and output structure without contradicting the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but efficient, front-loading the core behavior ('Report both lanes separately and never fail') before enumerating the diagnostic contents. The later clauses about catching a second runner are slightly wordy but still earn their place by clarifying a key diagnostic use case.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by enumerating the major output categories: existing/usable simulators, the server-selected simulator, screen geometry, and WDA port ownership. This is enough for an agent to know what to expect, though exact output formatting remains unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides full coverage for the optional 'device' parameter, including guidance on omitting it and the distinction from simctl's 'booted'. The tool description itself adds no parameter-specific detail, so the high schema coverage establishes the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action ('Report') and a concrete diagnostic resource: simulator existence/usability, server-chosen simulator, screen geometry, and WDA status with port ownership. This distinguishes it from sibling tools like ios_simulator_list or ios_simulator_restart_wda by emphasizing an aggregated diagnostic report.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Start here when anything else misbehaves' provides explicit situational guidance for when to invoke this tool. It does not spell out exclusions or contrast itself against specific sibling tools, but the context is clear enough for an agent to select it as a first-line diagnostic.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_eraseiOS Simulator: EraseA
Destructive

Wipe a simulator back to a factory state: installed apps, their data, the keychain and every granted permission. Irreversible, hence confirm; ios_simulator_uninstall is the narrower way to a first launch of one app. A booted simulator is shut down first and booted again afterwards, because simctl refuses to erase a running one.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
confirmYesMust be true. Explicit acknowledgement that this changes state on a real simulator.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and readOnlyHint=false, but the description goes further by naming precisely what is destroyed (apps, data, keychain, permissions), that it is irreversible, and a non-obvious side effect: a booted simulator is shut down then re-booted because simctl refuses to erase a running one. That is real behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, zero filler, front-loaded with the destructive scope before the alternative and the mechanical side effect. Every clause carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, two-parameter tool with no output schema, the definition is complete: safety profile (via annotations plus the description), scope of destruction, reversibility, sibling routing, and the shutdown/reboot side effect are all covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description earns an upgrade by explaining the rationale for `confirm` ('Irreversible, hence confirm') rather than just restating it. It does not add anything about `device` beyond the schema, which already documents UDID/name omission and the never-picks-arbitrarily guarantee.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Wipe... back to a factory state') and enumerates exactly what is destroyed: installed apps, their data, the keychain and every granted permission. It explicitly separates itself from ios_simulator_uninstall, so an agent can route correctly without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the sibling alternative and the condition that selects it: use uninstall when the goal is merely 'a first launch of one app' rather than a full reset. The irreversibility note plus the required `confirm` also tells the agent this is a last-resort operation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_get_crash_logiOS Simulator: Get Crash LogA
Read-only

Read one simulator crash report and return what matters in it: the exception, why the process was terminated, any application-specific message, and the faulting thread's top frames with library names resolved. The full report's path is returned too; it is often tens of kilobytes, so read it only when the summary is not enough. A Swift fatalError's message may not be in the report at all — on a simulator it goes to the app's stderr.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesThe report's `name` from ios_simulator_list_crash_logs, e.g. "Canopy-2026-10-08-101500.ips" or "Retired/Canopy-2026-10-02-213409.ips". Older reports move under Retired/, so a name that worked yesterday may need listing again.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds rich context beyond the readOnlyHint annotation: report size (tens of kilobytes), the fact that a Swift fatalError message may be absent from the report and instead appear on the app's stderr, and the summary-vs-full-report tradeoff. These are non-obvious behavioral traits an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: what is returned, the cost/benefit of fetching the full file, and the fatalError caveat. Front-loaded with the core purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with no output schema, the description covers what the summary contains, the tradeoff of the full report, and a significant real-world caveat about missing fatalError messages. No output schema exists, so the description appropriately explains what is returned.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema's `name` description already documents the filename pattern, Retired/ subfolder behavior, and where to get the name from list_crash_logs. The description adds no parameter detail beyond the schema, so a baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read one simulator crash report') and enumerates what it returns: exception, termination reason, app message, top frames with resolved libraries. This clearly distinguishes it from the sibling ios_simulator_list_crash_logs, which only lists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Tells the agent to read the full .ips path only when the summary is 'not enough', implying the summary is the default. It does not name list_crash_logs as the required prerequisite for obtaining the name, though the schema's description of `name` effectively routes the agent there.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_installiOS Simulator: InstallA
Idempotent

Install a build. The path must be a .app bundle directory built for the simulator — not an .ipa, and not a device build, both of which fail with a bare "No such file or directory" that reads like a typo. Installing over an existing copy replaces it and keeps its data.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to the .app bundle, e.g. ~/Library/Developer/Xcode/DerivedData/…/Build/Products/Debug-iphonesimulator/Foo.app
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses the important overwrite behavior: installing over an existing copy replaces it and keeps its data. It also explains the misleading 'No such file or directory' failure mode for invalid builds, which is exactly the kind of context an agent needs to interpret errors correctly. This adds real value beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences deliver the core instruction, the key input constraint, the failure mode, and the overwrite behavior with no filler. The most important constraint is front-loaded, and every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter install operation with no output schema, the description covers the required input shape, the common failure cases, and the side effect of reinstalling. Device-selection details are already fully specified in the schema, so nothing necessary for a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents both the .app path format and the device-selection rules, so the baseline is 3. The description adds meaning by explaining that .ipa and device builds fail with a confusing error, which sharpens the agent's understanding of the path parameter beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with the specific action 'Install a build' and precisely identifies the target resource as a simulator-built .app bundle. It also clearly separates this from invalid inputs like .ipa and device builds, making the tool's purpose easy to distinguish from sibling tools such as ios_simulator_launch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The primary use case is explicit: install a simulator build from a .app bundle. It also gives strong negative guidance by warning that .ipa files and device builds fail. It does not explicitly name an alternative tool for launching or listing apps, but the install operation itself is unambiguous enough that no direct sibling comparison is required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_launchiOS Simulator: LaunchA

Launch an installed app. Pass arguments to put it into a fixture or demo mode — that is what IOS_SIMULATOR_LAUNCH_ARGS sets as the default for every launch that does not override it. Standard output and error are captured to files under the output directory, so an app that dies on launch leaves something readable behind. Pass capture_logs: true to also get its Logger/os_log output, in one file read with ios_simulator_read_logs.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
argumentsNoLaunch arguments, e.g. ["-DemoMode", "YES"]. Overrides IOS_SIMULATOR_LAUNCH_ARGS rather than adding to it.
bundle_idYesThe app's bundle identifier, e.g. "io.mgcrea.Canopy". List them with ios_simulator_list_apps.
capture_logsNoWrite stdout, stderr and every Logger/os_log message to one fresh file, for ios_simulator_read_logs. Sets OS_ACTIVITY_DT_MODE=YES in the app's environment, which is what Xcode sets to mirror unified logging onto stderr; without it an app's Logger output reaches no file at all.
terminate_firstNoReplace a running copy rather than attaching to it. On by default so a launch means a fresh process and a predictable first screen.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=false, so the write-and-safe profile is covered. The description adds meaningful context beyond annotations: stdout/stderr captured to files, terminate_first default behavior, OS_ACTIVITY_DT_MODE env var, and the IOS_SIMULATOR_ID/LAUNCH_ARGS environment defaults. This is richer than annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the core action ('Launch an installed app'). Each sentence delivers distinct information (env defaults, log capture, capture_logs semantics). Slight density with env-var references but no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a launch tool with no output schema, the description covers what is needed: how to pass args, where logs go, how to read them (pointing to ios_simulator_read_logs), and terminate_first behavior. Missing explicit mention of app-not-installed failure mode, but core operational knowledge is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description reinforces and contextualizes key parameters — arguments behavior (overrides env default), capture_logs purpose (Logger output to file), and the output directory context — adding narrative that links parameters to the operation's side effects.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Launch an installed app'), which is immediately distinguishable from siblings like ios_simulator_install and ios_simulator_terminate. It doesn't explicitly name the closest alternative (ios_simulator_terminate or ios_simulator_restart_wda), but the action is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains how to use key features (arguments for fixture mode, capture_logs for logging) but never states when to use this tool versus ios_simulator_terminate, ios_simulator_restart_wda, or ios_simulator_open_url. Usage is implied through the feature descriptions rather than explicit routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_listiOS Simulator: ListA
Read-only

List the simulators on this machine, with the UDID every other tool takes. Shows the usable ones: a typical machine carries thirty-odd simulators and a good fraction of them are orphans whose runtime is no longer installed, which cannot be booted, driven or screenshotted at all. The result still says how many were left out and how to delete them, and include_unavailable brings them back with available: false and the reason, so "why can't I use that one" is still answerable here.

ParametersJSON Schema
NameRequiredDescriptionDefault
booted_onlyNoOnly simulators that are currently running.
name_containsNoCase-insensitive substring filter on the name, e.g. "iPhone 17".
include_unavailableNoAlso list simulators whose runtime is not installed. Off by default because they are not usable for anything; turn it on to see why a specific one is missing.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses substantial behavior: unavailable simulators are filtered out, the result reports how many were omitted and how to delete them, and include_unavailable reveals them with available: false and the reason. This is rich, non-obvious behavior that an agent needs to know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded in the first sentence. The subsequent illustrative detail about typical simulators is useful context but slightly extended; it earns its place by justifying the default filtering, yet could be trimmed without losing essential guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite lacking an output schema, the description covers the essential return values: UDID, available flag, reason, and count of excluded simulators. It also explains the default filtering and how to opt into seeing unavailable ones, making the tool self-sufficient for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds extra meaning for include_unavailable, explaining the returned available: false flag and the reason, which goes beyond the schema. booted_only and name_contains are already well documented in the schema, so no further elaboration is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'List the simulators on this machine' and highlights the key output, the UDID, which every other tool consumes. This distinguishes it from sibling tools like ios_simulator_list_apps, which lists apps rather than simulators.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: it shows usable simulators by default, and explains when to use include_unavailable to understand why a simulator is missing. It implies this is the tool to obtain a UDID for other tools, though it does not explicitly name alternatives or state 'use this before X'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_list_appsiOS Simulator: List AppsA
Read-only

List the apps installed on a simulator, with the bundle id every other tool takes. Defaults to your own apps: a stock simulator carries about thirty, and twenty-five of them are Apple's. Each entry also carries dataContainer — an ordinary path on this Mac, so an app's database or logs can be read directly with no copy step.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
include_allNoInclude Apple's built-in apps as well. Off by default; the list is long.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses meaningful behavior: results are filtered to the user's own apps by default, stock simulators contain about thirty apps, and each entry exposes a real filesystem path in dataContainer that enables direct reads. This is rich, non-obvious context that helps an agent trust and interpret the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler: the main purpose is front-loaded, followed by high-value behavioral details and a practical note about dataContainer. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only listing tool with two optional parameters and no output schema, the description plus schema fully cover how to invoke it, what the output will contain, and how to use the returned values. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents both parameters fully, including the device ambiguity rule and include_all default, so the description does not need to add parameter-level detail. The description's 'Defaults to your own apps' reinforces include_all but adds little beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action and resource: 'List the apps installed on a simulator', and immediately adds the key value proposition that it returns the bundle id used by other tools. This clearly separates it from sibling tools like ios_simulator_list and ios_simulator_ui_tree.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives practical context for when to use the tool: to obtain bundle ids that other tools consume, and it explains the default filtering behavior. It does not explicitly name an alternative or state a when-not-to-use condition, but the purpose is so distinct that the omission is minor.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_list_crash_logsiOS Simulator: List Crash LogsA
Read-only

List crash reports from simulator processes, newest first. A simulator app's crash is written by this Mac into ~/Library/Logs/DiagnosticReports alongside the Mac's own crashes; this keeps only the simulators' and says which simulator each came from. Most of them are the simulators' own system daemons, so pass process to find your app's. Read one with ios_simulator_get_crash_log. Nothing needs to be booted.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindsNoReport kinds to include, e.g. ["crash"]. Defaults to ["crash", "jetsam", "user_fault"]; kinds without a name come back as "bug_type_<n>". Pass ["all"] for everything.
limitNoMaximum reports to return, newest first (1-200). Defaults to 20.
deviceNoOnly reports from this simulator, by UDID or name as shown by ios_simulator_list. Omit for every simulator's — unlike the other tools, this does not default to the booted one, since a crash often outlives the boot it happened in.
processNoCase-insensitive substring of the process name or bundle id, e.g. "Canopy" or "io.mgcrea". The process name is the app's executable name, usually but not always its display name.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover readOnlyHint, so the description carries real behavioral weight: it explains where reports physically live (~/Library/Logs/DiagnosticReports), that output is filtered to simulators only and labeled by simulator, and that no boot is required. It also flags the non-obvious defaulting difference (device does not default to booted) — genuinely useful context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then layered with the most decision-relevant facts in a compact sequence. Every sentence earns its place; no filler or restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with no output schema, the definition supplies the location of the data, the filtering semantics, the follow-up tool, and the boot precondition — everything an agent needs to call it correctly and interpret the results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters, and the description mainly echoes `process`. However it adds interpretive value the schema lacks — that most results are system daemons, so `process` is the practical filter for finding your own app's crash.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List crash reports from simulator processes'), immediately scoping to simulators and ordering 'newest first'. It clearly distinguishes itself from the sibling ios_simulator_get_crash_log, which it names for reading individual reports.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete selection guidance ('pass `process` to find your app's') and routes the agent to the right sibling for the follow-up action. It also states an important precondition contrast ('Nothing needs to be booted'), though it does not explicitly exclude versus sibling listers like ios_simulator_read_logs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_open_urliOS Simulator: Open URLA

Open a URL on the simulator, which is how you exercise a deep link or a universal link without finding a way to tap one. An https:// link opens in Safari unless the app claims it; a custom scheme goes straight to whichever app registered it.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYese.g. "myapp://garden/42" or "https://example.com/garden/42".
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are neutral (no readOnly/destructive hints), so the description carries the behavioral burden. It discloses non-obvious routing behavior for https vs custom schemes, which is valuable context beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the first front-loads the purpose, the second adds a key behavioral detail. No filler or repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no output schema, the description plus detailed parameter schema covers purpose, usage context, scheme behavior, and device selection. Nothing needed for a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds extra meaning by explaining how the URL's scheme affects behavior, helping an agent choose an appropriate value beyond the schema's examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the exact action ('Open a URL on the simulator') and the purpose ('exercise a deep link or a universal link'), immediately distinguishing it from tap-based sibling tools. The additional scheme-routing details further clarify what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear use case: when you need to exercise a deep/universal link without tapping one. It implies this tool overrides manual tapping but does not explicitly name alternatives or exclusions, so it misses a fully explicit routing statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_poweriOS Simulator: PowerA
Idempotent

Boot or shut down a simulator. Booting is the one thing this server will not do for you implicitly — a cold boot takes tens of seconds and puts a window on the user's screen, and it changes which simulator an unqualified call resolves to afterwards. Both directions are idempotent: booting a booted simulator succeeds.

ParametersJSON Schema
NameRequiredDescriptionDefault
stateYesThe state to put it in. `booted` also waits for it to actually get there.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
wait_msNoHow long to wait for a boot to complete before reporting what it saw.
open_windowNoBring up a window on the device — Simulator.app, or DeviceHub on Xcode 27 — so the screen is visible. A `boot` on its own is headless, which is fine for an agent and confusing for a person watching.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare idempotentHint=true and readOnlyHint=false, but the description adds real behavioral context the annotations cannot: a cold boot takes tens of seconds, puts a window on the user's screen, and shifts which simulator an unqualified call resolves to. Idempotency is restated with concrete detail (booting a booted simulator succeeds), which reinforces rather than merely repeats the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the core action and each clause carrying distinct information (latency, user-visible side effect, resolution side effect, idempotency). The em-dash construction makes it slightly dense but nothing reads as filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With four fully documented parameters, idempotency annotations, and no output schema, the description covers the operationally risky facts an agent needs: latency, window visibility, and post-boot resolution changes. Only minor gaps remain around failure/timeout behavior, which is partly addressed by wait_ms in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds one genuinely non-schema nuance — that the boot changes what an unqualified call resolves to — but it does not describe the `state`, `wait_ms`, or `open_window` parameters, leaving the schema to carry that load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb pair and resource: 'Boot or shut down a simulator.' This is immediately distinguishable from siblings like ios_simulator_erase, ios_simulator_install, and ios_simulator_launch, which mutate content rather than power state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains when this tool is mandatory ('Booting is the one thing this server will not do for you implicitly'), which tells the agent it must call this before other tools can work on a fresh device. It does not explicitly name alternatives or state when-not-to-use beyond idempotency, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_press_buttoniOS Simulator: Press ButtonA

Press a hardware button. home is the way back to the home screen and the reliable way to background the app under test without terminating it.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesWhich button. `home` works on Face ID devices too — it is the gesture, not the physical button.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
settle_msNoMilliseconds to wait before the follow-up screenshot, so an animation finishes first. Raise it for a screen that loads data; a capture taken mid-transition shows neither state. This is a pause for an animation, not a wait for work to finish — which is why it stops at ten seconds. For anything longer, use ios_simulator_wait_for_element.
screenshotNoReturn a screenshot of the resulting screen. On by default, and worth leaving on: it is how you find out that the action landed where you meant it to. Turn it off only for a sequence whose intermediate states you do not need to see.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply readOnly/idempotent/destructive hints; the description adds the key behavioral consequence that home backgrounds the app without terminating it, and the schema notes that home is a gesture on Face ID devices. It does not contradict the annotations and gives useful behavioral context beyond the structured hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with the verb and resource front-loaded and the most useful guidance in the second sentence. There is no filler or repetition of what the schema already states.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich per-parameter descriptions, the annotations, and the simplicity of the action, an agent has enough to select and invoke the tool correctly. The lack of an output schema is mitigated by the screenshot parameter explicitly describing the returned screenshot behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; the tool description adds value by explaining what the `home` parameter accomplishes (returning home/backgrounding without termination). The remaining parameters are already richly described in the schema, including device-selection behavior and settle_ms semantics, so the overall parameter guidance is strong.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a concrete action ('Press a hardware button') and immediately explains the purpose of the only supported button: returning to the home screen and backgrounding the app without terminating it. This clearly differentiates it from terminate, launch, screenshot, and other simulator actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear when-to-use context: use home to go back to the home screen or to background the app safely without terminating it. The settle_ms parameter description further routes longer waits to ios_simulator_wait_for_element, but the prose does not enumerate exclusions for every sibling, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_pushiOS Simulator: PushA

Deliver a push notification, with no APNs certificate and no server. The payload is a normal remote-notification body and must contain an aps key. Only remote pushes are simulated — not VoIP, complications or file-provider. The app must be installed; it does not have to be running.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
payloadYesThe APNs payload, e.g. {"aps":{"alert":{"title":"Watering due","body":"Monstera"},"sound":"default","badge":1}}. Max 4096 bytes.
bundle_idYesThe app's bundle identifier, e.g. "io.mgcrea.Canopy". List them with ios_simulator_list_apps.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide readOnly/idempotent/destructive hints, so the description carries most of the burden. It discloses the simulated nature, the payload requirement to contain an 'aps' key, and the fact that the app need not be running. It stops short of describing the visible result or any permission behavior, but the core behavior is clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with no filler. Each clause adds a necessary constraint or limitation, and the most important scoping information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter action with a nested payload and no output schema, the description plus schema gives the agent everything needed to invoke it correctly: device selection behavior, payload format and size, bundle id pattern, and push-type restrictions. No critical selection or invocation information is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds semantic value beyond the schema: it requires the payload to be a 'normal remote-notification body' containing an 'aps' key. The schema already covers device selection rules, the payload example, byte limit, and bundle id pattern.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a specific verb and resource: 'Deliver a push notification' to the iOS simulator. It immediately distinguishes this tool from real APNs delivery by adding 'with no APNs certificate and no server,' and no sibling tool performs push, so there is no ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear context for use: simulator push testing without needing APNs infrastructure. It also states explicit exclusions ('not VoIP, complications or file-provider') and prerequisites ('The app must be installed; it does not have to be running'), though it does not name alternative tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_read_logsiOS Simulator: Read LogsA
Read-only

Read an app's log output: stdout, stderr and every Logger/os_log message the process emits, interleaved in one file. Only available for an app started with ios_simulator_launch capture_logs: true. Returns the newest limit lines plus a next cursor; pass it back to get only what arrived since, which is how to see what one tap logged. capturing turns false once the app's process has exited, and what it wrote stays readable. A crash's backtrace is not in here — see ios_simulator_list_crash_logs — but its fatalError message is.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMost lines to return; the newest are kept and the rest counted in `omitted`. Defaults to 200 — filter rather than raising this.
cursorNoThe `next` value from the previous read, to get only newer lines. Omit to read from the start of the capture.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
filterNoCase-insensitive regular expression a line must match, e.g. "error|fail" or "\[Sync\]". Applied before `limit`, so it finds matches across the whole range.
bundle_idNoWhich app's capture, e.g. "io.mgcrea.Canopy". Defaults to the most recent capture.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only assert readOnlyHint=true, but the description discloses the capture lifecycle ('capturing turns false once the app's process has exited, and what it wrote stays readable') and the crash-content boundary (backtrace excluded, fatalError included). This is substantial behavioral context beyond the safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core capability, then preconditions, then return contract, then boundaries. Every sentence carries distinct information — the crash-log routing and the capture-persistence note are not padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return contract itself: newest `limit` lines plus a `next` cursor. Combined with the precondition and the crash-log boundary, an agent has everything needed to call and interpret this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds integration semantics: the cursor is described in terms of the incremental workflow, filter is noted effectively in the 'see what one tap logged' framing, and the device-omission rule is reinforced. It stops short of restating every field, which is appropriate given the schema already covers them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read an app's log output') and enumerates exactly what is captured: stdout, stderr, and Logger/os_log messages interleaved. It also distinguishes itself from the sibling ios_simulator_list_crash_logs, so an agent can route correctly without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit precondition ('Only available for an app started with ios_simulator_launch capture_logs: true'), names the crash-log tool as the alternative for backtraces, and explains the incremental-read pattern ('pass it back to get only what arrived since'). When-to-use, when-not-to-use, and the alternative are all covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_restart_wdaiOS Simulator: Restart WebDriverAgentA

Start the WebDriverAgent runner, or restart it after it has died. Only the UI tree and the input tools need it — screenshots and everything simctl does keep working without it. The runner is started detached so it outlives this conversation, and its output goes to a log file rather than to you. It does not wait: give it fifteen seconds or so, then check ios_simulator_diagnostics.

ParametersJSON Schema
NameRequiredDescriptionDefault
portNoPort to bind, passed to the runner as USE_PORT. Defaults to IOS_SIMULATOR_WDA_PORT. Two simulators need two ports: they share this Mac's loopback, and a runner with no USE_PORT scans 8100-8199 and silently takes the next free one.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses key behavioral traits: the runner is started detached, it outlives the conversation, output goes to a log file, and it does not wait. This is exactly the kind of context an agent needs to use the tool correctly and verify success.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each earning its place: purpose, scope, runtime behavior, and verification step. The description is front-loaded with the core function and avoids fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a side-effecting tool with no output schema, the description covers what the tool does, when to use it, what side effects to expect, how long to wait, and where to check results. That is sufficient for an agent to invoke and verify it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool description itself does not add parameter-level meaning, but the input schema provides 100% coverage with detailed descriptions for both `port` and `device`. Baseline 3 is appropriate because the schema already carries the semantic weight.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource: 'Start the WebDriverAgent runner, or restart it after it has died.' It clearly differentiates from siblings by stating that only UI tree and input tools need it, while screenshots and simctl operations do not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when this tool is needed and when it is not: 'Only the UI tree and the input tools need it.' It also gives the follow-up action ('check ios_simulator_diagnostics') and a timing expectation, which is strong practical guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_screenshotiOS Simulator: ScreenshotA
Read-only

Capture the screen and return it as an image. By default it is scaled to exactly the device's point size, which means a position read off this image can be passed straight to ios_simulator_tap with no conversion — the returned metadata says coordinateSpace: "points" when that holds. Pair it with ios_simulator_ui_tree rather than choosing between them: the image shows you what the screen looks like, the tree gives you exact labels and identifiers. Re-screenshot after every action rather than chaining blind taps.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
qualityNoJPEG quality 1-100. Flat interface screenshots stay perfectly legible at 70.
save_pathNoAlso write the full-resolution PNG to this absolute path, for attaching to a bug report. The returned image is still the downscaled one.
max_dimensionNoLongest side of the returned image, in pixels. Leave it unset unless you have a reason: the default matches the device's point size, and any other value makes image positions stop being tap coordinates (the result then reports `coordinateSpace: "image_pixels"` and the `pointsPerPixel` factor to multiply by).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses the key behavioral traits: default scaling to device point size, the resulting coordinateSpace metadata ('points'), the shift to image_pixels when max_dimension is overridden, and the fact that save_path writes a full-resolution PNG while 'the returned image is still the downscaled one.' This is exactly the kind of non-obvious behavior an agent needs to interpret results correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each earning its place: core purpose, the critical coordinate-space behavior, sibling complementarity, and workflow rule. The most decision-relevant fact (tap-coordinate compatibility) is front-loaded in sentence two. No filler, no repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description conveys the return semantics that matter (image plus coordinateSpace metadata), and the schema handles the four optional parameters exhaustively. The readOnly annotation covers the safety profile. Nothing an agent needs to invoke this correctly — coordinate systems, sibling relationships, workflow cadence, parameter trade-offs — is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3 — and indeed the schema's per-parameter descriptions are rich on their own. The main description adds one genuinely additive semantic: the default scaling means 'a position read off this image can be passed straight to ios_simulator_tap with no conversion,' which gives the default parameter behavior a concrete cross-tool consequence not stated in the schema. This nudges it above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource — 'Capture the screen and return it as an image' — and immediately distinguishes itself from the closest sibling, ios_simulator_ui_tree: 'the image shows you what the screen looks like, the tree gives you exact labels and identifiers.' An agent can tell exactly what this tool does and how it differs from alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit pairing guidance: 'Pair it with ios_simulator_ui_tree rather than choosing between them,' complete with the reason for each tool's role. It also prescribes a workflow rule ('Re-screenshot after every action rather than chaining blind taps') and the device parameter description further advises when to omit it. This is actionable usage direction, not just a vague context hint.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_set_environmentiOS Simulator: Set EnvironmentA
Idempotent

Stage the simulator before a screenshot or a test: dark mode, Dynamic Type size, increased contrast, a frozen status bar, a simulated location, and app permissions. None of this is possible on a physical device, and it is most of the reason to prefer a simulator for UI work. Every field is optional; those given are applied in order and the result reports the state afterwards. A status bar override survives a reboot, so clear it when you are done or it quietly pollutes later screenshots.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
locationNoTeleport the device, for location-gated screens.
appearanceNoInterface style.
permissionNoSet an app permission directly. This is how you reach the denied branch of a permission check, which is otherwise a prompt nobody can tap.
status_barNoFreeze the status bar. Overrides persist until cleared.
content_sizeNoDynamic Type size. The accessibility- sizes are where layouts break.
clear_locationNoStop simulating a location.
clear_status_barNoDrop every status bar override, restoring the real one.
increase_contrastNoIncrease Contrast accessibility mode.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already marking the tool as non-read-only, idempotent, and non-destructive, the description adds important behavioral context beyond the annotations: fields are applied in order, the result reports the resulting state, and status bar overrides persist across reboots and can pollute later screenshots if not cleared. This is genuinely useful operational warning.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded. The first sentence states purpose and lists capabilities; the second justifies simulator preference; the third explains optionality and ordering; the fourth warns about persistence. Each sentence earns its place without redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 9-parameter tool with no output schema, the description covers the essential invocation semantics: optional fields, application order, state reporting, and the key persistence caveat. It doesn't detail what 'reports the state afterwards' includes, but given the strong schema coverage, this is complete enough for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds value by summarizing the parameter groups and by stating two cross-cutting facts not in the schema: every field is optional, and provided fields are applied in order. This helps an agent understand interactions between parameters like clear_location and location.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair: 'Stage the simulator before a screenshot or a test' and then enumerates the exact capabilities (dark mode, Dynamic Type, increased contrast, frozen status bar, simulated location, app permissions). This clearly distinguishes it from sibling tools like screenshot, tap, or launch, which do different jobs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: use this tool to prepare state before screenshots or tests. It also explains why simulator-only features matter for UI work. It does not explicitly name alternatives or exclusion conditions, but no sibling tool offers equivalent functionality, so the guidance is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_swipeiOS Simulator: SwipeA

Drag from one point to another, in points — how you scroll a list, pull to refresh, or swipe a row open. To scroll down a page, swipe from low on the screen to high on it. duration_ms is what separates a scroll from a fling: a short one throws the list past where you aimed.

ParametersJSON Schema
NameRequiredDescriptionDefault
to_xYesHorizontal position in points, from the left edge. This is the same space as the `tap` field from ios_simulator_ui_tree and as a default ios_simulator_screenshot image — no conversion.
to_yYesVertical position in points, from the top edge. Same space as ios_simulator_ui_tree `tap` and a default ios_simulator_screenshot image.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
from_xYesHorizontal position in points, from the left edge. This is the same space as the `tap` field from ios_simulator_ui_tree and as a default ios_simulator_screenshot image — no conversion.
from_yYesVertical position in points, from the top edge. Same space as ios_simulator_ui_tree `tap` and a default ios_simulator_screenshot image.
settle_msNoMilliseconds to wait before the follow-up screenshot, so an animation finishes first. Raise it for a screen that loads data; a capture taken mid-transition shows neither state. This is a pause for an animation, not a wait for work to finish — which is why it stops at ten seconds. For anything longer, use ios_simulator_wait_for_element.
screenshotNoReturn a screenshot of the resulting screen. On by default, and worth leaving on: it is how you find out that the action landed where you meant it to. Turn it off only for a sequence whose intermediate states you do not need to see.
duration_msNoHow long the drag takes. 400 is a controlled scroll; under 150 becomes a fling with momentum, which lands somewhere you did not choose.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the minimal annotations, the description discloses that duration_ms distinguishes a controlled scroll from a momentum fling, and that short drags 'throw the list past where you aimed.' This adds meaningful behavioral context. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the core action, the practical direction mapping, and the duration behavior. The most important conceptual guidance is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description, combined with the richly documented 100% schema coverage, gives an agent everything needed to invoke the tool correctly. No output schema exists, but returning a screenshot is handled by the screenshot parameter, which is already documented.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value by explaining the direction-to-screen relationship and the semantic difference between scroll and fling via duration_ms, which enriches the raw parameter meanings.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a concrete action and object: 'Drag from one point to another, in points.' It then names real user goals — scroll a list, pull to refresh, swipe a row open — which clearly separates it from sibling tap and type tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit guidance for when to use the gesture, including how to scroll down and what duration produces a fling. It does not explicitly name alternatives or state when not to use it, but the use cases are clear enough for an agent to select it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_tapiOS Simulator: TapA

Tap a position on screen, in points. Prefer ios_simulator_tap_element when the target has a label or an accessibility identifier — a position stops being right the moment the layout shifts, and nothing about a wrong tap looks wrong. Coordinates come from a default ios_simulator_screenshot image or from a tap field in ios_simulator_ui_tree, which are the same space.

ParametersJSON Schema
NameRequiredDescriptionDefault
xYesHorizontal position in points, from the left edge. This is the same space as the `tap` field from ios_simulator_ui_tree and as a default ios_simulator_screenshot image — no conversion.
yYesVertical position in points, from the top edge. Same space as ios_simulator_ui_tree `tap` and a default ios_simulator_screenshot image.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
hold_msNoHow long to hold the touch, in milliseconds. Around 700 makes it a long press, which is what opens context menus and edit affordances.
settle_msNoMilliseconds to wait before the follow-up screenshot, so an animation finishes first. Raise it for a screen that loads data; a capture taken mid-transition shows neither state. This is a pause for an animation, not a wait for work to finish — which is why it stops at ten seconds. For anything longer, use ios_simulator_wait_for_element.
screenshotNoReturn a screenshot of the resulting screen. On by default, and worth leaving on: it is how you find out that the action landed where you meant it to. Turn it off only for a sequence whose intermediate states you do not need to see.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry readOnly/destructive/idempotent hints, all false, so they don't reveal failure modes. The description adds meaningful behavioral context: coordinate taps silently break after layout changes and 'nothing about a wrong tap looks wrong.' This is the kind of behavioral warning that helps an agent decide between coordinate and element taps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences each carry distinct value: what the tool does, when not to use it, and how coordinates are sourced. The warning is front-loaded right after the purpose, before any lower-priority detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description plus fully documented input schema give an agent everything needed to select and invoke the tool correctly: purpose, coordinate space, failure mode, and parameter semantics. It stops short of explicitly describing the return value beyond the screenshot parameter, but the schema already covers that detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers 100% of parameters with detailed descriptions, including units, defaults, and distinctions like 'pause for animation, not wait for work.' The description reinforces the coordinate-space relationship, but does not need to compensate for schema gaps because none exist.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and object — 'Tap a position on screen, in points' — and immediately differentiates itself from ios_simulator_tap_element by naming the condition under which the element-based sibling should be preferred. The coordinate-source sentence also anchors exactly what the tool acts on.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing guidance: prefer ios_simulator_tap_element when the target has a label or accessibility identifier, with a concrete reason (layout shifts make coordinates stale). It also tells the agent where coordinates come from — default screenshot or ui_tree tap field — closing the main usage ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_tap_elementiOS Simulator: Tap ElementA

Tap the element with this accessibility identifier or label, letting the device resolve its position. This is the tool to reach for: it survives the screen scrolling, the layout changing and the copy being reworded, none of which a coordinate does. Give exactly one of id, label or predicate; identifiers from ios_simulator_ui_tree.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAccessibility identifier — the `id` field from ios_simulator_ui_tree, e.g. "garden.tab". The most durable way to address an element, because it is set in code and does not change when the visible text does.
indexNoWhich match to tap when several match, zero-based, counted in the order ios_simulator_ui_tree lists them. Giving it turns off the control preference `label` normally applies, because it means you have read the tree and are counting real positions in it. Leave it off unless that is what you are doing.
labelNoExact accessibility label, i.e. the visible text — e.g. "Today". Matched exactly, and it changes with the app's language, so prefer `id` where one exists. A label is shared by a control and every container around it, so this matches controls first and falls back to the rest only when no control carries it.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
predicateNoEscape hatch: a raw NSPredicate over element attributes, e.g. `type == "XCUIElementTypeButton" AND label BEGINSWITH "Add"`.
settle_msNoMilliseconds to wait before the follow-up screenshot, so an animation finishes first. Raise it for a screen that loads data; a capture taken mid-transition shows neither state. This is a pause for an animation, not a wait for work to finish — which is why it stops at ten seconds. For anything longer, use ios_simulator_wait_for_element.
screenshotNoReturn a screenshot of the resulting screen. On by default, and worth leaving on: it is how you find out that the action landed where you meant it to. Turn it off only for a sequence whose intermediate states you do not need to see.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

It discloses useful behavioral traits beyond annotations: the device resolves the element's position, and the approach is robust to scrolling, layout changes, and reworded copy. Annotations only cover read-only/idempotent/destructive hints, so this extra context genuinely helps an agent predict behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no filler: the core action comes first, followed by the rationale and the essential param rule. The 'identifiers from ios_simulator_ui_tree' note is compact and useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter action tool with no output schema, the description covers the main decisions an agent must make: which selector to use, where identifiers come from, and how this differs from coordinates. The screenshot parameter description already clarifies the output expectation, though the description itself could have mentioned what happens on no-match or multiple-match cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents all 7 parameters thoroughly, so this dimension starts near baseline. The description adds a key semantic constraint not enforced by the schema: exactly one of id, label, or predicate must be provided, and it points to ios_simulator_ui_tree as the source of identifiers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and object: tap an element by accessibility identifier or label. It also contrasts itself with coordinate-based interaction, signaling clearly that this is the element-aware counterpart to ios_simulator_tap.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly frames this as 'the tool to reach for' when the element may move or the text may change, and explains why it beats coordinate-based taps. It does not name ios_simulator_tap or list exclusions, but the usage context is clear and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_terminateiOS Simulator: TerminateA
Idempotent

Kill a running app. The app is not uninstalled and its data is untouched — this is how you get back to a cold start without erasing anything.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
bundle_idYesThe app's bundle identifier, e.g. "io.mgcrea.Canopy". List them with ios_simulator_list_apps.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide idempotentHint=true and destructiveHint=false, and the description adds meaningful context: the app is not uninstalled, its data remains intact, and the result is a cold start. This goes beyond the structured hints without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence with no filler. It front-loads the core action, then immediately states the key behavioral nuance (no uninstall, data untouched) and the practical purpose (cold start).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter kill operation, the description plus schema and annotations cover what an agent needs: required bundle_id, optional device selection guidance, non-destructive behavior, idempotency, and the use case. No out-of-schema return format is necessary for a command like this.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents both parameters fully, so the baseline is 3. The description adds value for the optional device parameter by explaining when to omit it, how IOS_SIMULATOR_ID applies, and that it avoids simctl's arbitrary selection behavior, which helps an agent pick the right value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Kill a running app') and a clear resource, and goes beyond a simple restatement of the title by explaining what it does not do: it does not uninstall the app and does not touch its data. This distinguishes it from destroy/erase-style operations, and 'back to a cold start without erasing anything' sharpens the intended effect.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear context for use: when you want a cold start without erasing app data. It implicitly contrasts with uninstall/erase operations, though it does not explicitly name an alternative sibling tool or say when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_typeiOS Simulator: TypeA

Type text into whatever currently has keyboard focus, or into a named field. Focus is the trap: with nothing focused the keystrokes go nowhere and the call still succeeds, so pass id or label to have the field tapped first unless you know a field is already active.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAccessibility identifier of the field to focus first — from ios_simulator_ui_tree.
textYesThe text to type. Sent character by character, as a real keyboard would.
labelNoExact label of the field to focus first, if it has no identifier.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
settle_msNoMilliseconds to wait before the follow-up screenshot, so an animation finishes first. Raise it for a screen that loads data; a capture taken mid-transition shows neither state. This is a pause for an animation, not a wait for work to finish — which is why it stops at ten seconds. For anything longer, use ios_simulator_wait_for_element.
screenshotNoReturn a screenshot of the resulting screen. On by default, and worth leaving on: it is how you find out that the action landed where you meant it to. Turn it off only for a sequence whose intermediate states you do not need to see.
clear_firstNoReplace the field's contents instead of appending. Only possible when `id` or `label` names the field — there is no way to clear a field addressed only by focus.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses the important silent-success trap: with no focus, keystrokes go nowhere but the call still succeeds. It also explains that id/label trigger a pre-tap. It does not cover what happens if the named field is not found, but the core behavioral risk is clearly exposed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The main description is two tight sentences with the most important caveat (focus trap) front-loaded. Every sentence carries load, and the parameter descriptions handle the remaining detail without bloating the main description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The schema covers all seven parameters, including device selection, screenshot behavior, settle semantics, and clear_first constraints, so an agent has most of what it needs. Missing top-level detail about return shape and invalid-identifier behavior is a minor gap given no output schema, but the overall definition is still quite complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaningful cross-parameter semantics by explaining that id/label are how the caller ensures focus, and it ties clear_first to the presence of id/label. This goes beyond the simple field-level descriptions in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: typing text into the current keyboard focus or a named field. It also explains the two ways to target input, which distinguishes it from the tap-oriented siblings and makes the tool's job immediately clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit usage rule: pass id or label to tap the field first unless a field is already active, and warns against relying on focus when nothing is focused. It does not name alternative sibling tools in the main description, though the settle_ms parameter does direct longer waits to ios_simulator_wait_for_element.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_ui_treeiOS Simulator: UI TreeA
Read-only

List the addressable elements on screen — type, label, accessibility identifier, and the exact point to tap — flattened rather than nested. Prefer this over reading coordinates off a screenshot whenever you can: a label or identifier survives the screen moving, and a pixel position does not. The raw hierarchy is tens of KB, so this returns controls only by default; use contains or types to narrow further and detail to widen. A short answer is not proof the screen is bare — check the filtered field, which counts what the filters left out and names the argument that brings it back. Coordinates are in points, the same space ios_simulator_tap takes.

ParametersJSON Schema
NameRequiredDescriptionDefault
typesNoKeep only these element types, without the `XCUIElementType` prefix, e.g. ["Button", "Cell"].
detailNoHow much of the hierarchy to return. `interactive` (default) is controls only — buttons, cells, fields, switches — and is what you want to decide where to tap. `labelled` adds text and images that carry a label, for reading the screen's content. `all` is every visible node and is usually far too large to be useful.interactive
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
containsNoKeep only elements whose label, identifier or value contains this, case-insensitively — e.g. "Today".
include_invisibleNoInclude elements XCUITest marks as not visible. Off by default, because on a scrolling list they outnumber the visible ones many times over — but the flag is not always truthful: a photo picker and a share sheet report their own contents as invisible while they are on screen and respond to a tap. Turn this on when `filtered.notVisible` says something was left out and the screen plainly has more on it than came back.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description reveals important behavioral traits: results are flattened, the raw hierarchy is tens of KB, defaults return only controls, the `filtered` field counts omissions, and coordinates are in the same point space as ios_simulator_tap. It also warns that `include_invisible` is not always truthful, which is valuable non-obvious behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: purpose, comparison to screenshots, default behavior, filtering guidance, and coordinate-space note are all packed into a compact, front-loaded description with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description explains what elements contain, how filtering affects results, what the `filtered` field means, and how coordinates relate to tapping. For a read-only inspection tool with this parameter richness, the description gives an agent enough context to invoke it correctly and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds practical parameter semantics by explaining how to narrow (`contains`, `types`) and widen (`detail`), and by tying the coordinate output to ios_simulator_tap's input space. This goes beyond merely restating the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List the addressable elements on screen — type, label, accessibility identifier, and the exact point to tap — flattened rather than nested.' It clearly differentiates the tool from screenshot-based inspection by explicitly saying to prefer this over reading coordinates off a screenshot.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance: 'Prefer this over reading coordinates off a screenshot whenever you can: a label or identifier survives the screen moving, and a pixel position does not.' It also advises how to narrow or widen results with `contains`, `types`, and `detail`, and warns to check `filtered` before concluding the screen is empty.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_uninstalliOS Simulator: UninstallA
DestructiveIdempotent

Remove an app from the simulator, with its data container — documents, databases and preferences all go, and nothing brings them back. To get back to a cold start while keeping the data, use ios_simulator_terminate. To test a genuine first launch of one app, this is narrower than ios_simulator_erase, which wipes every app on the simulator. Uninstalling an app that is not installed also succeeds, so success does not prove it was there.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
confirmYesMust be true. Explicit acknowledgement that the app's data is deleted.
bundle_idYesThe app's bundle identifier, e.g. "io.mgcrea.Canopy". List them with ios_simulator_list_apps.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and idempotentHint=true, but the description adds substantive context beyond them: what exactly is destroyed (documents, databases, preferences, 'nothing brings them back'), and the non-obvious behavioral quirk that uninstalling a missing app still succeeds, so success is not proof of prior presence. That last detail is a real edge case an agent could otherwise misinterpret.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: destruction scope, cold-start alternative, narrower vs erase, and the success-flag caveat. Front-loaded with the destructive consequence rather than burying it behind pleasantries.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool with no output schema, the description supplies the critical missing semantics: what is destroyed, alternatives for different intents, and the false-success edge case. Annotations cover the safety flag, schema covers parameters, and the description covers behavior and routing — nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all three parameters thoroughly (device omitting behavior, confirm must be true, bundle_id pattern and examples). The description adds no parameter syntax beyond the schema. Baseline 3 is correct when the schema fully carries parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (remove an app from the simulator) and immediately differentiates scope ('with its data container', narrower than erase). It explicitly names sibling tools (terminate, erase) with their distinguishing scope, so an agent can route correctly without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly provides when-to-use and when-not: 'to get back to a cold start while keeping the data, use ios_simulator_terminate' and 'to test a genuine first launch of one app, this is narrower than ios_simulator_erase, which wipes every app'. This is direct routing to alternatives with conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ios_simulator_wait_for_elementiOS Simulator: Wait For ElementA
Read-only

Poll until an element appears, or until it goes away. This is the tool for a screen that loads: a generation step, a network round trip, a long import. settle_ms on the action tools is a pause for an animation and caps at ten seconds — it is not a wait, and using it as one is how you end up verifying a server instead of the screen. Give exactly one of id, label or predicate, the same way ios_simulator_tap_element takes them. Your MCP client may have a request timeout of its own, commonly 60 seconds, and it will cut this call off before timeout_ms does — for a longer wait, raise it there too or call this twice.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAccessibility identifier — the `id` field from ios_simulator_ui_tree.
labelNoExact accessibility label, i.e. the visible text. Matched against controls first, as in ios_simulator_tap_element.
absentNoWait for the element to *stop* matching instead of to start. This is how you wait out a spinner, a progress view or a placeholder, which is the same wait from the other side.
deviceNoWhich simulator: its UDID or its name as shown by ios_simulator_list. Omit it when exactly one is booted — that is the normal case, and IOS_SIMULATOR_ID pins it when it is not. Unlike simctl's own `booted`, this never picks arbitrarily between two.
poll_msNoHow long to wait between polls. Each poll is one query to the device, so a long wait costs less at 2000 than at 250 and arrives at almost the same moment.
predicateNoA raw NSPredicate, e.g. `type == "XCUIElementTypeButton" AND label BEGINSWITH "Add"`.
screenshotNoReturn a screenshot of the resulting screen. On by default, and worth leaving on: it is how you find out that the action landed where you meant it to. Turn it off only for a sequence whose intermediate states you do not need to see.
timeout_msNoHow long to keep polling before giving up. Read the note about your client's own request timeout in this tool's description before setting it above 60000.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint=true already covers the safety profile, and the description earns substantial credit beyond it: the warning that an MCP client's own request timeout "will cut this call off before timeout_ms does," the polling semantics, and the "give exactly one of" constraint. No contradiction with the annotation — polling and observing are inherently non-destructive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with purpose front-loaded in the first clause, and every sentence earns its place: the settle_ms exclusion prevents a common misuse and the client-timeout note is a necessary caveat. It is dense, with the timeout caveat arguably better placed after the parameter rule, but there is no waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter polling tool with no output schema, the description covers purpose, use cases, exclusions, parameter exclusivity, and an external failure mode. The remaining gap is the return contract — nothing states what a timeout or successful wait returns beyond the optional screenshot — but this is minor and largely inferable from the polling semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and every parameter carries a rich description, so the baseline is 3. The description adds a genuinely non-derivable constraint — "Give exactly one of id, label or predicate" — and points to ios_simulator_tap_element as the convention reference, which raises it above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource in the opening clause — "Poll until an element appears, or until it goes away" — covering both wait directions immediately. It positions itself as "the tool for a screen that loads" and explicitly contrasts with the settle_ms pause on action tools, so an agent can tell it apart from the tap/action siblings without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use context ("a generation step, a network round trip, a long import") alongside an explicit when-not-to: settle_ms "caps at ten seconds — it is not a wait, and using it as one is how you end up verifying a server instead of the screen." It names the alternative pattern it is not, which is the strongest possible routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.3.1
    • Addedios_simulator_get_crash_log
    • Changedios_simulator_launch1 field changed
      • addedInput schema / properties / capture_logs
        Added value: +{
        +  "default": false,
        +  "description": "Write stdout, stderr and every Logger/os_log message to one fresh file, for ios_simulator_read_logs. Sets OS_ACTIVITY_DT_MODE=YES in the app's environment, which is what Xcode sets to mirror unified logging onto stderr; without it an app's Logger output reaches no file at all.",
        +  "type": "boolean"
        +}
    • Addedios_simulator_list_crash_logs
    • Addedios_simulator_read_logs
    • Addedios_simulator_uninstall
  2. 1 tool updatev0.2.2
    • Changedios_simulator_power1 field changed
      • changedInput schema / properties / open_window / description
        Previous value: -"Bring up the Simulator app so the screen is visible. A `boot` on its own is headless, which is fine for an agent and confusing for a person watching."New value: +"Bring up a window on the device — Simulator.app, or DeviceHub on Xcode 27 — so the screen is visible. A `boot` on its own is headless, which is fine for an agent and confusing for a person watching."
  3. 21 tool updatesv0.2.0
    • First observedios_simulator_add_media
    • First observedios_simulator_diagnostics
    • First observedios_simulator_erase
    • First observedios_simulator_install
    • First observedios_simulator_launch
    • First observedios_simulator_list
    • First observedios_simulator_list_apps
    • First observedios_simulator_open_url
    • First observedios_simulator_power
    • First observedios_simulator_press_button
    • First observedios_simulator_push
    • First observedios_simulator_restart_wda
    • First observedios_simulator_screenshot
    • First observedios_simulator_set_environment
    • First observedios_simulator_swipe
    • First observedios_simulator_tap
    • First observedios_simulator_tap_element
    • First observedios_simulator_terminate
    • First observedios_simulator_type
    • First observedios_simulator_ui_tree
    • First observedios_simulator_wait_for_element

TDQS

A4.3/5.0

Scored across 25 tools

Disambiguation5/5

Each tool targets a clearly distinct action, and the descriptions explicitly steer between look-alikes: tap vs tap_element, terminate vs uninstall vs erase, and the three log/crash tools are all distinguished with concrete guidance. Overlaps that could confuse (screenshot vs ui_tree) are addressed directly by telling the agent to pair them rather than choose.

Naming Consistency5/5

Every tool uses the same ios_simulator_ snake_case prefix with a predictable verb_noun or verb structure (list_apps, launch, terminate, press_button, open_url). No mixed casing or divergent verb styles; the pattern is uniform across all 25 tools.

Tool Count4/5

At 25 tools it sits at the heavy end, but the domain genuinely spans device lifecycle, app lifecycle, UI interaction, log reading, media, push, and WDA management, so the count is earned rather than padded. Each tool maps to a real capability with no redundancy.

Completeness4/5

Coverage is broad and lifecycle-complete for simulators, apps, UI input, logs, media, and push. Minor gaps remain around input gestures (no long-press, pinch, or rotation/orientation control), which agents can partially work around but would notice.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers