adb-mcp

adb-mcp

A comprehensive MCP server for Android Debug Bridge, enabling AI agents to control Android devices through structured tools like launching apps, UI automation, file operations, and log capture.

Category
访问服务器

README

adb-mcp

A comprehensive, structured-output MCP server around the Android Debug Bridge.

Give an AI agent (Claude Code, or any MCP client) direct, first-class control of an Android device — launch apps, drive the UI, capture logs and screenshots, push/pull files, wire up port forwards — so the workflow becomes:

agent → launch_package() → capture_screen() → tap_element("Send") → logcat_dump() → pull() → analyse()

…with no copy/paste of shell output, and no unrestricted adb shell tool (that escape hatch is opt-in and off by default).

90 tools across 9 groups. Every tool returns structured JSON — never raw terminal text.


Why

The usual loop is: you type adb shell …, copy the output, paste it to the AI, it reasons, tells you the next command, you type it. adb-mcp collapses that into tools the agent calls itself. It was built for mobile reverse-engineering / QA automation, but works for any adb task.

Design principles

  • Idempotent, named operationsforce_stop(pkg), reverse_port(...) — not execute_any_shell_command().
  • Structured outputs{"pid": 8421, "status": "running"}, not a wall of text.
  • Scoped, not omnipotent — no generic shell by default. run_shell exists only as an explicit opt-in (ADB_MCP_ALLOW_SHELL=1). Destructive tools (delete_file, clear_app_data, uninstall) are clearly named and delete_file refuses protected roots (/, /system, /data, …).
  • Multi-device aware — every device tool takes an optional serial; get_devices flags is_usb so you can tell a USB phone from a network/emulator target (e.g. WSA).

Install

pip install adbmcp          # from PyPI
# or from a clone:
pip install -e .

PyPI package name is adbmcp; the import package and python -m target are adb_mcp, and the installed console command is adbmcp.

Requires Python ≥ 3.10 and the Android platform-tools (adb) on your machine. adb is auto-detected from ANDROID_HOME, the default SDK location, scoop, or PATH; override with ADB_PATH.

Register with an MCP client

An MCP server is just a program the client launches and talks to over stdio. "Installing" it means telling your client what command to run plus any env — the same three things everywhere: command, args, env. After pip install adbmcp you get both an adbmcp command and python -m adb_mcp.server; use whichever your client resolves (see the Windows PATH note if a bare adbmcp isn't found). Sanity-check it launches:

adbmcp        # starts and waits on stdio; Ctrl-C to exit. No output = healthy.

<details open> <summary><b>Claude Code</b> (CLI)</summary>

claude mcp add adb --env ADB_SERIAL=RFCWC17BKJY -- adbmcp

Add --scope user to enable it in every project. Or drop a .mcp.json in a project root (see examples/mcp.json):

{
  "mcpServers": {
    "adb": {
      "command": "adbmcp",
      "args": [],
      "env": {
        "ADB_SERIAL": "RFCWC17BKJY",   // optional default device
        "ADB_MCP_ALLOW_SHELL": "0"      // set "1" to enable run_shell
      }
    }
  }
}

Run /mcp inside Claude Code to confirm it connected. </details>

<details> <summary><b>Claude Desktop</b></summary>

Edit claude_desktop_config.json (Windows: %APPDATA%\Claude\, macOS: ~/Library/Application Support/Claude/) and restart the app:

{
  "mcpServers": {
    "adb": {
      "command": "adbmcp",
      "args": [],
      "env": { "ADB_SERIAL": "RFCWC17BKJY" }
    }
  }
}

</details>

<details> <summary><b>Codex</b> (OpenAI Codex CLI)</summary>

codex mcp add adb -- adbmcp, or add to ~/.codex/config.toml:

[mcp_servers.adb]
command = "adbmcp"
args = []

[mcp_servers.adb.env]
ADB_SERIAL = "RFCWC17BKJY"

</details>

<details> <summary><b>opencode</b></summary>

Add to opencode.json (project root) or ~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "adb": {
      "type": "local",
      "command": ["adbmcp"],
      "enabled": true,
      "environment": { "ADB_SERIAL": "RFCWC17BKJY" }
    }
  }
}

</details>

<details> <summary><b>Cursor</b></summary>

.cursor/mcp.json (project) or ~/.cursor/mcp.json (global) — same shape as Claude:

{
  "mcpServers": {
    "adb": { "command": "adbmcp", "args": [], "env": { "ADB_SERIAL": "RFCWC17BKJY" } }
  }
}

</details>

<details> <summary><b>VS Code</b> (Copilot Agent mode)</summary>

.vscode/mcp.json — note the servers key and explicit type:

{
  "servers": {
    "adb": { "type": "stdio", "command": "adbmcp", "args": [], "env": { "ADB_SERIAL": "RFCWC17BKJY" } }
  }
}

</details>

Any other MCP-capable client (Cline, Zed, Windsurf, …) works the same way — point it at the adbmcp command with your env; only the config file location differs.

<a id="windows-path-note"></a>

Windows PATH note. Clients spawn the server in their own environment and may not inherit your shell's PATH, so a bare adbmcp can fail to resolve. If a client won't start it, use the absolute interpreter + module form (and pin ADB_PATH too):

{
  "command": "C:\\Users\\you\\AppData\\Local\\Programs\\Python\\Python312\\python.exe",
  "args": ["-m", "adb_mcp.server"],
  "env": {
    "ADB_PATH": "C:\\Users\\you\\AppData\\Local\\Android\\Sdk\\platform-tools\\adb.exe",
    "ADB_SERIAL": "RFCWC17BKJY"
  }
}

Configuration

env var meaning
ADB_PATH Path to adb (auto-detected if unset).
ANDROID_HOME / ANDROID_SDK_ROOT SDK root used for adb auto-detection.
ADB_SERIAL Default device serial. USB phone: RFCWC17BKJY; WSA/emulator: 127.0.0.1:58526.
ADB_MCP_ALLOW_SHELL 1/true enables the opt-in run_shell escape hatch (default off).

Every device-facing tool also accepts a serial argument to override per call, and you can switch the session default at runtime with set_default_device.


Tool reference (90)

Device (15)

get_devices · get_state · adb_version · get_device_properties · get_screen_info · get_battery · connect · disconnect · wait_for_device · reboot · set_default_device · get_default_device · root_adb · unroot_adb · remount

Apps (16)

list_packages · launch_package · launch_activity · force_stop · kill_background · clear_app_data · app_status · get_current_activity · get_package_info · install_apk · uninstall · grant_permission · revoke_permission · set_package_enabled · start_service · send_broadcast

Input (12)

tap · long_press · swipe · drag · text · keyevent · press_home · press_back · press_recents · press_power · press_enter · wake_and_unlock

UI automation (3)

dump_ui · find_elements · tap_element — parse the live view hierarchy (uiautomator) and tap elements by text / resource-id / content-description instead of guessing pixel coordinates.

Logs (8)

logcat_start · logcat_stop · logcat_dump · logcat_filter · logcat_clear · get_crash_log · get_anr_traces · capture_bugreport — background capture with parsed records {time, pid, tid, level, tag, message}.

Media (5)

capture_screen (inline PNG) · capture_screen_to_file · capture_screen_base64 · record_screen_start · record_screen_stop

Files (9)

list_files · file_exists · stat_file · pull · push · read_file · write_file · make_dir · delete_fileread_file/write_file/list_files support as_root (su -c …) for rooted devices (WSA/Magisk).

Network (11)

forward_port · reverse_port · list_forwards · list_reverses · remove_forward · remove_reverse · clear_forwards · get_ip_address · set_wifi · set_mobile_data · set_airplane_modereverse_port maps a device port to your PC (local API/CDN shims).

System (11)

get_prop · set_prop · get_setting · put_setting · list_processes · get_meminfo · get_top · get_uptime · dumpsys (scoped to a named service) · list_services · run_shell (opt-in)


Example: investigate an in-app action

Prompt: "Find what happens when I send a fleet."

launch_package("com.geargames.homeworld")
capture_screen()                       # observe
tap_element(text="Fleet")              # navigate via the view hierarchy
logcat_start(clear=True)
tap_element(text="Send")               # trigger
logcat_dump(tags=["Unity","libc"])     # structured records
pull("/sdcard/Android/data/com.game/files/save.db", "dumps/save.db")

Local-server / shim workflow

reverse_port(device_port=7071, host_port=7071)   # app's localhost:7071 -> your PC shim
reverse_port(device_port=7072, host_port=7072)
launch_package("com.geargames.homeworld")
logcat_filter(tags=["Curl","PlayFab"])

Development

pip install -e ".[dev]"
pytest -q          # device-free smoke tests (imports, registration, parsers)
ruff check .

CI runs the same on Python 3.10–3.12.

Safety

MCP servers execute local commands and can touch files, logs, and devices, so overly permissive ones become dangerous when an agent chains their tools. adb-mcp is deliberately scoped:

  • No always-on arbitrary shell. run_shell is the only general-shell tool and it is off unless ADB_MCP_ALLOW_SHELL=1.
  • Injection-hardened. adb shell concatenates its args through the device's sh, so every list-form command is shlex.quoted in one central place — a payload like "; rm -rf /sdcard" in a package name or dumpsys arg becomes a literal argument, never a second command. Covered by tests.
  • Few, guarded mutating toolswrite_file, delete_file (refuses /, /system, /data, …), clear_app_data, uninstall, install_apk, set_prop, put_setting, the set_* network toggles.

Point it at a device you own and trust, run one server per intended device (use ADB_SERIAL/serial), and leave ADB_MCP_ALLOW_SHELL off unless you need it. See SECURITY.md for the full model.

Publishing to PyPI (maintainer)

Releases are published to PyPI by the release workflow using Trusted Publishing (OIDC) — no API tokens are stored. One-time setup on PyPI, then every tagged release publishes itself:

  1. On PyPI → Your projectsPublishing, add a pending trusted publisher:
    • PyPI project name: adbmcp
    • Owner: FlashZ, Repository: adb-mcp
    • Workflow filename: release.yml
    • Environment: pypi
  2. Cut a release to trigger it:
    git tag v0.1.0 && git push origin v0.1.0
    # or: gh release create v0.1.0 --generate-notes
    

The workflow builds the sdist+wheel, runs twine check, and uploads.

License

MIT — see LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选