关于 podium-mcp
podium-mcp 是面向移动端端到端测试与调试的 MCP 服务,为 iOS 模拟器和真机以及 Android 设备提供统一 stdio 入口。它整合原生界面自动化、WebView 与 React Native 检查,以及无需视觉识别的 Canvas/WebGL 操作。
主要功能
- 01控制 iOS 与 Android 设备和应用
- 02检查原生界面并执行自动化流程
- 03验证操作结果并返回证据
- 04检查 WebView DOM 与网络流量
- 05调试 React Native 与 Metro
- 06无视觉识别地操作 Canvas/WebGL
适用场景
- 01在移动设备上执行端到端流程
- 02复现缺陷并收集日志与崩溃报告
- 03检查 WebView 页面和请求
- 04自动化 Canvas 或 WebGL 界面
MCP 相关
提供包含 51 个工具的单一 MCP stdio 端点,供 MCP 客户端控制设备、执行测试并检查应用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
51收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
podium-mcp
一根指挥棒。奏响所有乐器。
一个 MCP stdio 端点,提供 51 个工具,用于控制 iOS(模拟器 + 真机)和 Android 设备、自动化原生 UI、执行端到端流程、进行可信断言、调试 React Native、检查 WebView DOM + 网络,以及通过无视觉画布/WebGL 大脑操作 Pixi/Konva/Fabric/Phaser/Three/Babylon(已在 WebKit 中实时验证)——此外,还提供一座用于经过插桩的 Unity/GL 构建的实验性引擎桥接(AltTester)——只需一个连接,无需半打服务。
一个提示词 → podium 实时操控 Safari → 输入 URL → 浏览个人主页 → 打开一个代码仓库。素材采集自运行中的 iPhone 16 Pro 模拟器。
指挥台是指挥家站立的地方——在同一处指挥整个乐团。此 MCP 服务通过一个 stdio 端点整合了八组能力:
- 设备与应用管理 — 通过统一的平台标记设备模型管理 iOS 模拟器(
simctl)、真实 iPhone(devicectl)和 Android(adb)。 - 原生 UI 检查与手势 — 通过
idb/mobilecli执行操作,并在必要时回退到 Maestro(不会为每个手势单独启动 JVM)。 - 端到端流程与批量自动化 — 声明式 Maestro 流程、有序操作批次,以及工程师→QA 流程导出器。
- 可信断言 — 预言机阶梯(WebView-DOM › 原生 a11y › Maestro),可返回可证伪且有证据支持的判定,并且验证失败时默认拒绝通过。
- WebView DOM + 网络 — 将
WKWebViewDOM 映射到点击坐标、执行 JS、驱动导航,并将页面内 HTTP 流量捕获为 JSON/HAR。 - React Native 调试 — 通过 CDP 获取 Metro 控制台日志、网络请求和应用内状态,以及主机/模拟器崩溃报告。
- 真机 — 通过
adb操作 Android 模拟器/设备(手势 +uiautomator层级结构);通过devicectl管理真实 iOS 设备生命周期,并可选择使用 WebDriverAgent 后端。 - 画布与游戏引擎自动化,无需视觉 — 画布/WebGL 大脑将 Pixi/Konva/Fabric/Phaser/Three/Babylon UI 作为可寻址对象进行操作(已在 WebKit 中实时验证)。实验性引擎桥接通过 AltTester 插桩构建驱动 Unity/GL(或通过
window.__podiumEngineWebGL 桥接);代码已完成并通过模拟测试,但尚未在实时 Unity 构建中运行。 与其在每个客户端配置中接入多个 MCP 服务,podium-mcp不如通过一个连接提供所有功能,并配备共享的execFile层(不使用 shell)、统一的结构化错误处理、针对 Maestro iOS 驱动不稳定问题的自动重试,以及一个健康检查工具,用于确认主机上有哪些可用功能。
目录
- 原因
- 基准测试
- 要求
- 安装
- 用法
- 快速开始
- 51 个工具
- 判定阶梯——可信的断言
- 原生优先的手势后端
- WebView 和 RN 网络内省
- 已记录的限制
- 架构
- 开发与测试
- 路线图与贡献
- 发布
- 提示词手册与参考资料
- 设计思路
- 贡献 · 安全 · 许可证
原因
要端到端驱动 React Native 应用,通常意味着要协调多个 MCP 服务—— 一个用于设备和应用控制,一个用于 UI 流程,一个用于 Metro/调试器日志,另一个 用于 WebView 检查——每个服务都有自己的配置项、特性和故障模式。 podium-mcp 将这些整合到一个服务中,并提供:
- 一个基于
execFile的命令运行器(不使用 shell——参数会原样传递), - 统一的结构化错误处理(工具不会导致服务崩溃),
- 针对 Maestro 已知的 iOS 驱动不稳定问题自动重试,
- 工具链(例如
adb)缺失时优雅降级, - 有证据支撑的判定,让 Agent 知道一个流程是否确实成功。
基准测试
Podium 基于两项选择构建,让它快速且成本低廉:它以结构化数据驱动 UI, 而非截图;并通过原生 后端路由手势,无需每次操作都启动 JVM。
Token 成本——无视觉模式约便宜 5 倍
基于截图的 Agent 会在每一步都向视觉模型发送图像。 Podium 则返回精简的结构化元素列表。在一个等效的 8 步 移动流程中(1179×2556 截图与约 20 个元素的列表相比):
| 方式 | 每步 | 8 步流程 |
|---|---|---|
| 截图 / 视觉循环 | ~2,070 个 token | 16,557 个 token |
| Podium——无视觉、结构化数据 | ~390 个 token | 3,117 个 token |
| 节省 | 5.3× | −13,440 个 token(−81%) |
vision loop ████████████████████████████████ 16,557 tokens
Podium ██████ 3,117 tokens (5.3× cheaper, −81%)
差距会随着每一步不断扩大——一个 30 步的会话大约消耗 62k 对比 12k 个输入 token。除了每步成本外,完整的 51 个工具的 schema 会随 每个请求一同传输(约 3,612 个 token,约 71 个/工具);Podium 保持工具描述精简, 避免工具区块占据过多上下文窗口。
对于 canvas / WebGL UI,这项优势是结构性的,而不仅仅是成本更低: Canvas Brain 按名称和文本定位对象,而仅依赖截图的 Agent 必须 在每一帧都重新分析像素。
速度——原生优先的手势后端
手势通过 idb / mobilecli 路由,而不是每次操作都启动 Maestro 的 JVM
(在运行中的 iPhone 16 Pro 模拟器上测得):
| 操作 | Maestro(每次调用都启动 JVM) | Podium 原生模式 | 加速比 |
|---|---|---|---|
tap_on | ~14.7 s | ~0.6 s | ~24× |
inspect_screen | ~8.9 s | ~0.9 s | ~10× |
一个连接,而非六个
全部 51 个工具——设备和应用控制、UI 自动化、声明式 Maestro 流程、有证据支持的断言、WebView DOM + 网络捕获、React Native / Metro 调试,以及无视觉画布/WebGL 自动化(另有用于已插桩 Unity/GL 的实验性引擎桥接)——都通过单个 stdio 端点提供,取代通常由六七个独立 MCP 服务组成的工具栈。
Token 数量是启发式估算值(约 4 个字符/token;Anthropic 的图像公式约为 750 px/token)——运行
npm run token-bench可复现,也可以换用 Anthropiccount_tokensAPI 获取精确数量。速度数据是在运行中的 iPhone 16 Pro 模拟器上测得的(npm run benchmark)。
要求
- macOS,并安装 Xcode 命令行工具(
xcrun、simctl) - Node.js ≥ 22(使用原生
fetch和WebSocket;.npmrc设置了engine-strict=true) mobilecli——作为 npm 依赖自动捆绑;默认原生手势 + WebView 后端(无需单独安装)- (可选)
idb(idb+idb_companion)——两者都存在时优先使用的原生手势后端;自动检测 - (可选) 在
PATH上(或位于~/.maestro/bin)的 Maestro——run_flow引擎和手势回退路径 - (可选) 正在运行的 Metro 打包器,供
metro_*调试工具使用 - (可选) Android SDK +
adb——adb 路径仅用于检测;缺失时会优雅降级
平台范围(v0.3.0): podium 可自动化iOS 模拟器、真实 iPhone(通过
devicectl管理生命周期 + 可选启用 WebDriverAgent)以及 Android 模拟器/设备(通过adb手势 +uiautomator层级结构)。device_list会为每个目标标记平台,并按目标选择后端。缺少某个工具链(例如adb)时,相应路径会返回说明性结果,而不会失败。
安装
Claude Code 插件(推荐)
无需手动配置——只需一次性设置市场,然后安装:
/plugin marketplace add github:hoainho/podium-mcp
/plugin install podium-mcp@podium
该插件会自动启动 MCP 服务(全部 51 个工具),并提供五种技能:
| 技能 | 调用方式 | 功能 |
|---|---|---|
| 设备信息 | /podium-mcp:device-info <UDID> [<BUNDLE_ID>] | 健康检查、屏幕尺寸、方向、应用列表 |
| E2E 流程 | /podium-mcp:e2e <UDID> <BUNDLE_ID> [path or description] | 运行或编写 Maestro 流程 |
| Bug 复现 | /podium-mcp:bug-repro <UDID> <BUNDLE_ID> <description> | 捕获视频、日志和崩溃证据 |
| RN 调试 | /podium-mcp:rn-debug [UDID] [logs|apps|crash|all] | Metro 日志、已连接应用、崩溃报告 |
| 画布智能 | /podium-mcp:canvas <UDID> <intent> | 检查 / 解析 / 点击画布-WebGL UI,无需视觉识别 |
npx(零安装)
{
"mcpServers": {
"podium": { "command": "npx", "args": ["-y", "podium-mcp"] }
}
}
手动安装(从源代码)
git clone [email protected]:hoainho/podium-mcp.git
cd podium-mcp
npm install
npm run build
用法
将构建好的服务注册到任意 MCP 客户端。Claude Code(.mcp.json):
{
"mcpServers": {
"podium": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/podium-mcp/dist/index.js"]
}
}
}
通过原始 stdio 进行快速手动冒烟测试(列出已注册的 51 个工具):
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | node dist/index.js
请始终先调用 podium_health,确认主机上有哪些工具链可用。
快速入门(使用顺序)
podium_health——确认xcrun/maestro/ 原生后端是否可用。device_list——选择已启动模拟器的udid。- 读取状态——
app_list、app_state、screen_size、orientation_get。 - 操作设备——先调用
app_launch,再使用tap_on/input_text/swipe/press_key,以及set_location和orientation_set。使用run_steps批量执行多个操作。 - 编写并验证——使用
inspect_screen发现元素,使用run_flow执行声明式检查,然后用assert_visible/validate_flow给出有证据支持的结论。 - 检查 WebView——
webview_inspect→ 点击坐标、webview_eval、webview_navigate、webview_network。 - 捕获并调试——
screenshot/record_start→record_stop;metro_logs/metro_network/metro_state;crash_list/crash_get。
51 个工具
每个工具都会返回结构化 JSON,且不会抛出异常——失败会作为 MCP 工具错误返回。权威的参数说明请参阅
docs/tool-catalog.md。**平台支持(v0.3.0):**以下手势、检查和生命周期工具可在 iOS 模拟器、真实 iPhone(
devicectl+ 通过PODIUM_WDA_URL选择启用 WebDriverAgent)和 Android(通过adb控制模拟器/设备;通过uiautomator获取层级结构)上运行。device_list会为每台设备标注平台,并针对目标选择后端。
游戏引擎 — 通过 AltTester 使用 Unity / GL,无视觉 · 实验性(4)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
engine_inspect | udid, by?, value | AltTester(TCP)/ WebGL CDP 桥接 | 按名称/路径/组件/文本列出引擎对象及其绝对屏幕坐标——不使用截图 |
engine_tap | udid, by?, value | AltTester / CDP | 解析对象并点击其屏幕坐标 |
engine_swipe | udid, fromX/Y, toX/Y, durationMs? | AltTester / CDP | 在引擎视图内滑动 |
engine_call | udid, by?, value, component, method, parameters? | AltTester / CDP | 通过反射调用 C# 组件方法(相当于引擎版的 DOM 事件处理程序) |
状态:实验性。线协议格式已通过模拟对象进行单元测试;AltTester 路径尚未通过实时 Unity 构建验证(提供经过插桩的构建前,
engine-smoke会跳过),且 Unity-WebGL 需要应用公开window.__podiumEngine。引擎工具需要经过 AltTester 插桩的构建版本(开发/预发布),或 WebGL 桥接;在未经插桩的构建版本上,工具会安全失败并返回可执行的错误提示——绝不会回退到视觉方案。对于使用 JS 框架的 Canvas/WebGL 应用,下方的 Canvas 分析模块是经过验证的路径。
Canvas 分析模块 — Pixi/Konva/Fabric/Phaser/Three/Babylon,无视觉(3)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
canvas_inspect | udid, by?, value?, webviewId? | 注入式场景图桥接(CDP eval) | 列出 Canvas 对象及可直接用于点击的 CSS 像素坐标——不使用截图 |
canvas_resolve | udid, intent, webviewId? | 桥接 + 语义解析器 | 将模糊意图(“关闭”、“✕”)映射到按相关性排序且有依据的目标;若 confidentEnough 不满足则安全失败 |
canvas_tap | udid, intent, bundleId?, webviewId? | 解析器 + 原生点击 | 在绝对屏幕坐标处解析并点击有把握的匹配项(否则安全失败) |
**已通过实时验证:**六个框架均通过了 DPR 为 1 和 3 的 Playwright-WebKit(≈ WKWebView)测试套件(
npm run test:canvas,共 19 项测试)。Canvas 工具需要一个可检查的 WKWebView,其中托管受支持的框架,且能够访问其根对象(通常位于window上,或 Pixi 的__PIXI_APP__)。没有框架/没有可检查的 WebView → 安全失败并返回可执行的错误提示——绝不会回退到视觉方案。
诊断(1)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
podium_token_report | steps?, screenshotWidth?, screenshotHeight?, elementsPerStep?, toolCount? | token 估算器 | 无视觉输入与截图/视觉循环的输入 token 数、节省比例,以及每个请求的工具定义开销 |
健康状态与工具链(1)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
podium_health | — | which 探测 | 不会失败;报告 toolchain { xcrun, maestro, adb }、原生后端以及 platforms: [ios-sim, ios-real, android] |
设备与模拟器(6 项)
| 工具 | 关键参数 | 后端引擎 | 行为 |
|---|---|---|---|
device_list | — | simctl list -j + adb devices | 合并后的 iOS 设备清单;如果没有 adb → android: { available: false }(仅检测) |
device_boot | udid | simctl boot | 幂等——如果设备已启动 → alreadyBooted: true;最多等待 30 s |
screen_size | udid | simctl io screenshot + sips | { widthPx, heightPx }(实际像素) |
orientation_get | udid | 原生查询 → 截图启发式判断 | { orientation, basis }(原生查询时结果精确) |
set_location | udid, latitude, longitude | simctl location set | 将 QA 地理位置转圈问题的修复固化为工具 |
open_url | udid, url | simctl openurl | 深层链接 + https:// |
应用(6 项)
| 工具 | 关键参数 | 后端引擎 | 行为 |
|---|---|---|---|
app_install | udid, path (.app/.zip) | simctl install | 结构化工具错误 |
app_launch | udid, bundleId | simctl launch | 显式设置 30 s 超时(冷启动的 RN 应用不再被误报为失败) |
app_terminate | udid, bundleId | simctl terminate | 结构化工具错误 |
app_uninstall | udid, bundleId | simctl uninstall | 结构化工具错误 |
app_list | udid | simctl listapps + plutil | { count, apps: [{ bundleId, name, type }] } |
app_state | udid, bundleId | simctl listapps + launchctl | { installed, running }——按 bundle ID 精确匹配 |
捕获(3 项)
| 工具 | 关键参数 | 后端引擎 | 行为 |
|---|---|---|---|
screenshot | udid, saveTo? | simctl io screenshot | 返回 path + byteSize(不会产生臃肿的 base64 数据) |
record_start | udid, saveTo? (.mp4) | 分离运行的 simctl io recordVideo | { ok, path, pid };带时间戳的路径 + 时长看护机制(PODIUM_MAX_RECORDING_MS);每个 udid 仅限一个 |
record_stop | udid | 向录制器发送 SIGINT + 刷新 | { ok, path, sizeBytes } |
UI 检查与手势(8 项)
| 工具 | 关键参数 | 后端引擎 | 行为 |
|---|---|---|---|
inspect_screen | udid, compact? | 原生扁平 AX 列表 → maestro hierarchy | compact:true(默认)仅返回有意义的节点 |
tap_on | udid, bundleId, text|id|x+y, double?, long? | 原生点击 → Maestro 回退 | 通过元素列表解析 text/id;报告 backend |
input_text | udid, bundleId, text, submit? | 原生 → Maestro 回退 | 报告 backend |
swipe | udid, bundleId, direction, start/end? | 原生 → Maestro 回退 | 根据逻辑屏幕尺寸解析 %/像素覆盖值 |
press_key | udid, bundleId, key | 原生 → Maestro 回退 | 返回/电源/Tab 仅适用于 Android |
orientation_set | udid, bundleId, value | 原生 → Maestro 回退 | PORTRAIT / LANDSCAPE_LEFT / LANDSCAPE_RIGHT / UPSIDE_DOWN |
tap_with_fallback | udid, x, y, maxRetries?, offsetStep? | 原生点击 + 前后预言机 | 用于 WebGL/Canvas 覆盖层;不会盲目遍历(需选择启用 offsetStep) |
notification_bar_clear | udid, bundleId? | 原生点击 + 预言机 | 关闭 RN 调试通知栏 |
流程与批量自动化(4 项)
| 工具 | 关键参数 | 后端引擎 | 行为 |
|---|---|---|---|
run_steps | udid, bundleId, steps[] | 原生后端(idb/mobilecli) | 单次调用中按顺序批量执行操作;返回每步结果 |
run_flow | udid + yaml/files/dir(+tags) 中的任意一项 | maestro test | 执行前验证是否恰好指定一项;返回每步的通过/失败结果 |
export_flow | steps[], output path | 流程生成器 | 将 run_steps 批次导出为可复用的 Maestro 流程(工程师→QA 桥接) |
cheat_sheet | — | 内置的 assets/maestro-cheat-sheet.yaml | 完全离线的 Maestro 语法参考手册 |
断言与判定——预言机阶梯(5)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
assert_visible | udid, text|id, … | 预言机阶梯(WebView-DOM › a11y › Maestro) | 给出有依据的通过/失败结果;报告用于证明结果的预言机 |
assert_text | udid, text | 预言机阶梯 | assert_visible 的按文本简写形式 |
assert_not_visible | udid, text|id | 预言机阶梯 | 默认判定为失败——如果无法验证元素不存在,就判定为失败 |
wait_for_element | udid, text|id, timeoutMs? | 预言机阶梯(轮询) | 轮询直至元素可见或超时 |
validate_flow | udid, flow + assertions | 预言机阶梯 + 工作流运行 | 对刚构建的工作流是否可用给出可信、可证伪的判定 |
WebView DOM 与网络(4)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
webview_inspect | udid, selector?, webviewId?, max? | mobilecli(CDP) | 将 CSS 选择器解析为 DOM 元素,并提供绝对位置 tapX/tapY |
webview_eval | udid, expression, webviewId? | mobilecli(CDP) | 在页面上下文中运行 JS;受 PODIUM_DISABLE_WEBVIEW_EVAL=1 控制 |
webview_navigate | udid, action (goto/back/forward/reload), url? | mobilecli(CDP) | 控制 WebView 导航 |
webview_network | udid, durationMs?, format (json/har)?, saveTo?, redact?, includeResources? | CDP + 页面内 fetch/XHR shim + Resource Timing | 捕获 WebView 内的 HTTP 流量;导出已脱敏的 JSON 或 HAR 1.2 |
React Native 调试——Metro CDP(4)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
metro_apps | port? (8081) | GET http://localhost:<port>/json | 区分不同错误(超时、未运行或其他错误) |
metro_logs | wsUrl?/port?, durationMs?, maxLogs? | WebSocket + CDP Runtime.enable | 未提供 URL 时自动发现首个应用 |
metro_network | wsUrl?/port?, durationMs?, maxEntries? | CDP Network.enable | 请求(url/method/status/mimeType/ts) |
metro_state | expression?/wsUrl?/port?, timeoutMs? | CDP Runtime.evaluate | 读取应用内状态(默认读取全局暴露的 Redux store) |
崩溃诊断(2)
| 工具 | 关键参数 | 底层引擎 | 行为 |
|---|---|---|---|
crash_list | processName?, sinceHours?, udid? | 主机 + 模拟器 DiagnosticReports | 按时间从新到旧排列;标记 source: host | simulator |
crash_get | id, udid? | 同上 | 防止路径遍历(仅使用 basename);如实截断 |
预言机阶梯——可信断言
“运行正常”被定义为有依据、可证伪的判定,而非“看起来没问题”。断言和 validate_flow 通过三级阶梯判定可见性,并使用最强的可用信号:
- WebView DOM——存在可检查的
WKWebView时,查询真实 DOM。 - 原生辅助功能——原生 AX 元素集(通过
idb/mobilecli)。 - Maestro——作为后备方案使用
assertVisible/assertNotVisible。
assert_not_visible 默认判定为失败:如果无法确切验证元素不存在(例如 WebView 无法读取),就报告失败,而不是误报通过。每个判定都会指出得出结果的预言机,以便 Agent 评估其可信度。
原生优先的手势后端
命令式手势(tap_on、input_text、swipe、press_key、orientation_set、run_steps)和 inspect_screen 会通过当前最快的可用后端执行。系统只探测一次并缓存结果(同时设置较短的负缓存 TTL,以便启动后才运行的后端也能被检测到):
idb—— 安装了idb和idb_companion时使用(原生,速度最快)。mobilecli—— 随附的 npm 依赖(预编译的 Go 二进制文件)。默认选项,无需安装。- Maestro 回退 —— 没有可用的原生后端时,或需要执行原生后端无法表达的操作时使用(双击/长按、
UPSIDE_DOWN)。手势会生成一个最简流程,其中包含launchApp: { stopApp: false },将应用带到前台,但不会重启应用,因此可以保留状态。
每个结果都会报告所用的 backend。设置 PODIUM_DISABLE_NATIVE=1 可强制使用 Maestro。消除每次手势启动 JVM 的开销后,在 iPhone 16 Pro 模拟器上,tap_on 耗时从约 14.7 秒降至约 0.6 秒,inspect_screen 从约 8.9 秒降至约 0.9 秒。运行 npm run benchmark 可执行完整的通过/失败测试。
Maestro 不稳定时的重试机制: 使用回退后端时,其 iOS 驱动有时会报错:Failed to connect to 127.0.0.1:<port>。流程最多重试 2 次,间隔 2 秒/5 秒退避,并报告 retries 次数;如果仍然失败,则返回原始输出和修复提示。
WebView 和 RN 网络分析
两个独立的网络层,对应两个工具:
metro_network通过 CDP Network 域捕获 RN/Hermes 目标上的请求——对于原生 RN 应用自身发出的fetch,应使用此工具。webview_network捕获WKWebView内部的流量:它会注入fetch/XHR记录器(功能丰富——可捕获开始记录后调用的请求的方法、状态码、标头和正文),并且读取浏览器的 Performance Resource Timing 缓冲区(includeResources默认开启),获取自导航以来的所有请求,包括开始记录前的请求(URL/时序/大小)。合并结果可生成近乎完整的请求列表,并可导出为经过脱敏的 JSON 或 HAR 1.2。
如果 RN 外壳在 WebView 中承载 UI,那么应用的 API 调用会在 Web 层执行,因此 metro_network 看不到这些请求,应使用 webview_network。WebView 工具要求 WKWebView.isInspectable = true(调试/预发布版本中默认开启,生产环境中关闭);如果找不到可检查的 WebView,工具会返回一条可采取行动的错误信息。
已说明的限制(属于设计如此,并非缺陷)
- Canvas/WebGL 需要配合使用的 JS 框架 —— 当应用暴露场景图根节点(已通过实时验证)时,canvas 模块可按选择器操作 Pixi/Konva/Fabric/Phaser/Three/Babylon UI。原始/自定义 WebGL canvas、不透明/生产构建,或没有 AltTester/
window.__podiumEngine桥接的 Unity,都无法通过选择器定位——请改用基于截图坐标的tap_with_fallback,或为构建添加检测机制。 - WebView 工具仅供开发/QA 使用 —— 生产版 App Store 构建通常会设置
isInspectable = false;工具会返回可采取行动的错误信息,并回退到坐标点击。 - 无法从应用沙盒读取 WebView 内容进程的内存(平台限制)——请使用间接信号(内存警告、进程终止)。
- Maestro 的
text:匹配器使用完整字符串正则表达式(IGNORE_CASE) —— 无法匹配部分字符串;请原样复制层级结构中的text,或使用.*作为锚点。 - Android 要求
adb位于PATH中 ——adb可用后,手势、检查和截图功能即可正常运行;如果缺少adb,所有 Android 路径都会返回结构化的“未找到 adb”结果。 - 没有原生后端时,
orientation_get使用截图宽高比进行启发式判断 —— iOS 模拟器不提供直接的方向查询。 record_start/record_stop在进程内保存状态 —— 请在同一连接上按start→ … →stop的顺序执行;每个 udid 同时只能有一项录制(如果录制始终未停止,监控程序会将其结束)。
架构
src/
index.ts # MCP server entry — registers every tool group, warms caches
lib/
exec.ts # execFile-based runner (NO shell) + timeout/timedOut flag
result.ts # shared ok/error MCP content helpers
simctl.ts # xcrun simctl wrappers + device-list TTL cache
native.ts # gesture/inspect backend: idb → mobilecli → null (re-probe TTL)
idb.ts # idb gesture/inspect adapter
gesture.ts # unified native→Maestro executors (shared by screen + steps)
oracle.ts # the oracle ladder: WebView-DOM › a11y › Maestro
maestro.ts # Maestro engine: flow runner, idb retry, hierarchy
export-maestro.ts # run_steps → reusable Maestro flow
har.ts # HAR 1.2 export for webview_network
webview.ts # mobilecli CDP — WebView list/inspect/eval/navigate/network
metro.ts # Metro CDP — app discovery, logs, network, state
crash.ts # DiagnosticReports crash listing/reading
recording.ts # detached screen recording lifecycle + watchdog (platform-aware)
device-target.ts # DeviceTarget model + PlatformDriver registry (v0.3.0)
drivers/ # per-platform lifecycle: ios-sim, android, ios-real
adb.ts # Android adb driver (list/install/launch/screenshot/wm size)
adb-backend.ts # adb gesture/inspect (input + uiautomator → AX elements)
iosreal.ts # real iOS via devicectl (list/install/launch) + capture
wda.ts # opt-in WebDriverAgent backend (/source + tap/swipe/keys)
engine.ts # no-vision engine client (AltTester + WebGL-in-WebView)
engine-transport.ts # WebSocket transport for the AltTester bridge
canvas-types.ts # Canvas Brain shared contract (CanvasObject, selectors)
canvas-adapters.ts # in-page bridge: detect + walk Pixi/Konva/Fabric/Phaser/Three/Babylon
canvas-resolver.ts # semantic "close brain": intent → ranked, evidenced target
canvas-a11y.ts # Flutter/ARIA fallback reader → CanvasObject (scaffolding, not wired — #9)
canvas-vision.ts # opt-in vision fallback scaffolding (not wired — #9)
token-report.ts # token estimators + no-vision vs vision-loop comparison
tools/ # one file per group:
# health, device, screen, steps, flow, assert, validate,
# webview, debug, engine, canvas, token
assets/ # bundled offline Maestro cheat sheet + demo.gif
scripts/ # benchmark.ts, compare-mcps.ts, token-bench.mjs
e2e/ # smoke suites (smoke / full-smoke / webview-network-live / android-smoke / engine-smoke)
test/canvas-e2e/ # live Playwright-WebKit canvas bridge suite (6 frameworks)
docs/ # tool catalog, e2e transcript, roadmap, token-economics
开发与测试
npm run build # tsc
npm run typecheck # tsc --noEmit
npm test # vitest run — 359 unit/integration tests (exec/network mocked, no sim needed)
npm run test:canvas # live canvas bridge suite in Playwright WebKit — 19 tests (run `npx playwright install webkit` first)
npm run benchmark # spawn a fresh server over stdio and sweep the tool suite
node e2e/smoke.e2e.mjs # real E2E against a booted simulator (macOS + Xcode)
node e2e/full-smoke.e2e.mjs # drives the iOS-sim tool handlers (happy + structured-error paths)
node e2e/android-smoke.e2e.mjs # Android emulator/device smoke (story A3)
node e2e/engine-smoke.e2e.mjs # AltTester engine smoke; skips without an instrumented build (story C4)
31 个文件中共有 359 项单元/集成测试,另有 19 项实时画布桥接测试(共 378 项),全部通过——其中包括 v0.3.0 设备目标注册表、Android adb 驱动程序和 uiautomator 解析器、AltTester 引擎客户端和 WebGL 桥接、devicectl/WDA 真实 iOS 解析器,以及 v0.2.0 判定阶梯、录制看门狗、手势一致性、HAR 导出、WebView 和 Metro 流程。
标准:TypeScript 严格模式,不使用 as any / @ts-ignore,不执行 shell 命令(所有命令均通过 lib/exec.ts 执行),工具返回结构化错误,而不是抛出异常。请参阅 CONTRIBUTING.md 中的“添加新工具”检查清单。
CI 上的端到端测试:E2E (simulator) 工作流会在 macOS 运行器上启动真实的 iOS 模拟器,并每晚及按需运行冒烟测试套件(不作为 PR 门禁——模拟器运行速度较慢)。full-smoke.e2e.mjs 会验证目标存在时的正常路径,以及依赖缺失时的真实结构化错误路径(用于 WebView 的调试版 isInspectable 应用;用于 metro_* 的已连接 RN 应用)。
路线图与贡献
podium-mcp 已可用于生产环境中的 iOS/Android UI 自动化和无视觉画布/WebGL(Pixi/Konva/Fabric/Phaser/Three/Babylon——已通过实时验证)。贡献者可以切实推进的前沿领域,位于尚未解决的问题中:
高影响力——help wanted
- #1 — 使用实时插桩的 Unity 构建验证 AltTester/Unity 引擎路径(这是实现真实 Unity 自动化的最大缺口)。
- #2 — 为画布核心实现真实设备上的 WKWebView 端到端测试(目前已在 Playwright WebKit 中验证)。
- #3 — Unity-WebGL 适配器:自动检测并提供可直接接入的
window.__podiumEngine桥接。
适合入门的问题——good first issue
- #4 — 添加更多画布适配器(PlayCanvas、Cocos Creator、p5.js)。
- #5 — 提供
canvas_hittest/canvas_object_rect工具。 - #7 — 通过 Anthropic
count_tokensAPI 获取精确的 token 数量。 - #6 — 处理 Konva Group/Container 目标。
添加工具请遵循 CONTRIBUTING.md 中的一份检查清单:TypeScript 严格模式、不使用 shell、结构化错误且绝不抛出异常、添加 vitest 测试,并在工具目录中添加一行。欢迎提交 PR。
发布
server.json 是 MCP Registry 的官方清单。推送 v* 标签后,会依次运行
Publish to npm 和
Publish to MCP Registry(io.github.hoainho/* 命名空间使用 GitHub OIDC——无需长期有效的令牌)。两个工作流都会先运行 typecheck → build → test 作为门禁;只有匹配的 npm 版本发布后,Registry 发布才会成功,且版本不可变。
提示词指南与参考资料
prompts/— 可直接复制粘贴的提示词,适用于端到端流程、测试用例、功能验证、错误修复和设备控制。每条提示词都会注明其驱动的 podium 工具,并已在真实模拟器上验证。请从prompts/README.md开始。docs/tool-catalog.md— 权威的逐工具参考文档。docs/e2e-demo.md— 在已启动的 iPhone 16 Pro 模拟器上运行生产级 RN 应用时的真实交互记录。
设计理念
- 一个统一入口,一次连接。 单个服务为所有移动端功能提供入口,因此 Agent 只需配置一个端点,即可一次性发现全部 51 个工具。
- 从设计上保障安全。 所有外部命令都通过
execFile层执行,并使用明确的参数数组,绝不使用 shell 字符串。 - 绝不让主控程序崩溃。 工具会返回结构化结果和错误,而不是抛出异常;一次调用失败不会导致服务停止运行。
- 降级运行,而非直接失败。 如果缺少工具链(例如 Android 的
adb),会返回说明性结果,而不是硬性报错。 - 以证据为准,不靠猜测。 断言通过 oracle 梯级返回有证据支持的判定;无法验证时则采用失败关闭策略。
贡献
欢迎贡献,请参阅 CONTRIBUTING.md 和 行为准则。报告错误和提出功能请求时,请使用 issue 模板。
安全
请按照 SECURITY.md 中的说明私下报告漏洞,不要公开提交 issue。
SECURITY.md 还说明了 webview_eval / run_flow 的信任边界,以及对话记录中可能包含个人身份信息(PII)的注意事项。
许可证
MIT © 2026 hoainho
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。