给 Cursor / Codex 一双手

用自然语言驱动 Yyds.Auto

不必先写 Python。装上 MCP 和 Skill,直接说「打开设置,看看电池」——模型自己截图、找控件、点按。

最短路径 · 推荐 Cursor
手机装 App → 写入 .cursor/mcp.json → Agent 对话里下中文任务。大约 5 分钟。Codex 同一套 MCP,只是配置写成 toml。
MCP 在对话里截图并点击文字
真实对话:模型调用 take_screenshot,再 tap_text「等待」。这就是 MCP 控设备。
1
手机装 App
打开 Yyds.Auto,引擎亮绿
2
写入 MCP
Cursor:.cursor/mcp.json
3
一句话开工
「打开设置,看看电池」
推荐路径:Cursor + MCP。Skill 可后补,用来管坐标纪律。

三条路径,先选一条

日常对话用 MCP;多台手机 / CI 用 yctl;想把任务丢给手机自己跑,用端侧 Agent。点卡片跳到对应安装步骤。

推荐
MCP 对话
  1. 1
    Cursor / Codex / Claude
    自然语言
  2. 2
    yyds-auto-mcp
    stdio JSON-RPC
  3. 3
    设备引擎
    yyds.py :61140
多设备
Skill + yctl
  1. 1
    Agent 读 SKILL.md
    yyds-device / yyds-auto
  2. 2
    yctl -s 序列号 …
    无 adb forward
  3. 3
    设备引擎
    即时 tcp:61140
手机自己跑
端侧 Agent
  1. 1
    App / 桌面「AI 自动化」
    或 MCP agent_run
  2. 2
    设备上的模型循环
    看屏 → 决策 → 点击
  3. 3
    设备引擎
    本机执行
三条路径最终都打到设备上的 yyds.py :61140,再由 yyds.auto 做触控 / OCR / UI。

环境准备

Yyds.Auto 手机主页,引擎已激活
自动化引擎 / 脚本引擎亮绿,就可以被 MCP 或 yctl 调用。
手机装 App
安装 Yyds.Auto 并打开一次,等引擎亮绿。
电脑能看见设备
USB 打开调试,或 WiFi 同一局域网。adb devices 要有序列号。
MCP 要 Node 18+
后面用 npx 拉起 yyds-auto-mcp。
yctl 放进 PATH
走 Skill 命令行时才需要,编译见下方。
Yyds.Auto App
yyds.keep
守护进程
yyds.auto
:49009
触控 / OCR / UI
yyds.py
:61140
MCP / yctl 入口
MCP 连 61140;yctl 每个请求临时打开同一端口,不需要 adb forward。

安装 MCP

MCP 把设备能力变成工具。服务端是 yyds-auto-mcp, 也可从「软件下载」的 .tgz 离线安装。

npm
npm install -g yyds-auto-mcp
# 或每次临时拉起
npx -y yyds-auto-mcp
Cursor · 写这一份文件
Settings → Tools & MCP,或直接编辑 项目 .cursor/mcp.json / 全局 ~/.cursor/mcp.json(Windows:%USERPROFILE%\.cursor\mcp.json)。 保存后重启,MCP 面板里 yyds-auto 应在线。
.cursor/mcp.json
{
  "mcpServers": {
    "yyds-auto": {
      "command": "npx",
      "args": ["-y", "yyds-auto-mcp"],
      "env": {
        "YYDS_DEVICE_HOST": "127.0.0.1",
        "YYDS_DEVICE_PORT": "61140"
      }
    }
  }
}
Windows / macOS · Cursor
~/.cursor/
mcp.json写 MCP
skills/
yyds-auto/SKILL.mdMCP 手册
yyds-device/SKILL.mdyctl 手册
Cursor 全局目录。项目级则写到仓库里的 .cursor/。
Claude Desktop 与环境变量

写入 claude_desktop_config.json 后重启 Claude。

claude_desktop_config.json
{
  "mcpServers": {
    "yyds-auto": {
      "command": "npx",
      "args": ["-y", "yyds-auto-mcp"],
      "env": {
        "YYDS_DEVICE_HOST": "127.0.0.1",
        "YYDS_DEVICE_PORT": "61140"
      }
    }
  }
}

多台 USB 设备时,给每台分配不同本机端口,并用 YYDS_DEVICE_SERIAL 指定序列号。

变量默认作用
YYDS_DEVICE_HOST127.0.0.1USB 用本机;WiFi 填手机局域网 IP
YYDS_DEVICE_PORT61140本机端口;多设备时错开
YYDS_DEVICE_SERIAL首台设备多 USB 设备时指定转发目标

安装 Skill

Skill 是一份 SKILL.md:告诉模型何时动手、用哪套工具、坐标从哪来。每个 Skill 是一个文件夹,里面必须有 SKILL.md。

MCP 对话用
yyds-auto

指导模型调用 tap_element、take_screenshot、tap_text。仓库路径 yyds-auto-mcp/yyds-auto-skill

多设备 / CI
yyds-device

指导模型跑 yctl -s 序列号。仓库路径 .claude/skills/yyds-device

两个 Skill 都是文件夹 + SKILL.md。没有手册时,模型容易从截图瞎估坐标。

拷到对应编辑器的 skills 目录后,新开一轮对话即可。聊天里输入 / 可手动点 skill。

  • 项目:.cursor/skills/<name>/SKILL.md
  • 全局:~/.cursor/skills/(Windows %USERPROFILE%\.cursor\skills\)
  • Cursor 也会读 .agents/skills/、.claude/skills/、.codex/skills/
Windows / macOS · Cursor
~/.cursor/
mcp.json写 MCP
skills/
yyds-auto/SKILL.mdMCP 手册
yyds-device/SKILL.mdyctl 手册
Cursor 全局目录。项目级则写到仓库里的 .cursor/。
从仓库拷贝(PowerShell / bash)
PowerShell
# 在仓库根目录执行(已 git clone ChenAnZong/AndroidRPA)
$src = Get-Location

# Cursor 全局
New-Item -ItemType Directory -Force "$env:USERPROFILE\.cursor\skills" | Out-Null
Copy-Item -Recurse -Force "$src\yyds-auto-mcp\yyds-auto-skill" "$env:USERPROFILE\.cursor\skills\yyds-auto"
Copy-Item -Recurse -Force "$src\.claude\skills\yyds-device" "$env:USERPROFILE\.cursor\skills\yyds-device"

# Codex 全局
New-Item -ItemType Directory -Force "$env:USERPROFILE\.codex\skills" | Out-Null
Copy-Item -Recurse -Force "$src\yyds-auto-mcp\yyds-auto-skill" "$env:USERPROFILE\.codex\skills\yyds-auto"
Copy-Item -Recurse -Force "$src\.claude\skills\yyds-device" "$env:USERPROFILE\.codex\skills\yyds-device"
bash / zsh
# 在仓库根目录执行(已 git clone ChenAnZong/AndroidRPA)
# Cursor 全局
mkdir -p ~/.cursor/skills
cp -R yyds-auto-mcp/yyds-auto-skill ~/.cursor/skills/yyds-auto
cp -R .claude/skills/yyds-device ~/.cursor/skills/yyds-device

# Codex 全局
mkdir -p ~/.codex/skills
cp -R yyds-auto-mcp/yyds-auto-skill ~/.codex/skills/yyds-auto
cp -R .claude/skills/yyds-device ~/.codex/skills/yyds-device
只给当前项目
# 当前项目(Cursor / Codex / Claude Code 都能扫到)
mkdir -p .cursor/skills .codex/skills .agents/skills .claude/skills
cp -R yyds-auto-mcp/yyds-auto-skill .cursor/skills/yyds-auto
cp -R .claude/skills/yyds-device .cursor/skills/yyds-device
cp -R .cursor/skills/yyds-auto .codex/skills/yyds-auto
cp -R .cursor/skills/yyds-device .codex/skills/yyds-device
cp -R .cursor/skills/yyds-auto .agents/skills/yyds-auto
cp -R .cursor/skills/yyds-device .agents/skills/yyds-device

yctl 直控

yctl 跟本机 adb server 说话,按序列号临时打开 tcp:61140。没有 forward、没有预连接。MCP 管对话点工具;yctl 管脚本、多设备、CI。

开工只记这五条
引擎没起来会自动激活 keep / auto / py。锁屏先 unlock。
开工三板斧
yctl devices
yctl -s <SERIAL> unlock --home
yctl -s <SERIAL> screenshot -o shot.jpg
yctl -s <SERIAL> find "设置"
yctl -s <SERIAL> tap-text "设置"
编译并放入 PATH
# 仓库 yyds-cli,需要 Rust
cd yyds-cli
cargo build --release
# Windows: yyds-cli/target/release/yctl.exe
# macOS / Linux: yyds-cli/target/release/yctl
# 把该文件放到 PATH 后验证:
yctl devices
find / tap-text并联控件 text、Flutter content-desc、OCR
probe识别 Flutter / RN / 原生
ocr / screenshot读屏;截图给人看,不要当坐标
install app.apk绕过 adb install
run-code / auto /URI设备内 Python,或直通 API

自然语言作业

装好之后用中文下任务。模型应:看设备是否在线 → 必要时解锁 → 截图或 OCR → 用控件/文字点击,而不是猜坐标。

手机已连接。打开设置,读出电池电量。
MCP · take_screenshot
MCP · tap_element 「设置」

当前电量 87%,设置页已打开。

正确流程:先看屏,再用文字/控件点,不要从截图像素猜 x,y。
对话中 MCP 调用截图和 tap_text
模型先截图看 ANR 弹窗,再 tap_text「等待」。坐标来自工具,不是猜的。
1
连上手机
USB,或 WiFi 填 YYDS_DEVICE_HOST
2
新开 Agent 对话
让 MCP 和 Skill 重新加载
3
直接说目标
「打开设置,读出电池电量」
4
它若只说不做
点明「用 yyds-auto MCP」或「用 yctl,序列号是 XXX」
手机 App

端侧 Agent · 手机自己跑

App 打开「AI 自动化」,或桌面 YY畅控 顶栏同一入口。MCP 工具 agent_run 的 instruction 就是中文任务;agent_status / agent_stop 查看或打断。

设备没网时不要走 agent_run,改用 PC 上的 Cursor / Codex。

实用例子

左边是对 Cursor / Codex 说的话,右边是模型应执行的命令。接到 MCP 会调对应工具;装了 yyds-device 则走 yctl。 把 X 换成序列号即可自己跑。

先跑通这一条

解锁 → 打开设置 → 关于手机 → OCR 读型号。下面「读出型号和 Android 版本」是完整配方。

系统信息

读出型号和 Android 版本

对 Agent 说

解锁并回到桌面。打开设置,滑到「关于手机」点进去,OCR 这一页,把型号、Android 版本整理成表格。不要猜坐标。

MCP:take_screenshot → tap_element/tap_text「设置」→ scroll_to_find「关于手机」→ screen_ocr

实际会跑
yctl -s X unlock --home
yctl -s X tap-text "设置"
yctl -s X scroll-to-find "关于手机"
yctl -s X tap-text "关于手机"
yctl -s X ocr

不同 ROM「关于手机」可能叫「我的设备」。找不到就先 ocr 看可见文字。

系统信息

读电池电量与健康

对 Agent 说

打开设置,找到电池相关页,把当前电量、充电状态读出来。如果有「电池健康」也一并抄上。

MCP:tap_text「设置」→ scroll_to_find「电池」→ screen_ocr

实际会跑
yctl -s X tap-text "设置"
yctl -s X scroll-to-find "电池"
yctl -s X tap-text "电池"
yctl -s X ocr

MIUI/HyperOS 可能是「电量与性能」。先 find「电池」看命中再点。

过弹窗

点掉同意 / 允许 / 等待

对 Agent 说

截一张屏。如果出现「同意」「允许」「我知道了」「等待」「关闭」,点最可信的那一个,点完再截图确认弹窗消失。

MCP:take_screenshot → tap_text / tap_element(同意/允许/等待)→ take_screenshot

实际会跑
yctl -s X screenshot -o shot.jpg
yctl -s X find "同意"
yctl -s X tap-text "等待" --verify
yctl -s X screenshot -o after.jpg

--verify 会在点击后检查文字是否消失。多命中加 --index N。

滑动查找

滑到「隐私政策」再点

对 Agent 说

当前页往上滑,直到出现「隐私政策」或「用户协议」,点进去,把正文前两段摘出来。

MCP:scroll_to_find text=隐私政策 → tap_text → screen_ocr

实际会跑
yctl -s X scroll-to-find "隐私政策"
yctl -s X tap-text "隐私政策"
yctl -s X ocr

默认往上滑 10 次。要往下滑加 --direction down。

OCR 抽取

抽出验证码和手机号

对 Agent 说

OCR 全屏。把验证码、手机号、订单号单独列出来,不要点击任何按钮。看不清就先截图给我。

MCP:take_screenshot + screen_ocr(只读,不 tap)

实际会跑
yctl -s X screenshot -o shot.jpg
yctl -s X ocr

抽取类任务明确说「不要点击」,避免模型顺手点掉验证码页。

Flutter

Flutter 页点「登录」

对 Agent 说

先 probe 当前应用。如果是 Flutter / 游戏,不要 dump XML。用 OCR 点「登录」,点完截图确认。

MCP:先看前台应用 → tap_text「登录」(Flutter 走 OCR,不要 dump_ui_hierarchy 算坐标)

实际会跑
yctl -s X probe
yctl -s X tap-text "登录" --via ocr --verify
yctl -s X screenshot -o after.jpg

Flutter 的 text 经常是空的,字在 content-desc 或画布上。probe 的 strategy 行要听。

信息流

上滑三次抄标题

对 Agent 说

在当前信息流往上滑三次。每次滑动后等画面稳定,OCR 一次,把标题去重列出来。

MCP:swipe_direction up → wait_for_screen_stable → screen_ocr,循环三次

实际会跑
yctl -s X swipe-up
yctl -s X wait-screen-stable --timeout 5
yctl -s X ocr
# 重复 3 次

滑完立刻 OCR 会拍到动画中间帧。等 stable 再认。

中文输入

浏览器搜中文

对 Agent 说

用系统浏览器打开百度,点搜索框,输入「今日油价」并回车。等结果出来后 OCR 第一条标题。

MCP:open_url → tap_element 搜索框 → xinput(不要用 input_text 输中文)→ press_key enter → screen_ocr

实际会跑
yctl -s X open-url https://www.baidu.com
yctl -s X wait-text "百度" --timeout 15
yctl -s X tap-text "搜索"
yctl -s X xinput "今日油价"
yctl -s X key enter
yctl -s X wait-screen-stable --timeout 8
yctl -s X ocr

英文可以用 text;中文 / emoji 必须 xinput(YY 输入法)。

剪贴板

把文案贴进输入框

对 Agent 说

把这段文字放到剪贴板,点当前输入框,粘贴进去:【今晚 8 点直播,记得来】

MCP:set_clipboard → xinput 或点输入框后粘贴

实际会跑
yctl -s X clipboard set "今晚 8 点直播,记得来"
yctl -s X xinput "今晚 8 点直播,记得来"

有的框不吃剪贴板,优先 xinput。先 tap 让输入框获得焦点。

社交

打开微信给第一个会话发一句

对 Agent 说

打开微信,等主页出现。点第一个会话,在输入框用中文发「在吗」,发送。不要乱点通讯录。

MCP:launch_app com.tencent.mm → wait_for_app_foreground → take_screenshot → tap_element → xinput → tap_text「发送」

实际会跑
yctl -s X app start com.tencent.mm
yctl -s X app wait com.tencent.mm --timeout 15
yctl -s X screenshot -o wechat.jpg
yctl -s X tap-text "微信"
# 点第一个会话:先 find/OCR 看列表,再用返回的坐标 tap
yctl -s X xinput "在吗"
yctl -s X tap-text "发送"

会话列表不要用截图像素点。先 find / OCR 拿到坐标。包名以设备上为准。

安装

装 APK 并授权

对 Agent 说

把 C:\work\app.apk 装到这台手机,授予运行时权限。装完列出包名和版本。不要用 adb install。

MCP:install_apk(本地路径)→ get_app_info。不要让模型去跑 adb install。

实际会跑
yctl -s X install C:\work\app.apk --grant
yctl -s X app info com.example.app

厂商 ROM 常拦截 adb install。yctl install 是 push + pm install,引擎没起来也能装。

清数据

清数据后重新打开到登录页

对 Agent 说

强制停止 com.example.app,清除数据,再启动。等到出现「登录」再截图。

MCP:stop_app → clear_app_data → launch_app → wait_for_element「登录」→ take_screenshot

实际会跑
yctl -s X app stop com.example.app
yctl -s X app clear com.example.app
yctl -s X app start com.example.app
yctl -s X wait-text "登录" --timeout 20
yctl -s X screenshot -o login.jpg

clear 会丢掉登录态。包名先 app list / list_installed_apps 确认。

设备内 Python

在手机上跑一段 OCR

对 Agent 说

在设备引擎里执行:打印屏幕 OCR 结果。把 stdout 原样给我。

MCP:run_python_code:print(ocr())

实际会跑
yctl -s X run-code "print(ocr())"

这是引擎内 Python,不是电脑上的 Python。复杂脚本应做成工程再 project start。

端侧 Agent

把任务丢给手机自己跑

对 Agent 说

用端侧 Agent 执行:回到桌面,打开时钟,告诉我现在几点。跑完把 agent_status 给我。

MCP:agent_run instruction=「回到桌面,打开时钟,告诉我现在几点」→ agent_status / agent_stop

实际会跑
# 中文任务走 MCP agent_run,避免 PowerShell 把 JSON 编码搞乱
# 查进度:
yctl -s X get /agent/status
# 打断:
yctl -s X get /agent/stop

设备必须能访问模型 API。没网用 Cursor/Codex + MCP,不要走 agent_run。

并行

所有在线设备各截一张

对 Agent 说

列出 adb 设备。每一台都 unlock --home,截图保存为 shot-<序列号>.jpg,最后用一张表汇报哪些成功。

MCP:list_devices → 对每台 set_device_target 后 take_screenshot。多设备更建议直接 yctl -s。

实际会跑
yctl devices
yctl -s A unlock --home
yctl -s A screenshot -o shot-A.jpg
yctl -s B unlock --home
yctl -s B screenshot -o shot-B.jpg

yctl 不占 forward,多台可同时跑。MCP 多设备要错开本机端口。

并行

同一 APK 装到两台机

对 Agent 说

把 app.apk 装到序列号 A 和 B,都加 --grant。分别汇报成功或失败原因。

MCP:对每台 install_apk。CI 场景优先 yctl。

实际会跑
yctl -s A install app.apk --grant
yctl -s B install app.apk --grant

装包不依赖引擎。某台失败不要卡住另一台。

崩溃

复现时抓 Fatal / Tombstone

对 Agent 说

开始抓 com.example.app 的崩溃:Fatal、Tombstone、SELinux。我这边操作 60 秒,你把日志目录拉回来并指出第一处 FATAL。

MCP:没有同等能力时改走 yctl log。不要用 adb logcat 刷屏。

实际会跑
yctl -s X log crash -P com.example.app -D 60s
# 应用 FC/ANR 用这条;实时盯日志改用:
yctl -s X log tail -P com.example.app -l W

重启/卡开机用 log kernel --scan。给报告加 --compress。

定位策略

进新应用先 probe

对 Agent 说

告诉我当前前台包名,probe 它是原生、Flutter 还是游戏,并按它给的 strategy 点「我的」。

MCP:get_foreground_app → 再决定 tap_element 还是 tap_text/OCR

实际会跑
yctl -s X fg
yctl -s X probe
yctl -s X tap-text "我的"

新开一个 App 先 probe,能少走很多弯路。

对照与注意

Cursor / Codex 控一台手机
MCP + yyds-auto skill
不要 从截图估 x,y
多设备并行 / CI
yctl -s 序列号 + yyds-device
不要 为每台手动 adb forward
Flutter / 游戏
find / tap-text,或 --via ocr
不要 dump XML 算坐标
可重复脚本、打包 APK
开发文档里的 Python API
不要 把一次性对话当工程
四条硬纪律
  • 坐标只来自 find / tap-text / UI 树 / OCR。
  • USB 的 127.0.0.1 和 WiFi 的手机 IP 不要混用。
  • 锁屏先 yctl -s X unlock --home。
  • MCP 连不上先 yctl devices,再在终端单独跑 npx 配置里的 command。