Model or dataset
mobile-next/mobile-mcp avatar
mobile-next/mobile-mcp

mobile-mcp: an MCP server that drives iOS and Android from the accessibility tree

Model Context Protocol Server for Mobile Automation and Scraping (iOS, Android, Emulators, Simulators and Real Devices)

6,706 stars585 forksTypeScriptApache-2.0

At a glance

What is it?
mobile-next/mobile-mcp exposes one set of MCP tools for simulators, emulators and real phones, reading the native accessibility tree first and falling back to screenshots. It removes per-platform test glue, but it also removes the deterministic assertions that glue used to give you.
Who is it for?
Adopt mobile-mcp if you already run an MCP-capable agent (Claude Code, Codex, Gemini, GitHub Copilot, Antigravity) and want it to operate a booted simulator or an adb-authorized phone without writing XCUITest or Espresso. Do not adopt it as a replacement for a deterministic regression suite, and do not expect it to work on a machine without Xcode or the Android SDK.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The glue code mobile-mcp deletes, and who was writing it

Automating a phone normally means picking a side. On iOS that means XCUITest and the XCTest runner; on Android it means Espresso or UiAutomator. A team that wants one scripted flow to run on an iPhone and a Pixel writes it twice, in two languages, against two element-query APIs. mobile-mcp's README states the goal directly: a platform-agnostic interface that eliminates the need for distinct iOS or Android knowledge. The audience is not the QA engineer who already maintains an Appium suite. It is the person wiring an LLM agent to a device, where the caller is a model that can read a list of elements and decide what to tap next. The README lists the intended cases: native app automation for testing or data entry, scripted form flows without manually driving a simulator, multi-step journeys driven by an LLM, and data extraction. Every one of those assumes a human describes a goal rather than writes a selector.

Accessibility tree first, screenshots as the fallback

The mechanism the README describes is a two-tier read of the screen. The primary path is the native accessibility tree, which the project frames as fast and cheap because it sends no image tokens to the model. The fallback is a screenshot plus coordinate taps. That distinction matters more than it sounds. A screenshot-based agent pays for every pixel it looks at and can only guess where a button is; an accessibility snapshot returns named elements with coordinates and properties attached. The tool that exposes this is `mobile_list_elements_on_screen`, which the README says lists UI elements with their coordinates and properties. When the tree is not enough, `mobile_click_on_screen_at_coordinates`, `mobile_double_tap_on_screen`, `mobile_long_press_on_screen_at_coordinates` and `mobile_swipe_on_screen` act on raw positions. The data flow is therefore: agent asks for elements, gets a structured list, picks one, acts on it, asks again. State lives on the device, not in the server, so each call is a fresh read.

One tool surface across four target types

The platform support table lists four targets: iOS Simulator (Xcode plus a booted simulator via `xcrun simctl`), iOS Real Device (connected over USB and trusted), Android Emulator (Android SDK plus a running emulator via `adb`), and Android Real Device (`adb` plus USB debugging enabled and authorized). The same tool names apply to all four. Device management covers `mobile_list_available_devices`, `mobile_get_screen_size`, `mobile_get_orientation`, `mobile_set_orientation`, `mobile_set_location` and `mobile_clipboard`. App lifecycle is `mobile_list_apps`, `mobile_get_foreground_app`, `mobile_launch_app`, `mobile_terminate_app`, `mobile_install_app` (from .apk, .ipa, .app or .zip) and `mobile_uninstall_app`. Input runs through `mobile_type_keys`, `mobile_press_button` for hardware keys such as HOME, BACK and VOLUME_UP/DOWN, and `mobile_open_url`. Diagnostics are `mobile_get_device_logs`, which the README says collects logcat on Android and the unified log on iOS, plus `mobile_list_crashes` and `mobile_get_crash`. Screen recording is a start/stop pair. That is a wide surface, and it is the strongest argument for the project: a model that has learned these names once can point them at any of the four targets.

Getting it running, and the setup it assumes

The README does not include a full installation walkthrough in the material available, but it does give the invocation. The VS Code install badge encodes a server definition with `command` set to `npx` and `args` set to `-y` and `@mobilenext/mobile-mcp@latest`, which is the same shape any MCP client config takes. The package name on npm is `@mobilenext/mobile-mcp`. Clients named as compatible are Claude Code, Codex, Gemini, GitHub Copilot and Antigravity, plus anything else speaking MCP. The environment has to provide the device tooling itself: `xcrun simctl` for iOS simulators, `adb` for Android. There is no config key in the README for pointing the server at a specific device UDID; discovery is done at runtime by calling `mobile_list_available_devices`. A second path exists for hardware you do not own: the cloud tools `mobile_login_to_cloud_provider`, `mobile_list_remote_devices`, `mobile_allocate_remote_device` and `mobile_release_remote_device`, where login is described as a browser-based device-code flow and allocation reserves a physical device for exclusive use. The README claims the same tools apply, with no local setup.

Where the accessibility-first bet breaks down

The fallback to coordinates is also the failure mode. When an app draws its own controls on a canvas, or ships without meaningful accessibility labels, `mobile_list_elements_on_screen` returns either nothing useful or a set of unlabeled boxes. The agent then behaves like any other screenshot-driven tool: it taps a position that was correct on the last frame and stops being correct after a scroll, a keyboard slide, or an animation. Nothing in the README suggests the server waits for the UI to settle before returning, so a caller that reads the tree too early can act on a stale list. The second constraint is environmental rather than architectural. Because the server drives whatever `adb` and `xcrun simctl` can see, it inherits their limits: one USB cable per physical device, a trusted pairing prompt on iOS, USB debugging authorization on Android. A CI runner without a device farm cannot use the local path at all. The third is that the README describes the tools but not the guarantees. There is no stated retry behaviour, no timeout policy, and no claim that an action succeeded beyond whatever the next read shows. For a test suite that needs a pass or fail, that is a gap the caller has to close.

Appium and Maestro solve a different half of the problem

Appium is the obvious comparison and the difference is structural. Appium exposes a WebDriver endpoint and expects a test process to drive it with explicit selectors, waits and assertions; the test owns the control flow and the pass/fail decision. mobile-mcp exposes MCP tools and expects a model to own the control flow, deciding at each step what to read and where to tap. Appium also normalizes across platforms through driver plugins, whereas mobile-mcp normalizes by giving both platforms the same tool names and letting the accessibility layer do the translation. Maestro sits closer to mobile-mcp in spirit, using YAML flows with implicit waits and a simpler mental model, but its flows are still authored artifacts that run the same way every time. mobile-mcp's flows are not artifacts at all; they are whatever the agent decides this run. That is the trade: you gain tolerance for UI changes the agent can reason around, and you lose reproducibility. If you need a fixed assertion that a checkout total equals a specific value, Appium or Maestro is the better fit. If you need an agent to poke at an app it has never seen, mobile-mcp is aimed at exactly that.

Licence, release cadence and what a version bump costs you

The licence is Apache-2.0, which permits commercial use, modification and redistribution provided the licence and notices are preserved; that is a statement about the licence text, not legal advice, and anyone embedding the server in a shipped product should read the file rather than this paragraph. The release history in the material is short and recent: 1.0.3 on 2026-09-08, with 1.0.2 and 1.0.1 both dated 2026-08-09. The default branch is main and the repository is not archived. The practical consequence for adopters is that pinning matters. The VS Code badge uses `@mobilenext/mobile-mcp@latest`, which means an MCP client configured that way picks up whatever npm serves on the next start. Because the server's contract is the tool list a model sees, a version bump that renames or removes a tool changes agent behaviour without any code change on your side. Pinning to an explicit version in the client config is the only lever the README's material gives you. Beyond that, the maintenance cost is mostly environmental: keeping Xcode, the Android SDK and `adb` current on every machine that runs the server, since the server has no bundled device drivers of its own.

Who this is for, and what to check before you commit

Use mobile-mcp when the caller is an agent and the target is a device you can already reach with `adb` or `xcrun simctl`. That covers exploratory testing, data entry against a real app, scraping a screen that has no API, and multi-step journeys where the path is not known in advance. Skip it when you need a regression suite that produces the same verdict twice, when your app's controls are canvas-drawn with no accessibility labels, or when your build machines have no attached hardware and you have not signed up for the cloud path. The first thing to verify is mundane: run `mobile_list_available_devices` and confirm your simulator, emulator or phone appears, because every other tool depends on that discovery step. The second is to call `mobile_list_elements_on_screen` against your own app and read the output. If the elements you need are named and positioned, the accessibility-first path will carry the work. If they come back empty or generic, you are on the coordinate fallback, and the agent's reliability will be decided by the app's UI, not by this server.

Editorial conclusion

Adopt mobile-mcp if you already run an MCP-capable agent (Claude Code, Codex, Gemini, GitHub Copilot, Antigravity) and want it to operate a booted simulator or an adb-authorized phone without writing XCUITest or Espresso. Do not adopt it as a replacement for a deterministic regression suite, and do not expect it to work on a machine without Xcode or the Android SDK. Verify first that `mobile_list_available_devices` returns your target, then check how `mobile_list_elements_on_screen` labels the specific widgets you care about, because that output is what the agent will act on.

Official sources

  1. License: Apache-2.0
  2. mobile-next/mobile-mcp on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes