LayoutSee · 深度介绍
你的 AI 会写代码,
却连一个按钮都点不准
截图只能让它「看见」界面,View 树才能让它「摸到」控件。这是我做 LayoutSee 的原因。
一个 macOS 上的 Android 布局工作台 + MCP 服务:把真机视图树交给 Claude、Cursor、Comate,让 Agent 从「猜」变成「查」。
01先讲一个翻车现场
如果你试过让 Agent 操作真机,大概率见过这个画面。
任务很简单:「打开 App,搜索机械键盘,把第一个商品加入购物车」。
Agent 截了张图,模型盯着图看了三秒,说按钮在 (860, 2140),然后点了下去。屏幕上弹出了「猜你喜欢」的广告页。
为什么?因为就在两秒前,那个位置还是「加入购物车」,现在被一个运营弹窗盖住了。
真正可怕的是后半段:Agent 并不知道自己点空了。它继续截图,继续分析,继续一本正经地编下一步。
报错不可怕,可怕的是它以为自己成功了。
这不是模型不够聪明。把一张 1080×2400 的截图压缩成视觉 token 之后,那个 40×40 的关闭图标可能只剩十几个 token;模型再强,也没法从像素里凭空读出「这个控件叫 close,可点击,热区只有 24dp」。
02截图这条路,天生有三个坑
第一,坐标是猜的。 模型看图估像素,屏幕一缩放、分辨率一换、状态栏高度一变,坐标就漂。你以为是 10px 误差,实际点到了隔壁的 banner。
第二,界面是动的。 弹窗、骨架屏、运营位、键盘弹起、列表懒加载——你截的那一帧,永远只是过去。
第三,语义是缺的。 截图里没有 resource-id,没有父子层级,没有 clickable,也没有 bounds。模型只能从「长什么样」反推「是什么」,而这两件事在 UI 里经常对不上。
| 维度 | 截图 + 视觉模型 | View 树 + MCP |
|---|---|---|
| 元素身份 | 靠识别,文案一改版就漂 | resource-id / 类名 / 层级,确定 |
| 坐标 | 模型估,缩放即漂 | bounds 上报,ref 直点中心 |
| 遮挡判断 | 基本靠猜 | 诊断给出涉及节点与证据 |
| 上下文成本 | 一张图几千 token,小字还看不清 | 语义摘要默认 1200 token 预算 |
| 失败反馈 | 常常「看起来成功了」 | 显式错误码,过期就报错 |
于是所有人都在做同一件事:给模型更多截图、更多标注、更多 prompt,试图用视觉把结构「猜」出来。
但结构本来就在那里。
03Android 早就把答案放在那了
一行 uiautomator dump,就能拿到当前页面的 View 树 XML:每个节点的文本、resource-id、类名、坐标、是否可点击、父子关系,全都有。
那为什么大家不用?
因为原始 XML 是给机器看的,不是给模型看的:
- 一个页面 50 多个节点,嵌套十几层,一次 dump 好几千 token,还没开始干活上下文就满了;
bounds是[643,295][1258,1389]这种绝对坐标,换台设备就全废;- 点完之后页面变了,旧快照还在,Agent 拿着过期的 ref 继续点;
- 它不会告诉你「这个按钮被另一个 View 盖住了」——而这恰恰是最常见的线上问题。
所以真正的缺口从来不是「有没有 View 树」,而是:View 树离 Agent 能用的接口,还差一整个工程层。
04LayoutSee 就干这一件事
这两年,MCP 已经成了 Agent 接工具的事实标准。数据库、浏览器、文件系统都有了像样的接口,但轮到你手机里的 App,大多数方案还停在「截个图,让模型自己看」。
LayoutSee 补的就是这一块。
一句话:把 Android 运行时视图树,工程化成 Agent 能直接调用的 MCP 工具;顺便,给人类一张能看的工作台。
它也不是又一个 Appium 客户端:Appium 面向脚本和测试用例,要先写驱动逻辑;LayoutSee 面向 Agent 的即时决策——抓一次、找一次、点一次,不需要预先编排。同一套能力,人在工作台里也能直接用。
架构也不复杂:macOS 桌面端 + 本地 Core(Python,默认监听回环地址)+ 每台在线设备一个独立的 MCP 端点。手机通过 adb 接入,投屏走 scrcpy。Agent 和你在同一个 Core 上,看的是同一份快照。
05五步闭环:抓、读、找、点、验
这 12 个工具(9 读 3 写)不是为了凑数,它们刚好对应一个完整的操作闭环。
- 抓 —— capture_layout冻结页面、dump 视图树、截图、建索引,一次原子完成,返回 snapshotId。不是「先 dump 再截图」那种会错位的做法。
- 读 —— get_layout_summary / get_layout先看骨架,再按需深入。语义摘要是确定性生成的:同样的输入,永远同样的输出。实测一个 52 个节点的页面,压缩成 20 个可交互元素、1186 个 token。每个元素都带短 ref 和归一化边界(0–1 之间),换分辨率也不用重算。
- 找 —— find_element / query_xpath按文案、描述、resource-id 定位;XPath 直接在快照的原始 XML 上执行,返回 nodeKey。前者像人找东西,后者像工程师找东西,都给你。
- 点 —— tap / swipe / input_texttap 可以直接传 ref,Core 会取该节点 bounds 的中心点执行点击。不用你算坐标,也不给模型瞎猜的机会。
- 验 —— 再抓一次页面变了就重新抓,用新快照里的新 ref。拿旧 ref 去点会明确报 SNAPSHOT_STALE 或 REF_NOT_FOUND,而不是「假装成功」。
失败要显式。 这是给 Agent 做工具时最容易被忽略、也最重要的一条。
一次典型的调用长这样:
用户:把「加入购物车」点了,确认购物车角标 +1 Agent → capture_layout → 52 nodes, snapshotId=snap-7a3e Agent → find_element("加入购物车") → ref=r_1f2e bounds=[0.00,0.85,1.00,0.92], clickable=true Agent → tap(ref="r_1f2e") → ok Agent → capture_layout → 购物车角标 3 → 4 ✓
你看,整个过程没有一次「我觉得大概在这个位置」。
06它还会顺手做个「体检」
diagnose_layout 检查六类问题:重叠、遮挡、越界、点击热区过小、文本截断、不可见但可交互。每条返回类型、严重程度、涉及节点、量化证据和建议,最多 50 条。
QA 说「这个按钮点不动」,以前你要复现、录屏、猜层级;现在跑一遍诊断,大概率直接告诉你:按钮被一个透明的 loading 遮罩盖着,遮罩的 nodeKey 是某某某。
有证据的排查,和靠感觉的排查,是两种工作。
07给 Agent 用,也给你用
很多「AI 工具」的问题是:为了机器好用,把人挤没了。
LayoutSee 反过来:人机共用同一份结构。
- 实时投屏,键鼠直接操控真机,多台设备可同时在线;
- 点画面,树上定位;选节点,画面高亮——三向联动;
- 属性面板、XPath 查询,候选选择器直接标「4 命中 / 不稳定」,让你一眼看出哪个选择器能上生产;
- 插件系统接入日志抓取、adb 快捷操作,还能往 MCP 里加自定义工具。
Agent 要的是接口,人要的是眼睛。两个都得有。
08边界,先说在前面
吹完功能,说点不好听的:
- WebView 和自绘 Canvas 的内部元素可能拿不到。 截图能补视觉,但别指望它证明内部层级或 resource-id。
- 一次快照就是一次采集。 抓取期间页面跳变,就得重抓。这是时序问题,不是模型能力问题。
- 只支持 macOS + Android 真机。 iOS 还在路上,目前是界面预告。
- Core 默认监听回环地址。 但你把它接进外部 AI 客户端之后,数据怎么发由那个客户端决定——这句必须说清楚。
工具的价值是把「结构」这件事做扎实,不是替模型做所有判断。
09三分钟跑起来
- 下载并安装去官网下载页或 Releases 下 DMG:Apple 芯片选 arm64,Intel 选 x64。未签名包首次打开被拦,去「系统设置 → 隐私与安全性」点「仍要打开」。
- 装 adb,手机开 USB 调试
brew install android-platform-tools
- 复制 MCP 配置打开设备工作台,进 MCP Tab,复制配置:
{ "mcpServers": { "layoutsee-android-3B161V012A600000": { "type": "sse", "url": "http://127.0.0.1:11663/mcp/android-3B161V012A600000/sse" } } }
粘进 Claude / Cursor / Comate(端口与设备名以界面实际给出的配置为准),再把 layout-see Skill 丢给它。第一句话可以这么问:
「读取当前页面,找出所有可点击但不是按钮的元素。」
然后看它第一次给你带回 resource-id、边界和 ref 的答案。
10最后
过去两年,AI 学会了看图、学会了写代码、学会了用工具。
但它操作你的 App 时,还在靠猜。
截图是给眼睛看的,View 树是给手用的。 AI 已经长了眼睛,现在该给它一双手了。
如果这个小工具帮你少点了一次「猜」,欢迎去 GitHub 给个 Star;不好用就来开 Issue——最好带上快照和诊断证据,我们按证据聊。
致谢:设备接入与投屏能力基于 uiautomator2、scrcpy,接入层参考并二次开发自 uiautodev。