mirroir-mcp について
mirroir-mcpは、macOSのiPhone Mirroringを通じて実機のiPhoneを操作するMCPサーバーです。アプリの操作自動化やテストを行うエージェントや開発者向けに、画面認識とタッチ操作を提供し、固定座標のスクリプトに依存しません。
主な機能
- 01画面テキストとタップ位置の取得
- 02タップ・スワイプ・文字入力
- 03システム画面とアプリの操作
- 04OCRとオプションのアイコン検出
- 05アプリ探索とスキル生成
活用シーン
- 01iOSアプリのログインフローをテスト
- 02設定画面の操作とスクリーンショット取得
- 03再利用可能なアプリ操作スキルの作成
- 04スモークテストやチュートリアルの実施
MCP 対応
このMCPサーバーは、macOS iPhone Mirroringを介してiPhoneを確認・操作する38個のツールを、対応するMCPクライアントに提供します。stdioトランスポートに対応しています。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
mirroir-mcp
AI に目と手、そして本物の iPhone を与えましょう。macOS の iPhone ミラーリングを通じて、あらゆる AI エージェントが画面を見て、必要な場所をタップし、あとは自分で判断できるようにする MCP サーバーです。macOS のウィンドウにも実験的に対応しています。38 個のツールを、あらゆる MCP クライアントで利用できます。
ビジョン:テストし、プレイするエージェント
mirroir は、ゲーム向けのアーキタイプを認識するカバレッジを拡大しています。ゲームは 2 つのサーフェスに分かれます。シェル(メニュー、ショップ、ロードアウト、設定、勝敗画面)は、今日のスキルで既に操作できる、通常のテキストラベル付き UI です。シーン(プレイフィールド)は、エージェントが一度に 1 回ずつタッチして進める、ビジョン駆動のループです。現実的な目標は、ゲームの QA スモークテスト、チュートリアルのウォークスルー、スクリプト化されたデモであり、リアルタイムプレイではありません。iPhone ミラーリングが公開するポインターは 1 つだけなので、ツインスティック型や反射神経を要するゲームは対象外です(ゲームを参照)。
トークン削減により、シーンループを実用的なコストで利用できます。エージェントのコストの約 90%はスクリーンショットが占めるため、テキスト情報が豊富なシェル画面は画像なしで describe_screen を使って読み取り、スクリーンショットが避けられない場合は、領域/縮尺キャプチャの調整機能でフレームごとの画像コストを抑えます。コストモデルはシンプルです。フレームあたり約 2.7k トークン、毎分約 3 フレームです。
展開は Gaming Surface A–E として追跡しています。まずシェルのカバレッジをリリースし、実機でシーンループを計測してから対象範囲を広げます。
必要条件
- macOS 15+
- iPhone ミラーリングで接続された iPhone
インストール
/bin/bash -c "$(curl -fsSL https://mirroir.dev/get-mirroir.sh)"
または npx を使用:
npx -y mirroir-mcp install
または Homebrew を使用:
brew tap jfarcand/tap && brew install mirroir-mcp
初めてスクリーンショットを撮るとき、macOS から画面収録とアクセシビリティの許可を求められます。両方とも許可してください。
クライアントごとのセットアップ
Claude Code
claude mcp add --transport stdio mirroir -- npx -y mirroir-mcp
GitHub Copilot(VS Code)
MCP サーバーギャラリーからインストールします。拡張機能ビューで @mcp mirroir を検索するか、.vscode/mcp.json に追加してください。
{
"servers": {
"mirroir": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mirroir-mcp"]
}
}
}
Cursor
プロジェクトルートの .cursor/mcp.json に追加してください。
{
"mcpServers": {
"mirroir": {
"command": "npx",
"args": ["-y", "mirroir-mcp"]
}
}
}
OpenAI Codex
codex mcp add mirroir -- npx -y mirroir-mcp
または ~/.codex/config.toml に追加してください。
[mcp_servers.mirroir]
command = "npx"
args = ["-y", "mirroir-mcp"]
ソースからインストール
git clone https://github.com/jfarcand/mirroir-mcp.git
cd mirroir-mcp
./mirroir.sh
.mcp.json では、バイナリのフルパスを使用してください:<repo>/.build/release/mirroir-mcp。
すべての操作は、観察、推論、実行という同じループに沿って進みます。describe_screen は、タップ座標付きのすべてのテキスト要素を AI に渡します(目)。LLM が次の操作を決定します(頭脳)。tap、type_text、swipe が操作を実行し(手)、その後、観察に戻ります。スクリプトも座標も不要で、意図だけで操作できます。
基本機能に加えて、サーバーはより高度なナビゲーションおよびライフサイクルツールも提供します。press_back は「<」のシェブロンを OCR でタップして戻ります(標準位置へのフォールバックあり)。press_home/press_app_switcher/spotlight はシステムジェスチャーを実行します。scroll_to は対象のテキストが表示されるまでスクロールします。reset_app は App Switcher からアプリを強制終了します。set_network は「設定」からネットワーク接続を切り替えます。measure は、対象要素が表示されるまでの操作時間を計測します。複数の対象を設定している場合は、list_targets/switch_target を使ってウィンドウ自動化エンドポイントを切り替えます。スキルの作成には、record_step、save_compiled(コンパイル済みの再生)、calibrate_component(稼働中の画面でコンポーネント定義をテスト)を使用します。38 個すべてのツールについては、ツールリファレンスを参照してください。
アプリについて記述する
mirroir はどの iOS アプリも事前情報なしで探索できますが、何があるかを伝えておくと、より適切に動作します。APP.md ファイルを作成すると、mirroir は探索の開始前にその内容を読み込みます。
---
app: Santé
archetype: dashboard
obstacle_mode: auto
---
## Structure
Dashboard with 4 tabs: Résumé, Partage, Parcourir, Profil.
## Résumé Tab
- Summary cards for health metrics that drill down to charts
- Cards often show "Aucune donnée" on test devices
## Obstacles
- Health Access permission → tap "Autoriser"
- Notification permission → tap "Ne pas autoriser"
## Skip
- Supprimer les données de Santé
- Réinitialiser
現在、コードで実際に使用される内容は次のとおりです。archetype はレシピの自動検出を上書きします。obstacle_mode: auto のとき、obstacles は自動的に閉じられます。skip は permissions.json.skipElements と統合されます。tabs(インラインまたはセクションとして指定)は、優先度の高い対象として注入されます。Structure、タブの本文、Tips は、生成されるスキルで AI のコンテキストになります。
フィールド一覧、ローダーの解決ルール、権限システムとの連携については、APP.md 仕様を参照してください。パターンは 3 つのレベルが連携して機能します。要素(行の見た目)、画面(ページレイアウトの意味)、アプリ(開発者が把握している情報)です。パターンとスキルでは、システム全体について説明しています。
使用例
以下を Claude Code、Claude Desktop、ChatGPT、Cursor、または任意の MCP クライアントに貼り付けてください。
Open Messages, find my conversation with Alice, and send "running 10 min late".
Open Calendar, create a new event called "Dentist" next Tuesday at 2pm.
Open my Expo Go app, tap "LoginDemo", test the login screen with
[email protected] / password123. Screenshot after each step.
Start recording, open Settings, scroll to General > About, stop recording.
ゲーム
iPhone Mirroring を通じて、ゲームでは 3 種類の操作を利用できます。touch は呼び出しをまたいで指を押さえたままにし、仮想ジョイスティックや長押し(begin、move、end)を操作します。hold_keys は、Roblox のようにキーボードとマウスの操作に切り替わるゲーム向けに、右マウスボタンをドラッグしながら w などのキーを押し続けます。pinch と rotate は、ジェスチャー認識 UI で 2 本指のズームと回転を実行します。ミラーリングではアプリに単一ポインターのタッチが渡されるため、タッチ操作のみのゲームは独立した 2 本の指を認識できません。計測結果については、ゲームとマルチタッチを参照してください。
画面認識
describe_screen は AI の目にあたります。3 つのバックエンドが連携し、画面上のテキスト、アイコン、セマンティックな UI 構造をエージェントに伝えます。
Apple Vision OCR(デフォルト)
デフォルトのバックエンドは、Apple の Vision フレームワークを使用して画面上のすべてのテキスト要素を検出し、正確なタップ座標を返します。高速かつローカルで動作し、API キーや外部サービスは不要です。
アイコン検出(YOLO CoreML)
テキストのみの OCR では、ボタン、切り替え、タブバーアイコン、アクティビティリングなど、テキスト以外の UI 要素を検出できません。YOLO CoreML モデル(.mlmodelc)を ~/.mirroir-mcp/models/ に配置すると、サーバーは起動時に自動検出し、アイコン検出結果と OCR テキストを統合します。AI は、テキストのみの OCR では認識できない要素のタップ対象を取得できます。
| モード | ocrBackend の設定 | 動作 |
|---|---|---|
| 自動検出(デフォルト) | "auto" | モデルがインストールされていれば Vision + YOLO を使用し、そうでなければ Vision のみを使用 |
| Vision のみ | "vision" | Apple Vision による OCR テキストのみ |
| YOLO のみ | "yolo" | CoreML による要素検出のみ |
| 両方 | "both" | 常に両方のバックエンドを統合(モデルがない場合は Vision にフォールバック) |
AI ビジョンモード(embacle)
ローカル OCR の代わりに、describe_screen はスクリーンショットを AI ビジョンモデルに送信して、単なるテキストではなく、カード、タブ、ボタン、アイコン、ナビゲーション構造などの UI 要素を意味的に識別できます。これにより、特に複雑なレイアウトの画面で、エージェントにより豊富なコンテキストを提供できます。
embacle ランタイムは、Rust FFI を介して mirroir-mcp バイナリに直接組み込まれています。describe_screen は組み込みランタイムをプロセス内で呼び出すため、別サーバーやネットワークの往復、追加のセットアップは不要です。FFI レイヤー(EmbacleFFI.swift → libembacle.a)が、初期化、チャット完了リクエスト、Swift と Rust の境界を越えたメモリ管理を処理します。
embacle は、すでに認証済みの CLI ツール(GitHub Copilot、Claude Code)を通じてビジョンリクエストをルーティングするため、別途管理する API キーはありません。Copilot または Claude Code のサブスクリプションがあれば、すでに利用できます。
インストール
brew tap dravr-ai/tap
brew trust --tap dravr-ai/tap # recent Homebrew refuses to load untrusted taps
brew install embacle # CLI tools (embacle-server, embacle-mcp)
brew install embacle-ffi # Rust FFI static library (libembacle.a)
どちらも任意です。embacle-ffi がない場合、ビルドは Apple Vision とリンクし、describe_screen はローカル OCR を使用します。
次に、libembacle.a とリンクするように、ソースから mirroir-mcp を再ビルドするか、Homebrew から再インストールします。
# From source
swift build -c release
# Or via Homebrew (rebuilds automatically)
brew reinstall mirroir-mcp
設定不要での有効化
embacle FFI がバイナリにリンクされている場合、screenDescriberMode はデフォルトで "auto" になり、自動的にビジョンモードに解決されます。設定の変更は不要です。embacle-ffi をインストールして再ビルドすれば、describe_screen は AI ビジョンを使用するようになります。
embacle が利用可能な場合でもローカル OCR を強制するには、明示的に "ocr" を設定します。
// .mirroir-mcp/settings.json
{
"screenDescriberMode": "ocr"
}
利用可能な設定については、設定を参照してください。
スキル
同じエージェントのワークフローを繰り返していることに気付いたら、それをスキルとして記録します。スキルは SKILL.md ファイルです。AI が従う番号付きの手順で、レイアウトの変更や予期しないダイアログにも対応します。Tap "Email" のような手順では OCR を使用するため、座標をハードコードする必要はありません。
ファイルは ~/.mirroir-mcp/skills/(グローバル)または <cwd>/.mirroir-mcp/skills/(プロジェクトローカル)に配置します。
APP.md
アプリの構造を記述して探索をガイドします。上記のアプリを説明すると、APP.md の仕様全文を参照してください。APP.md ファイルは ~/.mirroir-mcp/skills/ または mirroir-skills リポジトリの patterns/apps/ に配置します。
---
version: 1
name: Commute ETA Notification
app: Waze, Messages
tags: ["workflow", "cross-app"]
---
## Steps
1. Launch **Waze**
2. Wait for "Où va-t-on ?" to appear
3. Tap "Où va-t-on ?"
4. Wait for "${DESTINATION:-Travail}" to appear
5. Tap "${DESTINATION:-Travail}"
6. Wait for "Y aller" to appear
7. Tap "Y aller"
8. Wait for "min" to appear
9. Remember: Read the commute time and ETA.
10. Press Home
11. Launch **Messages**
12. Tap "New Message"
13. Type "${RECIPIENT}" and select the contact
14. Type "On my way! ETA {eta}"
15. Press **Return**
16. Screenshot: "message_sent"
${VAR} プレースホルダーは環境変数から解決されます。フォールバックには ${VAR:-default} を使用します。
スキルマーケットプレイス
jfarcand/mirroir-skills から、すぐに使えるスキルをインストールできます。
git clone https://github.com/jfarcand/mirroir-skills ~/.mirroir-mcp/skills
探索から CI へ
generate_skill ツールを使用すると、AI エージェントがアプリを探索し、SKILL.md ファイルを作成できます。このツールは幅優先探索(BFS)を使い、アプリをナビゲーショングラフとしてたどります。画面はノード、タップ可能な要素はエッジです。エクスプローラーは各画面を説明し、要素をコンポーネント定義と照合してタップする対象を判断し、子画面を訪問した後、戻るシェブロンから前の画面に戻ります。重複した画面は構造フィンガープリントによってスキップされます。エクスプローラーが生の要素を構造化 UI コンポーネントとしてどのように解釈するかについては、以下のコンポーネント検出を参照してください。
エクスプローラーはビューポート単位で動作します。ページの長さを調整した後、現在のビューポートから計画を作成し、要素を上から順にタップして、スクロールしてさらにコンテンツを表示し、新しいビューポートごとに計画を作り直します。この方法は、OCR と AI ビジョンのどちらの記述方式でも動作します。実行間で順序を決定的にするには、seed を指定します。
探索範囲には上限があり、大規模なアプリで到達可能なすべての画面を検出するわけではありません。実用的な実行を維持するため、深度、画面数、実行時間に制限を設けています。特定のフローを対象にする場合は、goal を指定して探索に焦点を当てます。
graph TD
A["Launch App"] --> B["Describe Screen"]
B --> C{"Calibrated?"}
C -- No --> D["Scroll Full Page"]
D --> E{"skip_calibration?"}
E -- No --> F["Component Detect +\nClassify + Validate"]
E -- Yes --> G["Classify Elements\nDirectly"]
F --> H["Build Plan"]
G --> H
C -- Yes --> H
H --> I{"Untried\nElements?"}
I -- Yes --> J["Tap Element"]
I -- No --> K["Return to Root"]
J --> M["Describe +\nClassify Edge"]
M --> N{"Transition"}
N -- new screen --> O["Add to Frontier"]
O --> P["Backtrack"]
N -- revisited/dead --> P
P -- push: tap back --> H
P -- modal: tap close --> H
P -- tab: tap prev --> H
K --> Q{"Frontier\nEmpty?"}
Q -- No --> R["Next Frontier\nScreen"]
R --> B
Q -- Yes --> S["Generate SKILL.md"]
生成
2 つのモードがあります。自律探索(BFS)とガイド付きセッション(手動でのステップ実行)です。
自律 BFS 探索 — エージェントが自動で探索します。
Explore the Settings app and generate a skill that checks the iOS version.
内部では generate_skill(action: "explore", app_name: "Settings", goal: "check iOS version") を呼び出します。エクスプローラーがアプリを起動し、ルート画面から BFS を実行して、発見した経路の SKILL.md を出力します。
| パラメーター | デフォルト | 説明 |
|---|---|---|
app_name | 必須 | 探索するアプリ |
goal | なし | 特定のフローに向けて探索を絞り込みます(例:「ソフトウェアのバージョンを確認する」) |
goals | なし | 目標の配列。目標ごとに SKILL.md を 1 つ作成します |
max_depth | 6 | BFS の最大深度 |
max_screens | 30 | 訪問する画面の最大数 |
max_time | 300 | 停止するまでの最大秒数 |
strategy | auto | "mobile"(デフォルト)、"social"(Reddit、Instagram、TikTok)、または "desktop"(macOS のウィンドウ) |
explorer | bfs | 探索アルゴリズム:"bfs"(幅優先、デフォルト)または "dfs"(深さ優先) |
skip_calibration | false | キャリブレーション中のコンポーネント検出をスキップします。スクロールは引き続き実行されます。クリーンなセマンティック要素を生成する AI ビジョン記述器と組み合わせる場合に便利です |
seed | random | 探索順序を決定論的にする整数シード。同じシードを指定すると、同一のタップシーケンスが生成されます |
fresh | true | 永続化されたナビゲーショングラフを破棄し、最初から探索します。差分探索する場合は false に設定します |
ガイド付きセッション — AI が手動で操作し、各画面をキャプチャします。
generate_skill(action: "start", app_name: "MyApp")— アプリを起動し、最初の画面を OCR で読み取りますtap/swipe/type_textを使って操作し、generate_skill(action: "capture")で各画面を記録しますgenerate_skill(action: "finish")— キャプチャした画面をまとめて SKILL.md を作成します
テスト
CLI から AI を介さずにスキルを決定論的に実行します。
mirroir test apps/settings/check-about
mirroir test --junit results.xml --verbose # JUnit output
mirroir test --dry-run apps/settings/check-about # validate without executing
| オプション | 説明 |
|---|---|
--junit <path> | JUnit XML レポートを書き込みます |
--report-json <path> | Playwright JSON レポーター形式のドキュメントを書き込みます。mirroir-run が取り込む形式です |
--capture <key> | 各スキルの最終画面の OCR テキストを、cross_surface.<key> の下にある --report-json ドキュメントに添付します |
--screenshot-dir <dir> | 失敗時のスクリーンショットを保存します(デフォルト:./mirroir-test-results/) |
--timeout <seconds> | wait_for のタイムアウト(デフォルト:15) |
--verbose | ステップごとの詳細を表示します |
--dry-run | 実行せずに解析と検証を行います |
--no-compiled | コンパイル済みスキルをスキップし、完全な OCR を強制します |
--no-auto-recompile | ドリフトが発生したコンパイル済みスキルの自動再コンパイルをスキップします |
--agent <name> | 失敗したステップを AI で診断します(AI 支援診断を参照) |
終了コード 0 はすべて成功、1 は 1 つ以上の失敗を表します。すべてのステップがスキップされたスキルは失敗と見なされます。また、パーサーが読み取れないステップ(未知の動詞や不正な target: など)を含むスキルは、--dry-run を含め、実行前に拒否されます。
デフォルトでは、画面のフィンガープリントにドリフトが生じたコンパイル済みスキルを CLI が自動的に再コンパイルします。--no-auto-recompile を指定すると自動再コンパイルが無効になり、古い座標が再利用されます。
コンパイル済みスキル
スキルを一度コンパイルすると、座標とタイミングが記録されます。OCR を使わずに再生できるため、10 ステップのスキルでは OCR に 5 秒以上かかっていた処理が 1 秒未満になります。
mirroir compile apps/settings/check-about # compile
mirroir test apps/settings/check-about # auto-detects .compiled.json
mirroir test --no-compiled check-about # force full OCR
AI エージェントは、最初の MCP 実行の副作用としてスキルを自動コンパイルします。詳しくはコンパイル済みスキルを参照してください。
AI による診断
テスト手順が失敗した場合は、--agent を指定すると、失敗の原因と修正案について AI による診断を受けられます:
mirroir test --agent gpt-5.3 apps/settings/check-about
mirroir test --agent claude-sonnet-4-6 apps/settings/check-about
mirroir test --agent ollama:llama3 apps/settings/check-about
mirroir test --agent embacle apps/settings/check-about
組み込みエージェント:
| エージェント | プロバイダー | API キー |
|---|---|---|
gpt-5.3 | OpenAI | OPENAI_API_KEY |
claude-sonnet-4-6、claude-haiku-4-5 | Anthropic | ANTHROPIC_API_KEY |
ollama:<model> | Ollama(ローカル) | なし |
embacle、embacle:claude | embacle-server | CLI エージェントキー |
カスタムエージェントは、<cwd>/.mirroir-mcp/agents/<name>.yaml(プロジェクト内)または ~/.mirroir-mcp/agents/<name>.yaml(グローバル。プロジェクト内の設定が優先されます)に YAML プロファイルとして定義します。--agent にはファイルの <name> を指定します。
プロファイルは、次の 2 つのモードのいずれかで実行されます。
mode: api — クラウドまたはローカルの HTTP エンドポイントを呼び出します:
# ~/.mirroir-mcp/agents/my-gpt.yaml
mode: api
provider: openai # anthropic | openai | ollama | embacle
model: gpt-5.3
api_key_env: OPENAI_API_KEY
base_url: https://api.openai.com
system_prompt: "You are a terse iOS automation debugger."
max_tokens: 4096
mode: command — ローカルの CLI プロセスを実行します(認証済みの claude -p/copilot -p や、カスタムスクリプトなど)。診断ペイロードは 2 つの方法で渡されます。args のいずれかの項目に ${PAYLOAD} が含まれている場合は、その箇所が JSON ペイロードに置き換えられます。そうでない場合は、コマンドの標準入力にパイプで渡されます:
# ~/.mirroir-mcp/agents/claude-cli.yaml
mode: command
command: claude
args: ["-p", "${PAYLOAD}"]
system_prompt: "Diagnose the failed step and reply with JSON."
| キー | モード | 説明 |
|---|---|---|
mode | 両方 | api(デフォルト)または command |
provider | api | anthropic、openai、ollama、または embacle |
model | api | モデル識別子 |
api_key_env | api | API キーを格納する環境変数 |
base_url | api | エンドポイントのベース URL |
command | command | 起動する実行ファイル(PATH から解決するか、絶対パスを指定) |
args | command | 引数の配列。${PAYLOAD} は JSON ペイロードに置き換えられます |
system_prompt | 両方 | リクエストとともに送信するシステムプロンプト |
max_tokens | 両方 | 応答のトークン上限 |
API キーがありませんか? embacle を使用してください
embacle は、すでに認証済みの CLI ツール(GitHub Copilot、Claude Code など)経由でリクエストをルーティングするため、別途 API キーを用意する必要はありません:
brew tap dravr-ai/tap && brew trust --tap dravr-ai/tap && brew install embacle
mirroir test --agent embacle my-skill
パターンシステム
エクスプローラーは、iOS アプリを理解するために 3 層のパターンシステムを使用します。規模の異なる各層で、同じ宣言型の概念を適用します。
- 要素パターン(
patterns/elements/)— 行レベルの UI コンポーネント(テーブル行、タブバー、トグル、サマリーカードなど)に一致する 34 個の定義です。それぞれに一致ルール、操作動作、グループ化ロジックを指定します。 - 画面パターン(
patterns/screens/)— 要素の構成から画面レベルのナビゲーションモデルを識別する 7 個のアーキタイプレシピです。キャリブレーション中に自動検出するか、APP.md のarchetypeで宣言できます。 - アプリパターン(
patterns/apps/)— 構造、障害要因、スキップリスト、アーキタイプ宣言を含む APP.md ファイルです。開発者が管理する信頼できる情報源です。
組み込みアーキタイプ:settings-list、dashboard、social-feed、content-grid、conversation-list、utility-display、detail-form。
カスタムパターンは、~/.mirroir-mcp/components/(要素)、~/.mirroir-mcp/recipes/(画面)、または mirroir-skills リポジトリに配置します。
ビジョンインジケーター
AI ビジョン記述器は、UI 要素を文字ごと(「Activité」+「>」)ではなく、意味的に(「Activité chevron」)記述します。vision-indicators.md ファイルでは、これらの記述を OCR 互換の文字に対応付けます。これにより、どちらのバックエンドでもコンポーネントパイプラインが同じように機能します:
## Indicators
- chevron: >
- dismiss: ×
- back: <
ビジョン要素が対応付けられた接尾辞(例:「Entraînements chevron」)で終わる場合、正規化器はそれを 2 つの要素「Entraînements」+「>」に分割します。vision-indicators.md はコンポーネント定義と同じ場所に配置してください。
定義形式、照合ルールのリファレンス、検出パイプラインの詳細については、コンポーネント検出を参照してください。
mirroir-run でどこでもリプレイ
mirroir-mcp は iPhone を操作します — AX と OCR を使い、BFS で探索します。mirroir-run は .mirroir/ の SkillStep シナリオを、Web、プロセス、HTTP、iOS の各環境でリプレイします。Web では Playwright を使用し、サブプロセスと HTTP はネイティブに実行します。また、target: { kind: ios } ブロックはそれぞれ、iPhone ミラーリングに接続された Mac 上で mirroir-mcp test に渡します。どちらも同じ SkillStep 文法を使用するため、1 つのシナリオでブラウザーとスマートフォンを操作し、両方に同じ内容が表示されることを確認できます。単一の Rust バイナリです(このリポジトリの runner/)。Web、プロセス、HTTP のシナリオは macOS に依存せず、Linux CI 上で実行できます。2 つのバイナリの連携方法については、1 つのシナリオで Web と iOS を扱うをご覧ください。
任意のリポジトリに .mirroir/ ディレクトリを置くと、mirroir-run は作業ディレクトリからそれを検出します。
your-app/
└── .mirroir/
├── mirroir.yaml # the plan: must-pass / nice-to-pass entries
└── apps/<sample>/
├── SAMPLE.md # how to boot the app under test
├── APP.md # structure, obstacles, skip lists
└── scenarios/*.yaml # SkillStep flows to replay
cd your-app
mirroir-run # discover .mirroir/, replay the must-pass plan
mirroir-run --scenarios all # include nice-to-pass entries too
各プランのエントリーは、local: サンプルツリーを参照するか、インスタンスごとの vars: と boot: を指定して、共有のアーキタイプ(archetypes: ["<pack>/<name>@<ver>"])を拡張します。アーキタイプには、たとえば AI チャットコンソールのような再利用可能なアプリの構成を一度だけ定義し、アプリごとにパラメーターを設定します。
iOS 側の実行経路について。 generate_skill … emit=true(finish または explore 時)は、キャプチャしたフローを .mirroir/apps/<app>/ に、実行可能な iOS 側の実行経路として書き込みます。内容は、target: { kind: ios } シナリオ、それを宣言する SAMPLE.md、および must_pass プランエントリーです。mirroir-run は各 ios ブロックを、iPhone ミラーリングに接続された macOS ホスト上の mirroir-mcp test に渡し、それ以外のホストでは対象名を示して拒否します。ツリーが適切な .mirroir/ に配置されるよう、MCP は利用側のリポジトリで実行するか、output_dir を渡してください。~/.mirroir(ランナーのパックホーム)への書き込みは拒否されます。1 つのシナリオに両方の実行経路を含めることができます。web ブロック、ios ブロック、およびページのスクレイプ結果とスマートフォンの最終画面をその場で記録し、比較する captures: を持つ cross_surface: ステップを含められます。ゲートをチェックする実行で、両方の結果が得られます。詳しくは runner/docs/mirroir-dotfile.md をご覧ください。
Web ステップは Playwright の .spec.ts にコンパイルされ、chromium、firefox、webkit で実行されます。セレクターは 3 通りで解決されます。CSS の直接指定、Playwright エンジンのプレフィックス(role=button[name="Save"]、text=Welcome、xpath=…)、または Playwright 独自の優先順位(ロール、ラベル、プレースホルダー、data-test、表示テキスト)で解決されるラベルの指定です。コンパイルされた各 spec は、捕捉されていないページエラーと失敗したレスポンスも収集するため、ロケーターがすべて解決されても、ページが例外をスローすれば失敗になります。spec、設定、および失敗時のトレース/動画/スクリーンショットは、target/playwright/<sample>/<scenario>/ に保存されます。プロセスと HTTP のステップはネイティブにディスパッチされます。LLM ジャッジステップは、期待されるシグナルに基づいてエージェントの応答を採点し、ドリフト検出はベースラインとの差異を検出します。
| モード | コマンド |
|---|---|
| 文法に対してシナリオを検証する | mirroir-run --validate scenario.yaml |
| Playwright spec をディスクにコンパイルする | mirroir-run --emit playwright scenario.yaml |
| 1 つのシナリオをエンドツーエンドで実行する | mirroir-run --run-scenario scenario.yaml |
| サンプルディレクトリを起動し、そのシナリオを実行する | mirroir-run --sample .mirroir/apps/foo |
iOS ブロックを指定した mirroir-mcp に渡す | MIRROIR_MCP_BIN=/path/to/mirroir-mcp mirroir-run … |
| 単独のテキストドリフトチェック | mirroir-run --diff-text a.txt b.txt |
mirroir-run のインストール
# crates.io
cargo install mirroir-run
# Homebrew
brew install jfarcand/tap/mirroir-run
macOS(Intel + Apple Silicon)、Linux(gnu + musl)、Windows 用のビルド済みバイナリは、各 runner-v* リリースに添付されています。Windows ではサブプロセスの終了シグナルが実装されていないため、プロセスのシナリオはサポートされていません。シナリオ文法、SAMPLE.md スキーマ、ジャッジプロファイル、CI 統合については、runner/docs/ をご覧ください。
セキュリティ
AI にスマートフォンへのアクセスを許可するには、多層防御が必要です。mirroir-mcp はすべてのレイヤーで フェイルクローズ になっています。
- ツールの権限 — 設定ファイルがない場合、公開されるのは読み取り専用ツール 11 個(
screenshot、describe_screen、start_recording、stop_recording、get_orientation、status、check_health、list_targets、list_skills、get_skill、calibrate_component)のみです。press_backを含む、すべての変更を伴うツールは MCP クライアントに対して完全に非表示になるため、クライアントから認識されることはありません。 - アプリのブロック —
permissions.jsonのblockedAppsを設定すると、変更を伴うツールが許可されている場合でも、Wallet や Banking などの機密性の高いアプリを AI が操作できないようにします。 - root 不要 — macOS CGEvent API を使い、通常のユーザープロセスとして実行されます。デーモン、カーネル拡張機能、root 権限は不要で、アクセシビリティ権限だけが必要です。
- 緊急停止スイッチ — iPhone Mirroring を閉じると、すべての入力が即座に停止します。
// ~/.mirroir-mcp/permissions.json
{
"allow": ["tap", "swipe", "type_text", "press_key", "launch_app"],
"deny": [],
"blockedApps": ["Wallet", "Banking"]
}
CLI ツール
レコーダー
操作をスキルファイルとして記録します:
mirroir record -o login-flow.yaml -n "Login Flow" --app "MyApp"
Doctor
セットアップを確認します:
mirroir doctor
mirroir doctor --json # machine-readable output
設定
US 配列以外のキーボード向けに、キーボードレイアウトを設定します:
mirroir configure
更新
# curl installer
/bin/bash -c "$(curl -fsSL https://mirroir.dev/get-mirroir.sh)"
# npx
npx -y mirroir-mcp install
# Homebrew
brew upgrade mirroir-mcp
# From source
git pull && swift build -c release
アンインストール
# Homebrew
brew uninstall mirroir-mcp
# From source
./uninstall-mirroir.sh
設定
すべての設定は settings.json に保存されます。プロジェクトローカル(.mirroir-mcp/settings.json)またはグローバル(~/.mirroir-mcp/settings.json)に配置できます。プロジェクトローカルの設定はグローバル設定より優先されます。各設定には対応する環境変数もあります(例:MIRROIR_SCREEN_DESCRIBER_MODE)。
{
"screenDescriberMode": "auto",
"agent": "embacle",
"ocrBackend": "auto",
"keystrokeDelayUs": 15000,
"explorationMaxScreens": 30
}
画面のインテリジェンス、入力タイミング、スクロール動作、探索予算、AI プロバイダー、キーボードレイアウトを網羅する 40 項目以上の設定については、設定リファレンスを参照してください。
ドキュメント
| ツールリファレンス | 38 個すべてのツール、パラメーター、入力ワークフロー |
| 設定 | すべての設定:画面のインテリジェンス、入力タイミング、探索、AI プロバイダー |
| FAQ | セキュリティ、フォーカスの奪取、キーボードレイアウト、embacle/ビジョンモード |
| セキュリティ | 脅威モデル、緊急停止スイッチ、推奨事項 |
| 権限 | フェイルクローズの権限モデルと設定ファイル |
| 既知の制限事項 | フォーカスの奪取、キーボードレイアウトの不足、自動修正 |
| パターンとスキル | 要素パターン、画面レシピ、アプリの説明を記述する APP.md、検出パイプライン |
| 新しいアプリの探索 | 新しいアプリを導入するための手順書 — APP.md、権限、コンポーネント、探索目標 |
| YOLO アイコン検出 | 推奨される YOLO モデル、CoreML のセットアップ、設定 |
| コンパイル済みスキル | OCR を使わないスキルの再生 |
| テスト | FakeMirroring、統合テスト、CI 戦略 |
| 1 つのシナリオでの Web と iOS | mirroir-run が iOS ブロックを mirroir-mcp に渡す方法と、cross_surface がブラウザーとスマートフォンを比較する方法 |
| クロスサーフェス再生 | mirroir-run のシナリオ文法、.mirroir/ プラン、SAMPLE.md、判定プロファイル、CI |
| トラブルシューティング | デバッグモードとよくある問題 |
| コントリビューション | ツール、コマンド、テストの追加方法 |
| スキルマーケットプレイス | スキル形式、プラグインの検出、作成方法 |
コミュニティ
質問したり、スキルを共有したり、アイデアを話し合ったりするには、Discord サーバーに参加してください。
コントリビューション
コントリビューションを歓迎します。パッチを提出することで、コントリビューターライセンス契約に同意したものとみなされます。Git のコミットメタデータが電子署名として機能します。
制限事項レジストリ
このリポジトリでは、llm-registre を使って誠実さを徹底しています。本番コード内で、対応を先送りする記述(「まだ接続されていません」「今後対応します」「現時点では返します」など)をする場合、制限対象を示し、プロジェクトの非公開レジストリ内の課題を参照する LIMITATION(registre#n): マーカーがその行に付いていなければ、CI で禁止されます。同じチェックでは、500 行のファイル上限とインラインの clippy 許可リストも、プッシュ前と CI で検証します。rg "LIMITATION\(registre#" を実行すると、コードベースが意図的に対応していない項目をすべて確認できます。クローン後、git submodule update --init を実行し、ripgrep をインストールしてください。ワークフローについては、CONTRIBUTING.md を参照してください。
「mirroir」とは? — miroir(鏡)の古いフランス語の綴りです。著者のルーツにちなんだもので、誤字ではありません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。