Android MCP Server
by shuao-pro
README.md
# Android MCP Server
**AI-powered Android device automation via MCP (Model Context Protocol).**
Control an Android phone with natural language β through Claude Desktop, Cherry Studio, Kai 9000, or the built-in Web GUI with AI chat.
<p align="center">
<b>πΊπΈ English</b> | <a href="./README_zh.md">π¨π³ δΈζ</a>
</p>
<p align="center">
<a href="https://github.com/shuao-pro/android-mcp"><img src="https://img.shields.io/github/stars/shuao-pro/android-mcp?style=social" alt="Stars"></a>
<a href="https://github.com/shuao-pro/android-mcp"><img src="https://img.shields.io/badge/GitHub-shuao--pro%2Fandroid--mcp-181717?logo=github" alt="GitHub"></a>
<img src="https://img.shields.io/badge/python-3.10+-blue" alt="Python">
<img src="https://img.shields.io/badge/license-MIT-green" alt="License">
<img src="https://img.shields.io/badge/MCP-1.8+-purple" alt="MCP">
<img src="https://img.shields.io/badge/version-2.1.0-orange" alt="v2.1.0">
</p>
---
## β¨ Features
### Device Control (37 MCP Tools)
| Category | Tools |
|----------|-------|
| **Device** | `health_check`, `get_device_info`, `get_battery_info` |
| **Shell** | `shell` β any ADB-level command |
| **Input** | `click`, `long_click`, `swipe`, `drag`, `type_text`, `press_key` |
| **Apps** | `open_app`, `close_app`, `clear_app_data`, `install_app`, `uninstall_app`, `get_current_app`, `list_installed_apps` |
| **Screen** | `take_screenshot`, `get_ui_hierarchy` |
| **Files** | `read_file`, `write_file` (including `/data/data`) |
| **System** | `get_system_setting`, `put_system_setting`, `set_clipboard`, `get_clipboard`, `get_notifications`, `start_activity` |
| **Privilege** | `get_privilege_mode`, `set_privilege_mode` β switch device execution backend (auto / shizuku / root) |
| **Tasks** | `submit_task`, `get_task_status`, `get_task_result`, `cancel_task`, `list_tasks`, `run_task_and_wait` β long-running commands as background tasks |
| **Vision** | `find_element` β AI locates UI elements, `click_element` β find + click in one step |
### π‘οΈ Safety Guard
High-risk device operations are gated behind user confirmation:
- Destructive shell commands (`rm -rf`, `dd`, `mkfs`, `mount`, `reboot`, `su`, `pm uninstall/clear`, β¦)
- Writes to protected paths (`/system`, `/data`, `/vendor`, β¦)
- App install / uninstall / data clear, and system settings mutation
`SAFETY_MODE` controls the policy: `confirm` (default) prompts the user via MCP elicitation, `permissive` allows everything, and `strict` blocks risky operations outright.
### π Privilege Mode (Root / Shizuku)
The Android app executes commands through a unified **PrivilegeExecutor** that supports three modes:
| Mode | Backend | Use |
|------|---------|-----|
| `root` | `su` (uid 0) | Rooted devices (Magisk / KernelSU / APatch / SuperSU) |
| `shizuku` | Shizuku binder (uid 2000) | Non-root devices with Shizuku installed |
| `auto` (default) | root β shizuku fallback | Use root when available, otherwise Shizuku |
Selectable from the Android app UI, the Web Dashboard, or the `set_privilege_mode` MCP tool.
### β³ Long-running Tasks
Commands that may exceed the 30s HTTP timeout run as asynchronous background tasks on the device:
- `submit_task` / `run_task_and_wait` β run a command in the background and poll until it finishes
- `get_task_status` / `get_task_result` / `cancel_task` / `list_tasks` β monitor and control tasks
- On-device `TaskManager` runs commands on a dedicated thread pool (10 concurrent) with output truncation and automatic cleanup
### π€ Multi-step Agent
The Web Dashboard AI chat uses a closed-loop agent: it chains multiple tool calls (with screenshots + vision verification, long-running tasks, and retries) until the goal is done β up to 10 steps.
### AI Vision
- AI-powered screen element recognition via Claude Vision / GPT-4o / custom API
- Natural language β pixel coordinates β automated click
- Example: `find_element("the login button")` β `{center_x: 540, center_y: 960, confidence: 0.95}`
### Web Dashboard
- **AI Chat** β multi-step agent: describe a goal and it chains tool calls (screenshots + vision, long-running tasks, retries) until done
- **Live Screen** β 10fps WebSocket stream with click-to-touch
- **scrcpy** β native low-latency mirroring (one-click launch)
- **Setup Wizard** β guided 5-step setup with auto-detection + MCP SSE endpoint display
- **Settings Panel** β configure API providers + ADB device manager with .env sync
- **Privilege Mode** β switch Auto / Shizuku / Root from the sidebar
- **δΈ/English** β full i18n support
- **Shell Terminal** β live ADB shell in the browser
### MCP Clients
Connect any MCP-compatible client to the server:
| Client | Transport | Endpoint | Platform |
|--------|-----------|----------|----------|
| **Kai 9000** | Streamable HTTP | `:9000/mcp` | Android (F-Droid) |
| **Cherry Studio** | Streamable HTTP | `:9000/mcp` | Windows / macOS / Linux |
| **Claude Desktop** | SSE / stdio | `:9000/sse` or `stdio` | Windows / macOS / Linux |
| **Termux + curl** | SSE | `:9000/sse` | Android (Termux) |
> **Cherry Studio config:** Set MCP type to `streamableHttp`, URL `http://<lan_ip>:9000/mcp`.
> Or import `cherry-studio-mcp.json` from the project root.
### MCP Transport
| Mode | Endpoint | Use Case |
|------|----------|----------|
| `stdio` | (local pipe) | Claude Desktop local integration |
| SSE | `:9000/sse` | Claude Desktop remote, web frontends |
| Streamable HTTP | `:9000/mcp` | Kai 9000, modern MCP clients |
| **Combined** (default) | **both on `:9000`** | **SSE + Streamable HTTP simultaneously** |
---
## π Quick Start
### Prerequisites
- Python 3.10+
- Android device with **Shizuku** installed (or a rooted device β either works)
- ADB (Android SDK Platform Tools)
- scrcpy (optional, for native mirroring)
### 1. Install
```bash
git clone https://github.com/shuao-pro/android-mcp.git
cd android-mcp
pip install -e .
```
### 2. Setup
```bash
# First-time setup (configures .env)
bash scripts/setup.sh
```
Or manually:
```bash
cp .env.example .env
```
Install the Android APK to your phone:
```bash
# Pre-built APK (recommended) ι₯?from the android/ project
adb install "android/app/build/outputs/apk/debug/app-debug.apk"
# Or build from source
cd android && .\gradlew assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk
```
### 3. On Your Phone
1. Start **Shizuku** (grant root or wireless debugging permission), or use a rooted device
2. Open **Android MCP** app β pick a mode (Auto / Shizuku / Root) β grant permission β tap **Start**
3. Notification shows "MCP service running" on port 18080
4. Copy the **auth token** shown in the app into `.env` β `ANDROID_TOKEN=`
### 4. Start Server
```bash
# One-click (SSE + Web GUI + ADB forward)
./start.sh
# Windows
start.bat
```
Opens browser at `http://127.0.0.1:8080`.
### 5. Connect MCP Client
In the Web GUI, open **Menu β Setup** to see your MCP addresses:
| Client | Endpoint |
|--------|----------|
| **Kai 9000** (phone) | `http://192.168.x.x:9000/mcp` |
| **Claude Desktop** (remote) | `http://192.168.x.x:9000/sse` |
| **Same device** (Termux) | `http://127.0.0.1:9000/sse` or `/mcp` |
Add the address in Kai 9000 (Settings β MCP Servers β Add) or Claude Desktop:
```json
{
"mcpServers": {
"android": {
"command": "python",
"args": ["-m", "android_mcp.main", "--mode", "mcp"]
}
}
}
```
Now chat with the AI to control your phone β "open settings", "take a screenshot", "click the search button".
---
## βοΈ Configuration
Edit `.env`:
```env
# Device connection
ANDROID_HOST=127.0.0.1
ANDROID_PORT=18080
# Android bridge auth token (shown in the app UI β copy it here)
ANDROID_TOKEN=
# Safety guard β gate high-risk device operations (default: confirm)
SAFETY_MODE=confirm # permissive | confirm | strict
# Web GUI
WEB_HOST=127.0.0.1
WEB_PORT=8080
# MCP Server (SSE + Streamable HTTP) β for Kai 9000 & other clients
# Defaults to 127.0.0.1 (local-only, secure); set 0.0.0.0 for WiFi/phone clients
MCP_HOST=127.0.0.1
MCP_PORT=9000
# AI Vision (optional β enables AI chat + element recognition)
VISION_PROVIDER=anthropic # anthropic | openai | custom
VISION_API_KEY=sk-ant-api03-xxxxx
VISION_MODEL= # leave empty for default
VISION_API_BASE= # only for custom provider
```
---
## ποΈ Architecture
Three layers cooperate to turn a natural-language request into system-level actions on the device:
```mermaid
flowchart LR
subgraph CLIENTS["π€ MCP Clients"]
direction TB
C1["Claude Desktop<br/>stdio / SSE"]
C2["Kai 9000<br/>Streamable HTTP"]
C3["Cherry Studio<br/>Streamable HTTP"]
C4["Web Dashboard<br/>browser Β· :8080"]
end
subgraph SERVER["π Python Server Β· android_mcp/"]
direction TB
S1["FastMCP<br/>37 tools Β· :9000<br/>/sse + /mcp"]
S2["Web GUI Β· FastAPI<br/>:8080 Β· WebSocket"]
S3["tools/<br/>thin wrappers"]
S4["bridge/<br/>JSON-RPC transport"]
S5["vision/<br/>AI element locator"]
S6["safety/<br/>risk gate Β· user confirm"]
S7["tasks/<br/>submit Β· poll Β· result"]
S1 --- S3
S3 --- S4
S3 --- S6
S3 --- S7
S7 --- S4
S2 --- S4
S2 --- S5
end
subgraph PHONE["π± Android App Β· Kotlin Β· Root / Shizuku"]
direction TB
P1["HttpServer<br/>:18080"]
P2["Router<br/>JSON-RPC dispatch"]
P3["api/<br/>shell Β· input Β· file Β· system"]
P4["PrivilegeExecutor<br/>AUTO / ROOT / SHIZUKU"]
P5["Root (su)<br/>UID 0"]
P6["Shizuku<br/>UID 2000"]
P7["TaskApi + TaskManager<br/>async task queue"]
P1 --- P2
P2 --- P3
P2 --- P7
P3 --- P4
P7 --- P4
P4 --- P5
P4 --- P6
end
C1 --> S1
C2 --> S1
C3 --> S1
C4 --> S2
S4 -->|"HTTP JSON-RPC Β· X-MCP-Token<br/>ADB forward tcp:18080"| P1
S5 -.->|"Claude Vision / GPT-4o"| V["π§ Vision API"]
```
### Component breakdown
| Layer | Component | Responsibility | Key tech |
|-------|-----------|----------------|----------|
| **Clients** | Claude Desktop / Kai 9000 / Cherry Studio | Send tool calls as MCP messages | stdio, SSE, Streamable HTTP |
| | Web Dashboard | Browser panel, live screen, AI chat | FastAPI + WebSocket |
| **Python server** | `server.py` (FastMCP) | Registers 37 tools, speaks MCP | FastMCP |
| | `bridge/` | JSON-RPC β device, auto ADB forward | httpx, JSON-RPC 2.0 |
| | `tools/` | Thin `@bridge_call` wrappers | decorators |
| | `safety/` | Risk classification + user confirmation gate | MCP elicitation, SAFETY_MODE |
| | `web/` | Dashboard API, chat, scrcpy stream | FastAPI, uvicorn |
| | `vision/` | AI screen-element recognition | Claude Vision / GPT-4o |
| | `tasks/` | Long-running task submit / poll / result | task.submit/status/result RPC |
| **Android app** | `HttpServer` | Embedded HTTP server :18080, token auth | Java `ServerSocket` |
| | `Router` | JSON-RPC method dispatch | JSON-RPC 2.0 |
| | `api/*` | Shell, input, package, file, system, task | PrivilegeExecutor (Root / Shizuku) |
| | `TaskManager` / `TaskApi` | Background task queue + JSON-RPC API | thread pool, task state machine |
| | `util/` | Privilege executor + token store | `PrivilegeExecutor`, `RootHelper`, `ShizukuHelper`, `TokenStore` |
### Request lifecycle
Every tool call follows one path β e.g. `click(x, y)`:
1. **Client** sends `click(x, y)` over MCP (`:9000`) or the Web Dashboard (`:8080`).
2. **FastMCP / FastAPI** routes it to the matching `tools/` wrapper.
3. **`safety/`** classifies the operation; high-risk commands (destructive shell, writes to protected paths, app uninstall/clear) trigger an interactive user confirmation via MCP elicitation before continuing.
4. **`bridge/_core.py`** serializes it as a JSON-RPC 2.0 request, attaches the `X-MCP-Token` header, and POSTs to `http://127.0.0.1:18080/mcp` (re-establishing the ADB forward if needed).
5. **`HttpServer`** authenticates the token, then hands the request to `Router`.
6. **`Router`** dispatches to the right `api/*` module (e.g. `InputApi.tap`), which runs it via **Shizuku** (UID 2000) or **Root** (su, UID 0) β no root required, but rooted devices get full root access.
7. The JSON-RPC result travels back up the same chain.
### Ports & transports
| Port | Service | Transport | Consumers |
|------|---------|-----------|-----------|
| `:9000/sse` | MCP (SSE) | HTTP SSE | Claude Desktop (remote), web frontends |
| `:9000/mcp` | MCP (Streamable HTTP) | HTTP POST/GET | Kai 9000, Cherry Studio |
| `:8080` | Web Dashboard | HTTP + WebSocket | Browser |
| `:18080` | Android bridge | HTTP JSON-RPC (ADB-forwarded) | Python `bridge/` |
| *(stdio)* | MCP (stdio) | local pipe | Claude Desktop (local) |
> π‘ The server can run on the phone itself (Termux / Kai 9000). Set `ANDROID_HOST=127.0.0.1` β no ADB needed.
---
## π₯οΈ CLI Commands
```bash
# Start modes
python -m android_mcp.main --mode all-sse # SSE + Streamable HTTP + Web GUI (default)
python -m android_mcp.main --mode mcp # stdio only (Claude Desktop)
python -m android_mcp.main --mode mcp-sse # SSE + Streamable HTTP (headless)
python -m android_mcp.main --mode mcp-http # Streamable HTTP only
python -m android_mcp.main --mode web # Web GUI only
# Process management
python -m android_mcp.gateway start # Start as daemon
python -m android_mcp.gateway status # Check status
python -m android_mcp.gateway stop # Stop daemon
python -m android_mcp.gateway forward # Set up ADB port forward
```
---
## π Project Structure
```
android-mcp/
βββ android_mcp/
β βββ server.py # FastMCP server definition (tool registry)
β βββ main.py # Entry point (mode dispatch)
β βββ config.py # Environment config (.env loader)
β βββ safety.py # Risk classification + user confirmation gate
β βββ console.py # Colored console output helpers
β βββ utils.py # LAN IP + version helpers
β βββ gateway.py # CLI process manager
β βββ bridge/ # Low-level HTTP bridge to Android device
β β βββ __init__.py # Re-exports all bridge functions
β β βββ _core.py # JSON-RPC transport + ADB forward helpers
β β βββ device.py # Health, info, screenshot, shell, reboot
β β βββ input.py # Click, swipe, drag, keys, type_text
β β βββ apps.py # Package management
β β βββ system.py # Battery, clipboard, notifications, settings, mode
β β βββ files.py # File read/write/list/delete
β β βββ tasks.py # Long-running task submit/status/result/cancel/list
β βββ tools/ # MCP tool layer (thin wrappers over bridge)
β β βββ __init__.py # register_all_tools()
β β βββ decorators.py # @bridge_call error-handling decorator
β β βββ device.py # Health, info, battery, screenshot, UI hierarchy
β β βββ input.py # Touch, swipe, keys
β β βββ apps.py # Package management
β β βββ system.py # Shell, settings, clipboard, privilege mode
β β βββ files.py # File read/write
β β βββ tasks.py # Task tools (submit/poll/run_task_and_wait)
β β βββ vision.py # AI element recognition
β βββ vision/ # Vision model clients
β β βββ models.py # Data classes + Protocol
β β βββ clients.py # Anthropic + OpenAI clients (+ screen description)
β β βββ prompts.py # Prompt builder + parser
β βββ web/ # Web GUI
β βββ server.py # FastAPI + WebSocket
β βββ chat_agent.py # Multi-step agent loop (tool chaining + vision)
β βββ scrcpy_bridge.py # scrcpy + frame streaming
β βββ static/ # HTML/CSS/JS frontend
βββ android/ # Android APK project
β βββ app/src/main/
β β βββ java/com/example/androidmcp/
β β β βββ App.kt # Application class
β β β βββ MainActivity.kt # Main UI + privilege mode + auth
β β β βββ McpService.kt # Foreground service
β β β βββ api/
β β β β βββ FileApi.kt # File read/write/delete
β β β β βββ InputApi.kt # Touch, swipe, key events
β β β β βββ PackageApi.kt # App install/uninstall
β β β β βββ ShellApi.kt # Shell command execution
β β β β βββ SystemApi.kt # Screenshot, clipboard, settings, mode
β β β β βββ TaskApi.kt # Task submit/status/result/cancel/list
β β β βββ server/
β β β β βββ HttpServer.kt # Embedded HTTP server (:18080)
β β β β βββ Router.kt # JSON-RPC method dispatch
β β β βββ util/
β β β βββ PrivilegeExecutor.kt # Mode routing (AUTO/ROOT/SHIZUKU)
β β β βββ RootHelper.kt # su backend (uid 0)
β β β βββ ShizukuHelper.kt # Shizuku binder backend
β β β βββ TaskManager.kt # Background task queue + state machine
β β β βββ ExecResult.kt # Command result + process handle
β β β βββ TokenStore.kt # Bridge auth token (generate + persist)
β β βββ res/ # Layout, drawable, strings
β βββ gradle/ # Gradle wrapper
β βββ build.gradle.kts
β βββ settings.gradle.kts
βββ scripts/setup.sh # First-time setup
βββ tests/ # Test scripts
β βββ test_adb.py # ADB bridge tests
β βββ test_all.py # End-to-end tests
βββ start.sh # One-click start
βββ start.bat # Windows launcher
βββ pyproject.toml
βββ .env.example
```
---
## π Requirements
| Component | Requirement |
|-----------|-------------|
| Python | 3.10+ |
| Android | 11+ (API 30+) |
| Android App | Shizuku installed and running |
| ADB | Platform Tools (for port forward) |
| scrcpy | Optional (native mirroring) |
| AI Vision | Anthropic/OpenAI API key (optional) |
| MCP Client | Kai 9000 (F-Droid), Claude Desktop, or any SSE/stdio MCP client |
---
## π Links
| Resource | URL |
|----------|-----|
| **GitHub** | [github.com/shuao-pro/android-mcp](https://github.com/shuao-pro/android-mcp) |
| **Issues** | [Report a bug / Request feature](https://github.com/shuao-pro/android-mcp/issues) |
| **README δΈζ** | [README_zh.md](./README_zh.md) |
---
## π References
This project builds on the following open-source projects:
| Project | Purpose | License |
|---------|---------|---------|
| [Shizuku](https://github.com/RikkaApps/Shizuku) | Privileged shell execution on Android (no root) | Apache-2.0 |
| [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) | Model Context Protocol server (FastMCP) | MIT |
| [FastAPI](https://github.com/fastapi/fastapi) | Web GUI backend | MIT |
| [httpx](https://github.com/encode/httpx) | Async HTTP client for the device bridge | BSD-3-Clause |
| [scrcpy](https://github.com/Genymobile/scrcpy) | Low-latency screen mirroring | Apache-2.0 |
**Agent MCP frontends (clients):**
This server works with a variety of agent MCP frontends (e.g. Claude Desktop, Cherry Studio).
| Project | Purpose | License |
|---------|---------|---------|
| [Cherry Studio](https://github.com/CherryHQ/cherry-studio) | Desktop AI assistant / MCP client | AGPL-3.0 |
| [Termux](https://github.com/termux/termux-app) | Android terminal (run the server on-device) | GPL-3.0 |
**Root managers:**
| Project | Purpose | License |
|---------|---------|---------|
| [Magisk](https://github.com/topjohnwu/Magisk) | Systemless root solution | GPL-3.0 |
| [KernelSU](https://github.com/tiann/KernelSU) | Kernel-based root solution | GPL-2.0 |
| [APatch](https://github.com/bmax121/APatch) | Kernel-patch root solution | GPL-3.0 |
---
## π License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues