Skip to content

MCP tools and resources

Annotations tell a client what a tool does before calling it: read-only tools can be run freely, destructive ones may do something irreversible and are additionally guarded by the policy gate.

Every action tool accepts idem_key, which makes a repeat return the original result instead of touching the device again. Use it when retrying something you are unsure completed.

Tool Notes
ios_doctor Toolchain, tunnel and signing checks, each with a remedy. Run this first when anything misbehaves.
ios_list_devices Simulators and attached iPhones. ready: false comes with blockers.
ios_open_session Boots or verifies the device, starts WebDriverAgent, returns the first screen. Prefers a simulator when no device is named.
ios_session_status Device, foreground app, halted state, audit summary.
ios_close_session Releases the device and shuts down its runner.
Tool Notes
ios_list_apps Bundle identifiers, filterable by user/system/all.
ios_launch_app fresh=true restarts rather than resuming.
ios_terminate_app Force-quit.
ios_open_url Deep links. Usually the cheapest way to reach a screen. Settings is the exception: from iOS 26 App-prefs:root opens it, but a pane such as App-prefs:root=WIFI is ignored, and the result says so in its note.
ios_install_app From a local .app or .ipa.
Tool Notes
ios_observe The digest. query and region narrow it; prefer those over raising budget when truncated. include_elements adds structured JSON at roughly double the cost.
ios_screenshot annotate_refs=true boxes and labels every element with its ref, for UI with no accessibility data or whose visible text is not its label. It re-reads the screen first, so the refs on the image are current ones rather than the last observation’s, and it needs the vision extra (uv sync --extra vision).
ios_read_text Text of the screen or one element. Use this to extract content; ios_observe is shaped for deciding what to tap.
ios_find Searches the accessibility tree before compaction, so it reports matches the digest dropped. Each is shown (nameable the ordinary way) or hidden (on screen, not in the digest: name it by its id). Returns no refs by design.
ios_wait_for Waits for text to appear or disappear. Reports failure as data rather than raising.
ios_get_logs Device logs, when the UI does not explain a failure.
ios_export_trace Everything this session did.
Tool Notes
ios_tap ref preferred over target. Supports double and long_press_s.
ios_type Focuses the field first when given a ref or target, then reads it back: text that did not land returns ok: false with typed.shown. Never put a real credential here.
ios_type_secret Takes a keychain reference, not a value. See SAFETY.md.
ios_set_value Switches, sliders, steppers, pickers. Prefer this over tapping a switch: it checks current state, so asking for on when already on does nothing rather than turning it off.
ios_scroll until stops as soon as the text appears, and gives up when the content stops moving.
ios_swipe One swipe, for carousels and swipe-to-reveal.
ios_drag Between two refs, for reordering.
ios_press_button Hardware (home, volumeUp, siri) and keyboard (enter, tab, delete, dismiss_keyboard).
ios_handle_alert Read the alert text before choosing. Checks the alert actually went: if the press is ignored it taps the button in the tree, and if the alert still stands the result is ok: false.
ios_halt / ios_resume Stop and restart a session deliberately.
Tool Notes
ios_set_permission Simulator only.
ios_clipboard get or set. Writing beats typing long strings, which autocorrect can mangle.
ios_set_device_state Orientation anywhere; appearance, location and status-bar freeze are Simulator only.

ios://devices, ios://session, ios://session/screen, ios://session/screenshot, ios://capabilities. Resources are pulled rather than pushed into context, so ios://session/screen includes the structured element list that ios_observe omits.

ios://capabilities reports which tools work on the attached device, so an agent can check rather than discover it by failing.

ios_operator teaches the observe/act/verify loop, ref usage, when to fall back to a screenshot, and the safety rules.

Failures arrive as JSON with a machine-readable code, a hint, and often details naming candidates:

{
"error": "element_not_found",
"message": "Nothing on screen matches 'Snd'",
"hint": "Check the closest candidates below...",
"details": { "closest": ["e7: button 'Send'", "e2: button 'Save'"] }
}

Common codes: element_not_found, element_ambiguous, element_stale, element_not_interactable, action_requires_approval, app_not_allowed, session_halted, device_not_ready, tunnel_down, runner_crashed.

Two codes arrive without an error, because the screen the action left is the useful part. text_mismatch is recorded when typed text read back as something else; the result has ok: false and a typed entry saying what the field holds. alert_not_handled is recorded when an alert is still showing after it was pressed; the result has ok: false and the alert.