Metadata-Version: 2.4
Name: android-uiautomator2-mcp
Version: 0.1.0
Summary: Agent-friendly Android automation CLI and MCP server built on UIAutomator2
Author: Android MCP contributors
License-Expression: MIT
Requires-Python: <3.15,>=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: adbutils<3,>=2.12
Requires-Dist: mcp<3,>=2.0
Requires-Dist: pillow<13,>=12.3
Requires-Dist: pydantic<3,>=2.13
Requires-Dist: uiautomator2<4,>=3.7
Provides-Extra: dev
Requires-Dist: pytest<10,>=9.1; extra == "dev"
Requires-Dist: pytest-asyncio<2,>=1.4; extra == "dev"
Requires-Dist: ruff<0.17,>=0.16; extra == "dev"
Dynamic: license-file

# Android UIAutomator2 MCP

一个面向 Agent、脚本和未来测试编排器的 Android 自动化工具。项目以 UIAutomator2 和 ADB 为设备后端，同时提供独立 JSON CLI 与本地 stdio MCP；两者共享相同的核心服务、数据模型、安全策略和错误码。

## 架构

```text
Agent / Codex --------> MCP adapter ----+
                                         +--> OperationDispatcher --> AndroidService --> UIAutomator2 / ADB
脚本 / 用例编排器 ----> JSON CLI -------+
```

- `AndroidService` 是协议无关的 Python API，负责设备选择、串行化、重试、安全检查和具体操作。
- 同一进程使用线程锁，多个 CLI/MCP 进程通过 artifacts 下的按设备文件锁串行访问 UIAutomator。
- `OperationDispatcher` 提供统一操作目录、Pydantic 校验和 JSON Schema，供 CLI、MCP 以及未来用例编排器复用。
- `android-cli` 接受 JSON 参数并输出稳定 JSON/退出码，不依赖 MCP 客户端。
- `android-mcp` 是薄适配层，只处理 stdio、异步线程调度、MCP annotations 和图片内容。

## 环境要求

- Python 3.11-3.14
- Android Platform Tools，`adb` 可从 `PATH` 找到或通过环境变量指定
- 已启用 USB 调试或无线调试的 Android 设备

Windows PowerShell 安装：

```powershell
python -m venv .venv
.venv\Scripts\python -m pip install -e ".[dev]"
adb devices -l
.venv\Scripts\python -m uiautomator2 init
```

若当前 Python 发行版创建的虚拟环境不带 pip，可从外层 Python 安装：

```powershell
python -m pip --python .venv install -e ".[dev]"
```

`requirements.lock` 是本项目在 Python 3.14/Windows 上的完整验证锁。跨平台发布应以 `pyproject.toml` 的版本范围解析依赖。

## 独立 CLI

CLI 形式为 `android-cli <operation> --json '<JSON object>'`。未提供参数时使用空对象；也可通过 `--json-file <path>` 或 `--json-file -` 从标准输入读取。
以下示例假定已执行 `.venv\Scripts\Activate.ps1`；未激活时使用 `.venv\Scripts\android-cli.exe`。

```powershell
android-cli list_devices --pretty
android-cli get_device_info --json '{"serial":"EYEE4LDM79GMTKJ7"}' --pretty
android-cli wake_and_unlock --pretty
android-cli inspect_screen --json '{"max_nodes":100}'
android-cli click_element --json '{"selector":{"text":"Settings"}}' --pretty
android-cli tap --json-file .\tap.json
android-cli describe --describe-operation wait_for_element --pretty
```

成功输出到 stdout：

```json
{"ok":true,"operation":"tap","data":{"serial":"SERIAL","x":500,"y":800}}
```

失败输出到 stderr，不包含 Python 堆栈：

```json
{"ok":false,"error":{"code":"NO_DEVICE","message":"No ready Android device is connected","operation":"tap","retryable":true}}
```

稳定退出码：`0` 成功、`2` 参数错误、`3` 设备不可用、`4` 超时、`5` 权限/安全策略拒绝、`6` 执行失败。截图在 CLI JSON 中表示为带 `mime_type` 和 `encoding=base64` 的对象。

## MCP 接入

安装后直接启动本地 stdio 服务：

```powershell
android-mcp
```

Codex CLI 配置示例：

```powershell
codex mcp add android --env ANDROID_MCP_ADB_PATH="D:\Android\Sdk\platform-tools\adb.exe" -- "D:\path\to\auto-debug-mcp\.venv\Scripts\android-mcp.exe"
codex mcp list
```

也可以在可信项目的 `.codex/config.toml` 中配置：

```toml
[mcp_servers.android]
command = 'D:\path\to\auto-debug-mcp\.venv\Scripts\android-mcp.exe'
cwd = 'D:\path\to\auto-debug-mcp'
startup_timeout_sec = 30
tool_timeout_sec = 120
default_tools_approval_mode = "writes"

[mcp_servers.android.env]
ANDROID_MCP_ADB_PATH = 'D:\Android\Sdk\platform-tools\adb.exe'
```

Codex 配置语法参考 [OpenAI 官方 MCP 文档](https://developers.openai.com/codex/mcp/)。其他 MCP 客户端使用相同的 stdio command/env 配置。

## 工具能力

- 设备：`list_devices`、`get_device_info`、`get_current_app`、`wake_device`、`wake_and_unlock`
- 观察：`inspect_screen`、`get_ui_hierarchy`、`take_screenshot`
- 交互：`tap`、`click_element`、`long_press`、`input_text`、`swipe`、`drag`、`scroll`、`press_key`、`set_orientation`
- 同步：`wait_for_element`、`wait_for_app`
- 应用：`list_packages`、`get_app_info`、`launch_app`、`stop_app`、`open_deep_link`、`get_logcat`
- 文件：`pull_file`
- 默认关闭：`install_apk`、`uninstall_app`、`clear_app_data`、`push_file`、`run_shell`

`inspect_screen` 返回当前应用和精简 UI 节点，仅保留有文字、有内容描述或可交互的节点；保留节点有资源 ID 时会输出 `resource_id`。该工具不截图，需要图像时单独调用 `take_screenshot`。节点坐标使用 `[left, top, right, bottom]`，与设备原生屏幕坐标一致。为减少高频调用的返回长度，`clickable`、`checked`、`selected`、`focusable`、`scrollable` 仅在值为 `true` 时输出，`enabled` 仅在值为 `false` 时输出；与 `current_app.package` 相同的节点省略 `package_name`，跨应用节点仍会输出包名。

`wake_and_unlock` 在同一次设备调用内点亮屏幕并向上滑动，只用于无 PIN、图案或密码的滑动锁屏。设备已经亮屏且不在系统锁屏界面时不会滑动，避免误滚动当前应用；该工具不会输入凭据或绕过 Android 安全策略。

选择器字段支持 `text`、`text_contains`、`text_regex`、`resource_id`、`resource_id_regex`、`class_name`、`description`、`description_contains`、`description_regex`、`package_name`、`clickable`、`enabled`、`checked`、`selected`、`instance`。多个字段按 AND 匹配，至少需要一个字段。

`input_text` 传入空字符串可清空指定元素或当前焦点元素；`clear=true` 用于在输入非空文本前先清空当前内容。

## 配置

| 环境变量 | 默认值 | 作用 |
| --- | --- | --- |
| `ANDROID_MCP_ADB_PATH` | `adb` | ADB 可执行文件 |
| `ANDROID_MCP_DEFAULT_SERIAL` | 空 | 默认设备 serial |
| `ANDROID_MCP_ARTIFACTS_DIR` | `./artifacts` | 截图和 pull 文件目录 |
| `ANDROID_MCP_ALLOWED_HOST_ROOTS` | 当前目录和 artifacts | install/push 可读取的根目录，用系统路径分隔符分隔 |
| `ANDROID_MCP_TIMEOUT_SECONDS` | `15` | 默认操作和等待超时 |
| `ANDROID_MCP_LOGCAT_MAX_LINES` | `2000` | 服务端日志行数硬上限 |
| `ANDROID_MCP_MAX_PULL_BYTES` | `52428800` | 单次 pull 最大字节数 |
| `ANDROID_MCP_ENABLE_DANGEROUS` | `false` | 启用高影响结构化工具 |
| `ANDROID_MCP_SHELL_ALLOWLIST` | 空 | 允许的 shell 命令前缀，`;` 分隔 |

危险配置示例：

```powershell
$env:ANDROID_MCP_ENABLE_DANGEROUS = "true"
$env:ANDROID_MCP_SHELL_ALLOWLIST = "getprop;dumpsys activity;pm list packages"
android-mcp
```

`run_shell` 只接受 argv 数组，并拒绝管道、重定向、命令连接符、引号和命令替换。即使已启用危险操作，命令仍必须匹配允许前缀。install/push 会解析真实路径并拒绝允许根目录之外的文件。

## 开发与验证

```powershell
.venv\Scripts\ruff check src tests
.venv\Scripts\pytest -q
$env:ANDROID_MCP_TEST_SERIAL = "your-device-serial"
.venv\Scripts\pytest tests\test_device_integration.py -q
android-cli list_devices --pretty
android-cli take_screenshot --json '{"save":true}' --pretty
```

只读真机诊断：

```powershell
adb devices -l
.venv\Scripts\python -m uiautomator2 doctor
android-cli inspect_screen --json '{"max_nodes":50}'
android-cli get_logcat --json '{"max_lines":50,"level":"W"}'
```

常见问题：

- `ADB_NOT_FOUND`：设置 `ANDROID_MCP_ADB_PATH` 为 platform-tools 中的完整路径。
- `DEVICE_AMBIGUOUS`：在参数中传 `serial`，或设置 `ANDROID_MCP_DEFAULT_SERIAL`。
- `DEVICE_NOT_READY`：检查设备授权弹窗以及 `adb devices -l` 中的状态。
- `UIAUTOMATOR_CONNECT_FAILED`：执行 `python -m uiautomator2 doctor`，必要时重新执行 `python -m uiautomator2 init`。
- MCP 启动超时：使用虚拟环境内 `android-mcp` 的绝对路径，并将 `startup_timeout_sec` 调高到 30。

## 安全边界

本项目不会绕过锁屏密码、Android 授权弹窗或系统安全策略。`pull_file` 只能写入 artifacts 目录且受大小限制；高影响工具默认关闭。Agent 仍可能通过普通 UI 操作触发应用内副作用，接入端应使用 MCP tool approval 策略控制写操作。
