mcp-ios
Integrates with a local Appium server using the XCUITest driver and WebDriverAgent to create sessions and control a connected iOS device for real UI automation.
Drives a tethered iPhone or iPad via Appium/WebDriverAgent, enabling device inspection, screenshots, element-tree reads, taps, swipes, text input, button presses, app launching, URL opening, and running Shortcuts, with safe-by-default read-only/read-write/admin modes.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-iostake a screenshot of my iPhone and tell me what app is open"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-ios
A Model Context Protocol server to drive an iPhone/iPad — the iOS counterpart to mcp-android. Read this first: iOS is fundamentally more locked down than Android or macOS, so this server takes the only legitimate route to real UI control.
The honest landscape
A stock iPhone does not allow a background app to see and control other apps the way Android's Accessibility service (or macOS) does. Apple's sandbox forbids it. So there is no on-device "iOS-use" agent like the Mac/Android ones. The viable routes, in order of capability:
Route | Control level | Needs | Notes |
Appium + WebDriverAgent (XCUITest) ✅ (this server) | Full UI: tap, type, swipe, read elements, screenshots, launch apps | A Mac with Xcode; iPhone connected by USB (or same-network); WDA signed to the device | The real "phone-use". Built for automation/QA — perfect for a personal agent on your own device. |
Shortcuts | Run user-defined actions (set alarm, send message, toggles) | Shortcuts app; a URL/x-callback bridge | No arbitrary UI control, but great for safe, specific actions. Exposed here via |
MDM | Policy/config, app install | Enrollment | Device management, not interactive control. |
This server implements the Appium/WDA route: it runs on a Mac, talks to a local Appium server driving WebDriverAgent on the tethered iPhone, and exposes the same safe-by-default MCP shape as the rest of the suite. A set_alarm-style action can also go through Shortcuts (run_shortcut) when the device isn't tethered.
If you want control from the phone itself with nothing attached, that isn't possible on iOS — use
mcp-androidon the Fold 7 for that experience, or the Shortcuts subset here.
Related MCP server: ios-device-mcp
Setup (Appium route)
brew install node
npm i -g appium
appium driver install xcuitest
# Xcode + command line tools installed; sign WebDriverAgent to your device once (Xcode)
# Connect the iPhone by USB, Trust the Mac, enable Developer Mode on the device
appium # starts the Appium server (default http://127.0.0.1:4723)The server creates the XCUITest session lazily on the first tool call, so it starts even before Appium or the device are up — the first call that needs the device returns a clear "start appium / sign WDA / connect the device" message if it can't connect.
Security model
Concern | Flag | Default | Effect |
What can the server do? |
|
|
|
Which apps are in scope? |
| (all) | When set, launching/managing any other bundle ID is refused. |
Which apps are read-only forever? |
|
| Inspectable/launchable but never terminated, reset, or uninstalled. |
Can it install/terminate/reset apps? |
|
| The admin tools need this and admin mode; otherwise they aren't even advertised. |
Interactive confirmation | (automatic) | — |
|
Preview without touching the device |
|
| Write/admin tools validate + log intent, then return. |
Audit trail |
|
| Emits a JSON line to stderr per guarded operation. |
Connection: IOS_APPIUM_URL (default http://127.0.0.1:4723), IOS_UDID (target device), IOS_BUNDLE_ID (optional default app). See .env.example for all variables and docs/CLIENTS.md for the full per-client install guide.
Tools
Read (read-only+): list_targets, device_info, screenshot, page_source (element tree), current_app, list_apps
Write (read-write+): tap, swipe, input_text, press_button (home/volume), launch_app, open_url, run_shortcut (via Shortcuts)
Admin (admin + IOS_ALLOW_MANAGE): install_app, terminate_app, reset_app (the last two confirm via elicitation; protected apps refused)
screenshot returns an MCP image content block so the agent can see the screen before acting.
Quickstart — add to your agent
Published on npm as @dockndevai/mcp-ios. No clone or build needed — your MCP client runs it on demand with npx. It must run on the Mac with a running Appium server. Start in read-only mode.
Claude Code (CLI)
claude mcp add ios -e IOS_APPIUM_URL="http://127.0.0.1:4723" -e IOS_MODE="read-only" -- npx -y @dockndevai/mcp-iosClaude Desktop · Cursor · Windsurf — same block in claude_desktop_config.json, .cursor/mcp.json, or ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"ios": {
"command": "npx",
"args": [
"-y",
"@dockndevai/mcp-ios"
],
"env": {
"IOS_APPIUM_URL": "http://127.0.0.1:4723",
"IOS_MODE": "read-only"
}
}
}
}VS Code (GitHub Copilot, Agent mode) — in .vscode/mcp.json:
{
"servers": {
"ios": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@dockndevai/mcp-ios"
],
"env": {
"IOS_APPIUM_URL": "http://127.0.0.1:4723",
"IOS_MODE": "read-only"
}
}
}
}Example prompts
"Take a screenshot of my phone and tell me what's on screen."
"Open Safari and go to news.ycombinator.com." (needs
read-write)"Run my 'Good morning' Shortcut." (needs
read-write)
Run from source (development)
npm install
npm run build
node dist/index.js # with the environment variables set, and `appium` runningDevelop
npm run dev
npm test # security policy + elicitation confirmation (pure; no device needed)
npm run typecheckThe policy and elicitation tests are pure and run anywhere. The device-driving path can't be smoke-tested without a Mac + Xcode + signed WDA + a tethered iPhone, so it's built against your real device setup.
Publishing
This server ships a server.json for the official MCP registry and an mcpName for npm ownership validation. See PUBLISHING.md for publishing to npm and listing on the MCP registry, Smithery, Glama, Cursor, and PulseMCP.
License
MIT
Available Tools
6 toolscurrent_appCurrent appB
The app (bundle ID / process) currently in the foreground.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and only discloses the identity of the returned value. It says nothing about whether accessibility/automation permissions are required, what happens when no app is foregrounded, or whether the result is a string or a structured object.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short sentence with no filler. It is appropriately sized, though it leads with a noun phrase rather than an action, which slightly weakens front-loading for a first-time reader.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple zero-param read tool this is close, but with no output schema and no annotations, the description should specify the return shape and failure behavior. It only partially does so by noting the bundle ID / process form.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there is nothing for the description to compensate for. Schema coverage is 100% on an empty object.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource — the foreground app, identified by bundle ID / process — which is distinct from list_apps (all apps) and device_info. It lacks an explicit verb, but the noun phrase is unambiguous about what is returned.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance and no mention of alternatives such as list_apps or device_info. The phrase 'currently in the foreground' hints at the context, but the agent must infer when this tool is preferred over its siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
device_infoDevice infoA
Session capabilities and device info (model, iOS version, screen) reported by WebDriverAgent.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden; it does convey that the data is passively reported by WebDriverAgent, which implies a read with no side effects. It says nothing about whether values are cached/snapshot-at-session-start or live, or what happens if no session exists — gaps that matter for a session-scoped read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with the core resource front-loaded and the concrete payload fields appended. Nothing redundant and nothing padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter, no-annotation, no-output-schema tool, the description is nearly sufficient — it names the returned fields and the reporting agent. It falls short only on session preconditions and whether repeated calls return fresh values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. The enumerated return fields (model, iOS version, screen) add useful framing without being required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource — session capabilities plus device info — and enumerates concrete fields (model, iOS version, screen) and the source (WebDriverAgent). It isn't confused with any sibling (screenshot, page_source, current_app), though it never explicitly names what separates it from current_app, which also reports state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No statement of when to call this versus alternatives, no prerequisites (e.g., that a session must be active), and no exclusion criteria. The agent has to infer usage purely from the tool name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_appsList appsB
List installed apps (best-effort; depends on the WebDriverAgent build).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It usefully discloses that results are 'best-effort' and depend on the WebDriverAgent build, but it does not explain return behavior, permissions, or what happens when the dependency is unsupported.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with a useful parenthetical caveat. Every part earns its place and there is no redundant wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, low-complexity listing tool, the description covers the core purpose and a reliability caveat. However, without an output schema or annotations, it leaves open what 'apps' returns and how this differs from current_app or list_targets.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema baseline is 4. There are no parameter semantics to clarify in the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a clear verb and resource: 'List installed apps.' This is more specific than a title restatement, but it does not distinguish the tool from siblings such as list_targets or current_app.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like list_targets or current_app. The caveat about WebDriverAgent builds describes reliability, not usage conditions or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_targetsList targetsB
Show the configured Appium connection (URL, target UDID, default bundle ID) and, best-effort, the devices/simulators attached to this Mac.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses that device enumeration is 'best-effort' (i.e., may be incomplete or fail), which is real behavioral context, and the read-only 'Show' framing implies no mutation. It stops short of saying whether the call requires a live Appium server, what happens when none is configured, or how failures surface.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single well-formed sentence with the primary payload (the configured connection) front-loaded and the secondary, less reliable part (attached devices) qualified. No filler, though the parenthetical enumeration makes it slightly dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description must convey return values — and it does, naming the three connection fields and the device list. Combined with the 'best-effort' caveat, an agent knows enough to call it; only failure/precondition behavior is unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate. Baseline 4 applies; the description correctly implies a no-argument call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Show') and enumerates exactly what is returned: the Appium connection URL, target UDID, default bundle ID, plus attached devices/simulators. That makes the output concrete, though it doesn't explicitly contrast with the similar-sounding sibling device_info, so the boundary between the two needs inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance and no mention of alternatives. An agent facing both list_targets and device_info has no textual basis for choosing one over the other.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
page_sourceElement treeA
Dump the current screen's XCUITest element tree (XML) with labels, types, and bounds — use it to find exact tap coordinates.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose the return format (XML) and payload contents (labels, types, bounds) and implies a read-only snapshot of the current screen, but says nothing about output size/verbosity on complex screens, staleness of the snapshot, or failure modes when the screen is mid-transition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single em-dash-joined sentence that front-loads what is returned and ends with the actionable purpose. No filler, nothing repeated from the title alone.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, no-output-schema dump tool this is close to sufficient: format, contents, and purpose are all covered. The only gap is any hint about output volume or when the tree may not reflect the settled UI, which matters for a UI-automation agent parsing XML.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so there is nothing to disambiguate; the baseline of 4 applies. The description correctly implies the tool takes no input by scoping itself to "the current screen."
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: dumps the current screen's XCUITest element tree as XML, with labels, types, and bounds. This concretely distinguishes it from the sibling screenshot tool, which returns pixels rather than an inspectable element hierarchy.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"use it to find exact tap coordinates" gives a clear positive trigger, which is exactly the decision an agent needs. It stops short of an explicit exclusion (e.g., use screenshot for visual verification instead), so it lacks the alternative-routing that would earn a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
screenshotScreenshotA
Capture the current screen as a PNG image so you can see what's on the phone before acting.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry behavioral disclosure. It does convey that the result is a PNG image and implies a read-only capture, but says nothing about device requirements, latency, image scope (e.g., status bar, resolution), or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the output format stated early and a purpose clause that earns its place. No waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, output-less-schema tool, the description covers what it does and what it returns (PNG). Minor gaps: no mention of needed device context or when to prefer ui_dump.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a 0-param tool applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Capture the current screen as a PNG image') plus the concrete output format. It does not explicitly contrast with the closest sibling, ui_dump, but an agent can distinguish an image capture from a UI tree dump.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'...so you can see what's on the phone before acting' implies the timing (prior to interactions) but gives no explicit when-not or named alternatives such as ui_dump for structured element data.
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.
6 tool updates
v0.1.0- First observed
current_app - First observed
device_info - First observed
list_apps - First observed
list_targets - First observed
page_source - First observed
screenshot
TDQS
Scored across 6 tools
Most tools are clearly distinct (screenshot vs page_source vs current_app vs list_apps). However, list_targets and device_info overlap somewhat: both report device/connection information, which could cause an agent to pick the wrong one when it just wants device details.
All names use snake_case, which is consistent, but the naming convention mixes verb_noun (list_targets, list_apps) with noun phrases (device_info, screenshot, page_source, current_app). It is readable but not a predictable verb-first pattern throughout.
Six tools is a reasonable, well-scoped set for an inspection-oriented iOS/Appium bridge, and each tool earns its place. It is slightly thin for full iOS automation, but the count itself is not excessive or trivial.
The surface is inspection-only: there are no interaction tools such as tap, type text, swipe, launch/terminate app, or navigation. Since screenshot and page_source are explicitly framed as preparation 'before acting,' the absence of any acting tools is a significant gap that will block agent workflows.
Maintenance
Related MCP Connectors
Drive real devices from your AI Coding tool. Embed a client SDK (Unity, Godot, Flutter, iOS/macOS, Android, React Native, Web) in your app, then capture screenshots, traverse the UI tree, inject taps and key events, and run automated test tasks on the physical device over a secure relay.
Let your AI agent control real iPhones: screenshots, tap, swipe, type and open apps.
Securely control computers you explicitly pair through files, terminals, processes, screenshots, desktop UI/input, clipboard, browser automation, diagnostics, and document tools.
remote debug iOS/Android/Unity/Godot/Flutter/RN/Web on real-device.ui-tree/screenshots/taps,tests.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables agents to control a physical iPhone from macOS through local phone tools, including USB capture, Bluetooth HID, and AssistiveTouch interactions. It also exposes relay tools for remote access over Streamable HTTP with optional OAuth.MIT
- AlicenseBqualityBmaintenanceEnables controlling a real iPhone or iPad over USB for app development testing, including building and installing apps, launching with console logs, inspecting the accessibility tree, tapping, swiping, typing, taking screenshots, managing app files, and recording audio.281MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to operate a real iPhone from a Mac by reading the screen over USB and sending taps, swipes, typing, and app launches over Bluetooth, with every action returning a fresh screenshot so the agent can verify its work. Runs as a local MCP server, so agents can test iOS apps on physical devices and automate everyday phone tasks.43 npm10MIT
- AlicenseNot gradedqualityAmaintenanceFree, open-source Mac app and MCP server that lets AI agents take screenshots, tap, swipe, type and launch apps on a real iPhone. Includes owner-approved clients, an activity log and pause controls; supports USB and Wi-Fi after pairing.12Apache 2.0