# ios-agent [Health: Active]

**Category:** 🖥️ OS Automation  
**Repository:** https://github.com/emazaheri/ios-agent  
**GitHub Stars:** 3  
**Views:** 1  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/ios-agent

## Description
Drive a real iPhone or an iOS Simulator with an AI agent, through XCUIAutomation.

## Tools
Capabilities this server exposes over MCP:

- **ios_doctor** — Check that this machine can drive an iOS device, and say how to fix what it can't.

Run this first when a session fails to start, when a device does not
appear, or after an Xcode or iOS upgrade. Every failing check comes with
a concrete remedy.
- **ios_list_devices** — List iOS Simulators and attached physical iPhones available for automation.

`ready` is false when something blocks automation; `blockers` says what.
- **ios_open_session** — Attach to a device and start driving it.

Boots the simulator or verifies the phone, starts WebDriverAgent, and
opens a tuned session. Omitting `device` prefers an already-booted
simulator over a connected iPhone, so acting on a real device is always
a deliberate choice.
- **ios_session_status** — Report the current session: device, foreground app, and safety state.
- **ios_close_session** — Release the device and shut down its WebDriverAgent runner.
- **ios_list_apps** — List apps installed on the device, with their bundle identifiers.
- **ios_launch_app** — Bring an app to the foreground and return its screen.
- **ios_terminate_app** — Force-quit an app.
- **ios_open_url** — Open a URL or deep link.

Usually the cheapest way to reach a screen: a deep link skips the
navigation an agent would otherwise have to tap through.
- **ios_install_app** — Install an app from a local .app or .ipa.
- **ios_observe** — Read the screen as a compact list of elements with short refs.

Each line is one element: `e7  button "Send" @(340,70)`. Pass those refs
to the action tools rather than coordinates.

If the result says elements were omitted, narrow with `query` or
`region` instead of raising `budget`; a smaller answer is usually the
more useful one.
- **ios_screenshot** — Capture the screen as an image.

Use this when an element has no accessibility label, when the layout
matters, or when `ios_observe` cannot find something you can plainly
see. With `annotate_refs` each element is boxed and labelled with its
ref, so you can pick one by eye and pass it to an action tool.

Annotating re-reads the screen first, so the refs on the image are the
current ones rather than whatever was observed last. That costs a tree
fetch, and needs the `vision` extra installed.
- **ios_read_text** — Read the text of the screen, or of one element and everything inside it.

Use this to extract content, rather than `ios_observe`, which is shaped
for deciding what to tap.
- **ios_find** — Search the screen's accessibility tree, including what the digest hides.

Prefer `ios_observe` with a `query` when you want a usable digest you
can tap from: what it returns carries refs. Use this when `ios_observe`
shows nothing matching but the text is on the device, or when a tap
keeps missing. It reads the tree before compaction, so it reports
matches the digest dropped, which `ios_observe` by construction cannot,
and each one says whether it is `shown` or `hidden`. A hidden match is
the diagnosis: the words are on screen and perception is why you cannot
reach them. Name it by the `id` reported here.
- **ios_wait_for** — Wait for something to appear or disappear.

Prefer this over guessing a sleep. It returns as soon as the condition
holds, and reports failure rather than raising, so a timeout is
something you can reason about.
- **ios_get_logs** — Read recent device logs. Useful when an app misbehaves and the UI does not say why.
- **ios_export_trace** — Return the ordered record of everything this session has done.

Useful for explaining what happened, and for turning a successful run
into a regression test.
- **ios_tap** — Tap an element and return the resulting screen.

Prefer `ref` over `target`; it is exact and cannot be misread. Taps on
things like Send, Pay, or Delete need approval first.
- **ios_type** — Type into a field, focusing it first when a ref or target is given.

The field is read back afterwards. If the text did not land, the call
fails with `typed.shown` saying what the field holds; `reformatted`
means it landed with the app's own capitalisation or formatting.
- **ios_type_secret** — Type a stored secret without ever seeing its value.

The value is read from the host keychain and sent straight to the
device. Use this for every password and one-time code; never put a
real credential into `ios_type`, where it would enter the transcript.
- **ios_set_value** — Set a switch, slider, or picker wheel to a value.

'on' or 'off' for a switch, a percentage such as '40%' or a fraction
for a slider, and the option spelled the way the wheel spells it for a
picker. A wheel is turned a row at a time and read back after each
one, so an option it does not contain fails listing what it does.

Prefer this over tapping a switch: it checks the current state first,
so asking for 'on' when it is already on does nothing rather than
turning it off.

Steppers and segmented controls are not set this way. iOS reports
their parts and the digest shows them, so tap 'Increment',
'Decrement', or the segment by its own label.
- **ios_scroll** — Scroll, optionally until some text comes into view.

With `until`, this stops as soon as the text appears and gives up when
the content stops moving, so it will not spin at the end of a list.
- **ios_swipe** — Swipe once, for carousels, page views, and swipe-to-reveal rows.
- **ios_drag** — Drag one element onto another, for reordering lists and moving items.
- **ios_press_button** — Press a hardware button or a keyboard key.
- **ios_handle_alert** — Answer a system alert.

Read the alert text before choosing. Accepting blindly is how an agent
grants a permission or confirms a deletion nobody wanted.
- **ios_halt** — Stop this session from taking further action.
- **ios_resume** — Clear a halt after a human has decided it is safe to continue.
- **ios_set_permission** — Set a privacy permission without going through the alert.

Simulator only. On a real phone there is no API for this: drive the
Settings app, or answer the permission alert with ios_handle_alert.
- **ios_clipboard** — Read or write the device clipboard.

Writing is often faster and more reliable than typing a long string,
which the on-screen keyboard can mangle with autocorrect.
- **ios_set_device_state** — Change device-level state. Appearance, location, and status bar are Simulator only.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `uvx` (confidence: high):

```json
"mcpServers": {
  "ios-agent": {
    "command": "uvx",
    "args": ["ios-mcp"]
  }
}
```

## Documentation

## What ios-agent MCP server does

The ios-agent MCP server connects an AI agent to an iOS Simulator or a tethered iPhone. It uses Apple's XCTest-based XCUIAutomation through WebDriverAgent, rather than private simulator or accessibility frameworks. The project includes an MCP server, a terminal application, and the library that supports both interfaces.

The server exposes 31 tools and 5 resources through stdio or HTTP. Its design targets interactive agents rather than conventional test suites: screen state is reduced to a compact digest, and each action returns the screen it produced. When the next screen is sufficiently similar, the response can be a delta instead of a full repeat. Irreversible actions use a confirmation gate before execution.

## How it works

The ios-agent MCP server runs on a Mac and communicates with a simulator or connected phone through WebDriverAgent. Perception is processed on the host using multiple resolution tiers, allowing the system to retry locally in some cases instead of spending another model turn. This reduces the amount of accessibility data sent to the agent compared with raw WebDriverAgent page source.

The automation path uses public Apple APIs through XCTest. It does not depend on CoreSimulator's private accessibility framework or the Accessibility Inspector service. The same device interaction layer is also available through the command-line application, including a manual mode that does not require a model API key.

## Setup and configuration

For a simulator, the requirements are macOS, Xcode 16.3 or newer, an installed iOS runtime, and Python 3.12 or newer. A physical iPhone additionally requires go-ios, Developer Mode, and a signing identity. The phone setup includes a signed runner and is more involved than simulator setup.

Install the project with `uv sync`, then build WebDriverAgent with `./scripts/prepare_wda.sh simulator`. Run `uv run ios-agent doctor` to check the toolchain, runtimes, tunnel, WebDriverAgent signing expiry, devices, and model configuration. The doctor reports a remedy for detected failures. If no simulator runtime exists, Xcode can download an iOS platform; if a runtime exists without a simulator, ios-agent can offer to create one.

For MCP clients, configure a stdio server using `uv run --directory . ios-mcp serve`. The README includes an example for Claude Code. HTTP is also supported. The terminal agent's model provider is configured separately; documented providers include Anthropic, OpenAI, Azure OpenAI, Gemini, Vertex AI, Bedrock, Groq, Mistral, and local Ollama models.

## Tools and capabilities

- Operate an iOS Simulator or tethered iPhone through MCP.
- Read compact screen digests instead of raw accessibility XML.
- Return resulting screens or deltas after actions.
- Ask for confirmation before irreversible operations.
- Expose 31 MCP tools and 5 resources over stdio or HTTP.
- Inspect and drive devices through the accompanying terminal application's manual mode.

## Limitations and notes

The ios-agent MCP server requires macOS because it depends on Xcode and Apple's XCTest tooling. Physical-device use requires additional signing and device preparation; a free Apple ID provisioning profile lasts seven days. WebDriverAgent must track the installed Xcode version and may need to be rebuilt.

A simulator runtime is not included with Xcode by default and may require a download of roughly 8 GB. The project is designed for agents, not as a replacement description of a complete test-suite workflow. Model use is optional for manual terminal operation but may be configured for agent-driven runs.

_Full upstream README: https://allmcps.com/mcp/ios-agent/readme_

