Skip to content

UI Inspection

Retrieving the current Android UI hierarchy (uiautomator dump) as inline XML, and searching it by structured criteria (find_ui_elements, wait_for_ui_element). For touch and key injection, see input.

dump_ui_hierarchy

Retrieve the device's current UI hierarchy: uiautomator dump.

uiautomator dump only writes its result to a file on the device, so this dumps to a temporary path under /data/local/tmp, reads the XML back inline over adb shell (no host filesystem write, no local_root needed — the caller never has to know or manage the device-side path), and always removes the temporary file afterward. To search the hierarchy without handling XML yourself, use find_ui_elements; this module doesn't inject any input actions (see the input module for that).

Parameters:

Name Type Description Default
serial str

The target device's adb serial (see list_connected_devices).

required

Returns:

Type Description
UiHierarchyDumpResult

The serial, the full hierarchy xml (the raw <hierarchy> document, empty string if there was nothing to capture), node_count (a best-effort count of <node> elements — 0 for an empty hierarchy or if the XML couldn't be parsed), success (always True — see Error handling), and the raw uiautomator dump output.

Error handling

An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE. uiautomator dump itself failing to run (e.g. the uiautomator binary is missing on this build) raises UIAUTOMATOR_FAILED. The command running but finding no inspectable window content right now (screen off, locked, or otherwise no accessible root node) raises UI_HIERARCHY_UNAVAILABLE — distinct from an empty-but-successful hierarchy, which is returned as data with node_count=0, not raised. A permission rejection raises PERMISSION_DENIED; the dumped temp file vanishing before it could be read back raises REMOTE_FILE_NOT_FOUND; any other failure raises a generic BACKEND_ERROR.

Example

Called with serial="emulator-5554". A typical response:

{
  "status": "success",
  "message": "Dumped UI hierarchy (2 nodes) from emulator-5554.",
  "data": {
    "serial": "emulator-5554",
    "xml": "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><hierarchy rotation=\"0\">...</hierarchy>",
    "node_count": 2,
    "success": true,
    "output": "UI hierarchy dumped to: /data/local/tmp/adb_automation_mcp_ui_dump_....xml\n"
  },
  "error": null
}

find_ui_elements

Search the current UI hierarchy for nodes matching structured criteria.

Captures the hierarchy the same way dump_ui_hierarchy does, then filters <node> elements in Python and returns each match flattened to the attributes callers act on (text, resource_id, class, bounds + the bounds' center point, and the usual boolean state flags). At least one criterion must be given; all supplied criteria are combined with AND.

Parameters:

Name Type Description Default
serial str

The target device's adb serial (see list_connected_devices).

required
text str | None

Match nodes whose text attribute equals this exactly.

None
text_contains str | None

Match nodes whose text contains this substring (case-sensitive).

None
resource_id str | None

Match nodes by resource-id — either the full "package:id/name" or just the bare "name" (which also matches a Compose testTag surfaced as a prefix-less resource-id).

None
content_desc str | None

Match nodes whose content-desc equals this exactly.

None
class_name str | None

Match nodes by class — either the fully-qualified name ("android.widget.Button") or just the final segment ("Button").

None
package str | None

Match nodes whose package equals this exactly.

None
clickable bool | None

Match nodes whose clickable flag equals this bool.

None
enabled bool | None

Match nodes whose enabled flag equals this bool.

None
limit int

Maximum number of matched elements to return (1-500, default 50). match_count still reports the true total; truncated says whether the list was cut.

50

Returns:

Type Description
UiElementMatchResult

The serial, match_count (total matches), returned_count (how many are in elements), truncated, and elements — each an object with text / resource_id / class_name / package / content_desc, the boolean flags (clickable, enabled, focused, checkable, checked, selected, scrollable, long_clickable, password), and bounds ({left, top, right, bottom, center_x, center_y} or null). Zero matches is a normal success result.

Error handling

No criteria at all, or a limit outside 1-500, is rejected before any device round-trip (INVALID_ARGUMENT). An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE; uiautomator failing raises UIAUTOMATOR_FAILED; no inspectable window content right now raises UI_HIERARCHY_UNAVAILABLE. A malformed / truncated hierarchy is treated as zero matches, not a crash. Other failures raise PERMISSION_DENIED / REMOTE_FILE_NOT_FOUND / BACKEND_ERROR as for dump_ui_hierarchy.

Example

Called with serial="emulator-5554", text="Phone". A typical response:

{
  "status": "success",
  "message": "1 UI element(s) matched on emulator-5554.",
  "data": {
    "serial": "emulator-5554",
    "match_count": 1,
    "returned_count": 1,
    "truncated": false,
    "elements": [
      {
        "text": "Phone",
        "resource_id": "com.android.launcher3:id/icon",
        "class_name": "android.widget.TextView",
        "package": "com.android.launcher3",
        "content_desc": "Phone",
        "clickable": true,
        "enabled": true,
        "focused": false,
        "checkable": false,
        "checked": false,
        "selected": false,
        "scrollable": false,
        "long_clickable": true,
        "password": false,
        "bounds": {"left": 100, "top": 200, "right": 300, "bottom": 400, "center_x": 200, "center_y": 300}
      }
    ]
  },
  "error": null
}

wait_for_ui_element

Poll the UI hierarchy until an element appears or disappears.

Re-captures the hierarchy every poll_interval_s and re-checks the same structured criteria as find_ui_elements, until the condition holds or timeout_s elapses. Replaces blind sleeps in automation. The loop is always bounded — timeout_s is capped at 120s and poll_interval_s at 30s. At least one criterion must be given (AND-combined).

Parameters:

Name Type Description Default
serial str

The target device's adb serial (see list_connected_devices).

required
condition WaitCondition

"present" (default) waits until at least one node matches; "absent" waits until no node matches.

'present'
timeout_s float

Maximum seconds to keep polling (0 exclusive to 120). Default 10.

10.0
poll_interval_s float

Seconds between hierarchy captures (0.1 to 30). Default 1.

1.0
text str | None

Match nodes whose text equals this exactly.

None
text_contains str | None

Match nodes whose text contains this substring.

None
resource_id str | None

Match by full "package:id/name" or bare "name".

None
content_desc str | None

Match nodes whose content-desc equals this exactly.

None
class_name str | None

Match by fully-qualified class or final segment.

None
package str | None

Match nodes whose package equals this exactly.

None
clickable bool | None

Match nodes whose clickable flag equals this bool.

None
enabled bool | None

Match nodes whose enabled flag equals this bool.

None

Returns:

Type Description
UiWaitResult

The serial, condition, satisfied (always True on return), match_count and elements at the moment the condition held (for "absent" that's 0 / []), waited_s (roughly how long the loop ran), and poll_count (how many captures it took).

Error handling

No criteria, an out-of-range timeout_s / poll_interval_s, or a bad condition is rejected before any device round-trip (INVALID_ARGUMENT). The condition never holding within timeout_s raises TIMEOUT (retryable), with the last seen match count in its details. An unknown serial / adb failure raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE; uiautomator or hierarchy failures raise UIAUTOMATOR_FAILED / UI_HIERARCHY_UNAVAILABLE / PERMISSION_DENIED / BACKEND_ERROR as for dump_ui_hierarchy.

Example

Called with serial="emulator-5554", text="Success", timeout_s=5. A typical response:

{
  "status": "success",
  "message": "UI condition 'present' satisfied on emulator-5554 after 1.2s (2 check(s)).",
  "data": {
    "serial": "emulator-5554",
    "condition": "present",
    "satisfied": true,
    "match_count": 1,
    "waited_s": 1.2,
    "poll_count": 2,
    "elements": [{"text": "Success", "resource_id": "", "class_name": "android.widget.TextView", "package": "com.example.app", "content_desc": "", "clickable": false, "enabled": true, "focused": false, "checkable": false, "checked": false, "selected": false, "scrollable": false, "long_clickable": false, "password": false, "bounds": null}]
  },
  "error": null
}