Agent-Simulator推出,串流iOS模擬器至瀏覽器,支持Agent互動與React Native除錯
Agent-Simulator推出,串流iOS模擬器至瀏覽器,支持Agent互動與React Native除錯。
Agent-Simulator是一個開源工具,基於MCP協定,將iOS模擬器畫面串流至瀏覽器,讓使用者或AI Agent無需移動macOS游標,即可點擊、滑動、輸入,並檢視真實程式碼來源。開發者Jason Kneen強調其同時服務RN/Expo開發者、QA測試與AI Agent三類使用者,目前iOS版已可用,Android版開發中,呼籲星標、分享與貢獻,保持開源精神。
三大目標客群
- RN/Expo開發者:提供類Figma「圖層面板」,點擊運行中的App.tsx:42即跳轉真實來源。
- QA與示範流程:無XCUITest痛點的腳本化模擬,支持accessibility-label點擊、滑動、鍵盤輸入與截圖。
- AI Agent(如Claude Desktop、OpenAI Agents SDK、Cursor):透過MCP暴露完整瀏覽器功能,讓Agent「看見」畫面並「行動」。
核心功能
- 無游標輸入:透過axe → FBSimulatorHID → CoreSimulator,每個點擊/滑動/按鍵皆像素精準,無需Simulator.app焦點或macOS游標移動,支持任意縮放。
- 驅動任意iOS App:點擊、拖曳、滑鼠滾輪滾動、多工切換、主畫面、鎖定、鍵盤直通,適用Settings、Maps、Messages等非RN App。
- iOS無障礙樹:啟動即由axe describe-ui填充,每個畫面元素含label、role與frame,點擊前即可檢視。
- React元件樹:RN App搭配metro plugin,檢視渲染元件獲完整fiber堆疊與真實來源路徑(React 19 _debugStack + Metro /symbolicate)。
- 真實程式碼面板:選取元件後,屬性面板抓取實際檔案並高亮目標行,支持自訂程式碼、RN Libraries與Expo shims。
- MCP橋接:15項工具如sim_tree、sim_tap_by_label、sim_swipe、sim_type、sim_inspect、sim_source等,將瀏覽器全功能暴露給Agent。
系統架構
工具分三層架構,驅動單一iOS模擬器:
瀏覽器UI ── WS + HTTP ── server.js (Node) ── WS/stdin ── sim-server (Rust) ── iOS Simulator (axe + simctl)
│ │
└─ MCP client ── stdio ─┘
- sim-server (Rust):經simctl io screenshot擷取畫面編碼MJPEG,提供/stream.mjpeg、/snapshot.jpg、/api/tree與/health,從stdin讀取指令並shell axe。
- server.js (Node):協調sim-server,服務Vite UI,暴露/api/config、/api/tree、/api/source,橋接瀏覽器與MCP WebSocket客戶端,代理Metro /symbolicate。
- web-app (React + shadcn + Tailwind):深色/淺色主題、可調整面板、鍵盤擷取、拖曳滑動、滾輪滾動。
觸控注入流程:瀏覽器點擊經WS → server.js → stdin → sim-server → exec axe tap -x… -y… → FBSimulatorHID,座標以[0,1]比例End to End傳遞,sim-server轉換為device points(基於axe describe-ui根AXFrame,5秒TTL,旋轉時失效)。
介面佈局
| 區域 | 內容 |
|---|---|
| 標頭 | 裝置晶片、串流+橋接狀態丸、Inspect切換、主畫面/多工/鎖定/旋轉、面板切換、主題選單。 |
| 圖層面板(左) | 切換iOS無障礙樹(自動填充)與React元件樹(檢視時填充),點擊選取、懸停高亮、畫面內點擊自動展開祖先。 |
| 模擬器畫布 | 即時MJPEG,驅動模式隱藏原生游標換圓形指標,點擊現脈衝環、拖曳變滑動、滾輪滾動、鍵盤輸入焦點欄位;Inspect模式換十字準星與選取覆蓋。 |
| 屬性面板(右) | 選取圖層無障礙屬性、React元件名+來源、高亮JSX呼叫點或元件定義程式碼視窗。 |
| 狀態列 | UDID、模式旗標、上次檢視幀數、鍵盤快捷鍵提示。 |
鍵盤快捷鍵
- I:切換Inspect(無RN橋接時停用)。
- Esc:取消Inspect/解除選取固定。
- 其他按鍵(畫布焦點時):直送模擬器(適用任意文字欄位)。
MCP橋接細節
mcp/server.mjs為獨立Model Context Protocol伺服器,經stdio與MCP主機溝通,WebSocket橋接agent-simulator伺服器,暴露15工具:
| 工具 | 用途 |
|---|---|
| sim_info | 裝置UDID/名稱/串流URL/裝置點尺寸。 |
| sim_tree | 完整iOS無障礙樹,flat: true回傳標籤元素清單供LLM低成本脈絡。 |
| sim_tap | 點擊(x, y)模擬器比例座標。 |
| sim_tap_by_label | 依label/value(選type篩選)查AX元素並點中心,抗佈局變動。 |
| sim_swipe | 單呼叫原生滑動,含durationMs。 |
| sim_type | 輸入可印文字至焦點TextField。 |
| sim_key | 按USB-HID鍵碼(Return=40、Backspace=42、Esc=41、箭頭80–83)。 |
| sim_button | home/lock/power/side-button/siri/apple-pay。 |
| sim_multitask | 開啟App切換器。 |
| sim_screenshot | 回傳當前幀為MCP image內容。 |
| sim_inspect | 檢視(x, y) RN元件,回傳來源symbolicate堆疊。 |
| sim_source | 讀取file:line周圍程式碼視窗(絕對路徑)。 |
| sim_select_by_source | 給fileName+line,網格探測匹配渲染元件。 |
| sim_subscribe_selections | 串流inspectResult事件為MCP記錄通知。 |
| sim_unsubscribe_selections | 停止上述。 |
MCP客戶端設定範例
Claude Desktop於~/Library/Application Support/Claude/claude_desktop_config.json新增:
{
"mcpServers": {
"agent-simulator": {
"command": "node",
"args": ["/absolute/path/to/agent-simulator/mcp/server.mjs"],
"env": { "SIM_PREVIEW_URL": "http://localhost:3200" }
}
}
}
其他MCP主機(如OpenAI Agents SDK、Cursor)spawn node /path/to/mcp/server.mjs,設SIM_PREVIEW_URL指向運行伺服器。
Agent流程範例
- sim_tree flat:true → 看畫面所有元素。
- sim_tap_by_label "+" → 點擊計數器加號。
- sim_tap_by_label "Your name" type:"TextField"。
- sim_type "hello agent"。
- sim_key 40 → Return。
- sim_inspect x:0.86 y:0.24 → 回傳App.tsx:42。
- sim_source file:".../App.tsx" line:42 → 讀JSX。
快速啟動(1分鐘)
git clone https://github.com/jkneen/agent-simulator
cd agent-simulator
bun install
(cd sim-server && cargo build --release)
(cd web-app && bun install && bun run build)
xcrun simctl boot "iPhone 17 Pro" || true
open -a Simulator
bun start
open http://localhost:3200
UI自動附加已啟動模擬器,開Settings/Maps等即可驅動;左側iOS圖層樹由無障礙API填充,RN App載入inspector bridge後React樹才激活。
一指令示範(最有趣)
bun demo
自動:啟動iPhone模擬器、Metro於examples/expo-demo:8081、Expo Go載入exp://127.0.0.1:8081、agent-simulator:3200、開瀏覽器。Ctrl-C清理。操作:點擊預覽驅動(脈衝環+圖層展開)、I鍵Inspect(懸停/點擊React元件填屬性面板)、點+開examples/expo-demo/App.tsx:42高亮
旗標:--no-open跳瀏覽器、--port=3300改端口、--metro-port=8082改Metro、--device=
整合至自有RN/Expo App
metro.config.js:
const { getDefaultConfig } = require("expo/metro-config");
const { withAgentSimulator } = require("agent-simulator/runtime/metro-plugin");
module.exports = withAgentSimulator(getDefaultConfig(__dirname));
bun add -D agent-simulator。或index.ts匯入前registerRootComponent:
import "agent-simulator/runtime/inspector-bridge";
App啟動後,工具列BRIDGE丸轉綠,檢視點擊產生完整堆疊+來源。
串流品質與FPS上限
工具列Quality下拉,五預設+FPS/JPEG品質/縮放/擷取模式滑桿。切換經WS setCapture重啟sim-server,半秒內瀏覽器重訂閱。
| 預設 | 目標FPS | 解析度 | 模式 | 備註 |
|---|---|---|---|---|
| Eco | 2 | 300×650 | MJPEG | 省電背景監控。 |
| Balanced | 3 | 400×870 | MJPEG | 預設,匹配CSS渲染尺寸。 |
| Smooth | 最高10 | 400×870 | MJPEG | 適合滾動。 |
| Max | 最高30 | 400×870 | MJPEG | MJPEG路徑上限。 |
| Fluid | 最高60 | 400×870 | BGRA + keepalive | 實驗性,見限制。 |
點擊精度獨立於解析度,皆用[0,1]比例伺服器轉device points,低解析僅損畫面像素,非瞄準。
真實FPS數據(iPhone 17 Pro模擬器,M系列Mac)
| 路徑 | 要求 | 實際 |
|---|---|---|
| axe screenshot(單張) | — | 280–370 ms/張,~3 fps上限。 |
| axe stream-video --format raw --fps 30 | 30 | ~5–10 fps(axe截圖迴圈瓶頸)。 |
| axe stream-video --format bgra | 60 | 首幀後停滯,FBVideoStreamConfiguration硬編framesPerSecond: nil,iOS sim IOSurface回呼沉默。 |
Fluid 60 fps為願景,架構就位,但axe當前無法達標。解法:(1) fork axe傳framesPerSecond至BGRA;(2) Swift helper直連FBSimulatorControl.xcframework驅SimDevice/SimDeviceIOClient,皆半日工程,後端換入即替換。
Fluid keepalive:BGRA單幀後無更新,sim-server並行axe screenshot,300 ms無幀即PNG解碼→JPEG廣播,避免空白。閒置~3 fps,滾動BGRA貢獻,keepalive沉默。最差不掉0 fps。
環境變數:SP_FPS=10 SP_QUALITY=60 SP_SCALE=0.33 SP_CAPTURE=mjpeg bun start;SP_CAPTURE=bgra強制BGRA。
需求與安裝
- macOS + Xcode + 至少一iOS模擬器。
- Node ≥18(或Bun)。
- Rust toolchain(建sim-server一次)。
- axe:brew install cameroncooke/axe/axe。
- RN/Expo App僅React檢視需agent-simulator metro plugin,其他功能通用任意iOS App。
開發提示
- Agent腳本直用axe裝置點座標,UI處理比例轉換。
- axe describe-ui參考:axe describe-ui --udid
| jq '.[0]'。 - inspector-bridge.js改動無效Metro快取,重啟expo start --clear。
- SP_FPS/SP_QUALITY調MJPEG(預設fps=3 q=55)。
開發指令
(cd sim-server && cargo build --release) # Rust改動後
(cd web-app && bun run build) # UI改動後
bun mcp # 獨立MCP伺服器
npx @modelcontextprotocol/inspector node mcp/server.mjs # 監控MCP流量
專案佈局:
agent-simulator/
├── server.js Node協調、WS橋接、HTTP
├── scripts/demo.mjs 一鍵示範啟動
├── sim-server/ Rust MJPEG + axe驅動
├── runtime/ RN metro plugin + inspector bridge
├── web-app/ Vite + React + shadcn UI
├── web/ 舊單檔UI (/classic)
├── mcp/ MCP伺服器 (15工具)
├── examples/expo-demo/ 預配plugin Expo App
└── LICENSE AGPL-3.0-or-later
React來源解析(React 19)
纖維._debugSource移除,來源藏_fiber._debugStack(Error堆疊字串指bundle-URL行/欄)。檢視時:
- inspector-bridge解析_debugStack,收集每纖維最多12候選bundleFrames。
- server.js批POST至localhost:8081/symbolicate,一次往返挑非React createElement/jsxDEV內第一候選。
- UI收stack[i].source為真實絕對檔案路徑,涵蓋使用者元件、RN內部(RCTView、ScrollView)、Expo shim。
API細節
- GET /api/tree:代理axe describe-ui --udid,UI啟動/刷新拉取,MCP sim_tree包裝。
- GET /api/source?file=ABS&line=N&context=M:讀line周圍M行,回{file, lines, startLine0, endLine0, targetLine0, language},驅UI程式碼面板與sim_source。
授權與未來
AGPL-3.0-or-later。若嵌入商業產品或需其他授權,開issue討論雙授權。Android版開發中,需整理包裝成CodeSurf等擴充套件。
Introducing Agent-Simulator.
— Jason Kneen (@jasonkneen) April 21, 2026
An open source MCP based tool that allows you to stream the iOS simulator into a browser, interact, inspect and jump to react / expo code.
It also allows highlighting of native controls in other apps, and working on adapting it for swift.
MCP… pic.twitter.com/1JOKtzkznh
