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.
Available components
Last scanned (3 hours ago)
Scores higher than 65% of OCI servers
Category Testing and QA
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
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- License check failed: no license is declared. See how to fix → Fail
- Actively maintained (last published 1 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
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.
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
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 →
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 →
adb_reverse 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.
| Name | Type | Req | Description |
|---|---|---|---|
| device_port | integer | yes | TCP port on the DEVICE to forward, e.g. 8081 for Metro. |
| host_port | integer | – | TCP port on the HOST to forward to. Defaults to device_port. |
| remove | null|boolean | – | Remove the forward for device_port instead of creating it. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
app_state 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | yes | Application package name. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| source_path | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | yes | One of: "save", "load", "delete", or "list". |
| name | string | – | Snapshot name. Required for save/load/delete; ignored for list. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
boot_emulator 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).
| Name | Type | Req | Description |
|---|---|---|---|
| avd | string | yes | AVD name to boot (see list_avds). |
| no_snapshot | null|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_s | integer | – | Boot timeout in seconds. Default 180. |
| wait_for_boot | null|boolean | – | Wait until fully booted before returning. Default true. |
| wipe_data | null|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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| args | null|array | – | Extra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free). |
| package | string | yes | Application package name to install and launch, e.g. com.example.app. |
| project_dir | string | – | Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| task | string | – | Gradle task to run. Defaults to assembleDebug. |
No output schema declared.
No examples provided.
build_status 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.
| Name | Type | Req | Description |
|---|---|---|---|
| job_id | string | yes | Job id returned by gradle_build with background=true. |
No output schema declared.
No examples provided.
cellular 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.
| Name | Type | Req | Description |
|---|---|---|---|
| data | string | – | Mobile-data registration state: one of unregistered, home, roaming, searching, denied, off, on. Omit to leave unchanged. |
| network_delay | string | – | Latency: a named profile (none, gprs, edge, umts) or raw "<min>:<max>" in ms. Omit to leave unchanged. |
| network_speed | string | – | Data throughput: a named profile (gsm, gprs, edge, umts, hsdpa, lte, evdo, full) or raw "<up>:<down>" in kbps. Omit to leave unchanged. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| signal | null|integer | – | Signal strength 0-4 (0 = no bars, 4 = full). Omit to leave unchanged. |
| voice | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | yes | Application package name (e.g. com.example.app). |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
clear_device_lock 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.
| Name | Type | Req | Description |
|---|---|---|---|
| old_value | string | yes | The current credential, needed to clear the lock. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
clear_logcat 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.)
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
connect_wireless 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.
| Name | Type | Req | Description |
|---|---|---|---|
| host_port | string | yes | Device address to connect to, host:port (e.g. 192.168.1.42:5555). |
| pair_address | string | – | Pairing address host:port (Android 11+ Wireless debugging), if different from host_port. Only needed when pairing. |
| pairing_code | string | – | 6-digit pairing code shown on the device. Provide to pair before connecting. |
No output schema declared.
No examples provided.
describe_ui 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.
| Name | Type | Req | Description |
|---|---|---|---|
| compact | null|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. |
| filter | string | – | 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… |
| package | string | – | Optional package expected to own the focused window. If another app or SystemUI owns focus, the response calls that out explicitly. |
| query | string | – | 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… |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
doctor 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| duration_ms | integer | – | Drag duration in ms. Default 400. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| x1 | integer | yes | Start X in true device pixels. |
| x2 | integer | yes | End X in true device pixels. |
| y1 | integer | yes | Start Y in true device pixels. |
| y2 | integer | yes | End Y in true device pixels. |
No output schema declared.
No examples provided.
enter_pin 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.
| Name | Type | Req | Description |
|---|---|---|---|
| coords | string | – | 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. |
| digits | string | yes | The digits to enter, e.g. "1234". |
| grid | null|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… |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
finger_remove 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
fingerprint_touch 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.
| Name | Type | Req | Description |
|---|---|---|---|
| finger_id | integer | – | Id of the enrolled finger to touch with (must match a finger enrolled in Settings). Default 1. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
get_app_details 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.
| Name | Type | Req | Description |
|---|---|---|---|
| apk_path | string | – | 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. |
| package | string | – | Installed application package name (e.g. com.example.app). Required unless apk_path is given. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
get_coverage_report 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.
| Name | Type | Req | Description |
|---|---|---|---|
| args | null|array | – | Extra arguments passed to Gradle (e.g. --stacktrace). |
| json | boolean | – | Return structured JSON instead of the human-readable text summary. |
| project_dir | string | – | Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session. |
| task | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| args | null|array | – | Extra arguments passed to Gradle (e.g. --stacktrace). |
| file | string | yes | Source 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. |
| json | boolean | – | Return structured JSON instead of the human-readable text summary. |
| project_dir | string | – | Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session. |
| task | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| args | null|array | – | Extra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free). |
| background | boolean | – | 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_dir | string | – | Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session. |
| task | string | – | Gradle task to run. Defaults to assembleDebug. |
No output schema declared.
No examples provided.
gradle_project_properties 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.
| Name | Type | Req | Description |
|---|---|---|---|
| module | string | yes | Gradle module path, e.g. :app or :feature:login. |
| project_dir | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | yes | Application package name. |
| permission | string | yes | Full permission name, e.g. android.permission.CAMERA. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
has_biometric_enrolled 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
input_key_combo 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.
| Name | Type | Req | Description |
|---|---|---|---|
| keys | null|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… |
| preset | string | – | 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. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
input_text 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| text | string | yes | Text to type into the focused field. |
No output schema declared.
No examples provided.
install_app 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.
| Name | Type | Req | Description |
|---|---|---|---|
| apk_path | string | yes | Local filesystem path to the .apk to install. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
is_device_secure 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
last_crash 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | – | Optional package name to filter to (e.g. com.example.app); omit for the most recent crash from any app. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
launch_app 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | yes | Application package name (e.g. com.example.app). |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
launch_dev_client 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.
| Name | Type | Req | Description |
|---|---|---|---|
| host | string | – | Metro dev-server host as the DEVICE sees it. Default localhost (works once adb_reverse {device_port: 8081} is set). |
| package | string | – | Optional package to target the intent at (disambiguates if multiple apps claim the scheme). |
| port | integer | – | Metro dev-server port. Default 8081. |
| scheme | string | yes | The app's URL scheme from app.json (e.g. "myapp") — used to build the expo-development-client deep link. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
list_avds 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
list_gradle_projects 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | – | Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session. |
| task | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | – | Path to the Android project root containing the Gradle wrapper (gradlew). Optional if session_set_defaults has pinned a project_dir for this session. |
| task | string | – | 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 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.
| Name | Type | Req | Description |
|---|---|---|---|
| filter | string | – | Substring to filter package names. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
logcat 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.
| Name | Type | Req | Description |
|---|---|---|---|
| filter | string | – | Case-insensitive substring to keep (e.g. an app tag or "Exception"). |
| lines | integer | – | Number of recent lines to dump. Default 400. Ignored when since is given. |
| priority | string | – | 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. |
| redact | boolean | – | Mask common secrets (token, password, authorization, api key, secret) before returning log lines. Recommended for payment/auth SDKs and debug builds. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| since | string | – | 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… |
| tags | null|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 Long press ~99
Press and hold a coordinate (true device pixels) for a duration — for context menus, drag handles, and long-press actions.
| Name | Type | Req | Description |
|---|---|---|---|
| duration_ms | integer | – | Hold duration in ms. Default 600. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| x | integer | yes | X coordinate in true device pixels. |
| y | integer | yes | Y coordinate in true device pixels. |
No output schema declared.
No examples provided.
open_dev_menu 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
open_url 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | – | Optional package to target the intent at. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| url | string | yes | URL or deep link to open (ACTION_VIEW). |
No output schema declared.
No examples provided.
phone_call 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.
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | – | What to do: "call" (default — ring an incoming call), "accept", "cancel" (hang up), "busy", or "hold". |
| number | string | yes | Phone number for the call, e.g. "+15551234567". |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
prefer_pin 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
press_key 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.
| Name | Type | Req | Description |
|---|---|---|---|
| key | string | yes | Key name (enter, back, home, menu, tab, del, escape, up, down, left, right, ...) or a raw keycode number. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| verify_change | null|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 Pull file ~85
Copy a file off the device to a local path (adb pull) — e.g. retrieve a generated file, database, or screenshot.
| Name | Type | Req | Description |
|---|---|---|---|
| device_path | string | yes | File path on the device to copy off. |
| local_path | string | yes | Local destination path. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
push_file Push file ~93
Copy a local file onto the device (adb push) — e.g. seed test data or a file to import.
| Name | Type | Req | Description |
|---|---|---|---|
| device_path | string | yes | Destination path on the device, e.g. /sdcard/Download/x.json. |
| local_path | string | yes | Local file to copy onto the device. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
reload_app 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).
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | yes | Application package name (e.g. com.example.app). |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
render_stats 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | yes | Application package name. |
| reset | null|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. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
revoke_permission 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.
| Name | Type | Req | Description |
|---|---|---|---|
| package | string | yes | Application package name. |
| permission | string | yes | Full permission name, e.g. android.permission.CAMERA. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
rotate_screen 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.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
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
claude mcp add iksnerd-adb-mcp -- docker run --rm -i ghcr.io/iksnerd/adb-mcp:0.24.5
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.