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

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

+5 this week 46 Trust /100

Last scanned (3 hours ago)

Scores higher than 65% of OCI servers

Category Testing and QA

Trust breakdown (7 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 → Why this is hard to score →

Supply Chain Security0
  • No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.Unverified
  • Known CVEs could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.Unverified
  • Install-script risk not yet assessed.Unverified
  • Dependency health could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.Unverified
Provenance & Transparency35
Schema Quality & AI Usability81
  • 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 14605 tokens (~169/item across 86 items; 80 tools + 6 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 Management47
  • Stability observed for 14 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
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
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 7 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 82 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass

Unverified: 1 category

A category scored 0 because we could not verify it: 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.

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.

  • 4 Nov 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 40 to 43. That category is still filling its 30-day observation window: 12 days of observed history at the previous scan, 13 at this one. The score rises as the window fills, whether or not the server changes.

  • 3 Nov 26 0
    • Package version: 0.24.4 → 0.24.5 functional
  • 2 Nov 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 33 to 37. That category is still filling its 30-day observation window: 10 days of observed history at the previous scan, 11 at this one. The score rises as the window fills, whether or not the server changes.

  • 1 Nov 26 +2
    • Tool safety: pass → unverified ▼ security
    • Stability: 0.30 → unverified ▼ security
    • Schema quality: 100 → unverified ▼ functional
    • Capabilities: pass → unverified ▼ functional
    • Tool coverage: 100 → unverified ▼ functional
    • Destructive annotations: All 7 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation. functional
    • Package version: 0.24.3 → 0.24.4 functional
  • 30 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

  • 27 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

  • 25 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

  • 24 Oct 26 0
    • Package version: 0.24.1 → 0.24.3 functional
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 5 Nov 2026 · Analysed oci/ghcr.io/iksnerd/adb-mcp@0.24.5

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

Background: How many MCP packages publish verified provenance →

MCP tools · 80 exposed · ~14,039 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. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

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_portinteger–TCP port on the HOST to forward to. Defaults to device_port.
removenull|boolean–Remove the forward for device_port instead of creating it.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

app_state ~278

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. When it is on Metro it also identifies WHICH dev server: port, pid, and the project root that server is running in. That matters because "metro" does not mean the RIGHT metro — a dev server left running from another checkout still holds port 8081, so the app connects happily and runs that branch's code while this call looks healthy. Pass source_path to get an explicit stale_verdict (stale | current | undetermined) with its reason, never silence. Run this FIRST when JS edits seem to have no effect.

NameTypeReqDescription
packagestringyesApplication package name.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.
source_pathstring–Optional host file or directory containing the app's source. When supplied, app_state ALWAYS returns a stale_verdict (stale | current | undetermined) with the reason — it compares the newest source m…

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".
namestring–Snapshot name. Required for save/load/delete; ignored for list.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

boot_emulator ~256

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. If an emulator of this AVD is already running it returns that serial instead of launching a second one; no_snapshot and wipe_data then error, because they cannot apply to a running emulator (stop it with shutdown_emulator first).

NameTypeReqDescription
avdstringyesAVD name to boot (see list_avds).
no_snapshotnull|boolean–Cold boot without loading a saved snapshot. Default true when launching; if the AVD is already running it is ignored unless set true, which errors.
timeout_sinteger–Boot timeout in seconds. Default 180.
wait_for_bootnull|boolean–Wait until fully booted before returning. Default true.
wipe_datanull|boolean–Factory-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 ~236

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 in a single call, and it blocks for the whole build. A failed build returns the same summary and full-log path as gradle_build. If several APKs exist under build/outputs (multi-flavor projects, leftover androidTest APKs), the newest non-test one is installed.

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

No output schema declared.

No examples provided.

build_status ~75

Report a background gradle_build (started with background=true): running with elapsed time, or the final summary (passed/failed, error count, first errors, APK paths, full-log path). Jobs live only as long as this server process.

NameTypeReqDescription
job_idstringyesJob id returned by gradle_build with background=true.

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
datastring–Mobile-data registration state: one of unregistered, home, roaming, searching, denied, off, on. Omit to leave unchanged.
network_delaystring–Latency: a named profile (none, gprs, edge, umts) or raw "<min>:<max>" in ms. Omit to leave unchanged.
network_speedstring–Data throughput: a named profile (gsm, gprs, edge, umts, hsdpa, lte, evdo, full) or raw "<up>:<down>" in kbps. Omit to leave unchanged.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.
signalnull|integer–Signal strength 0-4 (0 = no bars, 4 = full). Omit to leave unchanged.
voicestring–Voice 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).
serialstring–Target 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.
serialstring–Target 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
serialstring–Target 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_addressstring–Pairing address host:port (Android 11+ Wireless debugging), if different from host_port. Only needed when pairing.
pairing_codestring–6-digit pairing code shown on the device. Provide to pair before connecting.

No output schema declared.

No examples provided.

describe_ui ~524

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 CURRENT VIEWPORT's hierarchy. Every mode is viewport-scoped: Android omits a ScrollView's off-screen children from the accessibility tree entirely, so scroll before concluding an element does not exist, and never use this to COUNT a long list (it will undercount) — render_stats reports the whole view tree. Canvas-drawn (RN/Flutter/Skia) content appears in NO mode.

NameTypeReqDescription
compactnull|boolean–Return 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.
filterstring–What 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…
packagestring–Optional package expected to own the focused window. If another app or SystemUI owns focus, the response calls that out explicitly.
querystring–Case-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…
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

doctor ~109

Diagnose the local toolchain, and the first call of any session that isn't going well: 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_msinteger–Drag duration in ms. Default 400.
serialstring–Target 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
coordsstring–Optional 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|object–Optional 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…
serialstring–Target 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
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

fingerprint_touch ~193

Simulate a fingerprint-sensor touch on an EMULATOR (adb emu finger touch). With a fingerprint enrolled it satisfies a BiometricPrompt, so you can drive the real biometric path instead of cancelling into the PIN fallback. finger_id must match an enrolled finger (default 1). Check has_biometric_enrolled FIRST: with nothing enrolled the prompt sits on "Touch the sensor" forever. GOTCHA: it reports OK even when the id matches nothing, and wrong ids trip a HAL lockout, so enroll deterministically rather than sweeping ids (the pin-and-lock guide: a skill, or the android://guide/pin-and-lock resource). Emulator-only.

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

No output schema declared.

No examples provided.

get_app_details ~177

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. Pass apk_path instead of package to read a local .apk (package id, version, launcher activity) with no device attached — handy right after gradle_build.

NameTypeReqDescription
apk_pathstring–Local path to an .apk to read instead of querying a device: returns its package id, version and launcher activity via aapt2. Needs no device; use it right after a build to get the applicationId.
packagestring–Installed application package name (e.g. com.example.app). Required unless apk_path is given.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

get_coverage_report ~307

Run a JaCoCo coverage-report Gradle task in project_dir (default 'jacocoTestReport') and summarize coverage: overall line/branch/method/class percentages plus a per-package breakdown, worst-covered first; multi-module reports are merged. 'jacocoTestReport' is NOT an Android Gradle plugin task: if it is missing, pass AGP's 'createDebugUnitTestCoverageReport' as task= (find it with list_gradle_tasks; see the build-and-test guide: a skill, or the android://guide/build-and-test resource). JVM unit tests only. Pass json=true for structured JSON.

NameTypeReqDescription
argsnull|array–Extra arguments passed to Gradle (e.g. --stacktrace).
jsonboolean–Return structured JSON instead of the human-readable text summary.
project_dirstring–Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstring–Gradle 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 ~311

Same JaCoCo run and task fallback as get_coverage_report, scoped to one source file: the missed and partially-covered line numbers plus per-method detail. Use it after get_coverage_report names the weakest package. file matches by suffix across every module (an ambiguous name returns every match; a miss lists the files that have data). JVM unit tests only. Pass json=true for structured JSON.

NameTypeReqDescription
argsnull|array–Extra 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.
jsonboolean–Return structured JSON instead of the human-readable text summary.
project_dirstring–Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstring–Gradle 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 ~243

Build the app with Gradle (default task assembleDebug) in project_dir. project_dir must contain the Gradle wrapper (gradlew). Runs on the host, not a device. Returns a compact summary (status, duration, error count, first errors) and the path of the full log, with credential-shaped values redacted. It also lists the APKs under build/outputs, newest first; that can include APKs left by earlier builds. For builds that take minutes pass background=true: it returns a job id and log path at once, and build_status reports the result.

NameTypeReqDescription
argsnull|array–Extra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free).
backgroundboolean–Start the build detached and return at once with a job id and log path; poll with build_status. Use for builds that take minutes.
project_dirstring–Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstring–Gradle task to run. Defaults to assembleDebug.

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_dirstring–Path 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.
serialstring–Target 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
serialstring–Target 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|array–Keys 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…
presetstring–Named 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.
serialstring–Target 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
serialstring–Target 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.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

is_device_secure ~80

Report whether a secure lock screen is set (probed with locksettings; this is what KeyguardManager.isDeviceSecure, which Keystore checks, reflects). Use it to verify set_device_lock worked before running a Keystore-gated flow.

NameTypeReqDescription
serialstring–Target 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
packagestring–Optional package name to filter to (e.g. com.example.app); omit for the most recent crash from any app.
serialstring–Target 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).
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

launch_dev_client ~257

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 {device_port: 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
hoststring–Metro dev-server host as the DEVICE sees it. Default localhost (works once adb_reverse {device_port: 8081} is set).
packagestring–Optional package to target the intent at (disambiguates if multiple apps claim the scheme).
portinteger–Metro 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.
serialstring–Target 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 ~126

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. Driving a React Native/Expo dev build? Follow the rn-expo guide before you start (a skill, or the android://guide/rn-expo resource) — the ordering (adb_reverse BEFORE launch, app_state before believing anything) is the part that costs sessions.

NameTypeReqDescription
serialstring–Target 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_dirstring–Path 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 ~152

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
project_dirstring–Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstring–Gradle task to scope to, e.g. ":app:tasks" to list the :app module's tasks or variants. Defaults to the root project's tasks.

No output schema declared.

No examples provided.

list_gradle_variants ~220

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_dirstring–Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session.
taskstring–Gradle task to scope to, e.g. ":app:tasks" to list the :app module's tasks or variants. 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
filterstring–Substring to filter package names.
serialstring–Target 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
filterstring–Case-insensitive substring to keep (e.g. an app tag or "Exception").
linesinteger–Number of recent lines to dump. Default 400. Ignored when since is given.
prioritystring–Minimum 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.
redactboolean–Mask common secrets (token, password, authorization, api key, secret) before returning log lines. Recommended for payment/auth SDKs and debug builds.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.
sincestring–Time 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|array–Keep 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_msinteger–Hold duration in ms. Default 600.
serialstring–Target 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
serialstring–Target 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
packagestring–Optional package to target the intent at.
serialstring–Target 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
actionstring–What to do: "call" (default — ring an incoming call), "accept", "cancel" (hang up), "busy", or "hold".
numberstringyesPhone number for the call, e.g. "+15551234567".
serialstring–Target 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
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

press_key ~300

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. Batching several presses (or a press whose timing matters relative to other actions) belongs in run_sequence, not in separate calls.

NameTypeReqDescription
keystringyesKey name (enter, back, home, menu, tab, del, escape, up, down, left, right, ...) or a raw keycode number.
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.
verify_changenull|boolean–Also 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.
serialstring–Target 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.
serialstring–Target 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).
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

render_stats ~229

Count an app's REAL view tree and recent frame health: total views, render-node kB, per-window breakdown, jank percentage and frame-time percentiles, plus Choreographer's "Skipped N frames" tally. Use this — not describe_ui — to MEASURE a screen: describe_ui is viewport-scoped (Android drops off-screen ScrollView children from the accessibility tree), so it undercounts a long list even at filter="all". The three numbers together are what argues an unvirtualised list: a large view count, render-node kB that grows as you scroll, and skipped frames on the main thread. Pass reset=true to zero the frame counters after reading so the next call measures one specific interaction.

NameTypeReqDescription
packagestringyesApplication package name.
resetnull|boolean–Zero gfxinfo's frame counters after reading, so the NEXT call measures only what happens in between. Use it to attribute jank to one interaction instead of to the whole session.
serialstring–Target 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.
serialstring–Target 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
serialstring–Target device serial (adb -s). Optional when exactly one device is attached.

No output schema declared.

No examples provided.

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.24.5. 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

# add to Claude Code
claude mcp add iksnerd-adb-mcp -- docker run --rm -i ghcr.io/iksnerd/adb-mcp:0.24.5
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).

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 46 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 80 tools: adb_reverse, app_state, avd_snapshot, boot_emulator, build_and_run, and 75 more. Their descriptions and schemas cost roughly 14,039 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 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.