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 (10 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.
Checks we ran (12)
- Source repository
- Provenance
- License
- Maintenance
- Security disclosure
- Schema quality
- Stability
- Tool coverage
- Injection markers
- Destructive annotations
- Judged manipulation
- MCP protocol
Checks we could not complete (4)
These are gaps on our side, not findings about this package. We only credit what we can confirm, so a category made up entirely of them scores 0.
- Malware scan in Supply Chain Security (scores 0 for this)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.
- Known CVEs in Supply Chain Security (scores 0 for this)Known CVEs could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.
- Install scripts in Supply Chain Security (scores 0 for this)Install-script risk not yet assessed.
- Dependency health in Supply Chain Security (scores 0 for this)Dependency health could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.
Does not apply to this package (2)
- Endpoint SecurityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
- Transport & ReachabilityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
The score does not measure everything. What the score does not measure →
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 →
run_instrumented_tests Run instrumented tests ~218
Run Gradle instrumented (on-device) tests (default task 'connectedAndroidTest') in project_dir — requires a booted device/emulator. Returns per-suite timing and failing-test stack traces; pass json=true for a structured JSON summary. Runs in the foreground and can take minutes; for a long run use gradle_build with task=connectedAndroidTest and background=true, then read the log.
| Name | Type | Req | Description |
|---|---|---|---|
| args | null|array | – | Extra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free). |
| json | boolean | – | For run_unit_tests/run_instrumented_tests: return the test summary as structured JSON (per-suite timing, full failure stack traces) instead of the human-readable text summary. |
| 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 the tool's standard task. |
No output schema declared.
No examples provided.
run_sequence Run sequence ~356
Run several interaction steps in ONE call — no agent round-trip between them. Use for scripted flows and, crucially, flows driven by NATIVE TIMERS (background-token clear, a biometric prompt that auto-fires on resume) where a round-trip per step would perturb the timing you're testing: e.g. key:home → sleep:19 → launch → sleep:9 → tap_text:Cancel (if_present:biometric) → assert_foreground(package) → describe_ui. Each step has an 'action' (sleep, tap, tap_text, tap_element, key, text, swipe, launch, stop, assert_foreground, wait_text, describe_ui) with its params; an if_present/if_absent guard skips a step unless a selector is (not) on screen — that's how you express a conditional cancel; and optional=true lets a step fail without aborting. Returns a per-step result (ok/skipped/error) with elapsed_ms plus the final hierarchy. A non-optional step error stops the rest.
| Name | Type | Req | Description |
|---|---|---|---|
| capture_final | null|boolean | – | Append the settled UI hierarchy after the last step (unless the run aborted) so you see the end state in this same response. Default true. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| steps | null|array | yes | Ordered steps to run in one call. Each has an 'action' (sleep, tap, tap_text, tap_element, key, text, swipe, launch, stop, assert_foreground, wait_text, describe_ui) plus that action's params, and op… |
No output schema declared.
No examples provided.
run_unit_tests Run unit tests ~258
Run Gradle JVM unit tests (default task 'test') in project_dir and return the result summary, including per-suite timing and failing-test stack traces. On an Android project 'test' runs EVERY variant's unit tests (debug and release both); pass task="testDebugUnitTest" (or ":app:testDebugUnitTest" in a multi-module build) to run just one and roughly halve the time. Pass json=true for a structured JSON summary. Runs in the foreground and blocks until Gradle finishes; for a long run use gradle_build with this task and background=true, then read the log.
| Name | Type | Req | Description |
|---|---|---|---|
| args | null|array | – | Extra arguments passed to Gradle (e.g. --stacktrace, -Pflavor=free). |
| json | boolean | – | For run_unit_tests/run_instrumented_tests: return the test summary as structured JSON (per-suite timing, full failure stack traces) instead of the human-readable text summary. |
| 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 the tool's standard task. |
No output schema declared.
No examples provided.
scaffold_android_project Scaffold android project ~168
Create a minimal Kotlin Android application in a new empty directory, including Gradle Kotlin DSL files, an AndroidManifest, a launcher Activity, resources, README, and gitignore. The tool never overwrites a non-empty directory. It also generates the Gradle wrapper when a system `gradle` is on PATH, so the result is immediately buildable with gradle_build; if no gradle is installed the result says so, and `gradle wrapper` has to be run in that directory before any Gradle tool here will work (they all drive ./gradlew).
| Name | Type | Req | Description |
|---|---|---|---|
| destination | string | yes | Empty or new directory to create the project in. |
| name | string | yes | Human-readable app name. |
| package | string | yes | Application id/package, e.g. com.example.app. |
No output schema declared.
No examples provided.
screenshot Screenshot ~314
Capture the current screen as a PNG so you can SEE the UI state. Call it after every action to confirm the screen changed before acting again — driving blind chains taps onto the wrong screen. The image is auto-downscaled (default max 760px) so it is accepted by the image reader; this is for seeing only — derive tap coordinates from describe_ui, not from this image. Auto-retries an all-black frame (an intermittent capture glitch) and, if it stays black, says why (FLAG_SECURE content like a native PIN pad, or a sleeping display) — when black, use describe_ui instead. Works on multi-display foldables (the default display captures correctly); pass display="cover"/"inner"/an index to grab a specific panel.
| Name | Type | Req | Description |
|---|---|---|---|
| display | string | – | Which physical display to capture on a multi-display device (a foldable). Omit for the default/built-in screen. Accepts a name alias ('inner'/'primary' or 'cover'/'outer'), an HWC index ('0','1'), or… |
| max_dim | null|integer | – | Max width/height of the returned image in pixels. Omit for the default 760; pass 0 (or a negative) to disable downscaling and get the full-resolution image. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
send_sms Send SMS ~131
Deliver an incoming SMS to the emulator (adb emu sms send) — the standard way to drive OTP / 2FA flows without a second phone. Pass a sender number (from) and the message text (e.g. the code). Emulator-only.
| Name | Type | Req | Description |
|---|---|---|---|
| from | string | yes | Sender phone number the SMS appears to come from, e.g. "+15551234567". |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| text | string | yes | Message body (e.g. an OTP code) delivered to the device's SMS inbox. |
No output schema declared.
No examples provided.
session_clear_defaults Session clear defaults ~41
Clear any project_dir/serial defaults pinned for this session, reverting to requiring them on every call (serial still falls back to the single-attached-device default).
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
session_set_defaults Session set defaults ~162
Pin a default project_dir and/or serial for the rest of this session so later calls can omit them — the fix for a multi-module or multi-flavor project (or multiple attached devices) forcing you to repeat the same project_dir/serial on every Gradle or device call. Only the fields you pass are changed; omit a field to leave its current default alone. An explicit project_dir/serial on any individual call always overrides the session default for that one call.
| Name | Type | Req | Description |
|---|---|---|---|
| project_dir | string | – | Default Android project root to use whenever a tool call omits project_dir. Leave empty to leave the current default unchanged. |
| serial | string | – | Default device serial to use whenever a tool call omits serial. Leave empty to leave the current default unchanged. |
No output schema declared.
No examples provided.
session_show_defaults Session show defaults ~28
Show the project_dir/serial defaults currently pinned for this session (set via session_set_defaults).
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
set_battery Set battery ~235
Set the battery level (0-100) and/or charging state — test low-battery UI and charging-only logic deterministically. On an emulator it uses the console (adb emu power); on a PHYSICAL device it forces the values via dumpsys battery, which persist until you call this again with reset=true (or the device reboots). Provide level, charging, or both — or reset=true to restore automatic reporting. (For a fake battery in a clean SCREENSHOT status bar only, use set_status_bar instead.)
| Name | Type | Req | Description |
|---|---|---|---|
| charging | null|boolean | – | true = plugged into AC, false = on battery. Omit to leave the charging state unchanged. |
| level | null|integer | – | Battery charge level 0-100. Omit to leave the level unchanged. |
| reset | boolean | – | Restore automatic battery reporting (dumpsys battery reset) and ignore level/charging. On a physical device the forced values persist until this (or a reboot); use it to clean up after testing. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
set_dark_mode Set dark mode ~69
Turn the system dark theme on or off (cmd uimode night) — to test light/dark appearances.
| Name | Type | Req | Description |
|---|---|---|---|
| enabled | boolean | yes | true = dark theme on, false = off. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
set_device_lock Set device lock ~156
Set a secure lock screen (type: pin [default], pattern, or password). REQUIRED before AndroidKeyStore / Keystore-backed crypto flows, which fail with 'A secure lock screen is required' on a fresh emulator that has no lock. Follow with is_device_secure to confirm.
| Name | Type | Req | Description |
|---|---|---|---|
| old_value | string | – | The CURRENT credential, required only when a lock is already set and you want to change it (locksettings refuses to overwrite otherwise). |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| type | string | – | Lock type: pin (default), pattern, or password. |
| value | string | yes | Credential to set, e.g. "1234". |
No output schema declared.
No examples provided.
set_location Set location ~75
Set the emulator's mock GPS location (longitude, latitude) — for location-gated features.
| Name | Type | Req | Description |
|---|---|---|---|
| latitude | number | yes | Latitude of the mock GPS fix. |
| longitude | number | yes | Longitude of the mock GPS fix. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
set_sensor Set sensor ~205
Set an emulated hardware sensor value (adb emu sensor set) — drive accelerometer/gyroscope/orientation (pass x, y, z) or a single-value sensor like light/proximity/temperature/pressure/humidity (pass x only). Use to exercise shake/tilt/rotation handlers or ambient-light/proximity logic. Emulator-only.
| Name | Type | Req | Description |
|---|---|---|---|
| sensor | string | yes | Sensor name, e.g. acceleration, gyroscope, magnetic-field, orientation (3 values) or light, proximity, temperature, pressure, humidity (1 value). |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| x | number | yes | First value (the only value for single-axis sensors like light/proximity). |
| y | null|number | – | Second value for multi-axis sensors. Omit for single-value sensors. |
| z | null|number | – | Third value for multi-axis sensors. Omit for single-value sensors. |
No output schema declared.
No examples provided.
set_status_bar Set status bar ~429
Pin a clean status bar via SystemUI demo mode (enabled=true) — fixed clock, chosen signal/battery, no notification icons by default — so screenshots for docs don't leak the wall clock or a random signal state. Optionally set clock (HHMM), battery (0-100), network_type (wifi/mobile/none) with mobile_level/data_type/carrier for mobile, and notifications_visible/notification_icon. Call with enabled=false to restore the live bar.
| Name | Type | Req | Description |
|---|---|---|---|
| battery | null|integer | – | Fixed battery level 0-100 (shown unplugged). Only when enabled=true; omit to leave unchanged. |
| carrier | string | – | Carrier/operator name shown in the status bar. Only used when network_type=mobile. |
| clock | string | – | Fixed clock as 4 digits HHMM, e.g. "1200". Only when enabled=true; omit to leave unchanged. |
| data_type | string | – | Mobile data-type icon shown next to the signal, e.g. lte, 4g, 5g, 3g, edge, 1x, h, h+, roam. Only used when network_type=mobile. |
| enabled | boolean | yes | true = enter demo mode (clean, fixed status bar); false = exit and restore the live status bar. |
| mobile_level | null|integer | – | Mobile signal bars 0-4. Only used when network_type=mobile. Default 4. |
| network_type | string | – | Network icon: "wifi" (default, full signal), "mobile", or "none" (hide network icons). Only when enabled=true. |
| notification_icon | string | – | Best-effort: an AOSP SystemUI icon resource name to show in the first notification slot. Support varies by SystemUI/Android version. Only when enabled=true. |
| notifications_visible | null|boolean | – | Show notification icons in the status bar. Default false (hidden, for clean screenshots). Only when enabled=true. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
shutdown_emulator Shutdown emulator ~54
Power off a running emulator (adb emu kill). Use when you are done with a device you booted.
| 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.
start_logcat_capture Start logcat capture ~101
Begin streaming logcat into a buffer for this device (optionally clearing first). Pair with stop_logcat_capture to get everything logged DURING a flow — use this instead of the one-shot 'logcat' when you need logs across an interaction.
| Name | Type | Req | Description |
|---|---|---|---|
| clear | null|boolean | – | Clear the logcat buffer before capturing. Default true. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
start_screen_record Start screen record ~59
Start recording the screen to an mp4 on the device (Android caps a single recording at ~180s). Pair with stop_screen_record.
| 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.
stay_awake Stay awake ~143
Keep the display from dozing during a driving session (svc power stayon true) — the fix when screenshots keep coming back black with screen_off:true because the device sleeps between steps (common on emulators with a short timeout). enabled=true holds the screen on while charging (emulators always are); enabled=false restores the normal timeout. describe_ui works regardless, but any screenshot/coordinate flow needs the screen on.
| Name | Type | Req | Description |
|---|---|---|---|
| enabled | boolean | yes | true = keep the screen on while charging (svc power stayon true); false = restore the normal display timeout. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
stop_app Stop app ~73
Force-stop an app by package name. Pair with launch_app to reset an app to a clean start when reproducing a bug.
| 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.
stop_logcat_capture Stop logcat capture ~240
Stop the running logcat capture and return what was collected since start, optionally filtered by a case-insensitive substring, a minimum priority (V/D/I/W/E/F), and/or tags (OR'd). Output is capped to the last 500 lines by default (override with tail) so a long capture doesn't blow the token budget — narrow with the filters first.
| Name | Type | Req | Description |
|---|---|---|---|
| filter | string | – | Case-insensitive substring to keep. |
| priority | string | – | Minimum priority to keep: V, D, I, W, E, or F. |
| redact | boolean | – | Mask common secrets (token, password, authorization, api key, secret) before returning captured lines. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| tags | null|array | – | Keep only lines whose log tag contains one of these (case-insensitive, OR'd). |
| tail | integer | – | Keep only the last N lines after filtering (the most recent, where a crash usually is). Default 500; pass a larger number for more, or a huge one to effectively disable the cap. |
No output schema declared.
No examples provided.
stop_screen_record Stop screen record ~75
Stop the screen recording, finalize the mp4, and pull it to a local path.
| Name | Type | Req | Description |
|---|---|---|---|
| local_path | string | yes | Local path to save the pulled mp4, e.g. /tmp/rec.mp4. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
No output schema declared.
No examples provided.
swipe Swipe ~236
Swipe/drag from a start point to an end point. Params: x1,y1 (start) and x2,y2 (end) in true device pixels — x and y are accepted aliases for x1 and y1. To SCROLL DOWN a list, swipe from a HIGH y to a LOW y (drag the content up); reverse to scroll up. A longer duration_ms gives a slower, controlled drag; a short one flings.
| Name | Type | Req | Description |
|---|---|---|---|
| duration_ms | integer | – | Swipe duration in ms. Default 300. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| x | null|integer | – | Alias for x1 (start X). |
| x1 | null|integer | – | Start X in true device pixels (alias: x). |
| x2 | integer | yes | End X in true device pixels. |
| y | null|integer | – | Alias for y1 (start Y). |
| y1 | null|integer | – | Start Y in true device pixels (alias: y). |
| y2 | integer | yes | End Y in true device pixels. |
No output schema declared.
No examples provided.
tap Tap ~346
Tap a single coordinate in true device pixels. Use a center value from describe_ui. If a tap seems to do nothing, the coordinate is almost always stale/misscaled — re-run describe_ui and use a fresh center. Prefer tap_on_text when you know the element's label. When a tap lands but nothing happens, pass identify=true (reports which element the coordinate hit — or that it hit a non-clickable wrapper / no reported element) and/or verify_change=true (reports whether the UI actually changed) to tell the failure modes apart. Note: some native views (e.g. Compose/RN NativeTabs bars) don't respond to coordinate taps at all — use tap_on_text/tap_element with via_accessibility=true there (EXPERIMENTAL, requires `adb-mcp bridge install` once per device).
| Name | Type | Req | Description |
|---|---|---|---|
| identify | null|boolean | – | Also report which UI element the coordinate lands in (a hit test against the hierarchy read just before tapping). Use when a tap seems to do nothing: it tells you whether the coordinate hit the eleme… |
| 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 tap (ui_changed: true/false). Costs two extra hierarchy reads (~2-3s); use when a tap silently doing nothing would send you down the wrong path. |
| 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.
tap_element Tap element ~398
Find an element by resource_id and tap its center — the id-addressed sibling of tap_on_text, for elements with no visible label. Runs describe_ui internally (filter=all, so even unlabeled wrapper nodes are findable) and re-resolves the element right before tapping, narrowing the window where a stale coordinate lands on an overlay (e.g. an Expo dev-menu bubble) the a11y tree never reported. Use exact match (partial=false) to avoid hitting the wrong item when ids overlap; verify_change reports whether the tap had any visible effect. If a coordinate tap lands but nothing happens (e.g. a Compose/RN NativeTabs bar), pass via_accessibility=true to dispatch a real accessibility click instead (EXPERIMENTAL — see that param's description).
| Name | Type | Req | Description |
|---|---|---|---|
| partial | null|boolean | – | Substring match instead of exact. Default true. |
| resource_id | string | yes | Resource id to find and tap, e.g. "com.example.app:id/submit_button" or just "submit_button" (matches by substring by default). |
| 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 tap (ui_changed: true/false). Costs two extra hierarchy reads (~2-3s); use when a tap silently doing nothing would send you down the wrong path. |
| via_accessibility | null|boolean | – | EXPERIMENTAL. Dispatch a real accessibility click (AccessibilityNodeInfo.performAction(ACTION_CLICK)) through the adb-mcp accessibility bridge instead of a coordinate tap — reaches native views (Comp… |
No output schema declared.
No examples provided.
tap_on_text Tap on text ~358
Find an element by its visible text or content-description and tap its center — the one-shot way to press a labelled button/row without computing coordinates yourself. Runs describe_ui internally and prefers a clickable match. Matching folds typographic punctuation to ASCII, so a typed "Don't allow" finds the system dialog's "Don’t allow" (U+2019) and an en/em dash matches a hyphen. Use exact match (partial=false) to avoid hitting the wrong item when labels overlap. If a coordinate tap lands but nothing happens (e.g. a Compose/RN NativeTabs bar), pass via_accessibility=true to dispatch a real accessibility click instead (EXPERIMENTAL — see that param's description).
| Name | Type | Req | Description |
|---|---|---|---|
| partial | null|boolean | – | Substring match instead of exact. Default true. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| text | string | yes | Text or content-description to find. |
| verify_change | null|boolean | – | Also report whether the UI hierarchy changed after the tap (ui_changed: true/false). Costs two extra hierarchy reads (~2-3s); use when a tap silently doing nothing would send you down the wrong path. |
| via_accessibility | null|boolean | – | EXPERIMENTAL. Dispatch a real accessibility click (AccessibilityNodeInfo.performAction(ACTION_CLICK)) through the adb-mcp accessibility bridge instead of a coordinate tap — reaches native views (Comp… |
No output schema declared.
No examples provided.
uninstall_app Uninstall app ~91
Uninstall an app by package name (adb uninstall). Use to remove a build before a clean install, or to verify first-run behavior after reinstalling. To keep the app but reset it, prefer clear_app_data.
| 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.
wait Wait ~121
Sleep for a number of seconds (fractions ok, capped at 300), then return. For TIME-based conditions where wait_for_text's polling doesn't apply: backgrounding an app long enough to trip a native auth timer, waiting out a cooldown or rate limit, letting a long animation finish. If the sleep sits BETWEEN actions whose timing you are testing, put the whole flow in run_sequence instead — an agent round-trip per step perturbs native timers.
| Name | Type | Req | Description |
|---|---|---|---|
| seconds | number | yes | How long to wait, in seconds. Fractions allowed; capped at 300. |
No output schema declared.
No examples provided.
wait_for_boot Wait for boot ~77
Block until a device finishes booting (sys.boot_completed=1). Only needed if you started an emulator elsewhere; boot_emulator already waits by default.
| Name | Type | Req | Description |
|---|---|---|---|
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| timeout_s | integer | – | Timeout in seconds. Default 120. |
No output schema declared.
No examples provided.
wait_for_text Wait for text ~208
Poll the UI until an element with the given text/content-description appears (or times out), then return it. Use this after an async action (network load, navigation, animation) instead of a blind wait-then-screenshot — it returns as soon as the element is present, with its tappable center. Note: canvas-drawn (RN/Skia) text never enters the hierarchy, so it will time out on those — screenshot instead.
| Name | Type | Req | Description |
|---|---|---|---|
| partial | null|boolean | – | Substring match instead of exact. Default true. |
| scroll | null|boolean | – | When true, swipe upward through the current scroll container while polling. Useful when Android omits off-screen ScrollView content from the accessibility tree. |
| serial | string | – | Target device serial (adb -s). Optional when exactly one device is attached. |
| text | string | yes | Text or content-description to wait for. |
| timeout_s | integer | – | How long to wait, in seconds. Default 15. |
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.
What did VerifyMCP test on the adb-mcp: Android emulator and device control over adb server?
VerifyMCP ran 12 checks on adb-mcp: Android emulator and device control over adb, covering Source repository, Provenance, License, Maintenance and 8 more. 4 items could not be completed, a gap on our side rather than a finding about adb-mcp: Android emulator and device control over adb: Malware scan, Known CVEs, Install scripts and Dependency health. One category scores 0 for that reason, because we only credit what we can confirm. Endpoint Security and Transport & Reachability do not apply to a container image, so they were not tested. The score does not measure everything, and the scoring documentation lists what it leaves out.