Skip to main content
Glama
Steph-ux

Android MCP

by Steph-ux

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

Action

Params

Description

list

All connected devices (USB, WiFi, emulators)

select

serial

Set default device

connect

host, port

WiFi ADB connection

disconnect

Disconnect current WiFi device

info

Model, OS, resolution, density

status

Is device connected and ready?

setup

Configure animations, stay-awake, ATX agent


android_screen — Capture & Stream

Action

Params

Description

screenshot

PNG capture (bypasses FLAG_SECURE) → image

region

x y width height

Capture a specific area → image

size

{width, height}

is_on

Is the screen on?

wake

Wake the screen

start_stream

Start ADB stream (~16fps)

stop_stream

Stop stream

live_frame

Latest stream frame → image

ocr

lang

Extract visible text (Tesseract)

find_image

template_b64 threshold

Template matching (OpenCV)

viewer

fps bitrate no_control

Launch scrcpy 90fps window on PC


android_interact — Touch, Keyboard, UI

Action

Params

Description

tap

x y

Tap

double_tap

x y

Double tap

long_press

x y duration_ms

Long press

swipe

x1 y1 x2 y2 duration_ms

Swipe

drag

x1 y1 x2 y2 duration_ms

Drag & drop

pinch

x y scale duration_ms

Pinch zoom

multi_touch

points

Multi-finger gestures

type

text

Type text

clear

Clear active field

submit

text

Type + Enter

key

key

System key (HOME, BACK, ENTER, VOLUME_UP…)

combo

keys

Key combination (keycodes)

hierarchy

Full UI XML tree (uiautomator2)

find

text partial_match

Find element and tap it

wait

text timeout partial_match

Wait for element

scroll

text direction max_swipes

Scroll to element

assert

text partial_match

Assert text is visible


android_app — Applications

Action

Params

Description

launch

package

Launch an app

close

package

Force-stop an app

list

include_system

List installed apps

install

apk_path

Install APK from PC

uninstall

package

Uninstall app

current

Foreground app package

url

url

Open a URL

intent

action uri package extras

Send Android intent

settings

section

Open system settings (main wifi bluetooth display…)


android_files — Files

Action

Params

Description

push

local_path remote_path

PC → phone

push_b64

remote_path data

Base64 → phone

pull

remote_path local_path

Phone → PC

pull_b64

remote_path

Phone → base64

list

directory

List directory contents


android_system — System & Network

Action

Params

Description

shell

command

ADB shell command

logs

lines package

Logcat

battery

Battery level and charging state

clipboard_get

Read clipboard

clipboard_set

text

Write to clipboard

volume

level stream

Set volume

rotation

rotation

Screen rotation (0-3)

wifi

enabled

WiFi on/off

bluetooth

enabled

Bluetooth on/off

mobile_data

enabled

Mobile data on/off

notifications

Active notifications

gps

lat lng

Mock GPS location

sensors

sensor

Accelerometer, gyro, light…

wifi_list

Available WiFi networks

wifi_connect

ssid password

Connect to WiFi

contacts

search limit

Read contacts

sms

to message

Send SMS (requires confirmation on phone)


android_automation — Batch & Macros

Action

Params

Description

batch

actions stop_on_error

Run N actions in one call

macro_start

name

Start recording a macro

macro_record

action …params

Add action to macro

macro_stop

Save macro

macro_list

List saved macros

macro_replay

name delay_ms

Replay a macro

macro_delete

name

Delete 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

Control

Action

Left click

Tap

Drag

Swipe

Right click

BACK

Scroll

Scroll

Alt+H

HOME

Alt+S

Screenshot → PC clipboard

Alt+F

Fullscreen

Alt+R

Rotation


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

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Steph-ux/android-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server