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, 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.

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 is irreversible — it is the only tool behind an explicit confirm.

  • IOS_SIMULATOR_ALLOW_WRITES=0 restores the device server's posture in one variable, and then the fourteen 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 fourteen of the nineteen tools work with no runner at all — only ios_simulator_ui_tree 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 fourteen 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_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-one. Six are read-only; the other fifteen disappear with IOS_SIMULATOR_ALLOW_WRITES=0.

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_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 — the only irreversible tool

ios_simulator_install

Install a simulator .app

ios_simulator_launch

Launch, with fixture arguments and captured output

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); uninstall (install overwrites, and erase covers first-run properly); 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.

Traps worth knowing

All measured on Xcode 26.6 (17F113).

  • 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.

  • 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 Simulator.app by default.

  • 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

21 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. The only irreversible tool here, and the reason it is the only one behind confirm. Use it to test a genuine first launch. 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.5/5.0
Behavior5/5

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

Beyond the destructiveHint annotation, the description discloses what state is destroyed, that the operation is irreversible, and that a booted simulator is automatically shut down and rebooted because simctl refuses to erase a running device. This is valuable behavioral context the annotations alone do not 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?

Four short sentences with no filler: what is wiped, why it is gated, when to use it, and how booted state is handled. Information is front-loaded and 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 destructive, confirmed erase operation with no meaningful output schema, the description covers the full behavioral contract: scope of destruction, irreversibility, confirmation requirement, intended use, and side effects on boot state. Nothing essential is missing for an agent to invoke 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?

Schema coverage is 100%, and the schema itself already documents both parameters thoroughly: device explains UDID/name behavior and IOS_SIMULATOR_ID pinning, while confirm explains the acknowledgement requirement. The tool description adds only the fact that confirm is the reason this tool is gated, so it does not need to compensate for missing 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?

The description names a specific verb and resource ('Wipe a simulator') and lists exactly what gets reset: installed apps, their data, keychain, and granted permissions. It distinguishes itself from siblings by calling itself 'the only irreversible tool here', so an agent can tell it apart from install, terminate, and power-related 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 explicitly says to use the tool 'to test a genuine first launch', which gives a clear positive use case. It also signals caution by noting irreversibility and the confirm requirement, though it does not explicitly name alternative tools or list when-not-to-use conditions.

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.

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.
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

A4.2/5.0
Behavior4/5

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

Annotations are all false, so the description carries the behavioral burden. It adds useful detail: stdout and stderr are captured to files under the output directory, and a launch that crashes leaves readable artifacts. It also explains the IOS_SIMULATOR_LAUNCH_ARGS default behavior 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?

The description is two sentences with no filler. The primary purpose is front-loaded, and the second sentence packs meaningful behavioral detail about output capture and crash diagnostics.

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 4-parameter tool with full schema coverage and no output schema, the description provides enough behavioral and parameter context to invoke the tool correctly. It could mention return behavior or explicit sibling alternatives, but those are minor gaps.

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 framing `arguments` as a fixture/demo-mode hook and explaining the relationship with IOS_SIMULATOR_LAUNCH_ARGS. This goes beyond simply restating the schema's parameter descriptions.

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 uses a specific verb and resource: 'Launch an installed app.' The qualifier 'installed' distinguishes it from install/list workflows, and the title/name are expanded with actual scope. An agent can tell this is the launch tool rather than install, terminate, or open_url.

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?

It gives clear context about launching installed apps and using arguments for fixture/demo mode, but it never explicitly says when to prefer this tool over siblings. The guidance is mostly implied rather than stated with alternatives.

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_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 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.

TDQS

A4.3/5.0
Behavior5/5

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

Beyond the annotations (idempotentHint=true), the description discloses operational details: a cold boot takes tens of seconds, puts a window on the user's screen, and changes which simulator an unqualified call resolves to afterwards. It also states that both boot and shutdown are idempotent, adding behavioral nuance not present in the annotations. This gives the agent a realistic expectation of side effects.

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 three sentences, each with a distinct purpose: stating the action, explaining the critical boot implications, and clarifying idempotency. It is front-loaded with the primary function. Slightly verbose due to the compound second sentence, but every sentence earns its place.

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 four-parameter tool with no output schema, the description covers the key operational aspects: boot/shutdown, idempotency, waiting behavior via `wait_ms`, the headless default, and the unqualified-call resolution shift. It could explicitly describe shutdown side effects, but the idempotency statement covers both directions. The absence of an output schema is mitigated by the description's behavioral clarity.

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 100% coverage with descriptions for all four parameters, including the meaning of `booted` waiting and the `booted` selection rule. The description adds context about idempotency and the resolution change, which enriches the `device` parameter's meaning, but this is marginal on top of thorough schema documentation. Baseline 3 applies.

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: 'Boot or shut down a simulator.' This clearly defines the tool's purpose and distinguishes it from sibling tools like ios_simulator_list, ios_simulator_launch, or ios_simulator_diagnostics, which serve different functions. The additional context about implicit booting further clarifies its unique role.

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 notes that 'Booting is the one thing this server will not do for you implicitly,' telling the agent when an explicit boot call is necessary. It also explains the consequences of booting (tens of seconds, window on screen, changing unqualified call resolution), which guides whether to use this tool proactively. It does not name sibling alternatives explicitly, but the usage context is clear.

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_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_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. Dates show when Glama detected each change.

  1. 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
Disambiguation5/5

Each tool targets a distinct resource or action: simulator state management, app inspection, UI querying, and input injection are cleanly separated. Potentially confusing pairs like tap vs tap_element and list vs list_apps are explicitly disambiguated by coordinate-based vs element-based and simulator-level vs app-level distinctions.

Naming Consistency4/5

All tools share the ios_simulator_ prefix and use lowercase snake_case, with most names following an imperative verb style. A few noun-like names (diagnostics, screenshot, ui_tree, power) deviate slightly from a strict verb_pattern but remain readable and predictable.

Tool Count4/5

21 tools is slightly above the ideal 3-15 range, but each tool covers a distinct, justifiable operation across simulator lifecycle, app contrl, UI automation, and state staging. The count feels broad rather than bloated.

Completeness4/5

The tool surface covers the main lifecycle: list/boot/install/launch/terminate/erase, plus UI interrogation and interaction, environment staging, media ingestion, and push notifications. Minor gaps like a single-app uninstall or hardware rotation/shake actions exist, but core simulation and UI-testing workflows are well supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mgcrea/mcp-ios-simulator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server