6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Marionette MCPでFlutterアプリの動作確認をAIに任せる

6
Last updated at Posted at 2026-02-20

はじめに

AI駆動開発により、開発はAIエージェントにほとんど任せられるようになってきました。しかし、生成されたコードが実際のアプリ上で正しく動くかどうかは、目視で確認する必要がありました。

Marionette MCPは、この確認作業をAIエージェントに任せるためのMCPツールです。実行中のFlutterアプリに接続し、ボタンのタップやテキスト入力、スクリーンショットの取得までをAIエージェントが自動でしてくれます!

この記事では、Marionette MCPのセットアップからサンプルアプリでの操作まで、一連の流れを紹介します。

Marionette MCPの仕組み

アーキテクチャ

Marionette MCPは、FlutterのVM Serviceを活用してアプリとAIエージェントを接続します。全体の流れは4ステップです。

  1. FlutterアプリがMarionetteBindingを初期化し、VM Serviceにカスタム拡張(ext.flutter.marionette.*)を登録する
  2. MCPサーバーがアプリのVM Service URLに接続する
  3. AIエージェントがMCPサーバーのツール(tapenter_textなど)を呼び出す
  4. MCPサーバーがVM Service経由でアプリにアクションを実行させ、結果を返す

AIエージェントはMCPサーバーを介してアプリを操作するため、アプリ側の変更はMarionetteBindingの初期化のみで済みます。

公式Flutter MCPサーバーとの違い

Flutterには公式のMCPサーバーも存在します。公式MCPサーバーはpub.devのパッケージ検索、依存関係の管理、コード解析といった開発時のタスクに焦点を当てています。実行中のアプリのウィジェットツリーの確認や操作にも対応していますが、開発支援全般をカバーする位置づけです。

Marionette MCPは実行時のUI操作に特化しています。ボタンのタップ、テキスト入力、スクロール、スクリーンショット取得といったユーザー操作の再現を、最小限のコード変更で実現します!

提供するツール

Marionette MCPは以下のツールをAIエージェントに提供します。

ツール 機能
connect VM Service URIを指定してアプリに接続する
disconnect 接続を切断する
get_interactive_elements 画面上の操作可能な要素を一覧取得する
tap キーまたはテキストで要素を指定してタップする
enter_text テキストフィールドに文字列を入力する
scroll_to 指定した要素が表示されるまでスクロールする
get_logs アプリケーションログを取得する
take_screenshots 画面のスクリーンショットを撮影する
hot_reload コード変更後にホットリロードを実行する

セットアップ手順

詳しい手順は公式のQuick Startも参照してください。

1. MCPサーバーのインストール

marionette_mcpをグローバルツールとしてインストールします。

dart pub global activate marionette_mcp

2. Flutterパッケージの追加

アプリのプロジェクトにmarionette_flutterを追加します。

flutter pub add marionette_flutter

3. MarionetteBindingの初期化

main.dartMarionetteBinding.ensureInitialized()を呼び出します。デバッグモードでのみ初期化するため、リリースビルドには影響しません。

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:marionette_flutter/marionette_flutter.dart';

void main() {
  if (kDebugMode) {
    MarionetteBinding.ensureInitialized();
  } else {
    WidgetsFlutterBinding.ensureInitialized();
  }

  runApp(const MyApp());
}

4. AIツールへのMCPサーバー登録

使用するAIツールにMarionette MCPサーバーを登録します。

Claude Code

claude mcp add --transport stdio marionette -- marionette_mcp
Cursor

プロジェクトの.cursor/mcp.jsonまたはグローバルの~/.cursor/mcp.jsonに以下を追加します。

{
  "mcpServers": {
    "marionette": {
      "command": "marionette_mcp",
      "args": []
    }
  }
}
Copilot(VS Code)

mcp.jsonに以下を追加します。

{
  "servers": {
    "marionette": {
      "command": "marionette_mcp",
      "args": []
    }
  }
}
Gemini CLI

~/.gemini/settings.jsonに以下を追加します。

{
  "mcpServers": {
    "marionette": {
      "command": "marionette_mcp",
      "args": []
    }
  }
}
Google Antigravity

MCP storeを開き、「Manage MCP Servers」→「View raw config」からmcp_config.jsonに以下を追加します。

{
  "mcpServers": {
    "marionette": {
      "command": "marionette_mcp",
      "args": []
    }
  }
}

5. アプリの起動と接続

Flutterアプリをデバッグモードで起動します。

flutter run

コンソールに出力されるVM Service URIをコピーし、AIエージェントに接続を依頼します。URIはws://127.0.0.1:XXXXX/YYYYY=/wsのような形式です。

サンプルアプリで試す

loggingパッケージの設定

Marionette MCPのget_logsツールは、Dartのloggingで出力されたログを取得します。アプリ側で以下の設定が必要です。

flutter pub add logging
import 'package:logging/logging.dart';

final _logger = Logger('MyApp');

void main() {
  Logger.root.level = Level.ALL;
  // ...
}

Logger.root.level = Level.ALLを設定することで、すべてのログレベル(INFO、WARNING、SEVEREなど)がMarionette MCP経由で取得可能になります。あとはアプリ内の任意の箇所で_logger.info()_logger.severe()を呼び出すだけです。

ValueKeyの付与

Marionette MCPがUI要素を特定するには、ウィジェットにValueKeyを設定する必要があります。キーが設定されていない要素はテキストやウィジェットの型で検索できますが、キーによる指定が最も確実です。

FilledButton(
  key: const ValueKey('submit_button'),
  onPressed: _submit,
  child: const Text('送信'),
),

キーの命名は、要素の役割がわかる名前を付けます。button_1のような連番より、submit_buttonclear_buttonのように意味を持たせた方が、AIエージェントが文脈を把握しやすくなります。

操作の実例

サンプルアプリを生成してみました。

サンプルアプリのフォーム画面(初期状態)

テスト内容

  • 名前とメールアドレスを入力する
  • 送信ボタンをタップする
  • 送信結果が正しく表示されることを確認する
  • ログを取得し、エラーや警告が出ていないことを確認する

AIエージェントへの指示

ws://127.0.0.1:XXXXX/YYYYY=/ws に接続し、以下の操作を実施してください。

- name_fieldに「山田太郎」を入力
- email_fieldに「taro@example.com」を入力
- submit_buttonをタップして送信
- 送信結果が表示されることを確認
- ログを取得し、エラーや警告が出ていないことを確認

各操作後にスクリーンショットを取得してください。

結果

手動で実施していたフォームの入力確認を、自然言語の指示だけで実施できました。各画面のスクリーンショットもエビデンスとして取得でき、送信結果が正しく表示されていることも確認できています。

入力後

ボタン押下後

正常系

さらに、送信処理に擬似的なエラーを仕込んだところ、AIエージェントは画面上の「送信に失敗しました」というメッセージだけでなく、get_logsで取得したアプリケーションログからもSEVEREレベルのエラーを検出し、問題を報告してくれました。UIの見た目だけでは気づきにくい内部エラーも、ログ取得まで含めて確認できるのは大きな利点です。

エラーログ

カスタムウィジェットへの対応

独自のデザインシステムを使用しているプロジェクトでは、標準のFlutterウィジェット以外の独自ウィジェットをMarionette MCPに認識させる設定が必要です。MarionetteConfigurationisInteractiveWidgetextractTextで対応します。

MarionetteBinding.ensureInitialized(
  MarionetteConfiguration(
    isInteractiveWidget: (type) =>
      type == MyPrimaryButton ||
      type == MyTextField ||
      type == MyCheckbox,
    extractText: (widget) {
      if (widget is MyText) return widget.data;
      if (widget is MyTextField) return widget.controller?.text;
      return null;
    },
  ),
);

isInteractiveWidgetは、get_interactive_elementsでカスタムウィジェットを検出対象に含めます。extractTextは、tap(text: "ラベル")のようにテキスト指定で要素を検索する際に、カスタムウィジェットからテキストを抽出します。

まとめ

AI駆動開発では、開発者が毎ステップでAIの出力を確認・判定する必要があり、そこに時間が取られてしまいます。Marionette MCPは、AIエージェントに自分で動かして確認する能力を与えます。スキルで実装→動作確認→修正のループをAIが自律的に回せるようになれば、開発者は最終レビューをするだけになります。

まだプロダクションレベルの運用には至っていませんが、動作確認まで含めて任せられる環境は、今後の開発体制を大きく変えてくれそうです。引き続き活用しながら、最適な使い方を探っていきたいと思います!

お知らせ (採用情報)

AppTime では一緒に働くメンバーを募集しております。
詳しくは採用情報ページをご確認ください。

みなさまからのご応募をお待ちしております!

参考リンク

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?