# Android-MCP: giving an LLM agent hands on a real Android device

> Android-MCP is an MCP server that bridges language model agents and Android phones, exposing gestures, keystrokes, screen capture and view hierarchy reads through ADB and the Accessibility API. It ships as a uvx package that a desktop MCP host launches, and it works against an emulator or a physical device over USB or WiFi ADB.

**CursorTouch/Android-MCP** — MCP Server for interacting with Android Devices.

- Repository: https://github.com/CursorTouch/Android-MCP
- Stars: 903 · Forks: 124
- Language: Python
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/cursortouch-android-mcp

## What the agent actually gets to do with the phone

The toolset is what makes this usable, so it is worth listing precisely what the documentation claims. Native Android integration works through ADB and the Android Accessibility API, and the operations named are launching apps, tapping, swiping, inputting text and reading view hierarchies. The prebuilt tools are described as covering gestures, keystrokes, capture, device state and shell command execution.

That list has a specific consequence. Because the server can read the view hierarchy, the agent gets the structure of the screen as data rather than as a picture, so it can look for a widget by its text or class and act on it directly. The documentation states this happens without relying on traditional computer-vision pipelines or preprogrammed scripts, and that no fine-tuned computer vision model or OCR pipeline is required. Bring your own LLM or VLM is listed as a feature in its own right.

The latency figure is quoted as typical latency between actions of two to four seconds, depending on device specifications and load. That number matters for how you design a test around it. An agent that taps and then waits for a state change is paying several seconds per step, and a flow with twenty steps is a test that takes a minute of wall clock before you count the model's own thinking time. It is a speed appropriate to exploratory, agent driven work, not to a fast regression suite.

The supported platform floor is Android 10, and the target can be an emulator or a physical device.

## How the server finds adb, and why the PATH override exists

The most detailed part of the documentation, and the most useful, is about how the server locates the adb binary, because this is where desktop MCP hosts usually break.

The search order is documented as adb on PATH first, then the platform-tools directory under ANDROID_HOME, then under ANDROID_SDK_ROOT, then the default Android Studio SDK folder, which is listed as ~/Library/Android/sdk on macOS, ~/Android/Sdk on Linux and %LOCALAPPDATA%\Android\Sdk on Windows, and finally /opt/homebrew/bin and /usr/local/bin.

Two behaviours follow from that description and both are unusual enough to note. An override that does not point at an executable is treated as an error rather than silently falling back to the search, which means a typo in the path fails loudly instead of picking up a different adb. And the resolved path is kept in the server process's ADBUTILS_ADB_PATH for the lifetime of that process, so moving adb means restarting the server.

The reason the documentation insists on this is stated plainly: desktop MCP hosts may give the server a different PATH from the one in your terminal. The Claude Desktop extension exposes the override as an adb Binary Path setting. The override variable for this project is ANDROID_MCP_ADB_PATH, and the documentation also mentions adbutils' own ADBUTILS_ADB_PATH as an alternative.

This is the single most likely thing to go wrong on a first run, and the documentation is unusually clear about it.

## Device selection is lazy, and physical devices win over emulators

The connection model is lazy, and that design choice is stated in two places in the documentation. The server starts first and connects when a tool runs, so the MCP host can start even when no device is available yet. The device is resolved lazily when a tool is called.

When there is more than one candidate, the documentation says the server auto-detects connected devices and prefers physical devices over emulators. That default will surprise anyone running a CI job with an emulator attached while a real phone happens to be plugged in locally, so the explicit selection flags matter.

There are three of them, plus an environment variable. The --device flag takes a USB serial such as RFCN2013V8D, or a WiFi ADB target such as 192.168.1.3:5555. The --wifi flag takes a host address and auto-appends port 5555. The --usb flag auto-detects the first USB-connected device. The environment variable alternative is ANDROID_MCP_DEVICE.

The WiFi path has a corresponding environment pair, ANDROID_MCP_CONNECTION set to wifi and ANDROID_MCP_HOST set to the address, which is how you configure a specific wireless target in the desktop host configuration rather than on the command line.

Before any of that, the documentation asks you to verify the connection the ordinary way, with adb devices, and explains what the output should look like: a list of devices attached, a serial, and the word device. It notes that emulators show serials like emulator-5554, and that an empty list or an unauthorized state means checking the USB debugging settings on the device.

## Three ways to launch it, and the Windows Python 3.14 trap

There are three documented installation paths, and the recommended one is the shortest because it installs nothing by hand.

The recommended path is uvx, which runs the server straight from the package index. The Claude Desktop configuration is a single entry in the mcpServers object:

```json
{
  "mcpServers": {
    "android-mcp": {
      "command": "uvx",
      "args": [
        "--python",
        "3.13",
        "android-mcp"
      ]
    }
  }
}
```

The configuration file location is given per platform as %APPDATA%\Claude\claude_desktop_config.json on Windows and ~/Library/Application Support/Claude/claude_desktop_config.json on macOS. The same entry with an env block carrying ANDROID_MCP_CONNECTION and ANDROID_MCP_HOST targets a WiFi device, and appending --wifi with a host address does the same thing as a flag.

The Windows caveat is specific and worth repeating. The documentation says to use Python 3.13 for uvx on Windows, because Python 3.14 currently fails to resolve a transitive pywin32 dependency used by the MCP stack. This is the kind of detail that turns a two minute setup into an afternoon, and it is only stated in a note.

For local development the second path clones the repository and syncs the environment:

```shell
git clone https://github.com/CursorTouch/Android-MCP.git
cd Android-MCP
uv sync
```

The documentation notes that uv sync follows the repository's .python-version, so local development uses Python 3.13 by default, and the Claude Desktop entry in this mode runs uv with a --directory argument pointing at the cloned path. The third path does the same thing for OpenCode, using a local MCP entry in opencode.json with the command array form.

## The package is small, and its dependencies tell you what it does

The project manifest describes a deliberately small package. It is named android-mcp, described as a lightweight MCP Server for Android Operating System, requires Python 3.13 or newer with 3.14 explicitly excluded, and its keywords are android, mcp, mobile and automation.

The runtime dependencies are four. fastmcp at 2.14.0 or newer is the server framework, uiautomator2 at 3.3.1 or newer is the Android automation library that carries the device control, pillow is there for image handling in the capture path, and tabulate formats the table output that the view hierarchy and device state tools return as tables. The build backend is hatchling, and the console entry point is android_mcp.__main__:main, so the executable name matches the package name on the command line.

The repository layout supports the same picture. There is a src directory for the package, a tests directory, an e2e_test.py at the top level with a companion run_e2e_test.command file, a manifest.json, a .mcpbignore file, a uv.lock for reproducible resolution, a .python-version file, plus SECURITY.md and CONTRIBUTING.md.

Two of those deserve a note. The manifest.json and .mcpbignore pair suggests the project is prepared for distribution as a packaged MCP bundle rather than only as a pip style install, and the presence of an end to end test script at the repository root means the project can exercise a real device rather than only unit testing its internals.

## Where this approach stops being the right one

The limitation that follows directly from the architecture is the one to state first. If the sequence of actions is known in advance, an LLM in the loop is overhead rather than value: the model has to decide each step, pay a few seconds of latency per action, and produce a result that can differ between runs. A script using uiautomator2 directly, or an Appium style test, will be faster, cheaper and deterministic. The documentation is explicit that Android-MCP exists for cases where you do not want preprogrammed scripts, which is exactly the case where determinism is not the goal.

Second, the hardware requirement is not negotiable in a useful way. You need a device with USB debugging enabled and authorised, or an emulator. That is fine for a development machine and a CI runner with an emulator image, and it is a problem for a device farm where you cannot enable debugging on the devices, for a physical handset in the field, or for any iOS comparison. The supported platform floor is Android 10, and there is no iOS story here at all.

Third, the security posture deserves a deliberate decision rather than a default. The server can execute shell commands on the device and read the full view hierarchy, which means an agent that goes wrong can do more than tap the wrong button. The repository carries a SECURITY.md, which is where the reporting and disclosure expectations are described, and any deployment should decide in advance which devices are attached and what an agent is permitted to install or run.

Finally, the release history is short. There are two tags, v0.1.0 as the initial release and v0.2.0, both on 2026-05-14, while the last push to the repository was on 2026-10-21. The code is moving and the version numbers are still at zero, which means the interface exposed to an agent can change between releases. Pin the version your host resolves, and read the diff before upgrading, because a tool contract change is what breaks an agent mid run rather than a crashing process.

## Conclusion

Android-MCP fits a team that already has an LLM agent and wants it to drive a real Android device for automated QA, app navigation or UI testing, particularly against an emulator in CI. It is a poor fit for work that needs a preprogrammed script, since every action goes through a model that decides what to do next, and it is a poor fit for a device you cannot put USB debugging on. Before adopting it, run adb devices and confirm the target is listed as authorised, decide whether you want uvx or a local uv sync checkout, and pin the Python version, because the package requires Python 3.13 and explicitly excludes 3.14, and an environment with a different Python will fail to resolve rather than degrade.

## FAQ

### What is Android-MCP and what can it do?

It is an MCP server that lets LLM agents operate an Android device, using ADB and the Android Accessibility API to launch apps, tap, swipe, input text and read view hierarchies. It works with any language model and needs no computer vision model or OCR pipeline.

### How do I install Android-MCP for Claude Desktop?

Add an android-mcp entry to the mcpServers object of claude_desktop_config.json, using the command uvx with the arguments --python 3.13 and android-mcp. On Windows the documentation asks for Python 3.13 specifically, since Python 3.14 currently fails to resolve a transitive pywin32 dependency.

### How does Android-MCP choose which device to use?

Devices are resolved lazily when a tool runs, and the server prefers physical devices over emulators when several are connected. Use --device with a serial or WiFi target, --wifi with a host address, --usb to auto-detect the first USB device, or the ANDROID_MCP_DEVICE environment variable to pick a specific one.

### Does Android-MCP work over WiFi instead of USB?

Yes. You can connect the device with adb connect and its host:port, then point the server at it using the --wifi flag with the host address, or by setting ANDROID_MCP_CONNECTION to wifi and ANDROID_MCP_HOST to the address in the host configuration.

### What are the requirements for running Android-MCP?

Python 3.13, ADB, and an Android 10 or newer device or emulator. The server looks for adb on PATH, then in the platform-tools directory under ANDROID_HOME, ANDROID_SDK_ROOT or the default Android Studio SDK location, and you can override the binary with ANDROID_MCP_ADB_PATH.

## Sources

- [CursorTouch/Android-MCP on GitHub](https://github.com/CursorTouch/Android-MCP)
- [Issues](https://github.com/CursorTouch/Android-MCP/issues)
- [License: MIT](https://github.com/CursorTouch/Android-MCP/blob/master/LICENSE)
- [README](https://github.com/CursorTouch/Android-MCP/blob/master/README.md)
- [Releases](https://github.com/CursorTouch/Android-MCP/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cursortouch-android-mcp
