Skip to main content
Glama
swamiabhishek45

Android Control MCP Server

README.md
# 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 `stderr` logging to guarantee stdio MCP stream integrity.
- **๐Ÿ”„ Multi-Device Support**: Auto-detects connected devices or targets specific devices via `ANDROID_DEVICE_ID`.

---

## ๐Ÿ—๏ธ Architecture

```text
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

1. **Node.js**: `v20.0.0` or higher (`node -v`)
2. **Android SDK Platform-Tools**: ADB (`adb`) installed and accessible in your system `PATH` (or configured via `ADB_PATH`).
3. **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

```bash
adb devices -l
```

You should see your device listed as `device`:
```text
List of devices attached
emulator-5554          device product:sdk_gphone64_arm64 model:sdk_gphone64_arm64
```

---

## ๐Ÿš€ Installation & Quick Start

```bash
# 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:

```env
# 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`

```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**:
  ```json
  {
    "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**:
  ```json
  {
    "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, default `false`)*: 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`.

```json
{
  "action": "click_element",
  "text": "Wi-Fi"
}
```

---

## ๐Ÿค– Recommended AI Workflow: Observe โ†’ Reason โ†’ Act โ†’ Verify

```text
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:

```bash
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 shell` execution tools.
- **Safe Process Invocation**: All commands use `child_process.execFile` with 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 `stderr` to maintain strict JSON-RPC protocol compliance on `stdout`.

---

## ๐Ÿ“„ License

MIT

TDQS

B3.2/5.0

Scored across 13 tools

Disambiguation4/5

Most tools have clearly distinct purposes, but android_tap, android_click_element, and android_execute_action overlap in interaction, differing only by abstraction level (raw coordinates, element-based, and high-level bundling). Descriptions help disambiguate these, so the overlap is minor.

Naming Consistency3/5

All tools share the 'android_' prefix, which is good, but the naming pattern is inconsistent: some are bare nouns (screenshot, scroll), some are verb phrases (type_text, launch_app), and some are noun phrases (current_app, device_info). This mix of conventions is still readable but not fully predictable.

Tool Count5/5

With 13 tools, the server is well-scoped for a mobile automation domain, offering both low-level gestures and high-level actions without redundancy. This count is appropriate and each tool earns its place.

Completeness4/5

The tool surface covers core UI automation: screen capture, interaction (tap, swipe, type, press, scroll), element discovery (ui_dump, find_element, click_element), and app control (launch_app, current_app). Missing advanced gestures like pinch or long-press, but these are not essential for typical agent tasks.

Maintenance

ActivityMaintained
ResponsivenessNo issues