Skip to main content

Android ADB MCP Server for device automation via Model Context Protocol

Project description

mcadb

A Model Context Protocol server that gives AI assistants direct control over Android devices through ADB. Point any MCP-compatible client at a phone plugged into USB, and it can take screenshots, tap buttons, launch apps, inspect UI elements, transfer files, and run shell commands — all through structured, type-safe tool calls.

Built on FastMCP with a modular mixin architecture. 50 tools across 6 domains. Tested on real hardware.

Quick Start

# Run directly (no install)
uvx mcadb

# Or install and run
uv add mcadb
mcadb

MCP Client Configuration

Add to your MCP client's config (Claude Desktop, Claude Code, etc.):

{
  "mcpServers": {
    "mcadb": {
      "command": "uvx",
      "args": ["mcadb"]
    }
  }
}

For Claude Code:

claude mcp add mcadb -- uvx mcadb

For local development:

claude mcp add mcadb -- uv run --directory /path/to/mcp-adb mcadb

Prerequisites

  • Python 3.11+
  • ADB installed and on PATH (adb devices should work)
  • USB debugging enabled on the Android device
  • Device connected via USB (or adb connect for network)

What Can It Do?

Standard Tools (always available)

Domain Tool What it does
Devices devices_list Discover connected devices (USB + network)
devices_use Set active device for multi-device setups
devices_current Show which device is selected
device_info Battery, WiFi, storage, Android version, model
Input input_tap Tap at screen coordinates
input_swipe Swipe between two points
input_scroll_down Scroll down (auto-detects screen size)
input_scroll_up Scroll up (auto-detects screen size)
input_back Press Back
input_home Press Home
input_recent_apps Open app switcher
input_key Send any key event (VOLUME_UP, ENTER, etc.)
input_text Type text into focused field
clipboard_set Set clipboard (handles special chars), optional auto-paste
Apps app_launch Launch app by package name
app_open_url Open URL in default browser
app_close Force stop an app
app_current Get the foreground app and activity
Screen screenshot Capture screen as PNG
screen_size Get display resolution
screen_density Get display DPI
screen_on / screen_off Wake or sleep the display
UI ui_dump Dump accessibility tree (all visible elements)
ui_find_element Search for elements by text, ID, class, or description
wait_for_text Poll until text appears on screen
wait_for_text_gone Poll until text disappears
tap_text Find an element by text and tap it
Config config_status Show current settings
config_set_developer_mode Toggle developer tools
config_set_screenshot_dir Set where screenshots are saved

Developer Mode Tools

Enable with config_set_developer_mode(true) to unlock power-user tools. Destructive operations (uninstall, clear data, reboot, delete) require user confirmation via MCP elicitation.

Domain Tool What it does
Shell shell_command Run any shell command on device
Input input_long_press Press and hold gesture
Apps app_list_packages List installed packages (with filters)
app_install Install APK from host
app_uninstall Remove an app (with confirmation)
app_clear_data Wipe app data (with confirmation)
activity_start Launch activity with full intent control
broadcast_send Send broadcast intents
Screen screen_record Record screen to MP4
screen_set_size Override display resolution
screen_reset_size Restore original resolution
Device device_reboot Reboot device (with confirmation)
logcat_capture Capture system logs
logcat_clear Clear log buffer
Files file_push Transfer file to device
file_pull Transfer file from device
file_list List directory contents
file_delete Delete file (with confirmation)
file_exists Check if file exists

Resources

URI Description
adb://devices Connected device list
adb://device/{id} Detailed device properties
adb://apps/current Currently focused app
adb://screen/info Screen resolution and DPI
adb://help Tool reference and tips

Usage Examples

Screenshot + UI inspection loop (how an AI assistant typically navigates):

1. screenshot()           → See what's on screen
2. ui_dump()              → Get element tree with tap coordinates
3. tap_text("Settings")   → Tap the "Settings" element
4. wait_for_text("Wi-Fi") → Wait for the screen to load
5. screenshot()           → Verify the result

Open a URL and check what loaded:

1. app_open_url("https://example.com")
2. wait_for_text("Example Domain")
3. screenshot()

Install and launch an APK (developer mode):

1. config_set_developer_mode(true)
2. app_install("/path/to/app.apk")
3. app_launch("com.example.myapp")
4. logcat_capture(filter_spec="MyApp:D *:S")

Multi-device workflow:

1. devices_list()                → See all connected devices
2. devices_use("SERIAL_NUMBER")  → Select target device
3. device_info()                 → Check battery, WiFi, storage
4. screenshot()                  → Capture from selected device

Architecture

The server uses FastMCP's MCPMixin pattern to organize 50 tools into focused, single-responsibility modules:

src/
  server.py          ← FastMCP app, ADBServer (thin orchestrator)
  config.py          ← Persistent config (~/.config/adb-mcp/config.json)
  models.py          ← Pydantic models (DeviceInfo, CommandResult, ScreenshotResult)
  mixins/
    base.py          ← ADB command execution, injection-safe shell quoting
    devices.py       ← Device discovery, info, logcat, reboot
    input.py         ← Tap, swipe, scroll, keys, text, clipboard, shell
    apps.py          ← Launch, close, install, intents, broadcasts
    screenshot.py    ← Capture, recording, display settings
    ui.py            ← Accessibility tree, element search, text polling
    files.py         ← Push, pull, list, delete, exists

ADBServer inherits all six mixins. Each mixin calls run_shell_args() (injection-safe) or run_adb() on the base class. The base handles device targeting, subprocess execution, and timeouts.

Security Model

All tools that accept user-provided values use injection-safe command execution:

  • run_shell_args() quotes every argument with shlex.quote() before sending to the device shell. This is the default for all tools.
  • run_shell() (string form) is only used by the developer-mode shell_command tool, where the user intentionally provides a raw command.
  • input_text() rejects special characters ($ ( ) ; | & < > etc.) and directs users to clipboard_set() instead.
  • input_key() strips non-alphanumeric characters from key codes.
  • Destructive operations (uninstall, clear data, delete, reboot) require user confirmation via MCP elicitation.
  • Developer mode is off by default and must be explicitly enabled. Settings persist at ~/.config/adb-mcp/config.json.

Docker

docker build -t mcadb .
docker run --privileged -v /dev/bus/usb:/dev/bus/usb mcadb

The --privileged flag and USB volume mount are required for ADB to detect physical devices.

MCP client config for Docker:

{
  "mcpServers": {
    "mcadb": {
      "command": "docker",
      "args": ["run", "-i", "--privileged", "-v", "/dev/bus/usb:/dev/bus/usb", "mcadb"]
    }
  }
}

Development

# Clone and install
git clone https://git.supported.systems/MCP/mcp-adb.git
cd mcp-adb
uv sync --group dev

# Run locally
uv run mcadb

# Lint
uv run ruff check src/

# Format
uv run ruff format src/

# Type check
uv run mypy src/

Configuration

Settings are stored at ~/.config/adb-mcp/config.json (override with ADB_MCP_CONFIG_DIR env var):

{
  "developer_mode": false,
  "default_screenshot_dir": null,
  "auto_select_single_device": true
}
Setting Default Description
developer_mode false Unlock advanced tools (shell, install, reboot, etc.)
default_screenshot_dir null Directory for screenshots/recordings (null = cwd)
auto_select_single_device true Skip device selection when only one is connected

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcadb-0.3.1.tar.gz (104.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcadb-0.3.1-py3-none-any.whl (31.4 kB view details)

Uploaded Python 3

File details

Details for the file mcadb-0.3.1.tar.gz.

File metadata

  • Download URL: mcadb-0.3.1.tar.gz
  • Upload date:
  • Size: 104.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mcadb-0.3.1.tar.gz
Algorithm Hash digest
SHA256 c23d5d5688a7028156829e8f93b141edb445a776753f3fa6802e3e2c19a92351
MD5 b0597f34342e694673a9deef09989266
BLAKE2b-256 06f5fabf3cea908c976fc1af4c95018df01532ad499bfa88979a005e78959086

See more details on using hashes here.

File details

Details for the file mcadb-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: mcadb-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 31.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mcadb-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 90ad5eb55395a0ea9deb264c24c9a2fa075789f2783f8b9e68a6bee0a6831952
MD5 b563c29531fcfa24f732e3a0c261a68f
BLAKE2b-256 8d705263df78b8559b8738d908eff709561e2d84f2e99057abc34f9c403fad1d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page