Advanced ADB MCP server for Android automation — optimised for small LLMs (gpt-oss-20b, qwen3vl). 15 semantic tools, OCR + Set-of-Mark dual-path screen understanding.
Strong tool naming (verb-first, clear intent) and comprehensive descriptions (avg 180 chars, well above 10-char minimum). All 13 tools have input schemas with types and descriptions. Good parameter documentation with enums (e.g., priority in get_logcat, panel in open_settings). Key gaps: output schemas not explicitly documented in source; error handling guidance minimal; no tool annotations (readOnlyHint/destructiveHint); some parameters lack constraints (e.g., max_lines unbounded). Composition is sound, tools chain well (list_devices → device_info → tap). Risk classification present but not formalized in schema.
Get detailed device info: model, manufacturer, Android version, SDK level, screen resolution, DPI, battery level, and Wi-Fi IP. Useful for adapting automation to the device's screen size.
Query an Android system service via dumpsys. Allowed services: window, activity, battery, power, package, notification, meminfo, cpuinfo, display, alarm, connectivity, wifi, telephony.registry, statusbar, input_method. Use parsed output for common services; set raw=true to get full text.
Read recent Android logs. Use tag_filter to narrow to a specific component (e.g. 'ActivityManager', 'WifiManager'). priority: V=verbose, D=debug, I=info, W=warn (default), E=error. Returns parsed lines with priority, tag, pid, and message.
Capture current screen. Returns UI element tree (JSON), OCR text spans, and optionally a Set-of-Mark numbered screenshot. Use mode='text' for text-only models, mode='vision' for vision models, mode='both' for both. Element IDs in the tree match the numbered badges in the image — pass id:N to tap().
Launch an Android app by name or package. Searches the launcher if direct package launch fails. Returns foreground status and updated screen tree.
Output schemas not documented in source code. Tool descriptions mention return fields (e.g., 'screen_changed', 'matched:true/false') but no formal schema definitions visible. LLMs cannot reliably parse responses without documented structure.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) in schema. Risk field present in metadata but not exposed to LLM via schema. Agents cannot distinguish safe reads from destructive writes without explicit hints.
Numeric parameters lack bounds. max_lines (default 200) unbounded; timeout_ms, duration_ms, poll_ms have no min/max constraints. Agents could pass absurd values (e.g., max_lines=999999, timeout_ms=-1).
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 58 | <=2025-11-25 | v2 |
List all ADB-connected devices with serial, state, model, and Android version. Always call this first to confirm a device is connected and get the serial for multi-device setups.
Open in-app Settings with fallback: Settings button → overflow/menu → Settings. Use after launch_app when the app is already open.
Jump directly into Android system settings by panel name. Supported panels: wifi, bluetooth, airplane_mode, display, sound, battery, storage, apps, about_phone, developer_options, accessibility, and others.
Press a hardware or system key. Common keys: back, home, enter, delete, recent, power, volume_up, volume_down, tab, search. Use 'back' to dismiss dialogs or navigate back.
Swipe on the screen. Use direction='up'|'down'|'left'|'right' for scroll gestures, or from_selector+to_selector for drag, or x1,y1,x2,y2 for precise swipe. duration_ms controls speed (higher = slower). By default (observe=true) returns the updated screen tree and screen_changed flag.
Tap an element. Prefer selector (semantic) over x,y coordinates. Selector keys: id (SoM number from get_screen), text, text_contains, resource_id, content_desc, class, index. Set long_press=true for long-tap. By default (observe=true) returns the updated screen tree and screen_changed flag so you can confirm your action worked without an extra get_screen call. Set observe=false to skip the post-tap screen capture.
Type text into the focused field or a specific element. Use selector to focus the target element first. Set clear=true to wipe existing text before typing. Set observe=true to capture the screen after typing.
Wait until a UI element appears, disappears, or changes. Essential after navigation actions in onboarding flows. Selector keys: text, text_contains, resource_id, content_desc, class, id (SoM number). Returns matched:true/false and the matched node if found.
Error handling guidance minimal. Descriptions mention 'SELECTOR_AMBIGUOUS' but no formal error response schema or recovery guidance documented. Agents lack actionable next steps on failure.
Selector parameter structure underspecified. tap() and wait_for() accept 'selector' as object with keys (id, text, resource_id, etc.) but no formal schema for the selector object visible. LLMs must infer valid keys from description text.