最近、Maestro CLIとMaestro MCPというものを見かけて気になっていました。
ネイティブアプリのE2Eテストを自然言語で書ける、という話を聞いて、実際に手元のサンプルアプリで触ってみることにしました。
普段からネイティブアプリの動作確認は手動でポチポチやることが多く、テストコードを書くのも地味に腰が重い作業だと感じていたので、試してみます。iOS・Androidの両方で試したかったので、その辺りも含めてざっくり確かめてみます。
Maestro
Maestroは、モバイルアプリやWebのUIテストをYAMLで書けるオープンソースのE2Eテストフレームワークです。人間がそのまま読めるYAMLでフローを書けて、waitFor のような待機処理を細かく書かなくても、要素が表示されるまでMaestroが勝手に待ってくれます(参考: What is Maestro?)。
まずは手でYAMLを書いてみたら、大変だった
最初はMCPを使わず、とりあえず手でYAMLを書いてMaestroを動かしてみました。ここで大変だったのが、要素の指定方法です。テキストで指定するか、DOMのIDで指定するか、座標で妥協するか。画面とコードを見比べて決めるしかなくて、この試行錯誤に想像以上に時間がかかりました。
「これは手で頑張るものじゃないな」と思い、Maestro MCPを試してみることにしました。テストシナリオを自然言語で伝えるだけで、AIが自動でYAMLを組み立ててくれるというので、試してみます。
Maestro MCP
Maestro MCPは、MCP(Model Context Protocol)経由でAIに操作させる仕組みです。デバイスの選定、画面のビュー階層の確認、フローの実行といった作業を、AIとの対話の中で進められます。公開されているツールは以下のようなものがあります。
| ツール | できること |
|---|---|
list_devices |
ローカルのデバイス(Androidエミュレーター、iOSシミュレーター、Chromium)を一覧表示する |
inspect_screen |
今の画面のビュー階層を圧縮したJSONで取得する |
take_screenshot |
デバイス画面のスクリーンショットを撮る |
run |
Maestroのフローを実行する(YAML直接指定、ファイル指定、ディレクトリ指定に対応) |
cheat_sheet |
Maestroのコマンドやフロー構文、ベストプラクティスをまとめたチートシートを返す |
open_maestro_viewer |
実行中のViewerのURLを返す |
Claude Codeに追加する手順
Maestro MCPをClaude Codeから呼べるようにするまでにやることは2つだけです。
まずMaestro CLI本体を入れます。ここが入っていないとMCPサーバーも起動しないので、先にこちらから。
curl -Ls "https://get.maestro.mobile.dev" | bash
maestro --version
maestro --version でバージョンが出ればOKです。パスが通らない場合はシェルを開き直すか、~/.maestro/bin をPATHに追加してください。
次にClaude Codeへ登録します。Maestro CLIには maestro mcp というサブコマンドがあるので、それをそのままMCPサーバーとして登録するだけです。
claude mcp add maestro -- maestro mcp
登録できたか確認します。
claude mcp list
Claude Codeを起動中の場合は、一度再起動してから /mcp を叩くとサーバーの接続状態と公開ツールが見られます。ここに maestro があれば準備完了です。
なお、私の環境では以下のような設定になっています。
{
"mcpServers": {
"maestro": {
"type": "stdio",
"command": "maestro",
"args": ["mcp"],
"env": {
"MAESTRO_CLI_NO_ANALYTICS": "true"
}
}
}
}
MAESTRO_CLI_NO_ANALYTICS はMaestro CLIの利用統計送信を止めるための環境変数です。
詳しい仕様は公式ドキュメント(docs.maestro.dev)にまとまっています。
サンプルアプリで試してみる
Claude Codeを起動して open_maestro_viewer を実行すると、ローカルのMaestro ViewerのURLが返ってきました。デバイスの画面と実行中のフローのコマンドをリアルタイムで表示してくれるので、ブラウザで開いておくと裏でどんな操作が進んでいるのか目で確認できます。この結果をもとにテストケースを組み立てます。
❯ open_maestro_viewer
Called maestro
Maestro Viewer is running at http://127.0.0.1:9999/ — open it in your browser to see live device state, flow commands, and tool activity.
例えば、サンプルアプリのお店登録フローで、こんな感じで依頼してみます。
「お店を登録して、一覧と詳細画面に表示されることを確認するテストを書いて」
list_devices でシミュレーターを選び、inspect_screen で画面のボタンやフォームのラベルを確認しながらYAMLを組み立ててくれました。
実際に出来上がったフローはこんな動きになります。
(この記事の画面キャプチャは maestro record --local で録画したものです)
Maestro MCPが以下のようなコマンドを自動で実行して画面要素を選択していました。
❯ list_devices
Called maestro
Found one connected device: iPhone 17 Pro - iOS 26.3 (9764F166-F326-411E-9E2A-0627C8BB32CA). Maestro Viewer is available at http://127.0.0.1:9999/ if you'd like to watch flows run visually.
What would you like to do next — inspect the current screen, or run a specific Maestro flow?
✻ Sautéed for 7s
❯ inspect_screen
Called maestro
The app is showing the "お店メモ" (Shop Memo) home screen with an empty state — "まだお店が登録されていません" (no shops registered yet), and there's a button near the bottom-right (likely an "add" FAB at [330,768][386,824]).
{
"screen": "ホーム画面",
"appId": "com.example.shopmemo",
"device": "iPhone 17 Pro - iOS 26.3",
"elements": [
{
"role": "app_root",
"a11y": "shop_memo",
"bounds": "[0,0][402,874]"
},
{
"role": "app_bar_title",
"a11y": "お店メモ",
"bounds": "[157,76][245,104]"
},
{
"role": "app_bar_action",
"note": "設定ボタンと思われる(ラベルなし)",
"bounds": "[354,66][402,114]"
},
{
"role": "empty_state_text",
"a11y": "まだお店が登録されていません",
"bounds": "[101,486][300,506]"
},
{
"role": "fab",
"note": "追加ボタンと思われる(ラベルなし)",
"bounds": "[330,768][386,824]"
}
],
"status_bar": {
"time": "15:59",
"cellular": "信号がありません",
"wifi": "SSID, Wi-Fi 3本中3本",
"battery": "100%(充電停止中)"
}
}
✻ Worked for 11s
このログを見ると分かるように、画面のどこに何があるかはAIが inspect_screen で勝手に調べてくれます。手書きのときに一番時間を食っていた「コードと画面を見比べて要素の指定方法を悩む」工程が、まるごとなくなりました。あとは open_maestro_viewer で実行の様子を眺めながら、AIと対話的に修正していきます。
触ってみて詰まったところ
いい感じに進んだ一方で、うまくいかない部分もありました。
生成されたYAMLで、要素が座標指定になってしまうケースがありました。
- tapOn:
point: "88%,18%"
label: "一覧行の削除アイコンをタップ"
これは店舗一覧の削除アイコンのように、テキストもラベルも付いていない無地の要素で起きていました。座標指定は画面レイアウトの変更に弱いので、テストが壊れやすくなりそうです。試しに、この要素にアクセシビリティ(a11y)の指定を追加してみたところ、ちゃんとラベルで拾えるようになりました。
テストのために触った部分が、そのままスクリーンリーダー対応にも繋がりそうというのは、やる前は全然想定していなかった発見でした。実際のプロジェクトで本格的にやるなら、こういう見直しも合わせて必要になりそうです。
修正後に実行した削除フローはこんな動きになります。
全部自動化するのは、たぶん無理だなと思った
iOSはシミュレーターのみでMaestroが動作し、実機には対応していません(Androidは実機でも動作します)。これはMaestro MCP固有の制約ではなく、Maestro自体がまだXcodeシミュレーターしかサポートしていないからです。
実際のプロジェクトに導入する場合はBluetoothやカメラなど実機特有の機能は自動化の対象から外して、手動テストとして残す判断が必要になりそうです。自動化できる部分だけMaestroのテストケースとして整備するなど棲み分けが現実的なんだろうなと感じました。
実機での挙動まで検証したいプロジェクトの人は、最初にこの制約を把握しておいた方がいいと思います。
触ってみた感触としては
セレクターを書く作業や、テストコードを書く作業が地味につらいと感じているなら、Maestro MCPは一度試してみる価値があると思います。特にAndroidエミュレーターやシミュレーターでの検証が中心なら、けっこう楽になる印象でした。
一方で、iOS実機での検証が必須なケースには、まだ課題が残りそうです。
おわりに
今回はあくまで個人的な検証で、サンプルアプリを触っただけなので、実プロジェクトに入れたときにどこまでうまくいくかはまだわかりません。それでも、AIエージェントが list_devices でデバイスを特定し、inspect_screen で画面のビューヒエラルキーをその場で取得し、そこから適切なセレクタを選んでフローを組み立てる、という流れは体感としてかなり快適だなと感じました。
今回は軽く触ってみただけですが、次はもう少し複雑なアプリで試したり、実際のプロジェクトに導入できそうか検討してみたいなと思っています。
セレクターの手書きに疲れている人は、一度触ってみるだけでも発見があるかもしれません。


