Skip to main content
Glama

android-build-mcp

CI License: MIT

An MCP server that gives a coding agent hands and eyes on an Android device.

Your agent can already shell out to gradlew and adb. The problem is what that costs: a failed build dumps four thousand lines of task progress into the context window, tap coordinates get guessed off a screenshot, and a JDK/Gradle mismatch sends it bisecting application code for an hour over an error that had nothing to do with the app.

This is the build-debug loop made cheap. 19 tools covering build, test, install, launch, screenshot, UI inspection, input, logs, and toolchain diagnosis — each one shaped to return the smallest thing that answers the question.

You: "The start button doesn't do anything on the tablet. Fix it."

Agent: android_doctor          -> toolchain OK, Gradle 8.7 / JDK 17 compatible
       android_build           -> assembleDebug + install + launch
       android_set_rotation    -> landscape
       android_dump_ui         -> Button "start" at (1580, 890), clickable=false
       android_logcat          -> IllegalStateException in onMeasure
       ...reads the layout, edits it, rebuilds, taps the button, confirms

Install

Requires Node 18+, the Android SDK platform-tools, and a JDK (Android Studio's bundled one is found automatically).

Not on npm yet — install from source:

git clone https://github.com/jjs03111/android-build-mcp
cd android-build-mcp
npm install && npm run build

Claude Code

claude mcp add android -- node /absolute/path/to/android-build-mcp/dist/index.js

Any MCP client — add to the client's server config:

{
  "mcpServers": {
    "android": {
      "command": "node",
      "args": ["/absolute/path/to/android-build-mcp/dist/index.js"]
    }
  }
}

No configuration needed if you have a standard Android Studio install. Run android_doctor to confirm.

Related MCP server: Android MCP Server

What this does beyond wrapping adb

It knows why builds fail. JDK/Gradle incompatibility is checked before the build starts, so you get "JDK 23 is newer than Gradle 8.7 supports (max 22)" instead of Unsupported class file major version 67 after a two-minute wait. SDK location not found, signature mismatches on install, and INSTALL_FAILED codes all come back with the actual remedy attached.

It doesn't flood the context. A failed Gradle build is thousands of lines, nearly all of it task progress. The failure summary keeps the compiler diagnostics and the FAILURE: block and drops the rest — typically a 50%+ reduction, all of it noise. Logcat filters to your app's pid. android_dump_ui returns text and coordinates instead of a megabyte of screenshot when what you needed was the label on a button.

It recognises failures it has seen before. Every failure path — Gradle, install, crash logs — runs its output past a set of known Android failure modes whose symptoms point nowhere near their causes. When one matches, the fix arrives attached to the error, not in a document somebody has to remember to consult:

  • Gradle refusing to run on a too-new JDK (Unsupported class file major version)

  • SDK location not found on a fresh clone, because local.properties is gitignored

  • OEM battery management killing foreground services within seconds on Samsung and Xiaomi

  • adb shell input text silently dropping every non-ASCII character

  • GridLayout cells collapsing when weights meet wrap_content

  • Package visibility filtering returning empty lists on Android 11+

  • Signature mismatches on install, and stale package references after an external uninstall

android_pitfalls exposes the same set for browsing and searching. An agent that hits one of these otherwise starts bisecting application code that was never the problem.

It finds your toolchain. adb via ANDROID_HOME, the platform's standard SDK locations, then PATH. The JDK via Android Studio's bundled JBR — chosen because it is version-matched to AGP, unlike whatever is on PATH. Gradle is launched through the wrapper's main class rather than gradlew.bat, which both sidesteps Node's refusal to spawn .bat files and guarantees the validated JDK is the one that runs.

Tools

Device

Tool

Purpose

android_list_devices

Connected devices with Android version, screen size, density, rotation

android_connect_wifi

Promote a USB device to wireless adb, or reconnect to a known address

Build

Tool

Purpose

android_build

Gradle assemble, optionally install and launch in one call

android_test

Run unit or instrumented tests, reporting which ones failed

android_install

Install an APK

android_launch

Start an app, optionally cold

android_clear_data

Wipe an app's data without uninstalling it

android_uninstall

Remove an app

Inspect

Tool

Purpose

android_screenshot

PNG of the screen, inline or to a file

android_dump_ui

View hierarchy as text, with tap coordinates for every element

android_logcat

Logs filtered by package, tag, priority, or the crash buffer

android_shell

Arbitrary adb shell command

Interact

Tool

Purpose

android_tap

Tap or long-press

android_swipe

Swipe, scroll, drag

android_input_text

Type into the focused field

android_key_event

Back, Home, Enter, arrows, volume

android_set_rotation

Force an orientation, or restore auto-rotate

Diagnose

Tool

Purpose

android_doctor

Check adb, SDK, JDK, devices, and JDK/Gradle compatibility

android_pitfalls

Look up known failure modes by error text, topic, or keyword

How this compares

vs. letting an agent run gradlew and adb through a shell tool. It already can, and when a build succeeds the difference is small. The difference shows up on failure and at scale: a failed build here returns the compiler errors instead of several thousand lines of task progress, a JDK/Gradle mismatch is caught before the build rather than two minutes into it, logs come back scoped to your app's process, and android_dump_ui hands over exact tap coordinates instead of the agent estimating them off a screenshot. Shell output is also unstructured, so every result has to be re-read by the model.

vs. mobile-mcp and other device-control servers. Those cover device automation — tap, swipe, screenshot, element inspection — and mobile-mcp covers iOS too, which this does not. The overlap is real, and if driving a device is all you need, they are the more established choice. What they do not cover is the build side: compiling the project, resolving the application id out of Gradle, installing, running tests, and explaining why the toolchain refused. That is what this server is for. Testing an app you did not build? Prefer theirs. Writing the app? This closes the edit-run-read cycle.

vs. Android Studio. Not a competitor. This exists so an agent can do the parts of the loop that do not need a person watching. Keep the IDE open.

Configuration

Everything is auto-detected. Override only if you need to:

Variable

Purpose

ANDROID_HOME / ANDROID_SDK_ROOT

Android SDK root

ANDROID_MCP_ADB

Path to the adb binary

ANDROID_MCP_JAVA_HOME

JDK to build with

Security

android_shell runs arbitrary commands on the connected device, and the build tools execute the target project's Gradle wrapper — which is code from that project. Point this at repositories you trust, the same way you would before opening one in an IDE. Nothing is sent anywhere: every tool talks only to the local adb server and the local filesystem.

android_clear_data and android_uninstall destroy app data irrecoverably; both are marked with destructiveHint so clients that gate destructive tools can prompt before running them.

Known limitations

  • android_input_text cannot type non-ASCII characters, nor the literal sequence %s. Both are limitations of Android's input text command: it is ASCII-only, and it decodes %s to a space with no escape available (even %%s decodes to % ). The tool rejects both cases with an explanation rather than silently mangling the text. Use an adb-driven IME (ADBKeyBoard) for CJK.

  • android_dump_ui cannot see inside WebView content; uiautomator only exposes the WebView node itself. Use android_screenshot for WebView-based UIs.

  • android_dump_ui cannot see past a locked screen either — you get the keyguard, not the app.

  • Wireless adb requires the host and the device to be on the same LAN. A VPN interface on the host does not bridge to the device's network, and routers with AP isolation block it outright. android_connect_wifi detects the subnet mismatch case and says so rather than reporting a bare timeout.

  • Release builds require the project's own signing config.

  • Developed and manually verified on Windows against a physical device (Galaxy A16, Android 16) and an emulator (API 35). macOS and Linux run the unit tests and a server smoke check in CI, and Linux additionally runs the full end-to-end suite on an emulator — but neither has been driven by hand, so rough edges in toolchain discovery are likelier there. Reports welcome.

Development

npm install
npm run build
npm test          # unit tests
npm run typecheck

npm test needs no device. The end-to-end suite does — start an emulator or plug in a phone, then:

node test/e2e/run.mjs

It prefers an emulator when one is running, so it will not rotate the screen or inject input on a phone you happen to have plugged in.

Contributing

The most useful contribution is a pitfall. If some Android failure cost you an afternoon because the symptom pointed nowhere near the cause, add it to src/services/pitfalls.ts: the symptom as you observed it, the actual cause, the fix, and — if the error has a recognisable signature — a regex so it fires automatically at the moment of failure instead of waiting to be looked up.

Bug reports that include the output of android_doctor are much faster to act on.

License

MIT

Available Tools

19 tools
android_buildBuild (and optionally install and launch) an Android appA

Run a Gradle assemble for an Android project and, when asked, install the APK and start it on a device — the full edit-run loop in one call.

Handles the toolchain details that normally break automated builds:

  • picks a JDK Gradle can actually run on (Android Studio's bundled JBR when present), instead of trusting the ambient JAVA_HOME

  • refuses to start, with an explanation, when the JDK is newer than the Gradle wrapper supports

  • condenses a failed build's log down to the compiler errors instead of returning thousands of progress lines

The first build of a project downloads the Gradle distribution and dependencies and can take several minutes.

Args:

  • project_path (string): absolute path to the Gradle root (contains gradlew)

  • module (string): module producing the APK (default: 'app')

  • variant ('debug' | 'release'): build variant (default: 'debug')

  • clean (boolean): run the 'clean' task first (default: false)

  • install (boolean): install the APK after a successful build (default: false)

  • launch (boolean): start the app after installing; implies install (default: false)

  • serial (string, optional): target device when installing

  • timeout_ms (number): build timeout (default: 900000)

  • response_format ('markdown' | 'json')

Returns: { "success": boolean, "task": string, // e.g. "assembleDebug" "durationMs": number, "apkPath": string, // present on success "packageName": string, // resolved from applicationId / namespace / manifest "gradleVersion": string, "javaMajor": number, // JDK major version used "installed": boolean, "launched": boolean, "output": string, // build tail on success, error summary on failure "hint": string // present when the failure is recognised }

Examples:

  • Use when: "build and run this app on my phone" -> project_path=..., install=true, launch=true

  • Use when: verifying a code change compiles -> project_path=..., install=false

  • Don't use when: the APK is already built and you only want it installed (use android_install)

Error Handling:

  • "Unsupported class file major version" is caught before the build starts and reported as a JDK/Gradle mismatch with the fix

  • "SDK location not found" means local.properties or ANDROID_HOME is missing

  • Install failures report the adb failure code (e.g. INSTALL_FAILED_UPDATE_INCOMPATIBLE) with the usual remedy

ParametersJSON Schema
NameRequiredDescriptionDefault
cleanNoRun the 'clean' task before assembling.
forceNoSkip the JDK/Gradle compatibility pre-check. Use only when the check is out of date and the combination is known to work.
launchNoStart the app after installing. Implies install.
moduleNoGradle module that produces the APK. Almost always 'app'.app
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
installNoInstall the APK after building.
variantNoBuild variant. 'release' requires signing config to be set up in the project.debug
timeout_msNoBuild timeout in milliseconds.
project_pathYesAbsolute path to the Gradle project root — the directory containing gradlew and settings.gradle.
response_formatNoOutput format: 'markdown' for human-readable, 'json' for machine-readable.markdown

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses important behaviors beyond annotations: JDK auto-selection, refusal when Gradle/JDK mismatch occurs, log condensing on failure, first-build download delays, and recognized error handling for SDK and install failures. No contradiction with annotations (readOnlyHint=false is expected for a build/install tool).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for purpose, details, args, returns, examples, and error handling. The Args section is redundant with the input schema and adds length without much value, but the rest is concise and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even without an output schema, the description provides a full return object, concrete examples, error handling guidance, and toolchain context. It covers the tool's complexity comprehensively, including first-build delays and JDK mismatch behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description's Args section mostly repeats the schema verbatim and omits the 'force' parameter entirely, which is a notable gap. It adds little meaning beyond what the schema already provides (e.g., 'implies install' is also in the schema).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Run a Gradle assemble for an Android project and, when asked, install the APK and start it on a device.' It clearly distinguishes itself from siblings through the exclusions note ('Don't use when... use android_install') and the overall edit-run loop framing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'Use when' and 'Don't use when' guidance is provided, naming android_install as the alternative for already-built APKs. Also gives concrete scenarios: 'build and run this app on my phone' vs 'verifying a code change compiles.'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_clear_dataClear an app's dataA
DestructiveIdempotent

Wipe an app's data and cache while leaving it installed — the equivalent of "Clear storage" in system settings.

Use this to get back to a first-run state without uninstalling. It is less disruptive than android_uninstall (the app and its install stay put) but it still destroys everything the app has stored: databases, preferences, cached files, and any signed-in session.

Args:

  • package_name (string, optional): application id to clear

  • project_path (string, optional): Gradle root; the package is resolved from it when package_name is omitted

  • module (string): module to read the package from (default: 'app')

  • serial (string, optional): target device

Returns: { "cleared": boolean, "packageName": string, "serial": string }

Examples:

  • Use when: testing onboarding or a first-run migration repeatedly

  • Use when: a corrupt local database is masking the bug you are chasing

  • Don't use when: you need the app gone entirely (use android_uninstall)

Error Handling:

  • Reports when the package is not installed

  • The app is force-stopped as a side effect; relaunch it with android_launch

ParametersJSON Schema
NameRequiredDescriptionDefault
moduleNoGradle module that produces the APK. Almost always 'app'.app
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
package_nameNoApplication id whose data to clear.
project_pathNoGradle root to resolve the package from.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint=true annotation, the description spells out exactly what gets destroyed (databases, preferences, cached files, signed-in sessions), notes that the app is force-stopped as a side effect, and mentions error reporting for missing packages. This gives the agent actionable safety and side-effect knowledge that structured annotations alone do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized into Args, Returns, Examples, and Error Handling sections, with the core purpose stated in the first sentence. Every section contributes practical information without redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description provides the return shape ({ cleared, packageName, serial }), error handling behavior, and concrete use cases. For a destructive, state-changing tool, this level of context makes it nearly self-contained for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, but the description's Args section adds a key semantic: project_path is used to resolve the package when package_name is omitted. It also restates the module default and serial's device-targeting role, which provides relational meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Wipe an app's data and cache while leaving it installed,' which is a specific verb+resource with clear scope. It also explicitly contrasts with android_uninstall, stating that the app and its install stay put, which definitively distinguishes it from a sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives direct usage context: 'Use this to get back to a first-run state without uninstalling,' then provides explicit 'Use when' and 'Don't use when' examples. It names the alternative android_uninstall, satisfying both when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_connect_wifiConnect to a device over Wi-FiA
Idempotent

Switch a USB-connected device to wireless adb, or reconnect to one that was paired before.

Wireless adb is what makes it practical to keep iterating on a phone that is not tethered to the machine. The device and the host must be on the same network.

Two modes:

  1. No 'host' given — requires a USB device. Reads the device's Wi-Fi address, runs 'adb tcpip', then connects. After this succeeds the USB cable can be unplugged.

  2. 'host' given — reconnects directly to a known address, no USB needed.

Args:

  • host (string, optional): device IP, with or without port, e.g. "192.168.0.12" or "192.168.0.12:5555"

  • port (number): TCP port to use (default: 5555)

  • serial (string, optional): USB serial to promote to wireless, when several devices are attached

Returns: { "serial": string, "host": string, "port": number, "alreadyConnected": boolean }

Examples:

  • Use when: you want to unplug the cable and keep building to the device

  • Use when: the wireless connection dropped after the phone slept and you need it back

  • Don't use when: you only need to know what is connected (use android_list_devices)

Error Handling:

  • "no usable IPv4 address" means the device is not on Wi-Fi; connect it to the same network as this machine

  • A device that has rebooted loses TCP/IP mode entirely and must be re-promoted over USB

ParametersJSON Schema
NameRequiredDescriptionDefault
hostNoKnown device address to reconnect to. Omit to promote a USB device.
portNoTCP port for the adb connection.
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses significant behavioral context beyond annotations: the need for same-network connectivity, the USB requirement for promotion, the fact that a rebooted device loses TCP/IP mode, and error messages. Annotations (readOnly=false, idempotent=true, destructive=false) are consistent, and the description adds meaningful details about side effects and failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: purpose, modes, arguments, return value, usage examples, and error handling. Despite its length, every sentence contributes value, and the front-loaded first sentence immediately conveys the tool's purpose. The structure improves scannability and comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is comprehensive for a tool with no output schema. It explains return values explicitly ('Returns: { serial, host, port, alreadyConnected }'), covers both usage modes, and provides error-handling guidance. Combined with the rich schema and annotations, the agent has all necessary context to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema description coverage is 100%, the description enriches parameter semantics with examples (e.g., '192.168.0.12' or '192.168.0.12:5555'), default port value, and the relationship between 'host' and mode selection. It adds practical meaning beyond the schema's formal definitions, so a score above baseline is warranted, though not a 5 since the schema already covers the basic meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Switch a USB-connected device to wireless adb, or reconnect to one that was paired before.' It specifies the verb (connect/switch) and resource (device over Wi-Fi) and distinguishes itself from siblings like android_list_devices by focusing on wireless connection setup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit 'Use when' and 'Don't use when' guidance, including an alternative tool: 'Don't use when: you only need to know what is connected (use android_list_devices).' It also explains the two modes (with/without host) and network prerequisites, making the tool's context of use very clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_doctorDiagnose the Android toolchainA
Read-onlyIdempotent

Check that the Android toolchain is usable and report exactly what is wrong when it is not.

Verifies adb, the SDK, the JDK, and connected devices; with a project path it also checks that project's Gradle wrapper against the JDK that would be used to build it — the mismatch that produces 'Unsupported class file major version'.

Run this first when a build or device command fails for a reason that is not obviously in the app's own code.

Args:

  • project_path (string, optional): Gradle root to include in the checks

  • module (string): module to inspect (default: 'app')

  • response_format ('markdown' | 'json')

Returns: { "healthy": boolean, "checks": [ { "name": string, "status": "ok"|"warn"|"fail", "detail": string, "fix": string } ], "toolchain": { "adb": string, "sdkRoot": string, "javaHome": string, "javaMajor": number } }

Examples:

  • Use when: a build fails and you do not yet know whether the cause is the project or the environment

  • Use when: adb commands fail and you want to know if the device is authorized

  • Use when: setting up on a new machine and want to confirm everything resolves

Error Handling:

  • Reports missing adb as a failed check with installation guidance, rather than throwing

ParametersJSON Schema
NameRequiredDescriptionDefault
moduleNoModule to inspect.app
project_pathNoGradle root to include in the diagnosis.
response_formatNoOutput format: 'markdown' for human-readable, 'json' for machine-readable.markdown

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Given annotations already declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, the description adds substantial behavioral detail: it enumerates the components verified (adb, SDK, JDK, devices, Gradle wrapper), explains the specific JDK mismatch it catches, and describes error handling (reports missing adb with guidance rather than throwing). No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than average but well-structured with clear sections (overview, args, returns, examples, error handling). The opening sentence is immediately informative. Minor redundancy exists between the 'Run this first' guidance and the later 'Use when' examples, but all sections serve a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a multi-check diagnostic tool with no output schema, the description is thorough: it explains what is checked, when to use it, the return object structure with example entries, and error behavior. It even names a specific failure mode ('Unsupported class file major version'). This gives an agent everything needed to invoke and interpret the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description's 'Args' section largely restates the schema's parameter descriptions (e.g., project_path as 'Gradle root to include in the checks'), adding little new meaning. It does not explain parameter interactions or edge cases beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action ('Check that the Android toolchain is usable') and a clear deliverable ('report exactly what is wrong'). It distinguishes itself from sibling tools by positioning itself as the first diagnostic step when build or device commands fail.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides strong contextual guidance: 'Run this first when a build or device command fails for a reason that is not obviously in the app's own code' and gives three concrete 'Use when' examples. It lacks explicit when-not-to-use or alternative tool names, but the context is clear enough to guide selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_dump_uiRead the on-screen UI treeA
Read-only

Dump the current screen's view hierarchy as text, with tap coordinates for every element.

This is the cheap way for an agent to see what is on screen. It gives exact text, resource ids and content descriptions, plus a centre point for each node that can be passed straight to android_tap — no guessing at pixel positions from a screenshot.

By default only meaningful nodes are returned (anything with text, a content description, a resource id, or that is clickable). Layout containers are dropped.

Args:

  • serial (string, optional): target device

  • include_all (boolean): return every node including empty containers (default: false)

  • filter (string, optional): case-insensitive substring; keeps only nodes whose text, id or description matches

  • response_format ('markdown' | 'json')

Returns: { "count": number, "nodes": [ { "index": number, "class": string, // e.g. "android.widget.Button" "text": string, "desc": string, // content-description "id": string, // resource-id "clickable": boolean, "center": [number, number], // pass to android_tap "bounds": string // "[left,top][right,bottom]" } ] }

Examples:

  • Use when: you need to press a button and must know where it is -> filter="submit"

  • Use when: verifying a screen shows the expected text after a change

  • Use when: a screenshot is ambiguous and you want the literal string values

  • Don't use when: you need to see rendering, colour or layout quality (use android_screenshot)

Error Handling:

  • "could not get idle state" means the UI is still animating; wait briefly and retry

  • WebView content is often opaque to uiautomator; a screenshot may be the only option there

ParametersJSON Schema
NameRequiredDescriptionDefault
filterNoKeep only nodes whose text, resource id or description contains this string.
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
include_allNoInclude layout containers and other nodes with no text or id.
response_formatNoOutput format: 'markdown' for human-readable, 'json' for machine-readable.markdown

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint=true, etc.), the description discloses default filtering (meaningful nodes only), error handling ('could not get idle state'), WebView limitations, and the exact return shape. This adds significant behavioral context without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (Args, Returns, Examples, Error Handling). Every sentence contributes meaningful information, and the purpose statement is front-loaded. No redundant content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description provides a full return contract, error handling, and interaction with sibling tools. It covers all necessary context for an agent to decide when and how to invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description enriches each parameter with practical usage (e.g., filter='submit') and clarifies the response_format options. It also explains how the output (center point) feeds into android_tap, adding value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Dump the current screen's view hierarchy as text, with tap coordinates for every element.' It clearly distinguishes from android_screenshot by explaining when a screenshot is preferred, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Use when' and 'Don't use when' sections give explicit context and name alternatives (e.g., android_screenshot for visual rendering). It also references android_tap for coordinates, showing how the tool fits into a workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_input_textType textA

Type text into the focused input field.

Two limitations come from Android's 'input text' command itself, not from this tool. Both are rejected up front with an explanation rather than silently mangling the text:

  • ASCII only. Korean, Japanese, Chinese, emoji and accented letters cannot be injected at all. Use an IME that accepts adb broadcasts (ADBKeyBoard is the usual one), or set the value directly in the app under test.

  • The literal sequence '%s' cannot be typed. Spaces are transmitted as '%s', and Android's decoder has no escape for a real one — even '%%s' decodes to '% '.

Tap the field first (android_tap) so it has focus.

Args:

  • text (string): ASCII text to type

  • serial (string, optional): target device

  • submit (boolean): press Enter afterwards (default: false)

Returns: { "typed": string, "submitted": boolean, "serial": string }

Examples:

  • Use when: filling a login form -> text="user@example.com"

  • Use when: entering a search term and running it -> text="pizza", submit=true

  • Don't use when: the text contains non-ASCII characters (see the limitation above)

Error Handling:

  • Rejects non-ASCII input, and text containing a literal '%s', with an explanation instead of mangling it

  • Text going nowhere means no field has focus; tap the field first

  • Text appended to existing content means the field was not empty; clear it first

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesASCII text to type.
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
submitNoPress Enter after typing.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description thoroughly discloses behavioral limitations inherited from Android's 'input text' command, including ASCII-only rejection, '%s' escaping, focus requirement, and text append behavior. It also explains error handling up front, adding substantial context beyond the readOnly/destructive hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Although lengthy, every section earns its place: limitations, prerequisites, args, returns, examples, and error handling. The structure uses clear headers and bullet points, front-loading the core purpose and limitations before details. No redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all essential aspects for correct invocation: returns object, error cases, focus prerequisite, clearing behavior, and ASCII limitations. With no output schema, the description provides a full picture of what to expect. The examples tie usage to practical scenarios and sibling-tool context (android_tap).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description enriches parameter meaning with crucial constraints: text is ASCII-only, submit implies pressing Enter, and serial is tied to android_list_devices. It also explains edge cases like '%s' and clearing the field first, which the schema does not capture.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Type text into the focused input field,' a specific verb+resource statement that clearly distinguishes this tool from siblings like android_tap and android_key_event. It also explicitly differentiates its scope by explaining what it does not do (non-ASCII, '%s').

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use ('filling a login form', 'entering a search term and running it'), when-not-to-use ('Don't use when: the text contains non-ASCII characters'), and prerequisites ('Tap the field first (android_tap) so it has focus'). It even suggests alternatives for non-ASCII cases, exceeding typical guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_installInstall an APKA
Idempotent

Install an APK onto a device, replacing any existing copy.

Args:

  • apk_path (string, optional): absolute path to the APK. Omit to use the last build output of project_path.

  • project_path (string, optional): Gradle root, used to locate the APK when apk_path is omitted

  • module (string): module that produced the APK (default: 'app')

  • variant ('debug' | 'release'): which build output to install (default: 'debug')

  • serial (string, optional): target device

  • grant_permissions (boolean): grant all runtime permissions at install time (default: false)

Returns: { "installed": boolean, "apkPath": string, "serial": string }

Examples:

  • Use when: an APK was built earlier and you want it on the device -> project_path=...

  • Use when: installing a downloaded APK -> apk_path=...

  • Don't use when: you also need to compile first (use android_build with install=true)

Error Handling:

  • INSTALL_FAILED_UPDATE_INCOMPATIBLE: the installed copy was signed with a different key; uninstall it first

  • INSTALL_FAILED_VERSION_DOWNGRADE: the device has a newer versionCode; uninstall or bump the version

  • INSTALL_FAILED_INSUFFICIENT_STORAGE: free space on the device

ParametersJSON Schema
NameRequiredDescriptionDefault
moduleNoGradle module that produces the APK. Almost always 'app'.app
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
variantNoBuild variant. 'release' requires signing config to be set up in the project.debug
apk_pathNoAbsolute path to an APK file.
project_pathNoGradle root, used to find the APK when apk_path is omitted.
grant_permissionsNoGrant all runtime permissions listed in the manifest (adb install -g).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds significant behavioral context beyond annotations: it replaces existing copies, details three common error codes with remedies, and clarifies that grant_permissions uses adb install -g. Annotations already indicate readOnlyHint=false and idempotentHint=true, and the description does not contradict them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized into Args, Returns, Examples, and Error Handling sections. It is detailed but every sentence earns its place; no fluff or repetition of schema fields, as it adds usage context instead.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description explicitly documents the return object with fields. It also covers error handling and prerequisites (e.g., release requires signing config). This makes it fully self-contained for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds extra semantics by explaining that apk_path can be omitted to use the last build output of project_path, and provides usage examples that map parameters to real scenarios. This goes beyond the schema's basic field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence clearly states the action: 'Install an APK onto a device, replacing any existing copy.' This distinguishes it from siblings like android_build (which compiles) and android_uninstall. The examples further reinforce the specific use cases for apk_path vs project_path.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description contains explicit 'Use when' and 'Don't use when' examples, including a named alternative: 'Don't use when: you also need to compile first (use android_build with install=true)'. This gives clear situational guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_key_eventPress a hardware or system keyA

Send a key event — Back, Home, Enter, arrows, volume and so on.

Args:

  • key (string): key name without the KEYCODE_ prefix. One of: BACK, HOME, MENU, APP_SWITCH, ENTER, TAB, DEL, FORWARD_DEL, ESCAPE, DPAD_UP, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_CENTER, VOLUME_UP, VOLUME_DOWN, WAKEUP, SLEEP, POWER, CAMERA, SEARCH, MEDIA_PLAY_PAUSE, MEDIA_NEXT, MEDIA_PREVIOUS, PAGE_UP, PAGE_DOWN, MOVE_HOME, MOVE_END

  • serial (string, optional): target device

  • repeat (number): how many times to send it, 1-20 (default: 1)

Returns: { "key": string, "repeat": number, "serial": string }

Examples:

  • Use when: navigating back out of a screen -> key="BACK"

  • Use when: dismissing to the launcher before a cold start -> key="HOME"

  • Use when: submitting a form without tapping -> key="ENTER"

  • Use when: the screen is off and you need to see it -> key="WAKEUP" (POWER toggles, so it can turn the screen back off)

  • Don't use when: typing characters (use android_input_text)

Error Handling:

  • An unrecognised key name is rejected with the list of supported keys

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYesKey name without the KEYCODE_ prefix.
repeatNoHow many times to send it.
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=false, and the description aligns by describing a send operation. It adds behavioral nuances beyond annotations: POWER toggles and can turn the screen back off, repeat value bounds (1-20), and rejection of unrecognized keys with a supported-key list. This gives the agent useful behavioral expectations without overstepping.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections: main purpose, Args, Returns, Examples, Error Handling. It is front-loaded and each section serves a purpose. The key list duplicates the schema enum, which is somewhat redundant, but the examples and error handling make the extra length worthwhile.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has moderate complexity with 3 parameters, but the schema covers all parameters. Annotations provide safety profile. The description adds practical usage guidance, return format (even though no output schema), and error handling. It completely covers what an agent needs to decide when and how to invoke this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each parameter already has a description. The description's Args section restates the key list and repeat bounds but adds semantic value through the Use-when examples that tie specific keys to actions. It also clarifies serial's role minimally, though the schema provides richer context (device from android_list_devices, required when multiple). Overall, it adds moderate value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+object: 'Send a key event', and the title clarifies 'hardware or system key'. It explicitly lists the key categories (Back, Home, Enter, arrows, volume) and differentiates from android_input_text by stating the don't-use case. This strongly distinguishes it from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes explicit 'Use when:' examples mapping scenarios to keys (e.g., navigating back -> BACK, screen off -> WAKEUP) and a clear 'Don't use when: typing characters (use android_input_text)', providing an alternative. It also notes error handling for unrecognized keys, giving clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_launchLaunch an appA
Idempotent

Start an installed app's launcher activity, optionally force-stopping it first.

Args:

  • package_name (string, optional): application id, e.g. "com.example.myapp"

  • project_path (string, optional): Gradle root; the package is resolved from it when package_name is omitted

  • module (string): module to read the package from (default: 'app')

  • serial (string, optional): target device

  • force_stop (boolean): kill the app before starting, guaranteeing a cold start (default: false)

Returns: { "launched": boolean, "packageName": string, "serial": string }

Examples:

  • Use when: bringing an app to the foreground before taking a screenshot

  • Use when: you need a cold start to reproduce a launch-time bug -> force_stop=true

  • Don't use when: the app is not installed yet (use android_install)

Error Handling:

  • Reports when the package is not installed, rather than silently doing nothing

  • An app with no launcher activity cannot be started this way

ParametersJSON Schema
NameRequiredDescriptionDefault
moduleNoGradle module that produces the APK. Almost always 'app'.app
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
force_stopNoForce-stop the app first so the next start is cold.
package_nameNoApplication id to launch.
project_pathNoGradle root to resolve the package from.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, destructiveHint=false), the description discloses error behavior: it reports when the package is not installed and cannot start apps without a launcher activity. It also clarifies the effect of force_stop (guaranteeing a cold start). These are useful behavioral traits not captured in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for arguments, return value, examples, and error handling. It is longer than minimal but each section adds necessary information. The redundant parameter list mirrors the schema, but the added usage examples justify the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema, the description includes the return type and shape, error cases, and distinct usage examples. It covers the parameter semantics and edge cases (app not installed, no launcher activity) making it self-sufficient for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already describes all parameters (100% coverage). The description adds value by explaining the relationship between project_path and package_name (when one can be omitted) and giving a concrete example for package_name. This extra context slightly elevates it above the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Start an installed app's launcher activity' which is a specific verb+resource, clearly distinguishing it from sibling tools like android_install (install) and android_screenshot (capture screen). It also notes the optional force-stop capability, further clarifying scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'Use when' and 'Don't use when' examples are provided, including a specific alternative (use android_install if not installed) and a use case for force_stop to reproduce a launch-time bug. This gives clear direction on when to choose this tool over siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_list_devicesList Android devicesA
Read-onlyIdempotent

List every Android device and emulator currently visible to adb, with model, Android version and screen geometry.

Call this first in any session: other tools need a serial when more than one device is attached, and this is where devices in a bad state (unauthorized, offline) surface.

Args:

  • detailed (boolean): also query each device for Android version, SDK level, screen size, density and rotation. Costs one extra adb round trip per device (default: true)

  • response_format ('markdown' | 'json'): output format (default: 'markdown')

Returns: { "count": number, "devices": [ { "serial": string, // e.g. "R3CN70XXXXX" or "192.168.0.12:5555" "state": string, // "device" = ready; "unauthorized" / "offline" = not usable "wireless": boolean, // connected over TCP/IP rather than USB "model": string, "androidVersion": string, // when detailed=true, e.g. "14" "sdkLevel": number, // when detailed=true, e.g. 34 "screenSize": string, // when detailed=true, e.g. "1080x2340" "density": string, // when detailed=true, e.g. "420" "rotation": number // when detailed=true, degrees: 0/90/180/270 } ] }

Examples:

  • Use when: starting work and you need a serial for the other tools

  • Use when: an install failed and you want to check the device is still authorized

  • Don't use when: you already have a serial and just want app logs (use android_logcat)

Error Handling:

  • Returns an empty device list rather than an error when nothing is plugged in

  • Devices in state 'unauthorized' need the on-screen "Allow USB debugging?" prompt accepted

ParametersJSON Schema
NameRequiredDescriptionDefault
detailedNoQuery per-device properties (version, screen size, rotation).
response_formatNoOutput format: 'markdown' for human-readable, 'json' for machine-readable.markdown

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=true, etc.), the description adds meaningful behavioral context: devices in 'unauthorized' or 'offline' states surface here, the tool returns an empty list rather than erroring when nothing is plugged in, and detailed mode costs an extra adb round trip. It also explains the significance of the 'unauthorized' state and on-screen prompt, enriching the agent's understanding without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but highly organized with clear sections (Description, Args, Returns, Examples, Error Handling). Every sentence serves a purpose: it explains core behavior, usage timing, parameter semantics, return shape, and failure modes. It is front-loaded with the most critical 'call this first' guidance, making it efficient for quick scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is self-contained and comprehensive. It defines the return object structure even though no output schema exists, covers error handling (empty list, unauthorized state), and explains when to use the tool in the broader workflow. The annotations handle safety/profile, so the description covers all other needed context for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant value beyond the schema. For 'detailed' it lists exactly which properties are queried (Android version, SDK level, screen size, density, rotation) and notes the performance cost. For 'response_format' it clarifies the human-readable vs machine-readable tradeoff. The Args section is rich and directly useful for parameter selection.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'List every Android device and emulator currently visible to adb, with model, Android version and screen geometry,' a specific verb+resource+scope statement. It clearly distinguishes this tool from siblings by focusing on device enumeration and serial discovery, explicitly contrasting with tools like android_logcat.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: 'Call this first in any session: other tools need a serial when more than one device is attached.' It also provides a when-not-to-use example with a named alternative: 'Don't use when: you already have a serial and just want app logs (use android_logcat).' This fully covers usage context and exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_logcatRead device logsA
Read-only

Read logcat from the device, filtered down to what is actually relevant.

Returns a snapshot of the existing buffer and exits; it does not stream. Filter by package to see only your app's output — this is usually what you want after a crash, because the unfiltered buffer is mostly unrelated system noise.

Args:

  • serial (string, optional): target device

  • package_name (string, optional): show only lines from this app's process

  • tag (string, optional): show only this log tag

  • priority ('V'|'D'|'I'|'W'|'E'|'F'): minimum level (default: 'V', or 'E' when crashes_only is set)

  • crashes_only (boolean): read the crash buffer — fatal exceptions and ANRs. This buffer survives the process, so it works after the app has died (default: false)

  • lines (number): how many lines to return, 1-2000 (default: 200). Normally the most recent N; with crashes_only it is the first N of the crash, since that is where the exception and the top frames are

  • clear_only (boolean): wipe the buffer and return immediately without reading (default: false)

  • response_format ('markdown' | 'json')

Returns: { "lines": string[], "count": number, "truncated": boolean, "serial": string, "pid": number, "diagnosis": string }

'diagnosis' is present when a crash matches a known Android failure mode.

Examples:

  • Use when: the app crashed and you need the stack trace -> crashes_only=true, package_name="com.example.app"

  • Use when: watching your own Log.d output -> tag="MyTag"

  • Use when: reproducing a bug cleanly -> clear_only=true, reproduce it, then call again to read

  • Don't use when: you want to see the screen (use android_screenshot)

Error Handling:

  • Filtering by package uses the process id, which requires the app to be running. After a crash there is no process, so combine package_name with crashes_only — that path filters the crash buffer by name instead

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNoOnly show this log tag.
linesNoMost recent N lines to return.
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
priorityNoMinimum log priority: Verbose, Debug, Info, Warn, Error, Fatal.
clear_onlyNoClear the log buffer and return immediately without reading. Use before reproducing a problem, then call again to see only what the reproduction produced.
crashes_onlyNoRead the crash buffer only (fatal exceptions, ANRs).
package_nameNoOnly show logs from this app's process. The app must be running.
response_formatNoOutput format: 'markdown' for human-readable, 'json' for machine-readable.markdown

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide readOnlyHint=true and destructiveHint=false, but the description goes well beyond: it clarifies the non-streaming snapshot behavior, explains that the crash buffer survives process death, and discloses that clear_only wipes the buffer. Error-handling notes about package filtering requiring a live process add important behavioral context not present in annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is organized into clear sections (Intro, Args, Returns, Examples, Error Handling), front-loaded with the core behavior, and every sentence provides practical value. It is longer than a one-liner but appropriately sized for 8 parameters and multiple usage modes, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies a detailed return type including fields like 'truncated' and 'diagnosis'. It covers parameter behaviors, default values, edge cases (crash buffer), and error handling, making it complete for an 8-parameter tool with branching semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema description coverage is 100%, the description adds substantive meaning: e.g., lines behaves differently with crashes_only (first N of the crash vs most recent N), package_name filtering uses the process id and 'the app must be running' is expanded with the crashes_only fallback, and priority's default changes when crashes_only is set. This goes well beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource: "Read logcat from the device, filtered down to what is actually relevant." It immediately clarifies the scope (device logs filtered) and distinguishes from sibling tools like android_screenshot and android_shell. The snapshot-vs-stream clarification further sharpens the purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The Examples section explicitly states when to use the tool (after crash, watching Log.d, reproducing a bug) and when not to use it ('Don't use when: you want to see the screen' with the alternative android_screenshot). The Error Handling section also gives concrete conditional guidance (combine package_name with crashes_only after a crash).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_pitfallsLook up known Android failure modesA
Read-onlyIdempotent

Search a curated set of Android development failure modes whose symptoms point nowhere near their causes.

These are problems where the obvious interpretation is wrong: a build that fails on a JDK version rather than the code, a service killed by vendor power management rather than a bug, keystrokes ignored because they are synthetic, a GridLayout that collapses because of how weights resolve. Each entry gives the symptom, the actual cause, and the fix.

Consult this when something fails in a way that does not make sense, before spending time bisecting the app's own code.

Args:

  • error_text (string, optional): observed error output; returns entries whose known signatures match it

  • topic ('build'|'device'|'service'|'input'|'layout'|'packaging', optional): filter by area

  • search (string, optional): case-insensitive substring match across title, symptom, cause and fix

  • response_format ('markdown' | 'json')

Returns: { "count": number, "pitfalls": [ { "id": string, "topic": string, "title": string, "symptom": string, "cause": string, "fix": string } ] }

Examples:

  • Use when: a build failed with unfamiliar output -> error_text=""

  • Use when: a background service keeps dying -> topic="service"

  • Use when: planning tablet support and you want the known traps first -> topic="layout"

  • Don't use when: the error is plainly in the app's own code

Error Handling:

  • Returns an empty list when nothing matches; that means the problem is not a known environment trap

ParametersJSON Schema
NameRequiredDescriptionDefault
topicNoRestrict results to one area.
searchNoSubstring to search for across all fields.
error_textNoObserved error output to match against known failure signatures.
response_formatNoOutput format: 'markdown' for human-readable, 'json' for machine-readable.markdown

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, so the safety profile is known. The description adds useful behavioral context beyond annotations, such as the meaning of an empty result ('returns an empty list when nothing matches; that means the problem is not a known environment trap') and the return structure, which is not present in the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections for arguments, returns, examples, and error handling. It is appropriately sized for a search tool with multiple filters and does not waste words, though the examples section could be slightly condensed without loss of meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity and the absence of an output schema, the description fully covers the return format, the filter semantics, and the empty-result behavior. It also sets clear expectations about the curated nature of the data, making the tool complete and self-contained for an agent to use confidently alongside sibling tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides 100% coverage of all four parameters, so the description's parameter prose is supplemental rather than essential. The description adds helpful examples and clarifications (e.g., 'error_text' matches against known signatures), but it omits the valid topic value 'host-bridge' that appears in the schema enum, introducing a minor inconsistency. This limits the added value to a baseline level.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Search a curated set of Android development failure modes whose symptoms point nowhere near their causes.' This clearly distinguishes the tool from sibling operational tools like android_build or android_logcat, which perform actions rather than provide knowledge.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use: 'Consult this when something fails in a way that does not make sense, before spending time bisecting the app's own code.' It also gives concrete examples ('Use when: a build failed with unfamiliar output') and an exclusion ('Don't use when: the error is plainly in the app's own code'), offering clear alternatives and boundary conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_screenshotTake a screenshotA
Read-only

Capture the device screen as a PNG.

By default the image is returned inline so it can be looked at directly. Screenshots are large — a phone screen is typically 0.5–2 MB, and a tablet more — so when you only need the file (for a report, or to diff later), pass output_path and set include_image=false to keep it out of the conversation.

To read UI text or find something to tap, android_dump_ui is far cheaper than a screenshot and gives exact coordinates.

Args:

  • serial (string, optional): target device

  • output_path (string, optional): absolute path to also write the PNG to

  • include_image (boolean): return the image inline (default: true)

Returns: Inline image plus: { "bytes": number, "outputPath": string, "serial": string }

Examples:

  • Use when: confirming a layout change actually rendered as intended

  • Use when: the app crashed and you want to see what is on screen

  • Don't use when: you need the text of a view or somewhere to tap (use android_dump_ui)

Error Handling:

  • A black or empty image usually means a secure window (FLAG_SECURE) or a locked screen

ParametersJSON Schema
NameRequiredDescriptionDefault
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
output_pathNoAbsolute path to write the PNG to, in addition to returning it.
include_imageNoReturn the image inline. Set false to only write it to output_path.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, but the description adds substantial behavioral context: typical screenshot sizes (0.5–2 MB), default inline return, the effect of output_path and include_image, and error handling for black/empty screens (secure window or locked screen). This fully discloses operational nuances beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact yet well-structured, using sections for overview, args, returns, examples, and error handling. Every sentence contributes value, with no redundancy or fluff. Front-loading the core purpose makes it immediately scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even without an output schema, the description fully documents the return format (inline image plus JSON with bytes, outputPath, serial) and common failure mode (black image). It covers size implications, optional parameters, and practical usage scenarios, making it complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers all three parameters with descriptions (100% coverage), and the description goes further by explaining the rationale for include_image=false (avoid large images in conversation) and the optional nature of serial when a single device is connected. This adds meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Capture the device screen as a PNG', a specific verb+resource statement. It also explicitly distinguishes from sibling android_dump_ui by noting that for UI text or tapping, dump_ui is cheaper and provides coordinates, making the tool's unique scope clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit 'Use when' and 'Don't use when' guidance, along with a named alternative (android_dump_ui). It also advises when to set include_image=false to avoid large images cluttering the conversation, giving concrete contextual direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_set_rotationRotate the screenA
Idempotent

Force the display into a specific orientation, or hand control back to the accelerometer.

Setting a fixed rotation turns auto-rotate off first; otherwise the sensor immediately overrides it. Use 'auto' to restore normal behaviour.

Rotating is the fastest way to check a layout in both orientations. Note that an app locking its own orientation in the manifest wins over this — the display will not turn.

Args:

  • orientation ('portrait' | 'landscape' | 'portrait_reverse' | 'landscape_reverse' | 'auto')

  • serial (string, optional): target device

Returns: { "requested": string, "rotationDegrees": number, "serial": string }

Examples:

  • Use when: checking a tablet layout in landscape -> orientation="landscape"

  • Use when: restoring the device after testing -> orientation="auto"

  • Don't use when: the app declares a fixed screenOrientation; change the manifest instead

Error Handling:

  • If the reported rotation does not change, the foreground app is locking its orientation

ParametersJSON Schema
NameRequiredDescriptionDefault
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
orientationYesTarget orientation, or 'auto' to re-enable the accelerometer.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses key behavioral traits beyond annotations: fixed rotation disables auto-rotate first, sensor might override, app manifest lockdown wins, and how to detect failure. This significantly expands on the annotation hints without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for Args, Returns, Examples, and Error Handling. Despite containing substantial detail, every sentence earns its place, and the structure makes it easy for an agent to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description supplies a return shape, error handling clues, and practical examples. It covers the essential context needed to select and invoke the tool correctly, making it complete for a tool with only two parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value by explaining the behavioral meaning of orientation values (fixed vs auto) and the effect of auto-rotate override, which goes beyond the schema's dry enum listing. It reinforces but doesn't fully reinvent parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: force a display into a specific orientation or restore accelerometer control. It distinguishes this from sibling Android tools by specifying both the action ('force') and the resource ('display').

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit 'Use when' and 'Don't use when' examples, including a concrete alternative ('change the manifest') for apps with fixed orientation. Also explains when to use 'auto' to restore normal behavior, giving clear situational context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_shellRun an adb shell commandA
Destructive

Run an arbitrary command on the device via adb shell, for anything the dedicated tools do not cover.

Arguments are passed as an array and are not interpreted by a host shell, so quoting is not a concern. Note that the device's shell still applies its own semantics to things like redirection.

Prefer a dedicated tool when one exists — they parse output and explain failures. Reach for this for one-off inspection: dumpsys, pm, settings, getprop and similar.

Args:

  • command (string[]): command and arguments, e.g. ["dumpsys", "battery"]

  • serial (string, optional): target device

  • timeout_ms (number): command timeout (default: 30000)

Returns: { "stdout": string, "command": string, "serial": string }

Examples:

  • Use when: reading battery state -> command=["dumpsys", "battery"]

  • Use when: listing installed packages -> command=["pm", "list", "packages", "-3"]

  • Use when: checking a system setting -> command=["settings", "get", "global", "window_animation_scale"]

  • Don't use when: a dedicated tool covers it (android_logcat, android_dump_ui, android_tap)

Error Handling:

  • The device shell's own error text is returned verbatim

  • Commands needing root fail on production builds; there is no workaround on a locked device

ParametersJSON Schema
NameRequiredDescriptionDefault
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
commandYesCommand and arguments as separate array elements.
timeout_msNoTimeout in milliseconds.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses key behavioral traits beyond annotations: argument passing semantics ('not interpreted by a host shell'), device shell behavior (redirection), error return behavior (device shell's error text verbatim), and root limitations. The destructiveHint annotation is complemented by warning that commands may need root and fail on production builds. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, arguments, returns, examples, error handling). Every sentence adds useful information. The examples are concise and instructive. The opening line immediately conveys the tool's purpose and scope without padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's open-ended nature (arbitrary command execution), the description provides all necessary context: usage boundaries, examples, return value shape, error handling, and device-specific caveats. Although there is no output schema, the 'Returns' field covers the response structure. No gaps for a sophisticated agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining why quoting is not a concern, giving concrete examples for each parameter (e.g., command=['dumpsys', 'battery']), and clarifying the optional serial semantics implicitly through context. This extra semantic enrichment justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource: 'Run an arbitrary command on the device via adb shell'. It clearly scopes the tool as a catch-all for anything dedicated tools do not cover, and distinguishes it from siblings by explicitly naming alternatives (android_logcat, android_dump_ui, android_tap) and listing sample use cases (dumpsys, pm, settings, getprop).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance ('one-off inspection', 'for anything the dedicated tools do not cover') and when-not-to-use guidance ('Prefer a dedicated tool when one exists'), with concrete examples under 'Don't use when'. It also provides four Use-when example commands, making the selection criteria actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_swipeSwipe or scrollA

Swipe between two points. Used for scrolling, dismissing, and drag gestures.

To scroll a list down (revealing content further down), swipe from a lower y to a higher one — the finger moves up.

Args:

  • x1, y1 (number): start point in pixels

  • x2, y2 (number): end point in pixels

  • duration_ms (number): gesture duration; longer is a drag, shorter is a fling (default: 300)

  • serial (string, optional): target device

Returns: { "from": [number, number], "to": [number, number], "durationMs": number, "serial": string }

Examples:

  • Use when: scrolling a list down -> x1=540, y1=1600, x2=540, y2=600

  • Use when: dragging an item -> duration_ms=1000

  • Don't use when: a single tap is enough (use android_tap)

Error Handling:

  • A swipe that is too fast to register is the usual cause of "nothing happened"; raise duration_ms

ParametersJSON Schema
NameRequiredDescriptionDefault
x1YesStart x in pixels.
x2YesEnd x in pixels.
y1YesStart y in pixels.
y2YesEnd y in pixels.
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
duration_msNoGesture duration in milliseconds.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, destructiveHint=false), the description adds valuable behavioral context: direction semantics ('To scroll a list down... swipe from a lower y to a higher one'), duration effects ('longer is a drag, shorter is a fling'), and error handling ('A swipe that is too fast to register... raise duration_ms'). This fully discloses observable behavior without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a one-sentence summary, then organized into clear sections (Args, Returns, Examples, Error Handling). Every sentence earns its place; no fluff. It is longer than minimal but appropriately structured for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's gesture complexity, the description covers: the action, param semantics, return format ('Returns: { "from": ... }'), example usage, an explicit alternative, and error handling. No output schema exists, so the description correctly carries the return-value documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by explaining the direction semantics (y-axis movement), the nuance of duration (drag vs. fling), and a concrete example mapping parameters to use cases. It does not merely repeat the schema definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('swipe') and resource action ('between two points'), and immediately clarifies its purpose with 'Used for scrolling, dismissing, and drag gestures.' It also distinguishes from the sibling `android_tap` explicitly, saying 'Don't use when: a single tap is enough (use android_tap).'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance with concrete examples: 'Use when: scrolling a list down -> x1=540, y1=1600, x2=540, y2=600' and 'Use when: dragging an item -> duration_ms=1000'. Also states a clear exclusion: 'Don't use when: a single tap is enough (use android_tap).'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_tapTap the screenA

Tap at a screen coordinate.

Get coordinates from android_dump_ui, which returns a ready-to-use centre point for every element. Coordinates are in device pixels and depend on the current rotation, so re-read the UI after rotating.

Args:

  • x (number): horizontal position in pixels

  • y (number): vertical position in pixels

  • serial (string, optional): target device

  • long_press (boolean): hold instead of tapping (default: false)

  • duration_ms (number): hold duration when long_press is set (default: 600)

Returns: { "tapped": [number, number], "longPress": boolean, "serial": string }

Examples:

  • Use when: android_dump_ui reported a button at (540, 1683) -> x=540, y=1683

  • Use when: opening a context menu -> long_press=true

  • Don't use when: you do not know where the element is (call android_dump_ui first)

Error Handling:

  • Coordinates outside the screen are silently ignored by Android; verify with android_dump_ui afterwards

ParametersJSON Schema
NameRequiredDescriptionDefault
xYesHorizontal pixel coordinate.
yYesVertical pixel coordinate.
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
long_pressNoHold instead of a quick tap.
duration_msNoHold duration for a long press.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations state readOnlyHint=false, destructiveHint=false, openWorldHint=true, and idempotentHint=false, but the description adds critical behavioral details: 'Coordinates outside the screen are silently ignored by Android' and 'verify with android_dump_ui afterwards.' It also explains the effect of long_press and duration. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for Args, Returns, Examples, and Error Handling. It is concise and each section earns its place, though the Args section partially repeats schema information. Overall, it's efficient and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 5 parameters and no output schema, the description fully covers return format, usage examples, prerequisite steps (android_dump_ui), and error handling. It leaves no significant gaps for an agent to successfully invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters, so baseline is 3, but the description adds valuable meaning beyond the schema: coordinates are in 'device pixels' and 'depend on the current rotation,' and android_dump_ui returns 'ready-to-use centre point' for elements. This helps the agent choose correct coordinate values, going slightly beyond the schema's basic descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with 'Tap at a screen coordinate,' using a specific verb and resource that clearly defines the action. It distinguishes itself from sibling tools like android_swipe (swipe) and android_dump_ui (reading UI) by focusing on the tap action and coordinate input.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: 'Get coordinates from android_dump_ui' and examples like 'Use when: opening a context menu -> long_press=true' and 'Don't use when: you do not know where the element is.' It also warns about re-reading UI after rotation, offering clear context and exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_testRun a project's testsA

Run a Gradle project's tests and report which ones failed.

This is the verification half of the loop: after changing code, prove the change works rather than assuming it. Failure output is condensed the same way android_build condenses it — you get the failing test names, not the whole Gradle log.

Two kinds of test:

  • 'unit' runs testDebugUnitTest on the JVM. Fast, no device needed.

  • 'instrumented' runs connectedDebugAndroidTest on a connected device or emulator. Slower, and requires a device.

Args:

  • project_path (string): absolute path to the Gradle root (contains gradlew)

  • module (string): module whose tests to run (default: 'app')

  • kind ('unit' | 'instrumented'): which test task to run (default: 'unit')

  • tests (string, optional): Gradle --tests filter, e.g. "com.example.MyTest" or ".LoginTest."

  • timeout_ms (number): timeout (default: 900000)

  • force (boolean): skip the JDK/Gradle compatibility pre-check (default: false)

  • response_format ('markdown' | 'json')

Returns: { "success": boolean, "task": string, // e.g. ":app:testDebugUnitTest" "durationMs": number, "failures": string[], // failing test names, when parseable "output": string, // condensed failure summary, or the tail on success "hint": string // present when the failure is a known one }

Examples:

  • Use when: you changed logic and want to know it still passes -> kind="unit"

  • Use when: narrowing to one failing test -> tests="com.example.CalcTest"

  • Use when: the behaviour only shows on a device -> kind="instrumented"

  • Don't use when: you only need the app compiled (use android_build)

Error Handling:

  • "instrumented" with no device connected fails at the device check, before Gradle starts

  • A project with no test sources reports success with an up-to-date task rather than a failure

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNo'unit' runs on the JVM; 'instrumented' runs on a connected device.unit
forceNoSkip the JDK/Gradle compatibility pre-check.
testsNoGradle --tests filter, e.g. 'com.example.MyTest' or '*.LoginTest.*'.
moduleNoGradle module that produces the APK. Almost always 'app'.app
timeout_msNoTimeout in milliseconds.
project_pathYesAbsolute path to the Gradle project root — the directory containing gradlew and settings.gradle.
response_formatNoOutput format: 'markdown' for human-readable, 'json' for machine-readable.markdown

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond annotations by disclosing output condensing, device requirements for instrumented tests, behavior when no test sources exist (success with up-to-date task), and the JDK/Gradle pre-check. All of these are non-obvious behaviors not captured in the annotations or schema. No contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-organized: a purpose sentence, verification role, test kind explanation, Args list, Return type, usage examples, and error handling. Every section earns its place given the tool's complexity and 7 parameters. No filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite lacking an output schema, the description provides a full return structure JSON, covers error cases, explains the two test kinds, and mentions the pre-check. This is complete for the tool's complexity. The agent can act with confidence.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already covers 100% of parameters with descriptions, so the baseline is 3. The description adds value by restating parameters in a compact Args list with additional context: examples for the tests filter, the meaning of project_path (contains gradlew), and the default module 'app'. This clarifies semantics beyond the schema, earning a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource: 'Run a Gradle project's tests and report which ones failed.' It clearly distinguishes itself from siblings by explicitly naming android_build as the alternative for compilation-only needs. The scope is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Examples' section provides explicit 'Use when' conditions for both unit and instrumented tests, as well as a 'Don't use when' that names android_build. This gives the agent clear decision rules for tool selection, going well beyond generic hints.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

android_uninstallUninstall an appA
DestructiveIdempotent

Remove an app from the device. This deletes the app's data and cannot be undone.

Args:

  • package_name (string, optional): application id to remove

  • project_path (string, optional): Gradle root; the package is resolved from it when package_name is omitted

  • module (string): module to read the package from (default: 'app')

  • serial (string, optional): target device

  • keep_data (boolean): keep app data and cache directories (adb uninstall -k) (default: false)

Returns: { "uninstalled": boolean, "packageName": string, "serial": string }

Examples:

  • Use when: an install fails with INSTALL_FAILED_UPDATE_INCOMPATIBLE and the old copy must go

  • Use when: testing a first-run experience from a clean state

  • Don't use when: you only want to clear state; force-stopping or clearing data is less destructive

Error Handling:

  • Reports when the package was not installed to begin with

ParametersJSON Schema
NameRequiredDescriptionDefault
moduleNoGradle module that produces the APK. Almost always 'app'.app
serialNoDevice serial from android_list_devices. Optional when exactly one device is connected; required when several are.
keep_dataNoRetain the app's data and cache directories.
package_nameNoApplication id to uninstall.
project_pathNoGradle root to resolve the package from.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already indicate destructiveHint=true and idempotentHint=true, but the description adds critical context: 'deletes the app's data and cannot be undone', the effect of keep_data ('adb uninstall -k'), and error behavior ('Reports when the package was not installed to begin with'). No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Structured with clear sections (Description, Args, Returns, Examples, Error Handling). Front-loaded with the core purpose and destructive warning. Every sentence contributes useful information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, no output schema), the description covers the return format, example use cases, error handling, and parameter resolution logic. It is self-contained and fully prepares the agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

While schema coverage is 100%, the description adds relational semantics: 'project_path... package is resolved from it when package_name is omitted' and clarifies keep_data as 'keep app data and cache directories (adb uninstall -k)'. This goes beyond the schema's per-field definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Remove an app from the device', which is a specific verb+resource statement. It further clarifies destructive consequences and distinguishes from sibling tools like android_clear_data by explicitly stating when uninstall is appropriate (e.g., INSTALL_FAILED_UPDATE_INCOMPATIBLE) versus when a less destructive alternative should be used.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit use cases: 'Use when: an install fails with INSTALL_FAILED_UPDATE_INCOMPATIBLE...' and 'Use when: testing a first-run experience'. It also gives a clear exclusion: 'Don't use when: you only want to clear state; force-stopping or clearing data is less destructive', naming the alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 19 tool updatesv0.1.0
    • First observedandroid_build
    • First observedandroid_clear_data
    • First observedandroid_connect_wifi
    • First observedandroid_doctor
    • First observedandroid_dump_ui
    • First observedandroid_input_text
    • First observedandroid_install
    • First observedandroid_key_event
    • First observedandroid_launch
    • First observedandroid_list_devices
    • First observedandroid_logcat
    • First observedandroid_pitfalls
    • First observedandroid_screenshot
    • First observedandroid_set_rotation
    • First observedandroid_shell
    • First observedandroid_swipe
    • First observedandroid_tap
    • First observedandroid_test
    • First observedandroid_uninstall

TDQS

A4.5/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: device enumeration, Wi-Fi connection, build, test, app lifecycle (install/launch/clear/uninstall), UI interaction (screenshot/dump/tap/swipe/input/key/rotation), and diagnostics (logcat/shell/doctor). Even overlapping actions like android_build with install=true are explicitly separated from android_install and android_launch, so an agent can reliably pick the right tool.

Naming Consistency3/5

All tools share the 'android_' prefix and snake_case, but the second part mixes styles: some are verb_noun (list_devices, clear_data, set_rotation), some are single verbs (build, test, install, tap), and some are nouns (pitfalls, logcat, shell, doctor). This is readable and predictable in terms of prefix, but the verb/noun pattern is not consistent across the set.

Tool Count4/5

With 19 tools, the count is slightly above the ideal 3–15 range, but each tool covers a distinct aspect of Android development (device management, build/test, app lifecycle, UI automation, diagnostics). The number feels appropriate for the broad scope, and none are redundant, so it earns a slightly-over-but-reasonable rating.

Completeness5/5

The tool surface covers the full lifecycle: build, test, install, launch, uninstall, clear data; UI interaction (tap, swipe, input, key events, rotation, screenshot, UI dump); device discovery and Wi-Fi connection; logcat with crash analysis; arbitrary shell access; and a toolchain doctor. There are no obvious dead ends, and the shell tool acts as an escape hatch for anything not explicitly covered.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    A comprehensive MCP server that enables AI agents to interact with Android devices through Android Debug Bridge (ADB), offering 198 tools for device control, app management, diagnostics, and more.
    100
    75
    15
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    A comprehensive MCP server for Android Debug Bridge, enabling AI agents to control Android devices through structured tools like launching apps, UI automation, file operations, and log capture.
    1
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jjs03111/android-build-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server