外部 MCP 客户端
把 Claude Desktop(或任意 MCP 客户端)指向服务器,给它一个目标,它就会直接调用
peek / tap / swipe。模型和对话循环都由你自己带来。
PhysiClaw 就是一个 Python 服务器:一头连着硬件,另一头连着大脑。大脑负责决策,MCP 服务器把这些决策变成相机画面和机械臂动作,而一个小巧的手机端桥接则让服务器能伸进 iOS,去做那几件触控笔做不到的事。下面要讲的,正是夹在「点那个按钮」和触控笔真正触到玻璃之间的全部环节。
┌──────────────────────────────────────────────────────────────┐│ BRAIN — sees a screen, picks a bbox + a gesture ││ external MCP client (Claude Desktop, …) OR built-in agent │└───────────────────────────────┬──────────────────────────────┘ │ MCP (12 tools: peek, tap, swipe, …) ▼┌──────────────────────────────────────────────────────────────┐│ PhysiClaw MCP SERVER (Python · core/) ││ orchestrator · vision (OCR + icon detect) · calibration math │└───────┬───────────────────────┬───────────────────┬──────────┘ │ USB-UVC │ USB-serial │ HTTP over Wi-Fi (LAN) ▼ ▼ ▼ ┌─────────────┐ ┌────────────────┐ ┌──────────────────────┐ │ ONE overhead│ │ GRBL / FluidNC │ │ PHONE-SIDE BRIDGE │ │ camera │ │ controller │ │ • bridge web page │ └──────┬──────┘ │ X·Y gantry + │ │ (Safari, /bridge) │ │ looks down │ Z SOLENOID │ │ • AssistiveTouch │ │ └───────┬────────┘ │ • 3 iOS Shortcuts │ │ │ stylus tip └──────────┬───────────┘ │ ▼ │ runs on └─────────────► ┌──────────────┐ ◄──────────────┘ │ PHONE │ │ (unlocked) │ └──────────────┘本页接下来会逐一拆解每个方框,再讲它们之间的连线。
PhysiClaw 把它的硬件暴露成一组 MCP 工具——也就是 Model Context Protocol,Claude Desktop 和其他客户端早已通用的那套标准。 任何能讲 MCP 的东西都能驱动机械臂。这里支持两种大脑,而它们用的是完全相同的工具接口:
外部 MCP 客户端
把 Claude Desktop(或任意 MCP 客户端)指向服务器,给它一个目标,它就会直接调用
peek / tap / swipe。模型和对话循环都由你自己带来。
内置 agent
PhysiClaw 在 agent/ 下自带了一个大脑——一套原生的工具循环,带记忆、技能和
cron/轮询触发器,传承自 OpenClaw。它调用的是同样的 12 个工具,只是回路里
少了一个桌面应用。
无论哪种方式,大脑要干的活都一样:读一张被标注好的屏幕,挑出一个边界框和 一个手势,剩下的交给服务器。它从不会看到电机坐标,也看不到像素。
core/一个单独的 Python 进程,拆成几个职责明确的模块。编排器
(core/orchestration/orchestrator.py)是脊梁——它掌管机械臂、相机、标定,
以及一把忙碌锁,确保两次工具调用永远不会同时让机械臂动起来。每个工具都会拿到这把锁,
干完自己的活,然后在退出时把触控笔停到屏幕外。
你最常打交道的几块:
id · kind · label · bbox · conf。详见
它如何看见。 overhead camera (ONE) │ looks straight down, ~25 cm up ▼ ┌───────────┐ stylus tip ───►│ PHONE │ X·Y gantry slides the tip across the glass; on a solenoid │ screen │ the solenoid drops it to register a touch └───────────┘只有一台相机,架在头顶笔直朝下俯视屏幕——没有第二台相机,也没有深度传感器。 可靠性来自每动一次就重新看一眼,而不是堆更多硬件。机械臂是一套 X/Y 龙门架, 能把触控笔定位到屏幕上任意一点;笔尖上的 solenoid 就是 Z 轴。一次点击就是一记 干脆的下压再抬起的脉冲(固件先猛击线圈,再以较低占空比保持,这样长按时不会掉下来); 长按则只是把笔尖按住久一点。对手机而言,这个笔尖和指尖毫无分别,所以任何 App 都能用, 无需逐个 App 配置。
触控笔几乎能做手指能做的一切——但不完全是一切。它没法向 iOS 索要一张像素级精确的截图, 也没法把内容打进系统剪贴板。桥接填的正是这几道缝,多一点都没有。它有三个部分, 都在准备手机时一次性配好:
一张桥接网页。 手机在 Safari 里打开 http://<server-ip>:8048/bridge(你扫一个
二维码来配对——两台设备只要在同一个 Wi-Fi 下即可)。这个页面每秒轮询服务器四次,
并把服务器要它显示的东西渲染出来:配置阶段的标定靶点,或运行时排队的剪贴板文本。
AssistiveTouch。 iOS 那个悬浮的辅助功能按钮。机械臂会物理地点击 AssistiveTouch 按钮,去触发触控笔本来够不着的系统动作——单击截图,双击和长按则运行 Shortcuts。
三个 iOS Shortcuts。 绑定到那些 AssistiveTouch 手势上: 截一张图、把最新的截图上传到服务器,以及把排队的文本取进剪贴板。
所以当大脑调用 screenshot 时,服务器并不自己抓像素——它驱动机械臂去点 AssistiveTouch,
iOS Shortcut 抓下手机自己的截图,把字节通过 Wi-Fi POST 回来,服务器再对那些像素跑
vision。剪贴板也是同样的路子:服务器把文本排进队列,机械臂长按 AssistiveTouch,
Shortcut 把文本拉进来。桥接是手机上唯一存在的东西,而它存在的全部理由,就是截图、剪贴板,
以及显示标定标记。
| 跳点 | 传输 | 载荷 |
|---|---|---|
| 大脑 ↔ 服务器 | MCP | 工具调用 + 图像/清单结果 |
| 服务器 ↔ 相机 | USB (UVC) | JPEG 帧 |
| 服务器 ↔ 控制器 | USB 串口 | G-code(GRBL 方言) |
| 服务器 ↔ 手机桥接 | HTTP over Wi-Fi (LAN) | 轮询状态、截图上传、剪贴板文本 |
其中三条是显而易见的线缆;第四条才是当年那套「手机原封不动」说法漏掉的那根。手机从不 通过 USB 连服务器——它是通过你的局域网够到服务器的,这也是为什么两者必须共享一个 Wi-Fi。 四条线都接好后,一个完整动作看起来是这样:
brain: peek → server crops camera frame, runs OCR+icons, returns listingbrain: tap [bbox] → server maps bbox → arm mm, moves, fires solenoid, parks off-screenbrain: peek → server re-photographs, returns a fresh listing to compare这个「看 → 决定 → 动 → 再查」的节奏,就是整个控制回路——而正因为每一步的结尾都是看一眼, 任何意外都不过是下一件要应对的事而已。