podium-mcp について
podium-mcpは、モバイルのE2Eテストとデバッグ向けのMCPサーバーです。iOSシミュレーターや実機、Androidを単一のstdioエンドポイントで扱い、ネイティブUI自動化、WebViewとReact Nativeの調査、画像認識なしのCanvas/WebGL操作を統合します。
主な機能
- 01iOSとAndroidのデバイス・アプリ制御
- 02ネイティブUIの検査と自動化フロー実行
- 03証拠に基づく結果による操作検証
- 04WebView DOMとネットワーク通信の調査
- 05React NativeとMetroのデバッグ
- 06画像認識なしでのCanvas/WebGL操作
活用シーン
- 01モバイルデバイスでE2Eフローを実行
- 02不具合を再現してログとクラッシュレポートを収集
- 03WebViewのページとリクエストを調査
- 04CanvasまたはWebGLの画面を自動化
MCP 対応
51個のツールを備えた単一のMCP stdioエンドポイントを提供し、クライアントからのデバイス制御、テスト実行、アプリ調査に対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
51掲載時のツール一覧 · 2 週間前に更新
このツールにパラメーターはありません。
詳細
podium-mcp
1本のバトンで、あらゆる楽器を。
iOS(シミュレーター+実機)と Android のデバイス制御、ネイティブ UI オートメーション、エンドツーエンドのフロー、信頼性の高いアサーション、React Native のデバッグ、WebView DOM とネットワークの検査、Pixi/Konva/Fabric/Phaser/Three/Babylon 向けのビジョン不要のキャンバス/WebGL ブレイン(WebKit でライブ検証済み)を備えた、51 個のツールを提供する単一の MCP stdio エンドポイントです。さらに、計測を組み込んだ Unity/GL ビルド(AltTester)用の実験的なエンジンブリッジも備えており、複数のサーバーを使い分けることなく、1 つの接続で利用できます。
1つのプロンプト → podium が Safari をライブ操作 → URL を入力 → プロフィールを確認 → リポジトリを開く。iPhone 16 Pro の稼働中のシミュレーターで撮影。
podium(指揮台)は、指揮者がオーケストラ全体を指揮するために立つ場所です。この MCP サーバーは、8 種類の機能を単一の stdio エンドポイントに統合します。
- デバイスとアプリの管理 — iOS シミュレーター(
simctl)、実機の iPhone(devicectl)、Android(adb)を、プラットフォームタグ付きの単一のデバイスモデルで扱います。 - ネイティブ UI の検査とジェスチャー —
idb/mobilecliを介して操作し、必要に応じて Maestro にフォールバックします(ジェスチャーごとに JVM を起動する必要はありません)。 - エンドツーエンドのフローとバッチオートメーション — 宣言型の Maestro フロー、順序付きアクションバッチ、エンジニアから QA へのフローエクスポーターを提供します。
- 信頼性の高いアサーション — オラクルラダー(WebView-DOM › ネイティブ a11y › Maestro)を使用し、反証可能で証拠に基づく判定を返します。判定できない場合は安全側に倒して失敗します。
- WebView DOM とネットワーク —
WKWebViewの DOM をタップ座標に対応付け、JS を評価し、ナビゲーションを操作して、ページ内の HTTP 通信を JSON/HAR としてキャプチャします。 - React Native のデバッグ — CDP を介して Metro のコンソールログ、ネットワークリクエスト、アプリ内状態を取得し、ホストとシミュレーターのクラッシュレポートも確認できます。
- 実機 —
adbを介した Android エミュレーター/デバイス(ジェスチャー+uiautomatorの階層構造)、devicectlによる実機 iOS のライフサイクル管理、およびオプトインの WebDriverAgent バックエンドに対応しています。 - ビジョン不要のキャンバスとゲームエンジンのオートメーション — キャンバス/WebGL ブレインにより、Pixi/Konva/Fabric/Phaser/Three/Babylon の UI をアドレス指定可能なオブジェクトとして操作します(WebKit でライブ検証済み)。実験的なエンジンブリッジでは、AltTester を組み込んだビルド、または
window.__podiumEngineWebGL ブリッジを介して Unity/GL を操作できます。コード実装済みでモックテストも完了していますが、稼働中の Unity ビルドではまだ実行されていません。 複数の MCP サーバーを各クライアントの設定に組み込む代わりに、podium-mcpはすべての機能を 1 つの接続の背後で提供します。共通のexecFileレイヤー(シェル不使用)、一貫した構造化エラー、Maestro の iOS ドライバーで発生する不安定さに対する自動リトライ、そしてホスト上で利用可能な機能を確認する単一のヘルスチェックツールを備えています。
目次
- 理由
- ベンチマーク
- 要件
- インストール
- 使い方
- クイックスタート
- 51 個のツール
- オラクルの段階 — 信頼できるアサーション
- ネイティブ優先のジェスチャーバックエンド
- WebView と RN のネットワークイントロスペクション
- 仕様上の制限事項
- アーキテクチャ
- 開発とテスト
- ロードマップと貢献
- リリース
- プロンプトの実践ガイドと参考資料
- 設計アイデア
- 貢献 · セキュリティ · ライセンス
理由
React Native アプリをエンドツーエンドで操作するには、通常、複数の MCP サーバーを使い分ける必要があります。デバイスやアプリの制御用、UI フロー用、Metro/デバッガーログ用、WebView の検査用などがあり、それぞれに独自の設定項目、癖、障害モードがあります。podium-mcp はこれらを、次の機能を備えた 1 つのサーバーに統合します。
execFileベースの単一のコマンドランナー(シェル不使用 — 引数はそのまま渡されます)、- 一貫した構造化エラー(ツールがサーバーをクラッシュさせることはありません)、
- Maestro で既知の iOS ドライバーの不安定さに対する自動リトライ、
- ツールチェーン(例:
adb)がない場合の適切な縮退動作、 - エージェントがフローの 実際の成功 を把握できる 証拠付き判定。
ベンチマーク
Podium は 高速かつ低コストを実現する 2 つの選択に基づいて構築されています。UI をスクリーンショットではなく 構造化データ として操作し、ジェスチャーをアクションごとの JVM 起動が不要な ネイティブバックエンド 経由で処理します。
トークン効率 — ビジョン不使用なら約 5 倍低コスト
スクリーンショット駆動型のエージェントは、すべてのステップで画像をビジョンモデルに送信します。 一方、Podium はコンパクトな構造化要素リストを返します。同等の 8 ステップのモバイルフロー(1179×2556 のスクリーンショットと約 20 要素のリストを比較)では、次のとおりです。
| アプローチ | 1 ステップあたり | 8 ステップのフロー |
|---|---|---|
| スクリーンショット/ビジョンのループ | 約 2,070 トークン | 16,557 トークン |
| Podium — ビジョン不使用、構造化データ | 約 390 トークン | 3,117 トークン |
| 削減量 | 5.3 倍 | −13,440 トークン(−81%) |
vision loop ████████████████████████████████ 16,557 tokens
Podium ██████ 3,117 tokens (5.3× cheaper, −81%)
この差はステップを重ねるごとに拡大します。30 ステップのセッションでは、入力トークン数が約 62k 対 12k になります。ステップごとのコストに加え、完全な 51 個のツールスキーマが各リクエストに含まれます(約 3,612 トークン、ツールあたり約 71 トークン)。Podium はツールの説明を簡潔に保つため、ツールブロックがコンテキストウィンドウを圧迫することはありません。
Canvas/WebGL の UI では、その利点は単に低コストというだけでなく、構造上の利点でもあります。Canvas Brain はオブジェクトを名前やテキストで指定しますが、スクリーンショットだけを使うエージェントはフレームごとにピクセルを再解析する必要があります。
速度 — ネイティブ優先のジェスチャーバックエンド
ジェスチャーは、アクションごとに Maestro の JVM を起動する代わりに、idb/mobilecli 経由で処理されます(実機の iPhone 16 Pro シミュレーターで計測)。
| 操作 | Maestro(呼び出しごとに JVM を起動) | Podium ネイティブ | 高速化 |
|---|---|---|---|
tap_on | 約 14.7 秒 | 約 0.6 秒 | 約 24 倍 |
inspect_screen | 約 8.9 秒 | 約 0.9 秒 | 約 10 倍 |
1 つの接続で、6 つではありません
51 個のツールすべて(デバイスとアプリの制御、UI 自動化、宣言型 Maestro フロー、証拠に基づくアサーション、WebView の DOM とネットワークのキャプチャ、React Native / Metro のデバッグ、ビジョン不要の Canvas/WebGL 自動化(および計測済み Unity/GL 向けの実験的なエンジンブリッジ))は、単一の stdio エンドポイントの背後にあり、通常必要となる半ダースもの個別の MCP サーバーを置き換えます。
トークン数はヒューリスティックな推定値です(約 4 文字/トークン、Anthropic の画像向け約 750 px/トークンの計算式)。
npm run token-benchで再現するか、正確な数を得るには Anthropic のcount_tokensAPI に切り替えてください。速度は、稼働中の iPhone 16 Pro シミュレーターで測定しました(npm run benchmark)。
必要条件
- Xcode コマンドラインツール(
xcrun、simctl)を備えた macOS - Node.js ≥ 22(ネイティブの
fetchとWebSocketを使用します。.npmrcでengine-strict=trueを設定しています) mobilecli— npm 依存関係として自動的に同梱されます。デフォルトのネイティブジェスチャー + WebView バックエンドです(別途インストールする必要はありません)- (任意)
idb(idb+idb_companion)— 両方が存在する場合に優先されるネイティブジェスチャーバックエンドです。自動検出されます - (任意) Maestro を
PATH上(または~/.maestro/bin)に用意してください —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 ツール)を自動起動し、5 つのスキルを同梱しています。
| スキル | 呼び出し | 機能 |
|---|---|---|
| デバイス情報 | /podium-mcp:device-info <UDID> [<BUNDLE_ID>] | ヘルスチェック、画面サイズ、向き、アプリ一覧 |
| E2E フロー | /podium-mcp:e2e <UDID> <BUNDLE_ID> [path or description] | Maestro フローを実行または作成 |
| バグ再現 | /podium-mcp:bug-repro <UDID> <BUNDLE_ID> <description> | 動画 + ログ + クラッシュの証拠をキャプチャ |
| RN デバッグ | /podium-mcp:rn-debug [UDID] [logs|apps|crash|all] | Metro ログ、接続中のアプリ、クラッシュレポート |
| Canvas の分析 | /podium-mcp:canvas <UDID> <intent> | ビジョンを使わずに Canvas-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"]
}
}
}
raw 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 brain が検証済みの経路です。
Canvas brain — Pixi/Konva/Fabric/Phaser/Three/Babylon、ビジョン不使用(3)
| ツール | 主なパラメーター | 使用エンジン | 動作 |
|---|---|---|---|
canvas_inspect | udid, by?, value?, webviewId? | 注入されたシーングラフブリッジ(CDP eval) | タップに使える CSS ピクセル座標とともに Canvas オブジェクトを一覧表示します — スクリーンショットは使用しません |
canvas_resolve | udid, intent, webviewId? | ブリッジ + セマンティックリゾルバー | 曖昧なインテント(「閉じる」、「✕」)を、順位付けされた根拠のあるターゲットに対応付けます。confidentEnough を満たさない場合は安全側に失敗します |
canvas_tap | udid, intent, bundleId?, webviewId? | リゾルバー + ネイティブタップ | 確信度の高い一致候補を絶対画面座標で解決してタップします(一致しない場合は安全側に失敗します) |
実機で検証済み: 6 つすべてのフレームワークが、DPR 1 および 3 の Playwright-WebKit(≈ WKWebView)テストスイートに合格しています(19 テスト、
npm run test:canvas)。Canvas ツールには、サポート対象のフレームワークをホストし、そのルートにアクセスできるインスペクト可能な WKWebView が必要です(一般的にはwindow上、Pixi では__PIXI_APP__上にあります)。フレームワークがない場合、またはインスペクト可能な WebView がない場合は、実行可能な対処方法を示すエラーを返して安全側に失敗し、ビジョンにはフォールバックしません。
診断(1)
| ツール | 主なパラメーター | 使用エンジン | 動作 |
|---|---|---|---|
podium_token_report | steps?, screenshotWidth?, screenshotHeight?, elementsPerStep?, toolCount? | トークン推定器 | ビジョンを使わない場合と、スクリーンショット/ビジョンループの場合の入力トークン数、削減率、およびリクエストごとのツール定義のオーバーヘッドを報告します |
ヘルスチェックとツールチェーン(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 秒待機します。 |
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 秒のタイムアウトを設定します(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 ごとに 1 つです。 |
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 フォールバック | back/power/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) | 1 回の呼び出しで順序どおりにアクションをまとめて実行し、ステップごとの結果を返します。 |
run_flow | udid + yaml/files/dir(+tags) のいずれか 1 つ, env? | maestro test | 実行前にいずれか 1 つだけが指定されていることを検証し、ステップごとの成功/失敗を返します。 |
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, フロー + アサーション | オラクルラダー + フローの実行 | 作成したばかりのフローが機能するかについて、信頼でき、反証可能な判定を返します |
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 シム + 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 ストア) |
クラッシュ診断(2)
| ツール | 主なパラメーター | 使用エンジン | 動作 |
|---|---|---|---|
crash_list | processName?, sinceHours?, udid? | ホスト + シミュレーターの DiagnosticReports | 新しい順に表示し、source: host | simulator のタグを付けます |
crash_get | id, udid? | 同上 | パストラバーサルを防止し(ベース名のみ)、正確に切り詰めます |
オラクルラダー — 信頼できるアサーション
「動作する」を、単に「問題なさそう」ではなく、反証可能で根拠のある判定として定義します。アサーションと validate_flow は、利用可能な最も強いシグナルを使い、3段階のラダーで表示状態を判定します。
- WebView DOM — 検査可能な
WKWebViewがある場合は、実際の DOM を照会します。 - ネイティブのアクセシビリティ — ネイティブ AX 要素セット(
idb/mobilecli経由)。 - Maestro — フォールバックとして
assertVisible/assertNotVisibleを使用します。
assert_not_visible はフェイルクローズです。不在を確実に検証できない場合(例:WebView を読み取れない場合)、誤って合格とするのではなく失敗を報告します。各判定では、それを導いたオラクルを明示するため、エージェントはその信頼度を考慮できます。
ネイティブ優先のジェスチャーバックエンド
命令型ジェスチャー(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 が報告されます。Maestro を強制するには PODIUM_DISABLE_NATIVE=1 を設定してください。ジェスチャーごとの 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 秒/5 秒のバックオフを挟んで最大 2 回リトライし、retries の回数を報告します。エラーが解消しない場合は、対処方法のヒントを添えて未加工の出力を返します。
WebView と RN のネットワーク調査
ネットワーク層は 2 種類あり、それぞれに対応するツールがあります。
metro_networkは CDP Network ドメインを介して RN/Hermes ターゲット上のリクエストを取得します。ネイティブ RN アプリ自身のfetchを調べる場合に適したツールです。webview_networkはWKWebView内部の通信を取得します。fetch/XHRレコーダーを挿入して、取得開始後の呼び出しについてメソッド/ステータス/ヘッダー/本文を詳細に記録し、さらにブラウザーの Performance Resource Timing バッファー(includeResources。デフォルトで有効)を読み取ります。これにより、取得開始前のリクエストも含め、ナビゲーション以降のすべてのリクエスト(URL/タイミング/サイズ)を取得します。統合した結果は、機密情報をマスキングした JSON または HAR 1.2 として出力されます。
UI を WebView で表示する RN シェルアプリでは、アプリの API 呼び出しは Web レイヤー内で実行されます。そのため metro_network では何も検出されず、webview_network が適切なツールです。WebView ツールを使用するには WKWebView.isInspectable = true が必要です(デバッグ/ステージングビルドではデフォルトで有効、本番環境では無効)。対象が見つからない場合は、対処方法がわかるエラーを返します。
仕様上の制限(バグではありません)
- Canvas/WebGL には対応する JS フレームワークが必要です — アプリがシーングラフのルートを公開している場合(実機で検証済み)、Canvas の仕組みはセレクターを使って Pixi/Konva/Fabric/Phaser/Three/Babylon の UI を自動操作します。標準の Canvas/カスタム WebGL Canvas、内部構造が見えないビルド/本番ビルド、または AltTester/
window.__podiumEngineブリッジのない Unity はセレクターで指定できません。その場合は、スクリーンショットから得た座標を使うtap_with_fallbackを使用するか、ビルドに計測機能を追加してください。 - WebView ツールは開発/QA 専用です — App Store の本番ビルドでは通常
isInspectable = falseが設定されます。この場合、ツールは対処方法がわかるエラーを返し、座標タップにフォールバックします。 - アプリのサンドボックスから WebView のコンテンツプロセスのメモリを読み取ることはできません(プラットフォーム上の制限)。メモリ警告やプロセス終了などの間接的なシグナルを使用してください。
- Maestro の
text:マッチャーは文字列全体に一致する正規表現です(IGNORE_CASE) — 部分文字列では一致しません。階層のtextをそのままコピーするか、.*を使ってアンカーしてください。 - Android では
PATHにadbが必要です —adbが存在すれば、ジェスチャー/検査/スクリーンショットを実行できます。存在しない場合、Android のすべての処理は構造化された「adb が見つかりません」という結果を返します。 - ネイティブバックエンドがない場合、
orientation_getはスクリーンショットの縦横比を使った推定です — iOS シミュレーターには直接の向き問い合わせ手段がありません。 record_start/record_stopは状態をプロセス内に保持します — 1 つの接続でstart→ … →stopの順に実行してください。udid ごとに有効な録画は 1 つだけです(停止されない録画はウォッチドッグが終了します)。
アーキテクチャ
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 strict、as any/@ts-ignore は使用しない、シェル実行は行わない(すべてのコマンドは lib/exec.ts 経由)、ツールは例外をスローせず、構造化エラーを返します。「新しいツールを追加する」際のチェックリストは CONTRIBUTING.md を参照してください。
CI での E2E: 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 — AltTester/Unity エンジンのパスを計測機能を組み込んだ実際の Unity ビルドで検証する(実際の Unity オートメーションにおける最大のギャップです)。
- #2 — キャンバスブレイン向けの実機 WKWebView e2e(現在は 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 による正確なトークン数を取得する。 - #6 — Konva の Group/Container ターゲットに対応する。
ツールの追加には、CONTRIBUTING.md に記載されたチェックリストに従います。TypeScript strict、シェルを使用しないこと、構造化エラーを返して例外をスローしないこと、vitest テストを追加すること、ツールカタログに行を追加することです。PR を歓迎します。
リリース
server.json は公式の MCP Registry マニフェストです。v* タグをプッシュすると、
Publish to npm に続いて
Publish to MCP Registry が実行されます
(io.github.hoainho/* 名前空間には GitHub OIDC を使用し、長期有効なトークンは不要です)。両方のワークフローでは、最初にゲートとして typecheck → build → test を実行します。Registry への公開は、対応する npm バージョンが公開された後にのみ成功し、バージョンは変更できません。
プロンプトの手引きと参考資料
prompts/— e2e フロー、テストケース、機能検証、バグ修正、デバイス制御用のコピー&ペースト可能なプロンプトです。それぞれ、操作する podium ツールが明記され、実際のシミュレーターで検証済みです。prompts/README.mdから始めてください。docs/tool-catalog.md— ツールごとの正式なリファレンスです。docs/e2e-demo.md— 本番用 RN アプリを実行する、起動済み iPhone 16 Pro シミュレーターとの実際の会話記録です。
設計方針
- 1つの入口、1つの接続。 単一のサーバーがすべてのモバイル機能を提供するため、エージェントは1つのエンドポイントを設定するだけで、51個すべてのツールを一度に検出できます。
- 安全性を設計に組み込みます。 すべての外部コマンドは、明示的な引数配列を使う
execFileレイヤーを介して実行し、シェル文字列は決して使用しません。 - 指揮役を決してクラッシュさせません。 ツールは例外をスローする代わりに、構造化された結果とエラーを返すため、1つの呼び出しの失敗でサーバー全体が停止することはありません。
- 失敗ではなく、機能を縮退させます。 ツールチェーン(Android の
adbなど)が見つからない場合は、致命的なエラーではなく、状況を伝える結果を返します。 - 推測ではなく、検証で証明します。 アサーションはオラクルラダーを通じて証拠に基づく判定を返し、検証できない場合は安全側に倒して失敗します。
貢献
貢献を歓迎します。CONTRIBUTING.md と Code of Conduct をご覧ください。バグや機能リクエストには、Issue テンプレートを使用してください。
セキュリティ
脆弱性は、SECURITY.md に従って非公開で報告してください。公開 Issue は作成しないでください。
SECURITY.md には、webview_eval / run_flow の信頼境界と、トランスクリプトに含まれる PII に関する注意事項も記載されています。
ライセンス
MIT © 2026 hoainho
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。