# Android Action MCP Server

English | [简体中文](./README.zh-CN.md)

A production-ready Model Context Protocol (MCP) server that enables AI assistants like Claude Code to interact with Android devices through ADB.

## Overview

This MCP server provides comprehensive programmatic access to Android devices, allowing AI assistants to:
- Capture UI trees and screenshots from Android devices
- Interact with UI elements (click, type, swipe, drag)
- Navigate apps and perform actions
- Monitor device state and network activity
- Manage apps and permissions
- Execute automation workflows

The implementation is inspired by:
- **scrcpy**: For efficient Android device communication patterns
- **playwright-mcp**: For MCP tool design patterns

## Features

### ✅ 31 Production-Ready Tools (100% Complete)

#### Tier 1: Essential Tools (11/11)
Core automation capabilities:
- **android_snapshot**: Capture structured UI tree (primary interaction method)
- **android_screenshot**: Capture PNG screenshots
- **android_click**: Tap, long-press, and double-tap gestures
- **android_type**: Text input with auto-focus
- **android_navigate**: Launch apps and open URLs/deep links
- **android_navigate_back**: Back button navigation
- **android_press_key**: Hardware/software key events
- **android_wait_for**: Wait for UI conditions or time delays
- **android_swipe**: Directional swipe gestures
- **android_device_info**: Device specs and capabilities
- **android_current_activity**: Get foreground app and activity

#### Tier 2: Important Tools (9/9)
Comprehensive automation features:
- **android_scroll**: Scroll until element visible
- **android_fill_form**: Batch form field filling
- **android_apps**: App management (list/switch/recent/close)
- **android_close**: Force stop apps
- **android_select_option**: Spinner (dropdown) selection
- **android_install**: APK installation
- **android_grant_permission**: Runtime permission granting
- **android_handle_dialog**: Multilingual dialog handling
- **android_console_messages**: Logcat message retrieval

#### Tier 3: Advanced Tools (6/6)
Specialized power-user features:
- **android_drag**: Drag-and-drop gestures
- **android_evaluate**: Safe shell command execution
- **android_resize**: Screen orientation control
- **android_clear_app_data**: Clear app data and cache
- **android_file_select**: File upload and selection
- **android_network_requests**: Network activity monitoring

#### Tier 4: Optional Tools (5/5)
Nice-to-have features:
- **android_hover**: Hover interactions (accessibility/stylus)
- **android_open_notification**: Open notification drawer
- **android_open_quick_settings**: Open quick settings panel
- **android_set_clipboard**: Set clipboard text
- **android_get_clipboard**: Get clipboard text

## Prerequisites

1. **Go 1.21+** installed
2. **ADB (Android Debug Bridge)** installed and in PATH
   ```bash
   # macOS
   brew install android-platform-tools

   # Ubuntu/Debian
   sudo apt-get install android-tools-adb
   ```
3. **scrcpy** installed (required for screenshot functionality)
   ```bash
   # macOS
   brew install scrcpy

   # Ubuntu/Debian
   sudo apt install scrcpy

   # Arch Linux
   sudo pacman -S scrcpy

   # Windows (via Scoop)
   scoop install scrcpy
   ```

   **Why scrcpy?** This project uses scrcpy's efficient screencap method for capturing screenshots, which provides better compatibility across different Android devices compared to the native `adb shell screenrecap` command. Some devices (e.g., Huawei EMUI) don't support the native command, but scrcpy works universally.

4. **Android device** with USB debugging enabled (API 21+)
   - Enable Developer Options: Settings → About Phone → Tap "Build Number" 7 times
   - Enable USB Debugging: Settings → Developer Options → USB Debugging

## Installation

### Option 1: Download Pre-built Binary (Recommended)

Download the latest release for your platform:

**[→ Download Latest Release](https://github.com/holocode-ai/android-action-mcp/releases/latest)**

Available platforms:
- **Linux**: `android-mcp-server-linux-amd64`, `android-mcp-server-linux-arm64`
- **macOS**: `android-mcp-server-darwin-amd64` (Intel), `android-mcp-server-darwin-arm64` (Apple Silicon)
- **Windows**: `android-mcp-server-windows-amd64.exe`

After downloading:

```bash
# macOS/Linux: Make executable
chmod +x android-mcp-server-*

# Verify with SHA256 checksum
sha256sum android-mcp-server-*
# Compare with checksums.txt from release

# Move to your preferred location (optional)
sudo mv android-mcp-server-* /usr/local/bin/android-mcp-server
```

### Option 2: Build from Source

```bash
# Clone the repository
git clone https://github.com/holocode-ai/android-action-mcp.git
cd android-action-mcp

# Build the server
go build -o android-mcp-server ./cmd/server

# Or use make
make build
```

### Verify ADB connection

```bash
# Connect your Android device via USB
# Check device is recognized
adb devices

# Output should show your device:
# List of devices attached
# XXXXXXXXXXXXX    device
```

## Usage

### With Claude Code (VS Code Extension)

#### Option 1: Project-specific configuration (Recommended)

This project includes a pre-configured `.claude/mcp.json` file. When you open this project in Claude Code, the MCP server will be automatically available.

To use in other projects, copy the example configuration:

```bash
# Copy the example config
cp mcp.json.example /path/to/your/project/.claude/mcp.json

# Update the command path to point to your build
```

#### Option 2: Global configuration

Add to your global MCP settings (`~/.config/claude-code/mcp.json`):

```json
{
  "mcpServers": {
    "android-action": {
      "command": "/absolute/path/to/android-mcp-server",
      "env": {},
      "disabled": false
    }
  }
}
```

**Note**: Replace the command path with the absolute path to your `android-mcp-server` binary.

### With Cline/Claude Dev (VS Code Extension)

Add to your MCP settings file (`~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` on macOS):

```json
{
  "mcpServers": {
    "android-action": {
      "command": "/absolute/path/to/android-mcp-server",
      "args": [],
      "disabled": false
    }
  }
}
```

### With Claude Desktop App

Add to Claude Desktop's MCP configuration:

**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
**Linux**: `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "android-action": {
      "command": "/absolute/path/to/android-mcp-server"
    }
  }
}
```

After adding the configuration, restart Claude Desktop to load the MCP server.

### With Other MCP Clients

The server uses stdio transport and is compatible with any MCP client:

```bash
# Run directly (communicates via stdin/stdout)
./android-mcp-server

# Show help
./android-mcp-server --help
```

## Tool Reference

### Core Element Interaction

#### android_snapshot
Capture structured UI tree - the primary method for UI interaction.

**Parameters:** None

**Returns:** Formatted text tree with elements, resource-ids, text, descriptions, bounds, and interaction capabilities

**Usage:**
```javascript
android_snapshot()
```

#### android_click
Perform click on UI element.

**Parameters:**
- `element` (string, required): Human-readable element description
- `ref` (string, required): Element reference from snapshot (resource-id, text, or content-desc)
- `long_click` (boolean, optional): Perform long press instead of tap
- `double_click` (boolean, optional): Perform double tap

**Usage:**
```javascript
android_click({
  element: "Login button",
  ref: "loginButton"
})
```

#### android_type
Input text into editable element.

**Parameters:**
- `element` (string, required): Element description
- `ref` (string, required): Element reference from snapshot
- `text` (string, required): Text to type
- `submit` (boolean, optional): Press Enter after typing
- `clear_first` (boolean, optional): Clear existing text before typing

**Usage:**
```javascript
android_type({
  element: "Username field",
  ref: "usernameInput",
  text: "user@example.com",
  clear_first: true
})
```

#### android_fill_form
Fill multiple form fields in one operation.

**Parameters:**
- `fields` (array, required): Array of field objects with `ref`, `type`, and `value`

**Usage:**
```javascript
android_fill_form({
  fields: [
    {name: "Username", ref: "username", type: "textbox", value: "user@example.com"},
    {name: "Password", ref: "password", type: "textbox", value: "secret123"},
    {name: "Remember me", ref: "rememberMe", type: "checkbox", value: "true"}
  ]
})
```

### Navigation & App Control

#### android_navigate
Launch app or open URL/deep link.

**Parameters:**
- `package` (string, optional): App package name
- `activity` (string, optional): Specific activity to launch
- `url` (string, optional): URL or deep link to open

**Usage:**
```javascript
// Launch app
android_navigate({package: "com.android.chrome"})

// Open URL
android_navigate({url: "https://example.com"})
```

#### android_apps
Manage running apps.

**Parameters:**
- `action` (string, required): "list", "switch", "recent", "close"
- `package` (string, optional): Package name for switch/close actions

**Usage:**
```javascript
// List running apps
android_apps({action: "list"})

// Switch to app
android_apps({action: "switch", package: "com.android.chrome"})
```

### Screen Analysis

#### android_screenshot
Capture PNG screenshot.

**Parameters:**
- `filename` (string, optional): Filename (default: screenshot-{timestamp}.png)
- `save_path` (string, optional): Directory to save screenshot

**Usage:**
```javascript
android_screenshot({
  filename: "app-screenshot.png",
  save_path: "./screenshots"
})
```

### Gestures & Scrolling

#### android_swipe
Perform swipe gesture.

**Parameters:**
- `direction` (string, required): "up", "down", "left", "right"
- `element` (string, optional): Element to swipe within
- `ref` (string, optional): Element reference
- `distance` (string, optional): "short", "medium", "long"
- `speed` (string, optional): "fast", "medium", "slow"

**Usage:**
```javascript
android_swipe({direction: "up", distance: "medium"})
```

#### android_scroll
Scroll in container until element visible.

**Parameters:**
- `container` (string, required): Scrollable container description
- `container_ref` (string, required): Container reference (must be [scrollable])
- `target_element` (string, optional): Element to scroll to
- `direction` (string, optional): Scroll direction
- `max_scrolls` (number, optional): Maximum scroll attempts

**Usage:**
```javascript
android_scroll({
  container: "Product list",
  container_ref: "productList",
  target_element: "Item 50"
})
```

### Wait & Synchronization

#### android_wait_for
Wait for condition or time delay.

**Parameters:**
- `text` (string, optional): Wait for text to appear
- `text_gone` (string, optional): Wait for text to disappear
- `element` (string, optional): Wait for element to appear
- `element_gone` (string, optional): Wait for element to disappear
- `time` (number, optional): Wait for N seconds
- `timeout` (number, optional): Max wait time (default: 30)

**Usage:**
```javascript
// Wait for loading to finish
android_wait_for({text_gone: "Loading..."})

// Wait 2 seconds
android_wait_for({time: 2})
```

### Debugging & Device State

#### android_device_info
Get device information.

**Parameters:** None

**Returns:** Device model, Android version, screen resolution, DPI, SDK version

**Usage:**
```javascript
android_device_info()
```

#### android_console_messages
Get logcat messages.

**Parameters:**
- `only_errors` (boolean, optional): Filter for errors/warnings only
- `tag` (string, optional): Filter by logcat tag
- `max_lines` (number, optional): Limit output lines (default: 100)

**Usage:**
```javascript
android_console_messages({only_errors: true, max_lines: 50})
```

#### android_network_requests
Monitor network activity.

**Parameters:**
- `package` (string, optional): Filter by package name
- `duration` (number, optional): Capture duration in seconds (default: 10)

**Usage:**
```javascript
android_network_requests({package: "com.example.app", duration: 5})
```

### File & Permission Management

#### android_install
Install APK package.

**Parameters:**
- `apk_path` (string, required): Local path to APK file
- `replace` (boolean, optional): Replace existing app (default: true)
- `grant_permissions` (boolean, optional): Grant all permissions (default: false)

**Usage:**
```javascript
android_install({
  apk_path: "./app-debug.apk",
  grant_permissions: true
})
```

#### android_grant_permission
Grant runtime permission to app.

**Parameters:**
- `package` (string, required): App package name
- `permission` (string, required): Permission name

**Usage:**
```javascript
android_grant_permission({
  package: "com.example.app",
  permission: "android.permission.CAMERA"
})
```

For complete tool documentation, see [CLAUDE.md](./CLAUDE.md).

## Architecture

```
┌─────────────────┐         ┌──────────────────┐         ┌─────────────────┐
│   AI Assistant  │ ◄─MCP─► │  Go MCP Server   │ ◄─ADB─► │  Android Device │
│  (Claude Code)  │         │  (This Project)  │         │                 │
└─────────────────┘         └──────────────────┘         └─────────────────┘
                                     │                            │
                                     ├─ 31 Tools                  │
                                     ├─ ADB Communication         │
                                     └─ Device Control            │
```

### Components

1. **MCP Server Layer** (`internal/mcp/`)
   - Implements MCP protocol using official Go SDK
   - Exposes 31 tools to AI clients
   - Handles stdio transport

2. **ADB Communication Layer** (`internal/adb/`)
   - Manages ADB connection to Android devices
   - Executes shell commands for device control
   - Based on scrcpy's proven architecture

3. **Tools Layer** (`internal/tools/`)
   - Implements individual MCP tools
   - UI tree parsing and element selection
   - Coordinate calculation and gesture handling

## Development

### Project Structure

```
android-action-mcp/
├── cmd/
│   └── server/          # Main entry point
├── internal/
│   ├── mcp/             # MCP server implementation
│   ├── tools/           # 31 MCP tool implementations
│   ├── adb/             # ADB communication layer
│   └── uitree/          # UI tree parsing and selector
├── android-test-app/    # Custom test application
├── go.mod
├── Makefile
├── CLAUDE.md            # Developer documentation
└── README.md            # This file
```

### Building

```bash
# Build
make build

# Run tests
make test

# Clean build artifacts
make clean
```

### Testing

All 31 tools have been tested on real hardware:
- **Test Device**: HUAWEI ANA-AN00, Android 12 (SDK 31), 1080x2340
- **Test App**: Custom MCP Test App (com.test.mcptest)
- **Test Coverage**: 100% of implemented tools tested with real device interactions

## Troubleshooting

### No devices connected

```bash
# Error: no Android devices connected
# Solution: Check USB connection and USB debugging is enabled
adb devices

# If device shows as "unauthorized", check device screen for authorization dialog
```

### ADB not found

```bash
# Error: failed to initialize ADB
# Solution: Install ADB and ensure it's in PATH
which adb

# macOS
brew install android-platform-tools

# Linux
sudo apt-get install android-tools-adb
```

### Permission denied

```bash
# Linux: ADB may need udev rules for USB access
# Create file: /etc/udev/rules.d/51-android.rules
# Content: SUBSYSTEM=="usb", ATTR{idVendor}=="XXXX", MODE="0666", GROUP="plugdev"
# Replace XXXX with your device's vendor ID (from lsusb)

sudo udevadm control --reload-rules
sudo udevadm trigger
```

### scrcpy not found

```bash
# Error: scrcpy not found or not in PATH
# Solution: Install scrcpy (required for screenshot functionality)

# macOS
brew install scrcpy

# Ubuntu/Debian
sudo apt install scrcpy

# Verify installation
which scrcpy
scrcpy --version
```

### Tool-specific issues

- **android_hover**: May not work on touchscreen-only devices (expected behavior)
- **android_set_clipboard**: May not work on some manufacturers (e.g., Huawei EMUI)
- **android_screenshot**: Must provide `save_path` parameter (base64 exceeds MCP token limits)

## References

- [Model Context Protocol](https://modelcontextprotocol.io/)
- [MCP Go SDK](https://github.com/modelcontextprotocol/go-sdk)
- [scrcpy](https://github.com/Genymobile/scrcpy) - Android screen mirroring (inspiration for ADB communication)
- [Android ADB Documentation](https://developer.android.com/tools/adb)
- [playwright-mcp](https://github.com/microsoft/playwright-mcp) - Reference implementation

## License

MIT License - See LICENSE file for details

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Project Status

✅ **Production Ready** - All 31 planned tools implemented and tested on real hardware.

The server provides comprehensive Android automation capabilities through the MCP protocol, enabling AI assistants to perform sophisticated testing and automation workflows.
