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. 65 tools across 8 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
Connectivity adb_connect Connect to device over TCP/IP
adb_disconnect Disconnect a network device
adb_pair Wireless debugging pairing (Android 11+)
device_properties Batch getprop (model, SoC, versions, serial, ABI)
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
Settings settings_get Read any system/global/secure setting
notification_list List recent notifications (title, text, package)
clipboard_get Read clipboard contents
media_control Play/pause/next/previous/stop/volume
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
Connectivity adb_tcpip Switch USB device to TCP/IP mode
Settings settings_put Write system/global/secure setting
wifi_toggle Enable/disable WiFi
bluetooth_toggle Enable/disable Bluetooth
airplane_mode_toggle Toggle airplane mode (with confirmation)
screen_brightness Set brightness 0-255
screen_timeout Set screen timeout duration

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")

Connect to a WiFi device:

1. adb_connect("10.20.0.25")    → Connect to network device
2. devices_list()                → Verify it appears
3. screenshot()                  → Capture from network device

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

Read settings and control media:

1. settings_get("global", "wifi_on")   → Check WiFi state
2. notification_list()                  → See recent notifications
3. media_control("pause")              → Pause media playback
4. clipboard_get()                     → Read clipboard contents

Architecture

The server uses FastMCP's MCPMixin pattern to organize 65 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
    connectivity.py  ← TCP/IP connect/disconnect, wireless pairing, properties
    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
    settings.py      ← System settings, radios, brightness, notifications, media

ADBServer inherits all eight 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.5.0.tar.gz (127.4 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.5.0-py3-none-any.whl (44.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mcadb-0.5.0.tar.gz
  • Upload date:
  • Size: 127.4 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.5.0.tar.gz
Algorithm Hash digest
SHA256 6711d08e26026599d73da27237bcaf1ace599ed70ba3c2d67a058b50f1511fea
MD5 6121a0a9aac5ee36339fbfc113fdbaa0
BLAKE2b-256 0f2b5f42be1acbfa1d4bfdb99a654e608859909701dd4765c236aae96e4640f6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: mcadb-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 44.1 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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 adc001ecca5e078528b277f3f47587e1d3bbefd7b06456ae97c8e88f4e920f52
MD5 79d036880f7decc68dc6e0a486837d2e
BLAKE2b-256 abfc18d941ec5156e7569230f5add48a82fa127a2d543ce60b91a23e99886e28

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