MCP Hub
Back to servers

Android MCP

Enables full Android control from any AI agent via 7 MCP tools, including screen capture, touch interaction, app management, and system control.

glama
Updated
May 10, 2026

Android MCP

Full Android control from any AI agent — Claude, OpenCode, Windsurf, Cursor… 7 categorical MCP tools · 90fps live viewer · WiFi ADB · zero app to install


Quick demo

android_screen(action="screenshot")                          # PNG capture
android_screen(action="ocr")                                 # visible text
android_interact(action="tap", params={"x": 540, "y": 960}) # tap
android_interact(action="find", params={"text": "Send"})     # find + tap
android_system(action="battery")                             # battery info
android_screen(action="viewer")                              # 90fps interactive window on PC

Architecture

AI Agent (Claude / OpenCode / Windsurf / Cursor…)
        ↓  MCP Protocol (stdio)
    server.py          ← 7 categorical tools
        ↓
    device_manager.py  ← device selection, multi-device
        ↓
    backends/
        ├── adb_backend.py       ← PRIMARY  : uiautomator2 + direct ADB
        └── companion_backend.py ← FALLBACK : Flutter app WebSocket
        ↓
    N Android phones / emulators

ADB backend (primary) — works on any device with developer mode enabled. Nothing to install on the phone. Uses uiautomator2 + ADB commands.

Companion backend (fallback) — optional Flutter app when ADB is unavailable on the network.


Requirements

  • Python 3.10+
  • ADB in PATH (winget install Google.PlatformTools)
  • Android: Developer mode + USB debugging (or WiFi debugging)

Installation

git clone https://github.com/Steph-ux/android-mcp
cd android-mcp
pip install -r requirements.txt

# Initialize uiautomator2 (once per device)
python -m uiautomator2 init

Live viewer 90fps (optional)

winget install Genymobile.scrcpy
python viewer.py

MCP Configuration

# Generate the correct JSON for your AI client
python mcp_config.py --client claude     # Claude Desktop
python mcp_config.py --client opencode  # OpenCode
python mcp_config.py --client windsurf  # Windsurf
python mcp_config.py --client cursor    # Cursor
python mcp_config.py --write            # write directly to config files

Claude Desktop example (claude_desktop_config.json):

{
  "mcpServers": {
    "android-mcp": {
      "command": "C:/Python312/python.exe",
      "args": ["D:/path/to/android-mcp/server.py"],
      "type": "stdio"
    }
  }
}

WiFi connection without USB (Android 11+)

# On the phone: Settings → Developer options → Wireless debugging → Pair device
adb pair 192.168.1.42:38765    # enter the code shown on the phone
adb connect 192.168.1.42:5555

Full guide → WIFI_PAIRING.md


The 7 MCP tools

Call convention: android_xxx(action="...", params={...}, device_id="serial") device_id is always optional (uses the currently selected device).


android_device — Device management

ActionParamsDescription
listAll connected devices (USB, WiFi, emulators)
selectserialSet default device
connecthost, portWiFi ADB connection
disconnectDisconnect current WiFi device
infoModel, OS, resolution, density
statusIs device connected and ready?
setupConfigure animations, stay-awake, ATX agent

android_screen — Capture & Stream

ActionParamsDescription
screenshotPNG capture (bypasses FLAG_SECURE) → image
regionx y width heightCapture a specific area → image
size{width, height}
is_onIs the screen on?
wakeWake the screen
start_streamStart ADB stream (~16fps)
stop_streamStop stream
live_frameLatest stream frame → image
ocrlangExtract visible text (Tesseract)
find_imagetemplate_b64 thresholdTemplate matching (OpenCV)
viewerfps bitrate no_controlLaunch scrcpy 90fps window on PC

android_interact — Touch, Keyboard, UI

ActionParamsDescription
tapx yTap
double_tapx yDouble tap
long_pressx y duration_msLong press
swipex1 y1 x2 y2 duration_msSwipe
dragx1 y1 x2 y2 duration_msDrag & drop
pinchx y scale duration_msPinch zoom
multi_touchpointsMulti-finger gestures
typetextType text
clearClear active field
submittextType + Enter
keykeySystem key (HOME, BACK, ENTER, VOLUME_UP…)
combokeysKey combination (keycodes)
hierarchyFull UI XML tree (uiautomator2)
findtext partial_matchFind element and tap it
waittext timeout partial_matchWait for element
scrolltext direction max_swipesScroll to element
asserttext partial_matchAssert text is visible

android_app — Applications

ActionParamsDescription
launchpackageLaunch an app
closepackageForce-stop an app
listinclude_systemList installed apps
installapk_pathInstall APK from PC
uninstallpackageUninstall app
currentForeground app package
urlurlOpen a URL
intentaction uri package extrasSend Android intent
settingssectionOpen system settings (main wifi bluetooth display…)

android_files — Files

ActionParamsDescription
pushlocal_path remote_pathPC → phone
push_b64remote_path dataBase64 → phone
pullremote_path local_pathPhone → PC
pull_b64remote_pathPhone → base64
listdirectoryList directory contents

android_system — System & Network

ActionParamsDescription
shellcommandADB shell command
logslines packageLogcat
batteryBattery level and charging state
clipboard_getRead clipboard
clipboard_settextWrite to clipboard
volumelevel streamSet volume
rotationrotationScreen rotation (0-3)
wifienabledWiFi on/off
bluetoothenabledBluetooth on/off
mobile_dataenabledMobile data on/off
notificationsActive notifications
gpslat lngMock GPS location
sensorssensorAccelerometer, gyro, light…
wifi_listAvailable WiFi networks
wifi_connectssid passwordConnect to WiFi
contactssearch limitRead contacts
smsto messageSend SMS (requires confirmation on phone)

android_automation — Batch & Macros

ActionParamsDescription
batchactions stop_on_errorRun N actions in one call
macro_startnameStart recording a macro
macro_recordaction …paramsAdd action to macro
macro_stopSave macro
macro_listList saved macros
macro_replayname delay_msReplay a macro
macro_deletenameDelete a macro

Live viewer — scrcpy 90fps

python viewer.py                  # auto-detect device, 90fps, interactive
python viewer.py --fps 60         # 60fps
python viewer.py --record         # record to .mp4
python viewer.py --record out.mp4 # named output file
python viewer.py --multi          # one viewer per connected device
python viewer.py --no-control     # read-only mode
ControlAction
Left clickTap
DragSwipe
Right clickBACK
ScrollScroll
Alt+HHOME
Alt+SScreenshot → PC clipboard
Alt+FFullscreen
Alt+RRotation

Tests

# Unit tests (no device required)
pytest tests/test_server_unit.py -v      # 94 tests

# Integration tests (ADB device required)
pytest tests/test_integration.py -v

Project structure

android-mcp/
├── server.py              # MCP server — 7 tools
├── viewer.py              # scrcpy 90fps interactive viewer
├── mcp_config.py          # JSON config generator
├── device_manager.py      # Multi-device management
├── relay.py               # ⚠️ LEGACY — companion fallback only
├── requirements.txt
├── pyproject.toml
├── WIFI_PAIRING.md
├── backends/
│   ├── adb_backend.py     # Primary backend (uiautomator2 + ADB)
│   └── companion_backend.py  # Fallback backend (Flutter app)
├── examples/
│   ├── agent_loop.py      # Autonomous automation loop
│   └── whatsapp_auto.py   # WhatsApp automation example
└── tests/
    ├── conftest.py
    ├── test_server_unit.py   # 94 unit tests
    └── test_integration.py   # Real device tests

Examples

# WhatsApp — send a message
await android_app("launch", {"package": "com.whatsapp"})
await android_interact("find", {"text": "Alice"})
await android_interact("type", {"text": "Hello!"})
await android_interact("key",  {"key": "ENTER"})

# Batch in a single call
await android_automation("batch", {"actions": [
    {"action": "key",  "key": "HOME"},
    {"action": "tap",  "x": 540, "y": 200},
    {"action": "type", "text": "search query"},
    {"action": "key",  "key": "ENTER"},
]})

# Macro: record + replay
await android_automation("macro_start",  {"name": "login"})
await android_automation("macro_record", {"action": "tap",  "x": 540, "y": 400})
await android_automation("macro_record", {"action": "type", "text": "password"})
await android_automation("macro_stop")
await android_automation("macro_replay", {"name": "login"})

See examples/whatsapp_auto.py and examples/agent_loop.py for full use cases.


License

MIT

Reviews

No reviews yet

Sign in to write a review