MCP server giving AI agents eyes and hands inside Android devices via ADB
Agent Droid Bridge is a well-structured Android control MCP server with 20 tools covering device interaction, app management, and UI automation. Most tools have solid descriptions (median ~150 chars) and complete input schemas with type constraints. However, several issues prevent a higher score: (1) Output schemas are not documented in visible tool definitions, return types are inferred from Pydantic models but not explicitly stated in descriptions; (2) A few parameters lack descriptions or have minimal ones (e.g., 'device_serial' is repeated across all tools with identical boilerplate); (3) Error handling descriptions are present but vary in actionability; (4) STDIO-only transport caps protocol readiness at 50, regardless of definition quality. The tool naming is excellent (verb-first, action-oriented), and parameter constraints are well-applied (enums, min/max bounds). This is a B-grade server with clear, usable tools but missing the documentation and protocol maturity for A-tier production use.
Polls for a change to the Android UI, returning the new hierarchy and success status.
The output of an ADB command. Parsed safely via shlex and never passed to a system shell.
Full static metadata for a single installed app. Request only the sections you need. Use search to filter components or permissions by name.
Returns the current Android screen as an XML UI hierarchy. Use this when you need to locate element coordinates, read text, or find resource IDs to interact with. Do not call this after every action — only call it when you actually need to read screen content. To check if the screen changed after an action, use snapshot_ui before the action and detect_ui_change after.
Fire an intent at a component. Requires intent_type: 'activity', 'broadcast', or 'service'. Broadcasts can produce verbose output — use filter to extract relevant lines. Returns success, exit code, filtered or full output lines, and error if any. For advanced intent flags not covered here, use execute_adb_command directly.
Output schemas not explicitly documented. While Pydantic models exist internally (e.g., LaunchAppExtraResult, ManageAppResult), tool descriptions do not state what fields will be returned. LLMs cannot plan downstream tool chains without knowing what data they'll receive.
Parameter 'device_serial' repeated across all 20 tools with identical description ('Optional device serial number'), boilerplate text that adds no value. Every tool description becomes longer without clarity. Should be documented once in a separate section or use a shared parameter annotation.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 71 | <=2025-11-25 | v2 |
Install an APK from a host path onto the device. Returns the package name and version if aapt is available, or None for those fields if not. Returns the package manager error string on failure.
An Android app launched by its component name (package/activity).
Launch an app by package name without requiring a component name. Resolves the launcher activity automatically using pm resolve-activity. Returns the resolved component, app name, and PID when available. PID is best-effort — it may be None on success if the process had not registered by the time of the check. If resolution fails, the error message will suggest using get_app_info with sections=['components'] followed by launch_app with the explicit component.
All Android devices currently visible to ADB, with their serial numbers, connection state, and model names.
List installed packages on the device. Use search to narrow results before requesting detailed mode — detailed runs a separate dumpsys call per package and is expensive on large lists.
Control app runtime state. Clear_data is irreversible — it permanently removes all user data for the app. Clear_cache requires root and reports requires_root=true when unavailable.
Grant, revoke, check, or list runtime permissions for an app. Use list to see all permissions without specifying one. Use check to verify grant status before acting.
A key event sent to the Android device using the given keycode integer.
Extract the installed APK from the device by package name. Returns the written file path(s) and sizes.
Takes a lightweight snapshot of the current UI state and returns a short token. Use this before performing an action (tap, swipe, launch, key press) when you only need to confirm the screen changed afterward — not read its content. Pass the returned token to detect_ui_change as baseline_token. This avoids loading the full XML hierarchy into context unnecessarily. Do not use this when you need to read or interact with screen elements — use get_ui_hierarchy for that.
A swipe gesture on the Android screen from (x1,y1) to (x2,y2) over the given duration.
A PNG screenshot of the current Android device screen with width, height, and base64-encoded image data.
A tap gesture at the given pixel coordinates on the Android screen.
Text input into the currently focused Android input field. Spaces are encoded automatically.
Remove an installed app by package name.
Tool descriptions lack examples of when to use alternative tools. For instance, 'launch_app' vs 'launch_app_extra' distinction is unclear from description alone, LLMs may pick wrong tool. Pattern guidance: include 'Use this when...' language.
Error handling descriptions are present but inconsistent in actionability. Most tools mention ToolError but do not suggest recovery paths (e.g., 'If device not found, call list_devices() first').
Destructive operations (manage_app with 'clear_data', uninstall_app) lack confirmation or dry-run support.