Multi-platform mobile automation via MCP - Control Android devices through AI agents
Project description
phone_pilot - Mobile Automation via MCP
通过 MCP (Model Context Protocol) 让 AI Agent 控制 Android 手机。支持 Cursor、Claude Desktop 等 MCP 客户端。
一行安装
# 从 PyPI 安装(推荐)
pip install phone-pilot
# 直接运行 MCP 服务器(无需安装,需要 uv)
uvx phone-pilot-mcp
安装选项
# 核心安装(仅 Android 支持)
pip install phone-pilot
# 含 HarmonyOS 支持
pip install "phone-pilot[harmony]"
# 含语言检测与翻译
pip install "phone-pilot[vision]"
# 全部安装
pip install "phone-pilot[all]"
# 开发模式(本地源码安装)
pip install -e .
架构概述
phone_pilot/
├── core/ # 核心协调层
│ ├── protocols.py # Driver 接口定义
│ ├── skills.py # 统一技能 API
│ ├── storage.py # 存储路径管理(.recordings/)
│ ├── run_store.py # RunSession 运行记录管理
│ ├── resource.py # @res: 资源缓存管理
│ ├── verify.py # 验证引擎(多维度断言 + 证据收集)
│ ├── checkpoint.py # 屏幕状态检查点(保存/对比)
│ └── ui/
│ ├── chain.py # UIChain 流式 API
│ ├── graph.py # UIGraph DAG 拓扑引擎
│ └── element.py # UIElement 数据模型
├── extensions/ # 平台无关的扩展
│ ├── vision/ # 图像处理(模板匹配)
│ ├── ocr/ # 文字识别(Tesseract)
│ ├── lang/ # 语言检测与翻译(可选)
│ ├── diff/ # 截图对比
│ └── llm/ # LLM 全局页面分析(自愈兜底,可选)
├── android/ # Android 平台实现(ADB + UIAutomator)
├── harmony/ # HarmonyOS 平台实现(hmdriver2 + HDC,功能暂不完善,待开发)
├── ios/ # iOS 平台(计划中)
├── memory_analyze/ # 内存分析(meminfo / hprof / Activity 泄漏检测)
├── mcp/ # MCP Server(phone_* 统一工具)
├── script_api/ # Python 脚本编写唯一入口(模块包)
└── FEATURE_MATRIX.md # 三平台功能对照表
快速开始
MCP 服务器启动
# 启动 MCP 服务器(stdio 传输)
phone-pilot-mcp
# 命令行调用工具
phone-pilot-call --list-tools
phone-pilot-call phone_list_devices
phone-pilot-call phone_screenshot --args '{"device_serial":"<serial>"}'
MCP 工具一览
工具使用 phone_* 前缀,支持多平台:
# ⭐ 推荐首选:一次获取完整页面状态(LLM 最优)
phone_get_page_state(device_serial)
# → 返回: Activity、元素列表(带编号)、可滚动区域、全部文本
# ⭐ 含元素标注的截图(编号+边框叠加在截图上,LLM 看图更准确)
phone_get_page_state(device_serial, annotate_elements=True)
# → 额外返回 screenshot_annotated_base64
# 通过元素编号直接点击(配合 phone_get_page_state 使用)
phone_tap_element(index=3)
# → 自动定位元素 #3 的中心坐标并点击
# 基础操作
phone_tap(device_serial, x, y)
phone_swipe(device_serial, x1, y1, x2, y2)
phone_screenshot(device_serial)
# UI 查找
phone_find_element(device_serial, text_contains="设置")
# 图像/OCR
phone_find_image(device_serial, template_path="@res:icon_coin")
phone_ocr_find(device_serial, query="登录", lang="chi_sim")
# 应用管理
phone_launch_app(device_serial, package="com.example.app")
phone_force_stop(device_serial, package="com.example.app")
# 验证管道
phone_run_script(path="workflow/navigate.py")
phone_verify(device_serial, assertions='[...]')
phone_checkpoint_save(device_serial, name="before")
phone_checkpoint_diff(device_serial, name="before")
# 导航与设备控制
phone_go_home(device_serial)
phone_go_back(device_serial)
phone_unlock(device_serial, pin="1234")
phone_clear_background(device_serial)
phone_clear_data(device_serial, package="com.example.app")
phone_open_deeplink(device_serial, uri="myapp://page/detail")
# 录屏与日志
phone_start_recording(device_serial, name="test")
phone_stop_recording(device_serial) # 自动拉取到本地
phone_start_logcat(device_serial, tags="MyTag", level="D")
phone_stop_logcat(device_serial)
phone_search_logcat(device_serial, pattern="Error", regex=True)
# 智能查找与等待
phone_scroll_to_find(device_serial, text="目标文本", direction="up_down")
phone_wait_for_element(device_serial, text="加载完成", timeout_s=15)
phone_dismiss_popup(device_serial)
phone_smart_find(device_serial, text="目标", use_ocr=True)
# 应用管理(扩展)
phone_install_app(device_serial, apk_path="/path/to/app.apk")
phone_uninstall_app(device_serial, package="com.example.app")
phone_launch_from_home(device_serial, query="微信")
# 内存分析
phone_memory_snapshot(device_serial, package="com.example.app")
phone_memory_check_leak(device_serial, package="com.example.app")
# 文件操作
phone_pull_file(device_serial, remote_path="/sdcard/log.txt")
phone_push_file(device_serial, local_path="test.txt", remote_path="/sdcard/test.txt")
# 高级功能
phone_read_clipboard(device_serial)
phone_get_notifications(device_serial)
phone_toggle_wifi(device_serial, enabled=False)
phone_execute_shell(device_serial, command="dumpsys battery")
phone_get_device_info(device_serial)
phone_get_page_state 是 LLM 交互的核心工具:一次调用获取当前页面的 Activity、所有可交互元素(带编号和坐标)、可滚动区域和全部文本。设置 annotate_elements=True 会在截图上叠加元素编号和边框标注,LLM 看图后可直接用 phone_tap_element(index=3) 点击目标元素,无需多次往返查询。
Python 脚本方案(script_api)
面向非程序员的简洁 API,通过 script_api.py 编写自动化脚本:
from phone_pilot.script_api import (
ScriptContext, find_text, find_image, scroll_to_find,
screenshot, retry, run_script, chain,
)
ctx = ScriptContext(
device_serial="your_device",
auto_screenshot=True,
auto_dump_hprof=False, # 脚本成功结束后自动 dump 内存快照
popup_guard=True, # 启用弹窗自动检测与关闭(默认开启)
llm_healing=False, # 启用 LLM 全局分析兜底(需 OPENAI_API_KEY)
max_heal_attempts=3, # 单步最大自愈尝试次数
)
def main() -> int:
# 清理后台并启动应用
chain(ctx).clear_background().restart_app_pkg("com.example").wait(5).done()
# 查找并点击文本
find_text(ctx, "任务中心").tap(wait=3)
# 滚动查找(支持双向搜索)
elem = scroll_to_find(ctx, "目标文本", direction="up_down", max_count=5)
elem.tap(wait=2)
# 日志监控
ctx.start_logcat("verify", tag="MyTag", level="D")
# ... 执行操作 ...
ctx.stop_logcat("verify")
# 录屏
ctx.start_record("demo")
# ... 执行操作 ...
ctx.stop_record()
# 手动截图
screenshot(ctx, "final_state")
return 0
if __name__ == "__main__":
run_script(main, ctx=ctx)
存储结构
所有运行时产物统一存储在 .recordings/ 目录下(通过 .gitignore 排除):
.recordings/
├── cache/ # 图片缓存、SQLite DB
├── devices/ # 设备信息
├── hprof/ # 非脚本环境的 hprof dump
├── verify/ # 验证报告
└── runs/ # RunSession 脚本运行产物
└── {script}_{git}_{ts}/
├── script.py # 脚本副本
├── git_info.json # Git 信息(commit, branch, dirty)
├── git_diff.patch # 未提交变更
├── console.log # 完整控制台日志
├── steps.json # 所有步骤结果汇总
├── run_meta.json # 运行元信息
├── report.html # HTML 可视化报告(自动生成)
├── screenshots/ # 步骤截图 + 手动截图
├── recordings/ # 录屏文件
├── logcat/ # Logcat 日志文件
├── meminfo/ # 内存快照与泄漏分析
└── healing_events.json # 自愈事件记录
HarmonyOS 支持
需要额外安装:pip install phone-pilot[harmony]
通过 hmdriver2 库实现完整 UI 自动化:
- 输入操作:tap/swipe/long_press/double_click/input_text/keyevent
- 屏幕操作:screenshot、get_screen_size、screenrecord
- UI 树:dump_hierarchy、find_elements
- 应用管理:launch/stop/clear/install/uninstall
- 设备管理:unlock/screen_on/screen_off、device_info
详见 phone_pilot/FEATURE_MATRIX.md 获取完整三平台功能对照。
错误自愈机制
脚本执行过程中遇到元素查找失败等错误时,自动尝试修复:
- 经验库查询 — 查找之前同一页面同一操作的成功纠正记录,零成本复用
- PopupGuard 弹窗检测 — Window 层级 + UI 树结构 + 文本规则三层检测,自动关闭弹窗
- LLM 全局分析(可选) — 截图 + UI 树 + 错误上下文综合诊断,给出修复建议
# 启用自愈(默认 popup_guard=True)
ctx = ScriptContext(
popup_guard=True, # 弹窗自动检测(默认开启)
llm_healing=True, # LLM 兜底分析(需 OPENAI_API_KEY)
max_heal_attempts=3, # 单步最大自愈次数
)
# retry() 也支持自愈
result = retry(lambda: find_text(ctx, "目标"), desc="查找目标", ctx=ctx)
纠正经验按 action + query + app_package + activity 维度存储,跨脚本共享。
LLM 修复成功后自动写入经验库,下次遇到相同问题可直接复用。
在 Cursor / Claude Desktop 中注册 MCP
方式一:uvx(推荐,无需安装)
{
"mcpServers": {
"phone_pilot": {
"command": "uvx",
"args": ["phone-pilot-mcp"]
}
}
}
方式二:pip 安装后直接使用
{
"mcpServers": {
"phone_pilot": {
"command": "phone-pilot-mcp",
"args": []
}
}
}
方式三:开发模式(本地源码)
{
"mcpServers": {
"phone_pilot": {
"command": "uv",
"args": ["run", "--project", "<project_path>", "phone-pilot-mcp"],
"cwd": "<project_path>"
}
}
}
详细配置示例见 cursor_mcp_config.example.json。
资源缓存与 @res 引用
# 添加资源(图片等)
phone-pilot-call phone_res_add --args '{"path":"phone_pilot/resource/icon_Coin.png"}'
# 通过 @res: 引用(在脚本或 MCP 中均可使用)
phone-pilot-call phone_find_image --args '{"device_serial":"<serial>","template_path":"@res:icon_coin"}'
资源缓存存储在 .recordings/cache/pic/ 目录下。
本地 Web Dashboard
提供一个本地网页查看运行记录和 @res 图片资源,支持浏览、删除和生成 HTML 报告。
启动方式
# CLI 命令(推荐,安装后可直接使用)
phone-pilot-web
# 模块运行
python -m phone_pilot.web
# 指定端口
phone-pilot-web --port 9090
# 不自动打开浏览器
phone-pilot-web --no-browser
启动后浏览器自动打开 http://127.0.0.1:8686,即可查看:
- 运行记录 — 列出所有脚本运行历史,显示状态、耗时、设备、Git 信息;可一键生成/查看 HTML 可视化报告
- 图片资源 — 显示所有
@res:缓存的图片,支持复制引用路径、预览缩略图、删除
无额外依赖,仅使用 Python 标准库
http.server+ 项目已有的jinja2。
环境变量
| 变量 | 说明 | 默认值 |
|---|---|---|
PHONE_PILOT_CACHE_DIR |
缓存根目录(设备信息、图片缓存等),设置后使用 <值>/.recordings/ |
项目根目录 |
PHONE_PILOT_RECORDINGS_DIR |
RunSession 运行记录根目录 | <cwd>/.recordings/ |
PHONE_PILOT_LOG_LEVEL |
日志级别 (quiet/normal/verbose) | normal |
PHONE_PILOT_CMD_DELAY_S |
ADB/HDC 命令间延迟秒数 | 0.4 |
PHONE_PILOT_DISABLE_TRANSLATION |
禁用翻译功能 | 未设置 |
OPENAI_API_KEY |
OpenAI API Key(LLM 自愈分析用) | 未设置 |
OPENAI_BASE_URL |
OpenAI 兼容 API 地址 | https://api.openai.com/v1 |
OPENAI_MODEL |
LLM 模型名称 | gpt-4o-mini |
前置条件
- Python >= 3.13
adb已安装且设备已连接授权- HarmonyOS 支持需要
hdc命令行工具
可选依赖
| 依赖 | 用途 | 安装方式 |
|---|---|---|
OpenCV (cv2) |
图像模板匹配 (phone_find_image)、截图对比 (phone_compare_screenshot) |
pip install opencv-python |
| Tesseract + pytesseract | OCR 文字识别 (phone_ocr_find) |
系统安装 tesseract-ocr(macOS: brew install tesseract;Ubuntu: apt install tesseract-ocr),再 pip install pytesseract |
| 中文语言包 | OCR 中文识别 | macOS: brew install tesseract-lang;Ubuntu: apt install tesseract-ocr-chi-sim |
未安装可选依赖时,相关 MCP 工具会返回错误提示而非崩溃。可通过
python scripts/check_verification_env.py检查当前环境。
MCP 工具验证(A 类真机)
执行 A 类验证前会通过 adb 获取当前连接设备 作为 device_serial;需 apk_path、package、资源文件等由 运行前资源清单 提供,执行前会提示确认:
- 资源清单:
docs/verification/verification_resources.json(可配置device_serial、apk_path、package、resource_file、resource_key、push_file/pull_file等) - 环境自检:
python scripts/check_verification_env.py(4/4 通过后再跑验证) - A 类验证:
python scripts/verify_mcp_tools_a.py(交互确认);加--yes跳过确认,--write-checklist写回检查表
示例脚本(script_api,随安装包交付)
- 抖音观看 5 个视频:清空后台 → 打开抖音 → 每 10 秒向上滑动到下一个视频,共 5 个。与
example_script.py一致,使用 phone_pilot.script_api,安装 phone_pilot 后直接运行。python easy_use/douyin_watch_5_videos.py DOUYIN_PACKAGE=com.ss.android.ugc.aweme.lite python easy_use/douyin_watch_5_videos.py
- MCP 前置链路验证(仅用于 agent 通过 MCP 调用确认环境可跑通):
python scripts/douyin_watch_5_videos.py。实际交付给外部项目运行的是上面easy_use/下的脚本。
开发
# 安装开发依赖(含 lint/test)
pip install -e ".[dev]"
# 或完整可选依赖
pip install -e ".[all]"
# 使用 Makefile(推荐)
make lint # ruff check
make test # pytest
make check # lint + test
版本: 0.5.1 许可: MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file phone_pilot-0.5.9.tar.gz.
File metadata
- Download URL: phone_pilot-0.5.9.tar.gz
- Upload date:
- Size: 349.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
969ce0657aa8dcebb75bc4642d7f2860e5f6cf7c258e239968a44436dce1e5f1
|
|
| MD5 |
9beb15bcdbfa1ed8f12ebd2696473615
|
|
| BLAKE2b-256 |
e873a198a0152e1aefd24004fafe320f53327c3a734bcc85d7ecc12d61a3a3c4
|
File details
Details for the file phone_pilot-0.5.9-py3-none-any.whl.
File metadata
- Download URL: phone_pilot-0.5.9-py3-none-any.whl
- Upload date:
- Size: 376.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c78ea70af5455fee03a4b040ce0c84e37a75c4e27af5e8dec6043faef94411ff
|
|
| MD5 |
f0e38406873b1e5d2a98dc3e361a5803
|
|
| BLAKE2b-256 |
55b7508c97fd7a5c020f2c6f7dad7f0d69dc9bc14b7ca6874aa7cd3519a9cc0c
|