This server defines 22 tools with explicit input schemas and descriptions visible in src/index.ts. However, quality is inconsistent and below production baseline. Naming is generally good (action verbs like 'android_screenshot', 'android_touch'), but descriptions are often too terse (many under 80 chars, well below the 194-char baseline). Parameters lack depth, most have minimal descriptions that don't explain constraints, valid ranges, or why an agent should choose one tool over another. No output schemas are documented, making it unclear what fields the LLM should expect after a tool call. Error handling is absent from the tool definitions, no guidance on recovery, retryable vs fatal errors, or what to do when deviceSerial is invalid. The most critical issue: android_execute_command (DESTRUCTIVE risk) has no safety mechanism, no dry-run option, and minimal documentation about its dangers. This violates the confirmation-request pattern. Overall, the server demonstrates basic competence with schema structure but lacks the depth, safety guards, and LLM-friendly documentation of production-grade tools.
android_execute_command lacks safety mechanisms for destructive operations. No dry-run, confirmation step, or actionable error guidance. Violates confirmation-request pattern. An agent could run 'rm -rf /' without safeguards.
No output schemas documented for any tool. LLMs cannot infer what fields a tool returns, forcing them to guess at response structure. This breaks tool chaining, if android_list_packages returns an array of objects, what are the field names? Missing fields in responses prevent downstream tool calls.
Tool descriptions are uniformly terse (55-70 chars on average). Baseline is 194 chars. Descriptions lack context for WHEN to use a tool, dependencies, or side effects. Example: 'Perform a swipe gesture between two coordinates' tells the LLM WHAT but not WHY or when to choose swipe vs touch. Descriptions should explain 'Call this when you need to scroll content on a scrollable element; not suitable for button presses.'
Recommendations
Add documented output schemas for all tools. For android_screenshot, document: 'Returns {"success": boolean, "imagePath": string (if outputPath provided), "imageBase64": string (if no outputPath), "timestamp": ISO8601 string}'. For android_list_packages, document: 'Returns {"packages": [{"name": string, "version": string}], "total": number, "deviceSerial": string}'. This enables downstream tool chaining and LLM reasoning.
Expand tool descriptions to 100-200 chars explaining WHAT, WHEN, and SIDE EFFECTS. Example: 'android_swipe: Perform a swipe gesture to scroll content. Use when the target element is a scrollable list or view. Not suitable for single button presses, use android_touch instead. Returns success status and coordinates swiped.'
Add 'constraints' and 'examples' fields to parameter descriptions. For duration/distance parameters: 'duration (milliseconds): Valid range 0 - 5000. Default 100. Too short may not register; too long risks timeout.' Include real examples, not just placeholders.
Implement a confirmation step for android_execute_command. Modify the tool to accept a dry_run boolean parameter (default true). When dry_run=true, return the command that WOULD be executed without running it. Update description: 'Execute shell commands on the Android device. DESTRUCTIVE: This tool can delete files, factory reset, or damage the device. Always pass dry_run=true first to preview the command, then set dry_run=false to execute. No confirmation prompt, the agent is responsible for safety.'
Parameter descriptions are sparse and lack format/constraint guidance. Example: 'duration' in android_touch says 'Touch duration in milliseconds (default: 100)' but doesn't specify valid range (is 0 valid? 100000?). LLMs cannot validate input without explicit constraints. The rubric baseline is 72 chars per param description; these average ~40.
deviceSerial parameter is optional on all tools but its behavior when omitted is undefined. Does it default to the first connected device? Will it fail if multiple devices are connected? This ambiguity forces LLMs to guess or call a discovery tool. Should document: 'If omitted, targets the first connected device. If multiple devices are attached, you MUST specify deviceSerial or this will fail.'
No error handling guidance in tool definitions. What happens if resourceId is not found in android_uiautomator_click? Does it timeout? Return an error? If so, what is the error message and how should the LLM recover? Missing error schemas force agents into blind retry loops. Should document: 'Returns error 'Element not found' if resourceId does not match any UI element, verify the resourceId is correct or call android_uiautomator_dump to see available elements.'
android_stop_scrcpy_stream and android_get_latest_frame have empty input schemas (no properties listed). While technically valid JSON Schema, this signals incomplete definitions. Should these accept deviceSerial for multi-device scenarios? Currently undocumented.
android_uiautomator_find allows searching by EITHER resourceId OR text, but the schema doesn't enforce mutual exclusivity or require at least one. An LLM could call it with neither and get undefined behavior. Schema should clarify: 'At least one of resourceId or text is required; if both are provided, both conditions must match.'
Scrcpy-related tools (android_start_scrcpy_stream, android_stop_scrcpy_stream, android_get_latest_frame, android_capture_frame_scrcpy) lack documentation on stateful behavior. Does starting a stream create a persistent connection? Does stopping it close it? Can you call get_latest_frame without starting a stream first? Tool ordering and state dependencies are completely undocumented.
No security or permission documentation. android_execute_command allows arbitrary shell commands, what does 'arbitrary' mean? Are there filters, allowlists, or blocklists? No documentation of what an agent can or cannot do. Agents need to know: 'This tool can execute any shell command with ADB privileges. Destructive commands like rm, format, or system shutdown are not filtered. Use with extreme caution.'
android_execute_command
Document state machine for scrcpy tools. Add to android_start_scrcpy_stream: 'Starts a persistent stream. Call this FIRST before get_latest_frame or capture_frame_scrcpy. Only one stream can be active at a time, call stop_scrcpy_stream to close the previous one before starting a new one.' Add to android_stop_scrcpy_stream: 'Closes the active scrcpy stream. Safe to call even if no stream is running (returns success with message "No active stream").'
Add error recovery guidance. For android_uiautomator_click, document: 'On failure, error will be "Element with resourceId '{resourceId}' not found". If this occurs, call android_uiautomator_dump to view the current UI hierarchy and find the correct resourceId. Common issues: app state changed, element became invisible, or resourceId typo.'
Clarify deviceSerial behavior in a shared parameter description, then reference it in every tool: 'deviceSerial (optional): Target a specific Android device by serial number. If omitted and only one device is connected, it will be used automatically. If multiple devices are connected and deviceSerial is omitted, the operation will FAIL. Call android_list_devices (if available) or use adb devices to find serial numbers.'
Document mutual exclusivity and constraints for android_uiautomator_find. Update schema to mark at least one of resourceId/text as required (via oneOf or minProperties validation). Update description: 'Find UI elements by resourceId and/or text. At least one parameter is required. If both are provided, only elements matching BOTH criteria are returned. Returns a list of matching elements with their bounds and properties.'
Add security warnings to tool descriptions where applicable. For android_execute_command: 'CRITICAL SECURITY WARNING: This tool executes arbitrary shell commands with device privileges. There are NO built-in filters or allowlists. Commands like "rm -rf /", "fastboot erase all", or "pm uninstall android" can permanently damage the device. Always validate command safety before execution. Recommended: use specific, high-level tools (android_launch_app, android_screenshot) instead of raw shell commands.'
Document which tools have write/destructive side effects in their descriptions (the risk field exists but should be mirrored in prose). For all WRITE tools: add a sentence: 'This operation modifies device state and cannot be undone. Verify your parameters before calling.' For DESTRUCTIVE tools: 'WARNING: This operation is irreversible. Test in a development environment first.'
Add batch variants or multi-operation tools where agents would call the same tool repeatedly. For example, introduce android_click_multiple_elements(resourceIds: [string]) to click multiple elements in sequence, reducing round-trips and improving efficiency.
Validate all enum-like parameters. android_uiautomator_scroll_in_element documents direction as enum with ['up', 'down', 'left', 'right'] in the schema, good. Apply the same pattern to keyCode in android_send_key_event: define a constrained enum of valid Android key codes rather than a free-form string.