Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

adb-mcp — Android emulator and device control over adb

OCI · GHCR.IO/IKSNERD/ADB-MCP:0.22.2 · SCANNED AUG 22

Drive an Android emulator or device over adb: screenshot, inspect UI, tap, type, build and test.

38 Trust /100
Trust breakdown (6 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score →

Supply Chain Security0
  • Malware scan not yet available for this package.Unverified
  • Known CVEs could not be checked: this artifact ships no SBOM, so there is no dependency list to read. Publishing one would let us assess it.Unverified
  • Install-script risk not yet assessed.Unverified
  • Dependency health could not be checked: this artifact ships no SBOM, so there is no dependency list to read. Publishing one would let us assess it.Unverified
Provenance & Transparency35
Schema Quality & AI Usability82
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 13576 tokens (~163/item across 83 items; 78 tools + 5 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management0
  • Stability not yet verified: not enough scan history yet (needs a 30-day window).Unverified
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass

Unverified: 2 categories

Categories scored 0 because we could not verify them: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

Install

How do I install the adb-mcp — Android emulator and device control over adb server?

adb-mcp — Android emulator and device control over adb runs locally as a container image, launched with docker run --rm -i ghcr.io/iksnerd/adb-mcp:0.22.2. Ready-made configuration for Claude, Cursor, VS Code, Codex and 3 more is on this page, copied from each client's own documentation.

oci · ghcr.io/iksnerd/adb-mcp:0.22.2

# add to Claude Code
claude mcp add iksnerd-adb-mcp -- docker run --rm -i ghcr.io/iksnerd/adb-mcp:0.22.2
// .cursor/mcp.json
{
  "mcpServers": {
    "iksnerd-adb-mcp": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/iksnerd/adb-mcp:0.22.2"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "iksnerd-adb-mcp": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/iksnerd/adb-mcp:0.22.2"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add iksnerd-adb-mcp -- docker run --rm -i ghcr.io/iksnerd/adb-mcp:0.22.2
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "iksnerd-adb-mcp": {
      "type": "local",
      "command": [
        "docker",
        "run",
        "--rm",
        "-i",
        "ghcr.io/iksnerd/adb-mcp:0.22.2"
      ],
      "enabled": true
    }
  }
}
# ~/.hermes/config.yaml
mcp_servers:
  iksnerd-adb-mcp:
    command: "docker"
    args: ["run", "--rm", "-i", "ghcr.io/iksnerd/adb-mcp:0.22.2"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "iksnerd-adb-mcp": {
      "Transport": "stdio",
      "Command": "docker",
      "Arguments": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/iksnerd/adb-mcp:0.22.2"
      ]
    }
  }
}
// mcp.json
{
  "mcpServers": {
    "iksnerd-adb-mcp": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/iksnerd/adb-mcp:0.22.2"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 16 Aug 26 38

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 22 Aug 2026 · Analysed oci/ghcr.io/iksnerd/adb-mcp:0.22.2

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem oci
Reason No attestation published
MCP tools · 78 exposed · ~13,364 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.

Tool Tokens
adb_reverse ~208

Forward a DEVICE TCP port to a HOST port (adb reverse) so the emulator/device can reach a server on this machine — the canonical use is tcp:8081 for Metro. CRITICAL for RN/Expo dev clients: if the app can't reach its dev server it may SILENTLY fall back to the embedded bundle and ignore every code edit you make — set this up before a dev-client session, and suspect it whenever edits seem to have no effect (app_state confirms whether the running process is on Metro or the embedded bundle). remove=true undoes the forward.

NameTypeReqDescription
device_portintegeryesTCP port on the DEVICE to forward, e.g. 8081 for Metro.
host_portintegerTCP port on the HOST to forward to. Defaults to device_port.
removenull|booleanRemove the forward for device_port instead of creating it.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

app_state ~182

Report an app's RUNTIME state: installed?, running?, foreground?, top activity, pid(s), main-process uptime, install/update times, and — for React Native/Expo — whether it is serving a live METRO bundle or its baked-in EMBEDDED one. Optionally pass source_path to compare the newest host source mtime with the latest epoch-timed Metro/HMR marker and flag stale JavaScript after git checkout/stash operations. Run this FIRST when JS edits seem to have no effect.

NameTypeReqDescription
packagestringyesApplication package name.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
source_pathstringOptional host file or directory containing the app's source. When supplied, app_state compares its newest mtime with the latest Metro/HMR marker to flag stale JavaScript.

No output schema declared.

No examples provided.

avd_snapshot ~129

Manage emulator AVD snapshots (adb emu avd snapshot): action=save|load|delete a named snapshot, or list them. Save a known-good state, then load it to reset the device deterministically between runs — faster than a wipe_data cold boot. Emulator-only.

NameTypeReqDescription
actionstringyesOne of: "save", "load", "delete", or "list".
namestringSnapshot name. Required for save/load/delete; ignored for list.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

boot_emulator ~191

Boot an AVD by name and return its device serial (e.g. emulator-5554). Launches the emulator detached so it outlives this call, and waits for full boot (sys.boot_completed) by default. Use the returned serial for later tools if you boot more than one device. Booting can take 30-120s on a cold start.

NameTypeReqDescription
avdstringyesAVD name to boot (see list_avds).
no_snapshotnull|booleanCold boot without loading a saved snapshot. Default true.
timeout_sintegerBoot timeout in seconds. Default 180.
wait_for_bootnull|booleanWait until fully booted before returning. Default true.
wipe_datanull|booleanFactory-reset the AVD on this boot (-wipe-data). Default false. Use to start from a pristine device.

No output schema declared.

No examples provided.

build_and_run ~220

One-shot build → install → launch: runs Gradle (default task assembleDebug) in project_dir, installs the resulting APK on the device, and launches package. Equivalent to gradle_build + install_app + launch_app but in a single call. If several APKs exist under build/outputs (multi-flavor projects, leftover androidTest APKs), the newest non-test one is installed — the artifact the build just produced.

NameTypeReqDescription
argsnull|arrayExtra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free).
packagestringyesApplication package name to install and launch, e.g. com.example.app.
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
taskstringGradle task to run. Defaults to assembleDebug.

No output schema declared.

No examples provided.

cellular ~334

Shape the emulated cellular radio (adb emu gsm / network): data and voice registration state (unregistered/home/roaming/searching/denied/off/on), signal strength (0-4), and mobile-data throughput/latency (network_speed like "lte"/"edge" or "<up>:<down>" kbps; network_delay like "umts" or "<min>:<max>" ms). Test offline/roaming/weak-signal and slow-network behaviour deterministically. Every field optional; set at least one. Emulator-only.

NameTypeReqDescription
datastringMobile-data registration state: one of unregistered, home, roaming, searching, denied, off, on. Omit to leave unchanged.
network_delaystringLatency: a named profile (none, gprs, edge, umts) or raw "<min>:<max>" in ms. Omit to leave unchanged.
network_speedstringData throughput: a named profile (gsm, gprs, edge, umts, hsdpa, lte, evdo, full) or raw "<up>:<down>" in kbps. Omit to leave unchanged.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
signalnull|integerSignal strength 0-4 (0 = no bars, 4 = full). Omit to leave unchanged.
voicestringVoice registration state: one of unregistered, home, roaming, searching, denied, off, on. Omit to leave unchanged.

No output schema declared.

No examples provided.

clear_app_data ~81

Wipe an app's data and cache (pm clear) to reset it to a first-launch state — the fastest way to reproduce onboarding/permission flows from scratch.

NameTypeReqDescription
packagestringyesApplication package name (e.g. com.example.app).
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

clear_device_lock ~75

Remove the secure lock screen, supplying the current credential as old_value. Use to restore a clean state after testing a Keystore flow.

NameTypeReqDescription
old_valuestringyesThe current credential, needed to clear the lock.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

clear_logcat ~114

Empty the device's logcat ring buffer (adb logcat -c). The sharpest isolation primitive for a press→observe loop: clear, perform ONE action, then logcat — every line you read was caused by that action. Without it, a filter hit may be minutes old and an empty result may just mean the buffer rotated. (For reaching BACK in time instead, use logcat's since param.)

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

connect_wireless ~149

Connect to a device over Wi-Fi/TCP (adb connect), optionally pairing first (adb pair) with the 6-digit code from Android 11+ Wireless debugging. Pass host:port; for pairing also pass the pairing address + code shown on the device.

NameTypeReqDescription
host_portstringyesDevice address to connect to, host:port (e.g. 192.168.1.42:5555).
pair_addressstringPairing address host:port (Android 11+ Wireless debugging), if different from host_port. Only needed when pairing.
pairing_codestring6-digit pairing code shown on the device. Provide to pair before connecting.

No output schema declared.

No examples provided.

describe_ui ~419

Read the on-screen UI hierarchy as a list of elements, each with its text, content_desc, resource_id, class, clickable flag, pixel bounds, and a precomputed center in TRUE DEVICE PIXELS. This is your source of truth for AIMING: pass an element's center straight to tap. Never guess coordinates from the screenshot (it is downscaled and you will miss). The response header states the FOCUSED WINDOW (if it's a system overlay — biometric prompt, permission dialog — the elements belong to that overlay, not your app) and how many nodes the filter hid. Default filter keeps labelled/clickable/id-carrying elements minus redundant wrappers; filter="clickable" returns only tap targets (much smaller); filter="all" returns every bounded node — the only mode where absence proves an element isn't in the hierarchy. Canvas-drawn (RN/Flutter/Skia) content appears in NO mode.

NameTypeReqDescription
compactnull|booleanReturn one line per element (center, bounds, flags, labels) instead of JSON — ~10x fewer tokens, same aiming information. Use for repeated look-drive loops and geometry work.
filterstringWhat to include: 'auto' (default — elements with text, content_desc, resource_id, or clickable; identical-bounds label-less wrappers dropped), 'clickable' (tap targets only, the smallest view), or 'a…
packagestringOptional package expected to own the focused window. If another app or SystemUI owns focus, the response calls that out explicitly.
querystringCase-insensitive substring to match against text, content_desc, and resource_id — return only matching elements. The cheap way to ask 'is X on this screen?'. Combine with filter='all' to prove absenc…
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

doctor ~97

Diagnose the local toolchain: Android SDK path (and whether it really is an SDK), adb/emulator availability, known AVDs, attached devices, per-device accessibility bridge status, plus the host build tools — a JDK (Gradle needs one) and a system gradle (needed only so scaffold_android_project can generate a wrapper). Run this first when something isn't working, especially a Gradle tool failing with "SDK location not found".

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

drag ~175

Press-hold-move-release drag from (x1,y1) to (x2,y2) in true device pixels (input draganddrop, Android 11+). Unlike swipe (which flings), this holds at the start first — use it for drag handles, long-press-to-reorder lists, and drag-and-drop targets a quick swipe skips.

NameTypeReqDescription
duration_msintegerDrag duration in ms. Default 400.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
x1integeryesStart X in true device pixels.
x2integeryesEnd X in true device pixels.
y1integeryesStart Y in true device pixels.
y2integeryesEnd Y in true device pixels.

No output schema declared.

No examples provided.

enter_pin ~335

Enter digits on a numeric PIN pad by tapping each key with a settle delay. Use when input_text does nothing because the pad renders its own key views. Visibility is PAD-SPECIFIC — run describe_ui on the pad screen first: a native-view pad (digits listed as Buttons with text) works with the default hierarchy lookup, no extra args. Only CANVAS-DRAWN pads (React Native / Skia SDK pads, whose keys are invisible to describe_ui) need 'grid' (the pad's bounding box; digits placed on a standard 3x4 dialpad) or 'coords' (explicit per-digit x,y) — read those bounds off a screenshot.

NameTypeReqDescription
coordsstringOptional explicit per-digit tap points as 'digit:x,y' pairs separated by ';', e.g. '1:540,1600;2:640,1600'. Overrides grid and hierarchy for the digits given. Use when the pad is not a regular grid.
digitsstringyesThe digits to enter, e.g. "1234".
gridnull|objectOptional bounding box {x1,y1,x2,y2} of the PIN pad. Provide this for custom-drawn (React Native / Skia) pads whose keys are invisible to describe_ui: digits are placed on a standard 3x4 dialpad grid…
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

finger_remove ~64

Lift the simulated finger off the sensor (adb emu finger remove) — the complement to fingerprint_touch, for flows that watch for the finger-up event. Emulator-only.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

fingerprint_touch ~226

Simulate a fingerprint-sensor touch on an EMULATOR (adb emu finger touch). With a fingerprint enrolled, this satisfies a BiometricPrompt — drive the app's REAL biometric unlock path instead of cancelling into the PIN fallback every run. finger_id must match an enrolled finger (default 1). Check has_biometric_enrolled FIRST: with nothing enrolled this just sits on "Touch the sensor" forever. GOTCHA: the command reports OK even when the id matches nothing — if the prompt doesn't resolve, the enrolled id differs (re-enrollments increment it): try finger_id 2..5, send a second touch after ~1s, or re-enroll deterministically at session start (Settings > Security > Fingerprint, calling this tool for each wizard touch). Emulator-only; physical devices cannot inject biometrics.

NameTypeReqDescription
finger_idintegerId of the enrolled finger to touch with (must match a finger enrolled in Settings). Default 1.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

get_app_details ~85

Report an installed app's version name/code and its launchable activity (dumpsys package + resolve-activity) — to confirm what build is installed and find the activity to launch.

NameTypeReqDescription
packagestringyesApplication package name (e.g. com.example.app).
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

get_coverage_report ~386

Run a JaCoCo coverage-report Gradle task in project_dir (default 'jacocoTestReport', which runs the JVM unit tests first) and summarize the resulting code coverage: overall line/branch/method/class percentages plus a per-package breakdown, worst-covered package first. In a multi-module build every module's report is merged into one set of totals, and the merged report files are listed. IMPORTANT — 'jacocoTestReport' is NOT a task the Android Gradle plugin defines; it exists only if the project declares it. If the task is not found, run list_gradle_tasks and look for AGP's built-in 'createDebugUnitTestCoverageReport' (present when a build type sets enableUnitTestCoverage = true) and pass it as task=; both write the same JaCoCo XML and both are read. Covers JVM unit tests only, not instrumented (on-device) tests — there is no on-device analogue. Pass json=true for structured JSON instead of the text form.

NameTypeReqDescription
argsnull|arrayExtra arguments passed to Gradle (e.g. --stacktrace).
jsonbooleanReturn structured JSON instead of the human-readable text summary.
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstringGradle task that generates the JaCoCo XML report. Defaults to jacocoTestReport, which is NOT a task the Android Gradle plugin defines — it exists only if the project declares it. If it is missing, ch…

No output schema declared.

No examples provided.

get_file_coverage ~409

Same JaCoCo run as get_coverage_report (default task 'jacocoTestReport', same fallback to AGP's 'createDebugUnitTestCoverageReport' when that task doesn't exist), scoped to one source file: line/branch coverage, the exact missed and partially-covered line numbers, plus per-method detail — the per-function breakdown get_coverage_report's package-level summary doesn't carry. Use it to find WHICH lines to write a test for, after get_coverage_report says which package is weakest. file matches by suffix (e.g. "Foo.kt" or "com/example/Foo.kt") across every module of a multi-module build; an ambiguous bare filename returns every matching file, a miss lists what coverage data does exist so you can correct it. Same JVM-unit-test-only scope as get_coverage_report. Pass json=true for structured JSON instead of the text form.

NameTypeReqDescription
argsnull|arrayExtra arguments passed to Gradle (e.g. --stacktrace).
filestringyesSource file to report coverage for — a filename (e.g. Foo.kt) or package-qualified path (e.g. com/example/Foo.kt). Matched by suffix; an ambiguous bare filename returns every match.
jsonbooleanReturn structured JSON instead of the human-readable text summary.
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstringGradle task that generates the JaCoCo XML report. Defaults to jacocoTestReport, which is NOT a task the Android Gradle plugin defines — it exists only if the project declares it. If it is missing, ch…

No output schema declared.

No examples provided.

gradle_build ~192

Build the app with Gradle (default task assembleDebug) in project_dir, and report the produced APK path(s). project_dir must contain the Gradle wrapper (gradlew). Runs on the host, not a device.

NameTypeReqDescription
argsnull|arrayExtra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free).
jsonbooleanFor run_unit_tests/run_instrumented_tests: return the test summary as structured JSON (per-suite timing, full failure stack traces) instead of the human-readable text summary. Ignored by gradle_build…
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstringGradle task to run. Defaults to the tool's standard task.

No output schema declared.

No examples provided.

gradle_project_properties ~190

Dump Gradle's evaluated properties for one module, such as :app or :feature:login. Use after list_gradle_projects when you need the module's namespace, Android SDK settings, build directory, or other effective configuration rather than just its task/variant names. This is the module's FULL effective property set — the same one ./gradlew properties would print, which can include credentials a build.gradle reads from ~/.gradle/gradle.properties or env (e.g. private Maven repo auth). Values for keys that look secret-shaped (password/token/key/credential) are redacted before being returned.

NameTypeReqDescription
modulestringyesGradle module path, e.g. :app or :feature:login.
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.

No output schema declared.

No examples provided.

grant_permission ~92

Grant a runtime permission to an app (pm grant), e.g. android.permission.CAMERA — skips the in-app permission dialog so you can drive straight to the feature.

NameTypeReqDescription
packagestringyesApplication package name.
permissionstringyesFull permission name, e.g. android.permission.CAMERA.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

has_biometric_enrolled ~145

Report whether any fingerprint is enrolled (and how many), from dumpsys fingerprint. Check this BEFORE a biometric flow: with nothing enrolled, fingerprint_touch can never satisfy a BiometricPrompt — it just sits on "Touch the sensor" — so branch to enrolling one or to the PIN path instead of guessing. Works on emulators and physical devices. Note: the framework exposes only an enrolled COUNT, never which finger id is enrolled, and a wrong fingerprint_touch id trips a HAL lockout after a few tries — so enroll deterministically rather than sweeping ids.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

input_key_combo ~257

Press several keys together as a chord (input keycombination, Android 11+). Use preset="select_all" (or copy/paste/cut/undo/redo/save/find) for a named shortcut, or keys=["ctrl","a"] / ["alt","tab"] to spell one out — modifier(s) first, then the action key; each is a key name (ctrl/alt/shift/meta, a-z, enter, tab, ...) or a raw keycode. For a single key use press_key instead.

NameTypeReqDescription
keysnull|arrayKeys to press together, modifier(s) first, e.g. ["ctrl","a"] or ["alt","tab"]. Each is a key name (ctrl, alt, shift, meta, a-z, enter, tab, ...) or a raw keycode number. Needs at least 2. Omit if pre…
presetstringNamed combo shortcut (select_all, copy, paste, cut, undo, redo, save, find) that expands to the right chord — use this instead of keys when a name will do.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

input_text ~107

Type text into the currently focused input field via the IME. Tap the field first so it has focus. Afterwards the soft keyboard may cover buttons lower on screen — dismiss it with press_key escape (or back) before tapping them. For native non-IME PIN pads this does nothing; use enter_pin instead.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
textstringyesText to type into the focused field.

No output schema declared.

No examples provided.

install_app ~76

Install (or reinstall, -r) an APK from a local file path onto the device. Use to deploy a build you want to test.

NameTypeReqDescription
apk_pathstringyesLocal filesystem path to the .apk to install.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

is_device_secure ~64

Report whether a secure lock screen is set (KeyguardManager.isDeviceSecure). Use it to verify set_device_lock worked before running a Keystore-gated flow.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

last_crash ~150

Return the most recent app crash from the system DropBox (dumpsys dropbox — JVM/React-Native and native crashes), with the full exception header and stack in one call. Optionally filter to a package. Use this instead of grepping logcat when an app just crashed: DropBox keeps the whole fatal (header + Caused by + frames) together even after it has scrolled out of the logcat ring buffer.

NameTypeReqDescription
packagestringOptional package name to filter to (e.g. com.example.app); omit for the most recent crash from any app.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

launch_app ~108

Launch an app by package name (starts its LAUNCHER activity) and echo the resolved component on success. Fails with a clear message (not a raw monkey dump) when the package isn't installed or has no launcher activity. Combine with stop_app to restart an app cleanly from a known state.

NameTypeReqDescription
packagestringyesApplication package name (e.g. com.example.app).
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

launch_dev_client ~249

Launch an Expo dev build straight at a Metro dev server, skipping the Dev Launcher's server-picker screen. Builds the "<scheme>://expo-development-client/?url=http://host:port" deep link and opens it. Pass scheme (your app.json "scheme"); host/port default to localhost:8081. PREREQUISITE: run adb_reverse tcp:8081 first so the device can reach Metro, otherwise the dev client falls back to its embedded bundle. For plain Expo Go (not a dev build) use open_url with the exp:// URL instead.

NameTypeReqDescription
hoststringMetro dev-server host as the DEVICE sees it. Default localhost (works once adb_reverse tcp:8081 is set).
packagestringOptional package to target the intent at (disambiguates if multiple apps claim the scheme).
portintegerMetro dev-server port. Default 8081.
schemestringyesThe app's URL scheme from app.json (e.g. "myapp") — used to build the expo-development-client deep link.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

list_avds ~45

List the Android Virtual Devices (AVDs) installed on this machine that can be booted. Start here when no emulator is running yet; the returned names feed boot_emulator.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

list_devices ~71

List attached emulators/devices and their adb state (device = ready, offline, unauthorized). Use it to confirm a device is up before driving it, or to get the serial when several are attached.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

list_gradle_projects ~140

List the Gradle modules (sub-projects) in project_dir (gradlew projects) — the map of a multi-module build, e.g. :app, :core, :feature:login. Use it to find which module to point gradle_build/list_gradle_variants at, or to address a task at one module with '<path>:<task>' (e.g. :app:assembleDebug). A single-module build reports no sub-projects.

NameTypeReqDescription
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.

No output schema declared.

No examples provided.

list_gradle_tasks ~215

List the available Gradle tasks in project_dir (gradlew tasks) — to discover build/test/install targets. In a multi-module build this lists the ROOT project's own tasks by default; pass task="<module>:tasks" (e.g. ":app:tasks", from list_gradle_projects) to scope to a submodule instead.

NameTypeReqDescription
argsnull|arrayExtra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free).
jsonbooleanFor run_unit_tests/run_instrumented_tests: return the test summary as structured JSON (per-suite timing, full failure stack traces) instead of the human-readable text summary. Ignored by gradle_build…
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstringGradle task to run. Defaults to the tool's standard task.

No output schema declared.

No examples provided.

list_gradle_variants ~218

List the buildable build variants in project_dir (parsed from the assemble* tasks) — the Android analogue of "list schemes". Each variant V maps to an assembleV / installV Gradle task; pass it as the task= arg to gradle_build/build_and_run to disambiguate a multi-flavor project. Test-only APK tasks (androidTest/unitTest) are excluded. In a multi-module build the ROOT project usually has no variants of its own (no Android plugin applied there) — pass task="<module>:tasks" (e.g. ":app:tasks", from list_gradle_projects) to scope to the module that actually builds APKs.

NameTypeReqDescription
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstringGradle task to scope to, e.g. ":app:tasks" to list variants for the :app module. Defaults to the root project's tasks.

No output schema declared.

No examples provided.

list_packages ~72

List installed package names, optionally filtered by substring — to confirm an app is installed and get its exact package name for launch_app/stop_app.

NameTypeReqDescription
filterstringSubstring to filter package names.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

logcat ~444

Dump recent native log lines — the last N (default 400) or, with since="2m"/"90s", everything from that long ago on the device clock (the right axis when the report is 'I just hit an error'; on a chatty emulator 400 lines can span seconds). Optionally filtered by a case-insensitive substring, a minimum priority (V/D/I/W/E/F — e.g. priority="E" for errors and up), and/or tags (OR'd). This is how you find the REAL reason a native call failed when the UI only shows a generic 'X failed' alert: filter by your app tag or 'Exception'/'Caused by' and read the 'Caused by:' line — that is the root cause. Dumps and exits (does not stream); chatty spam is stripped.

NameTypeReqDescription
filterstringCase-insensitive substring to keep (e.g. an app tag or "Exception").
linesintegerNumber of recent lines to dump. Default 400. Ignored when since is given.
prioritystringMinimum priority to keep: V, D, I, W, E, or F (matches adb's own "*:E"-style filter — E keeps Error and Fatal). Omit for no priority filtering.
redactbooleanMask common secrets (token, password, authorization, api key, secret) before returning log lines. Recommended for payment/auth SDKs and debug builds.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
sincestringTime window instead of a line count: only lines from the last e.g. "2m", "90s", "1h30m" (device clock). The right axis when the report is "I just hit an error" — on a chatty emulator 400 lines can sp…
tagsnull|arrayKeep only lines whose log tag contains one of these (case-insensitive, OR'd), e.g. ["SessionStore","AuthModule"]. Omit for no tag filtering.

No output schema declared.

No examples provided.

long_press ~99

Press and hold a coordinate (true device pixels) for a duration — for context menus, drag handles, and long-press actions.

NameTypeReqDescription
duration_msintegerHold duration in ms. Default 600.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
xintegeryesX coordinate in true device pixels.
yintegeryesY coordinate in true device pixels.

No output schema declared.

No examples provided.

open_dev_menu ~88

Open the React Native dev menu (KEYCODE_MENU) on the foreground app — the reliable way to reach a dev build's Reload/Debug JS Remotely/etc. options when reload_app's broadcast doesn't apply. Follow with tap_on_text or describe_ui to pick a menu item.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

open_url ~94

Open a URL or deep link via an ACTION_VIEW intent (am start) — the way to jump straight to a deep-linked screen. Optionally target a specific package.

NameTypeReqDescription
packagestringOptional package to target the intent at.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
urlstringyesURL or deep link to open (ACTION_VIEW).

No output schema declared.

No examples provided.

phone_call ~148

Drive an emulated voice call (adb emu gsm). action="call" (default) rings an incoming call from number; "accept"/"cancel"/"busy"/"hold" transition an in-progress call. Use to test call-interruption behaviour and CALL_PHONE flows. Emulator-only.

NameTypeReqDescription
actionstringWhat to do: "call" (default — ring an incoming call), "accept", "cancel" (hang up), "busy", or "hold".
numberstringyesPhone number for the call, e.g. "+15551234567".
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

prefer_pin ~83

Try to move a standard BiometricPrompt to its PIN/password fallback by selecting an explicit system button, or sending BACK as the generic cancel path. App-controlled prompts may suppress or rename this option, so confirm the resulting PIN pad with describe_ui before calling enter_pin.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

press_key ~274

Press a hardware/navigation key by name (enter, back, home, menu, tab, del, escape, up, down, left, right, dpad_center, app_switch, search, power, wakeup, sleep, volume_up, volume_down, ...) or a raw Android keycode number. Handy to submit a form (enter), dismiss the keyboard (escape), or go back (back). To turn the screen ON use wakeup (not power, which toggles and may sleep an awake screen); sleep turns it off. A key can be silently consumed with no effect (e.g. back while a biometric prompt is up) — pass verify_change=true to get ui_changed: true/false instead of guessing.

NameTypeReqDescription
keystringyesKey name (enter, back, home, menu, tab, del, escape, up, down, left, right, ...) or a raw keycode number.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
verify_changenull|booleanAlso report whether the UI hierarchy changed after the key press (ui_changed: true/false). Costs two extra hierarchy reads (~2-3s); use when the key may be silently consumed (e.g. back while a biomet…

No output schema declared.

No examples provided.

pull_file ~85

Copy a file off the device to a local path (adb pull) — e.g. retrieve a generated file, database, or screenshot.

NameTypeReqDescription
device_pathstringyesFile path on the device to copy off.
local_pathstringyesLocal destination path.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

push_file ~93

Copy a local file onto the device (adb push) — e.g. seed test data or a file to import.

NameTypeReqDescription
device_pathstringyesDestination path on the device, e.g. /sdcard/Download/x.json.
local_pathstringyesLocal file to copy onto the device.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

reload_app ~195

Best-effort: trigger a Metro/JS reload on a React Native dev-client build via the classic <package>.RELOAD_APP_ACTION broadcast. Only works on debug builds of classic (non-bridgeless) RN architectures that register the receiver — on newer RN/Expo dev clients it may silently no-op with no error. If the app doesn't visibly reload, use open_dev_menu then tap_on_text("Reload") instead. PREREQUISITE: the app must be able to reach Metro at all — run adb_reverse {device_port: 8081} first, or a reload lands you back on the EMBEDDED bundle and your edits still won't appear (app_state tells you which bundle the running process is actually serving).

NameTypeReqDescription
packagestringyesApplication package name (e.g. com.example.app).
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

revoke_permission ~104

Revoke a runtime permission from an app (pm revoke) — to test the denied path or re-trigger the permission-request dialog on next use. Pairs with grant_permission. Note: revoking some permissions kills the app process.

NameTypeReqDescription
packagestringyesApplication package name.
permissionstringyesFull permission name, e.g. android.permission.CAMERA.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

rotate_screen ~62

Rotate the emulator to its next orientation (adb emu rotate) — the quick way to exercise landscape/portrait layout and rotation-driven state loss. Emulator-only.

NameTypeReqDescription
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

run_instrumented_tests ~203

Run Gradle instrumented (on-device) tests (default task 'connectedAndroidTest') in project_dir — requires a booted device/emulator. Returns per-suite timing and failing-test stack traces; pass json=true for a structured JSON summary instead of the text form.

NameTypeReqDescription
argsnull|arrayExtra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free).
jsonbooleanFor run_unit_tests/run_instrumented_tests: return the test summary as structured JSON (per-suite timing, full failure stack traces) instead of the human-readable text summary. Ignored by gradle_build…
project_dirstringPath to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstringGradle task to run. Defaults to the tool's standard task.

No output schema declared.

No examples provided.

run_sequence ~356

Run several interaction steps in ONE call — no agent round-trip between them. Use for scripted flows and, crucially, flows driven by NATIVE TIMERS (background-token clear, a biometric prompt that auto-fires on resume) where a round-trip per step would perturb the timing you're testing: e.g. key:home → sleep:19 → launch → sleep:9 → tap_text:Cancel (if_present:biometric) → assert_foreground(package) → describe_ui. Each step has an 'action' (sleep, tap, tap_text, tap_element, key, text, swipe, launch, stop, assert_foreground, wait_text, describe_ui) with its params; an if_present/if_absent guard skips a step unless a selector is (not) on screen — that's how you express a conditional cancel; and optional=true lets a step fail without aborting. Returns a per-step result (ok/skipped/error) with elapsed_ms plus the final hierarchy. A non-optional step error stops the rest.

NameTypeReqDescription
capture_finalnull|booleanAppend the settled UI hierarchy after the last step (unless the run aborted) so you see the end state in this same response. Default true.
serialstringTarget device serial (adb -s). Optional when exactly one device is attached.
stepsnull|arrayyesOrdered steps to run in one call. Each has an 'action' (sleep, tap, tap_text, tap_element, key, text, swipe, launch, stop, assert_foreground, wait_text, describe_ui) plus that action's params, and op…

No output schema declared.

No examples provided.

Common questions

What is the adb-mcp — Android emulator and device control over adb server?

adb-mcp — Android emulator and device control over adb is listed in the public MCP registry as io.github.iksnerd/adb-mcp. Drive an Android emulator or device over adb: screenshot, inspect UI, tap, type, build and test. This page covers its container image (ghcr.io/iksnerd/adb-mcp:0.22.2).

Is the adb-mcp — Android emulator and device control over adb server safe to use?

adb-mcp — Android emulator and device control over adb scores 38 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the adb-mcp — Android emulator and device control over adb server expose?

adb-mcp — Android emulator and device control over adb exposes 78 tools: adb_reverse, app_state, avd_snapshot, boot_emulator, build_and_run, and 73 more. Their descriptions and schemas cost roughly 13,364 tokens of context every time the server is loaded.

Is the adb-mcp — Android emulator and device control over adb server still maintained?

adb-mcp — Android emulator and device control over adb is still listed as active in the MCP registry. We last reached this channel on 22 August 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.