Skip to main content
Glama
README.md
# adb-visual-mcp

A small, stateless, pure-visual MCP server for Android devices. It exposes only the I/O needed to operate an emulator or phone: screen capture, taps, swipes, and keyboard input. Visual reasoning stays in the calling agent.

The server talks to Android through `adb shell` and `adb exec-out`; it does not use the accessibility tree, OCR, Appium, or a cached UI model.

## Tools

- `devices()` lists devices and readiness.
- `adb_command(args, device?, timeout_s?, max_output_chars?)` runs any adb command and returns exit code, stdout, and stderr.
- `screenshot(device?, grid_rows?, grid_cols?)` returns JSON geometry plus a PNG. The optional grid is only a visual reference overlay.
- `click(x, y, device?, button?, count?)` taps absolute screen coordinates. Right and middle map to a long press.
- `mouse(action, device?, ...)` supports `scroll` and `drag` (swipe).
- `keyboard(action, device?, text?, keys?)` types text or sends Android key events.

The visual and input tools accept an optional `device` serial. With no argument, exactly one ready device must be present. The server never caches the selected device or current screen.

`adb_command` is the escape hatch for everything the typed tools do not cover (installing APKs, reading properties, package management). Its `args` is either an argument list or a single string that is split like a shell line. Without `device` it runs without `-s`, so global commands such as `devices` and `version` work. Output is capped per stream; long output keeps the head and tail and reports how many characters were dropped.

```json
{
  "args": ["shell", "pm", "list", "packages"],
  "device": "emulator-5554",
  "timeout_s": 30,
  "max_output_chars": 20000
}
```

## Install

Requires Python 3.10+, `adb`, and a running Android device or emulator.

```bash
uv sync
uv run adb-visual-mcp --version
```

Set the adb path when it is not on `PATH`:

```bash
export ADB_VISUAL_MCP_ADB=/data/zqf/android-sdk/platform-tools/adb
export ADB_VISUAL_MCP_DEVICE=emulator-5554
```

## Run

stdio, for an MCP client that launches the process:

```bash
uv run adb-visual-mcp
```

Streamable HTTP:

```bash
uv run adb-visual-mcp --transport streamable-http --host 127.0.0.1 --port 8000 --path /mcp
```

## Interaction model

```text
screenshot -> visual reasoning -> click/mouse/keyboard -> screenshot to verify
```

The server does not identify buttons or choose coordinates. Callers should use a grid overlay when fine positioning is needed and should not invent coordinates for visually uncertain targets.

## Notes

`keyboard type` uses `adb shell input text`; it is intended for ASCII text. For non-ASCII input, use the device's own IME or a dedicated helper app. `mouse move` is intentionally unsupported because Android touchscreens have no hover pointer.

## Development

```bash
uv run pytest
uv run python tests/smoke.py
```

TDQS

B3.2/5.0

Scored across 6 tools

Disambiguation4/5

Each tool targets a distinct interaction (keyboard input, mouse scroll/drag, click tap, screenshot capture, device listing), so selection is generally clear. The main overlap is `adb_command`, a generic escape hatch that can replicate every other tool's function (e.g. `shell input tap`, `shell screencap`, `devices`), though this is an intentional, documented fallback rather than true ambiguity.

Naming Consistency3/5

Five tools are single lowercase words (keyboard, mouse, devices, screenshot, click) while `adb_command` uses a snake_case namespace prefix, and the set mixes nouns (devices, screenshot) with a verb (click) and input-device names (keyboard, mouse). It is readable and loosely noun-oriented, but there is no predictable verb_noun or resource pattern an agent can rely on.

Tool Count5/5

Six tools is well-scoped for a focused Android-device-control server: discovery, three input primitives, capture, and a raw escape hatch. Each tool earns its place without redundant wrappers or an oversized surface.

Completeness4/5

The surface covers the core interaction loop (find device, see screen, tap/drag/scroll, type) and `adb_command` closes arbitrary gaps like app install, UI hierarchy dumps, or device connect/restart. Minor gaps remain: no dedicated swipe/fling or long-press tool, and no built-in wait-for-UI or clipboard operations, though all are reachable through `adb_command`.

Maintenance

ActivityMaintained
ResponsivenessNo issues