Android Control MCP Server
Enables AI assistants to observe, reason about, and control connected Android devices via ADB, providing tools for screenshots, UI hierarchy parsing, semantic element clicking, gestures, text input, and app lifecycle management.
README
Android Control MCP Server
A production-ready Model Context Protocol (MCP) server built in Node.js that enables AI assistants (such as Claude Desktop, Cursor, and custom agentic workflows) to observe, reason about, and control connected Android devices.
🌟 Features
- 👀 Computer-Use Observation: High-resolution PNG screen capture returned directly as MCP image blocks alongside device metadata.
- 🔍 UIAutomator Hierarchy Parsing: Intelligent XML dump parser that transforms verbose Android UI trees into compact, structured JSON.
- 🎯 Semantic Element Clicking: Click buttons and controls by their visible text, accessibility description, or resource ID without needing manual pixel calculations.
- ⚡ Fast Gestures & Input: Pixel-accurate tapping, multi-coordinate swiping, directional scrolling, hardware key emulation, and shell-escaped text typing.
- 📱 App Lifecycle Management: Launch applications by package name and inspect the currently focused foreground activity.
- 🛡️ Safety & Sandboxing: Input coordinate validation against actual screen bounds, strict allowlisted keycodes, argument sanitization, command timeouts, and strict
stderrlogging to guarantee stdio MCP stream integrity. - 🔄 Multi-Device Support: Auto-detects connected devices or targets specific devices via
ANDROID_DEVICE_ID.
🏗️ Architecture
AI Client (Claude Desktop, Cursor, Agent)
│
│ stdio transport (JSON-RPC)
▼
Node.js MCP Server
│
├── Stderr Structured Logger
├── Zod Schema Validation
│
├── ADB Controller Layer
│ ├── Device Resolver (auto-detect or target serial)
│ ├── Input Engine (tap, swipe, keyevent, text, scroll)
│ ├── Screenshot Manager (exec-out binary stream)
│ └── App Manager (launch, foreground inspection)
│
└── UIAutomator Engine
├── XML Hierarchy Dump & Normalizer
├── Bounds & Center Coordinate Extractor
└── Semantic Element Finder & Click Resolver
│
▼
Android Device / Emulator
📋 Prerequisites
- Node.js:
v20.0.0or higher (node -v) - Android SDK Platform-Tools: ADB (
adb) installed and accessible in your systemPATH(or configured viaADB_PATH). - Android Device or Emulator:
- Physical Device: Connect via USB, enable Developer Options and USB Debugging.
- Emulator: Android Studio AVD, Genymotion, or headless emulator.
Verify Device Connection
adb devices -l
You should see your device listed as device:
List of devices attached
emulator-5554 device product:sdk_gphone64_arm64 model:sdk_gphone64_arm64
🚀 Installation & Quick Start
# Clone or navigate to the repository
cd c:/Users/Abhishek/Code/mcp
# Install dependencies
npm install
# Run unit tests
npm test
# Start the MCP server
npm start
⚙️ Configuration
Create a .env file or pass environment variables:
# Target device ID (serial number). If omitted and 1 device is connected, it auto-selects.
ANDROID_DEVICE_ID=
# Custom path to ADB executable if not in PATH
# Windows: C:\Users\<user>\AppData\Local\Android\Sdk\platform-tools\adb.exe
# macOS: /Users/<user>/Library/Android/sdk/platform-tools/adb
ADB_PATH=adb
# Log level: debug | info | warn | error
LOG_LEVEL=info
# Default ADB timeout in milliseconds
ADB_TIMEOUT_MS=15000
🔌 Connecting to MCP Clients
1. Claude Desktop Configuration
Add the following to your claude_desktop_config.json:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"android-control": {
"command": "node",
"args": ["C:/Users/Abhishek/Code/mcp/src/index.js"],
"env": {
"ANDROID_DEVICE_ID": "",
"ADB_PATH": "adb",
"LOG_LEVEL": "info"
}
}
}
}
2. Cursor / Windsurf MCP Configuration
In Cursor's Features > MCP Servers or Windsurf settings:
- Name:
android-control - Type:
command - Command:
node C:/Users/Abhishek/Code/mcp/src/index.js
🛠️ MCP Tools Reference
1. android_device_info
Get comprehensive device hardware and OS metadata.
- Parameters:
deviceId(optional string): Target device serial.
- Example Response:
{ "deviceId": "emulator-5554", "model": "Pixel 8", "manufacturer": "Google", "androidVersion": "15", "sdk": 35, "resolution": { "width": 1080, "height": 2400 }, "connectionState": "connected" }
2. android_screenshot
Capture the Android screen as an MCP Image Content Block (image/png).
- Parameters:
deviceId(optional string): Target device serial.
- Returns: PNG base64 image data block + dimension metadata.
3. android_ui_dump
Dumps the current screen UIAutomator hierarchy into a compact, AI-friendly JSON format.
- Parameters:
deviceId(optional string): Target device serial.
- Example Output:
{ "package": "com.android.settings", "activity": "com.android.settings.Settings", "totalElements": 24, "interactiveElementsCount": 8, "elements": [ { "index": 0, "text": "Network & internet", "resourceId": "android:id/title", "className": "TextView", "clickable": true, "bounds": [196, 340, 1016, 400], "center": [606, 370] } ] }
4. android_find_element
Search for UI elements matching specific criteria on the current screen.
- Parameters:
text(optional string): Visible text (exact or partial).contentDescription(optional string): Accessibility label.resourceId(optional string): Resource ID.className(optional string): Widget class name.clickable(optional boolean): Filter by clickability.exactMatch(optional boolean, defaultfalse): Exact string match.
5. android_click_element
Find an element and click its center point in a single step.
- Parameters:
text(optional string): Element text.contentDescription(optional string): Element content description.resourceId(optional string): Element resource ID.className(optional string): Element class.
6. android_tap
Tap at exact (x, y) coordinates with screen boundary validation.
- Parameters:
x(number): X coordinate.y(number): Y coordinate.
7. android_swipe
Perform a drag / swipe gesture between two points.
- Parameters:
x1,y1(numbers): Start coordinates.x2,y2(numbers): End coordinates.duration(optional number, default: 300): Duration in milliseconds.
8. android_type_text
Type text into the currently focused input. Handles space encoding (%s) and shell character escaping.
- Parameters:
text(string): Text to type.
9. android_press_key
Press a hardware or navigation key.
- Supported Keys:
HOME,BACK,ENTER,TAB,ESC,DELETE,SPACE,VOLUME_UP,VOLUME_DOWN,POWER,APP_SWITCH,CAMERA, etc. - Parameters:
key(string): Key name or numeric keycode.
10. android_scroll
Directional scrolling calculated against actual screen dimensions.
- Parameters:
direction(string:up|down|left|right)amount(optional number): Scroll distance in pixels.
11. android_launch_app
Launch an application by its package name.
- Parameters:
packageName(string): e.g.com.android.settings,com.google.android.youtube.activity(optional string): Specific activity name.
12. android_current_app
Inspect the currently focused foreground package and activity.
13. android_execute_action (Unified Computer-Use Tool)
Single unified action dispatcher supporting all actions: tap, swipe, type, press_key, click_element, scroll, launch_app.
{
"action": "click_element",
"text": "Wi-Fi"
}
🤖 Recommended AI Workflow: Observe → Reason → Act → Verify
1. OBSERVE:
AI calls `android_screenshot` and `android_ui_dump`.
2. REASON:
AI inspects visual and UI structure to identify target elements.
3. ACT:
AI calls `android_click_element`, `android_type_text`, or `android_scroll`.
4. VERIFY:
AI captures another screenshot/dump to confirm desired state change.
🧪 Testing
Run the automated test suite:
npm test
Tests use Vitest and mock the ADB execution layer, allowing full unit verification without requiring a physical Android device attached during CI/CD.
🔒 Security Best Practices
- No Arbitrary Shell Execution: The server does NOT expose raw
adb shellexecution tools. - Safe Process Invocation: All commands use
child_process.execFilewith explicit argument arrays to prevent shell injection. - Input Sanitization: Package names, keycodes, and coordinate parameters are strictly validated via Zod schemas and bounds checking.
- Stderr Isolated Logging: All logs are directed exclusively to
stderrto maintain strict JSON-RPC protocol compliance onstdout.
📄 License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。