Flutter Lamp について
Flutter Lamp は、実行中のアプリを調査する Flutter 開発者向けの MCP サーバーです。Dart VM Service Protocol で構造化された実行時データを収集し、根拠に基づく診断とブラウザダッシュボードを提供します。
主な機能
- 01例外、ログ、ネットワークリクエストの収集
- 02フレーム時間、再ビルド、状態変化の分析
- 03ルート、ウィジェットツリー、メモリの確認
- 04根拠に基づく原因と性能の診断
- 05ライブブラウザダッシュボード
活用シーン
- 01実行時の例外と発生前の状況を追跡
- 02ジャンクフレームと再ビルドの集中箇所を特定
- 03障害タイムラインとネットワークリクエストを確認
MCP 対応
MCP クライアントに Flutter の実行時検査・診断ツールを提供します。実行中アプリの Dart VM Service に接続し、セッションデータをブラウザダッシュボードにも表示できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
22掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| uri | string | はい | VM Service URI。例:http://127.0.0.1:52719/abcdef=/ または ws://... |
詳細
💡 Flutter Lamp
実行中の Flutter アプリをAIにリアルタイムで見せられます。ログの貼り付けはもう不要です。
Claude Code、Claude Desktop、Cursor、Codex、Geminiを、実行中のFlutterアプリに Dart VM Service Protocol経由で直接接続するMCP サーバーです。 例外、ログ、ネットワーク呼び出し、フレーム時間、メモリを構造化データとして ストリーミングで取得するほか、証拠を重視した根本原因の診断エンジンと ライブダッシュボードも備えています。
理由
現在、AIを使ってFlutterをデバッグするには、スタックトレースやflutter run
の出力、DevToolsのスクリーンショットをコピーして貼り付ける必要があります。
AIはメッセージのやり取りの合間、何が起きているか把握できません。
Flutter Lampを使えば、AIが実行時の状態を把握できます。公式のFlutter/Dart APIを使って アプリのライブ状態を読み取るため(DevToolsの情報をスクレイピングすることはありません)、 「エラーを貼り付けてください」ではなく、AIがアプリに「たった今、何が起きて、なぜですか?」と 尋ねられるようになります。
❌ You: *pastes 40 lines of red stack trace*
✅ AI: connect_vm → get_exceptions → diagnose_runtime
→ "RenderFlex overflow in Column at home.dart:42, triggered right after
GET /api/user returned 500. Confidence 85%. Fix: …"
機能
- 🔌 実行中の任意のFlutterアプリのVM Serviceに1行で接続
- 💥 スタックトレースを再構成したリアルタイム例外通知(フレームワーク内および未処理の例外)
- 📝 コンソールと構造化ログ(Stdout/Stderr/
dart:developer) - 🌐
dart:ioのプロファイリングによるネットワークキャプチャ。Dioとpackage:httpに対応し、インターセプターは不要です - 🎞️ ジャンク検知、パーセンタイル、ビルドとラスター処理の判定を含むフレーム時間
- 🧭 ルートの把握 — 現在の画面、画面遷移、発生した画面に紐付けられたエラー
- 🧠 状態管理のアクティビティ — Riverpod、Provider、Blocの変動と再ビルドの集中発生を関連付け
- 🔁 ウィジェットの再ビルドの特定 — 再ビルドされたウィジェット、その頻度、ファイルと行番号を示し、パッケージのコードと分けてアプリのコードを上位に表示
- 🧬 Inspectorから取得するウィジェットツリーと選択中のウィジェットのスナップショット
- 🧮 メモリ(Dartヒープ/外部)とVMタイムラインイベント
- 🩺
diagnose_runtime— 証拠を関連付けて、要約・根本原因・証拠・確信度・修正方法を提示します。確信度が70%未満の場合は、幻覚を避けるため**「Unknown」**と表示します - 📊
http://127.0.0.1:7373で利用できるライブブラウザダッシュボード — AIとの接続に依存せず、すべての情報をWebSocket経由でストリーミング - 🧩 再利用可能な**
flutter-runtime-diagnosisClaude Codeスキル**を同梱
ツール
| ツール | 用途 | 安全性 |
|---|---|---|
connect_vm | 実行中のアプリの Dart VM Service(ws:// または http://)に接続します。 | 変更あり |
ensure_tcp_device | Android のトランスポートを設定します。ワイヤレス接続を推奨し、必要に応じて USB に切り替えます。 | 変更あり |
runtime_health | 1 回の呼び出しでトリアージします。判定と、例外/ネットワーク/フレーム/ログ/メモリの概要を返します。 | 読み取り専用 |
what_changed | 障害発生前のウィンドウから、タイムラインとともに根拠を提示します。 | 読み取り専用 |
get_navigation | 現在のルートと最近の遷移、およびルートごとの障害を返します。 | 読み取り専用 |
get_rebuilds | ウィジェット、ファイル、行に特定されたウィジェット再ビルドのホットスポットを返します。 | 読み取り専用 |
get_state_activity | Riverpod、Provider、Bloc の時間経過に伴うアクティビティと、ビルド負荷の高いフレームと同時に発生する頻度を返します。 | 読み取り専用 |
export_session | セッション全体をバージョン付き JSON としてエクスポートします。brief(診断と引用された根拠)または full を指定できます。 | 読み取り専用 |
explain_diagnosis | 診断に至った理由として、特定された根拠、代替案、不足情報を説明します。 | 読み取り専用 |
get_capabilities | 有効なコレクター、ツールの安全性クラス、観測できない情報を返します。 | 読み取り専用 |
runtime_status | 接続、セッション、再接続の状態、イベント数、保持期間、セッションが応答に要したコスト、VM とホストのクロック差を返します。 | 読み取り専用 |
get_logs | コンソールと dart:developer のログを返します(重要度/ソース/テキストで絞り込み可能)。 | 読み取り専用 |
get_exceptions | スタックトレース付きのフレームワーク例外と未処理例外を返します。 | 読み取り専用 |
get_frames | フレームのビルド/ラスタライズ時間を返します。onlyJanky で絞り込めます。 | 読み取り専用 |
get_network | HTTP リクエスト(Dio と package:http)を返します。失敗時はヘッダーと所要時間も含みます。 | 読み取り専用 |
get_widget_tree | Flutter Inspector からウィジェットツリーのスナップショットを取得します。 | 読み取り専用 |
get_selected_widget | Inspector で現在選択されているウィジェットを返します。 | 読み取り専用 |
get_memory | Dart ヒープと外部メモリ(MB)を返します。 | 読み取り専用 |
get_timeline | 最近の VM タイムラインイベント(ビルド/ペイント/レイアウト/GC)を返します。 | 変更あり |
diagnose_runtime | 安定した cause ラベル、根拠 ID、タイムライン、代替案、網羅性(何も観測できなかったカテゴリを含む)とともに根本原因を返します。 | 読み取り専用 |
diagnose_performance | アプリの動作がぎくしゃくする理由を、パーセンタイル、フェーズ別内訳、再ビルドの帰属とともに説明します。 | 読み取り専用 |
get_dashboard_url | ライブブラウザーダッシュボードの URL を返します。 | 読み取り専用 |
変更ありとは、ツールがアプリまたは VM の状態を変更することを意味し、プロジェクトの状態は変更しません。ここにあるツールはいずれもコードやファイルを書き込みません。connect_vm は、ネットワークキャプチャが動作するよう、アプリ上で dart:io HTTP タイムラインロギングを有効にします。recordFrom: true を指定した get_timeline は、VM の記録フラグを変更します。各ツールには MCP の readOnlyHint 注釈が付いているため、クライアント側でこれを適用できます。
エージェントは、すべてのツールを呼び出すべきではありません。推奨される手順は
runtime_health → what_changed → 対象を絞った get_* → diagnose_runtime です。
詳しくは AI エージェントとの連携を参照してください。
インストール
Node ≥ 20 が必要です。 クローンは不要です。初回実行時に npx が取得します。
npx -y flutter-lamp
または、グローバルにインストールします。
npm install -g flutter-lamp
ソースから
git clone https://github.com/itsonu/flutter-lamp.git
cd flutter-lamp
npm install
npm run build
node dist/index.js
Claude Code プラグイン(推奨)— MCP サーバーと
flutter-runtime-diagnosis スキルをワンステップでインストールします。
/plugin marketplace add itsonu/flutter-lamp
/plugin install flutter-lamp@flutter-lamp
このプラグインでは、公開済みの正確なサーバーバージョンが固定されています。Flutter Lamp は
MCP Registry にも
io.github.itsonu/flutter-lamp として登録されています。
または、MCP クライアントの設定にサーバーを追加し、クライアントを再起動してください。
Claude Code — プロジェクト内の .mcp.json:
{
"mcpServers": {
"flutter-lamp": {
"command": "npx",
"args": ["-y", "flutter-lamp"]
}
}
}
CLI から実行する場合:
claude mcp add --scope user flutter-lamp -- npx -y flutter-lamp
--scope user を指定すると、すべてのプロジェクトで利用できます。指定しない場合は、現在のプロジェクトだけに登録されます。
Cursor(~/.cursor/mcp.json)と Claude Desktop
(claude_desktop_config.json)では、同じ mcpServers 形式を使用します。
クローンから実行する場合は、command に node を、args に
/absolute/path/to/flutter-lamp/dist/index.js を指定してください。
任意の環境変数:
| 変数 | デフォルト | 意味 |
|---|---|---|
DASHBOARD_PORT | 7373 | ダッシュボードの HTTP/WS ポート。 |
DASHBOARD_HOST | 127.0.0.1 | バインドアドレス(デフォルトでは localhost のみ)。 |
DASHBOARD_DISABLE | — | ダッシュボードを無効にするには 1 に設定します。 |
FLUTTER_LAMP_REDACT | on | 生の認証情報を保持するには off に設定します。 |
FLUTTER_LAMP_REDACT_EXTRA | — | マスキング対象にする追加のヘッダー名パターンをカンマ区切りで指定します。 |
使い方
-
Flutter アプリをデバッグ/プロファイルモードで実行します。
flutter run表示された行をコピーします。
A Dart VM Service on <device> is available at: http://127.0.0.1:PORT/TOKEN=/ヒント:
flutter run --vm-service-port=8181を使うと、再起動しても URI が変わりません。 -
接続して診断するよう AI に依頼します。たとえば、「Flutter アプリの
<uri>に接続して、例外が発生する原因を教えてください。」 と依頼します。バンドルされたスキルを使うと、Claude Code は接続 → 収集 →diagnose_runtimeの全フローを自動で実行し、VM Service に接続できる場合は ログの貼り付けを求めることはありません。 -
ブラウザーで http://127.0.0.1:7373 を開くと、ライブダッシュボードを表示できます。ダッシュボードは AI の代わりではなく、AI と並行して動作します。
ケーブルなしでデバッグする(Android)
USB 経由で開始した flutter run は、ケーブルを抜くとすぐに VM Service のトンネルが失われます。一方、TCP トランスポート経由で開始した場合は失われません。利用できるトランスポートをサーバーに問い合わせます。
ensure_tcp_device # read-only: lists transports, recommends one
ensure_tcp_device { promote: true } # puts a USB-only device on TCP (needs the cable once)
次に、サーバーが推奨するワイヤレスシリアルを指定して起動します。
flutter run -d 192.168.88.3:5555
ケーブルが必要なのは、一度だけ昇格させるときです。いつでも adb usb を実行して元に戻せます。
ライブダッシュボード
依存関係のないダーク UI(ネイティブ HTTP + WebSocket、ビルド不要)で、実行時データをリアルタイムに表示します。
概要 — セッションレポート:ヘルス、FPS、メモリ、最悪フレーム、MCP のアクティビティ、および関連イベントにリンクする検出結果(最悪フレームの検出結果を開くと、そのフレームに絞り込んだタイムラインが表示されます) · ログ(検索/フィルター/自動スクロール) · ネットワーク(展開可能なヘッダーとタイミング) · 例外(展開可能なスタックトレース) · タイムライン · パフォーマンス(リアルタイムのキャンバスグラフ) · MCP — 接続したエージェント、呼び出した各ツール、レイテンシ、エラー、レスポンスサイズ · インスペクター — 利用できるインスペクションリンクと、取得専用のリンク · 診断 — 測定されたトポロジー、コレクターごとのヘルス、およびこのターゲットではまったく観測できない項目。
操作:一時停止/再開 · 表示をクリア · JSON をエクスポート · タブごとの検索 · 自動再接続。
この UI は、似ているようで異なる状態を区別します。0 MB は測定値、not sampled yet は測定されていないことを示します。また、タブが空の場合は、フィルターによって行が非表示になっているのか、コレクターがこのターゲットを監視できないのか、監視しているもののまだ何も検出していないのかを表示します。切断前に取得した値には、その旨が表示され、現在の値であるかのように見えることはありません。
仕組み
Running Flutter app
│ Dart VM Service Protocol (JSON-RPC over WebSocket)
▼
VmService client ──▶ Collectors (log · exception · frame · network · …)
│
▼
RuntimeStore (one centralized, capped event stream;
every event: timestamp · source · severity · category)
│ │
┌──────────┘ └──────────┐
▼ ▼
MCP tools (stdio) Dashboard (HTTP + WebSocket)
→ Claude Code / Cursor / … → your browser
すべてのデータは、1つのイベントストアを通ります。新しい実行時ソースを追加するには、Collector インターフェースを実装して登録するだけです。ほかのレイヤーを変更する必要はありません。設計原則:Flutter/Dart の公式 API のみを使用する、テキストではなく構造化 JSON を使う、DevTools をスクレイピングしない、そして証拠で裏付けられない原因を断定しない。
制限事項
- デバッグビルド/プロファイルビルドのみ対応します。 VM Service、Inspector、
dart:ioHTTP のプロファイリングは、リリースビルドでは利用できません。 - ネットワーク情報は要求に応じて取得されます。 Dart は
dart:ioHTTP のプッシュストリームを公開していないため、リクエストはget_networkまたはdiagnose_runtimeの実行時に取得されます。継続的にストリーミングされるわけではありません。 - 例外を常に観測できるとは限りません。
Debug.PauseExceptionを発生させるには、アプリで例外時の一時停止を有効にする必要があります。Flutter.Errorは、構造化エラー報告が有効な場合にのみウィジェットインスペクターから送信されます。構造化エラー報告は、プロファイルモードおよび Web ではフレームワークによって無効にされるため、これらのターゲットでは、スローされたフレームワークエラーの痕跡がまったく残りません。コレクターはアプリに確認し、その場合はdegradedを報告するため、例外リストが空でも、例外がなかったと誤って判断されることはありません。 - Dart 側の HTTP のみ対応します。 プラットフォーム(Kotlin/Swift)コードや WebView からの呼び出しは、
get_networkに表示されません。 - 保持されるデータには上限があります。 各カテゴリはそれぞれ固定件数を保持します(ログ 3,000 件、状態 2,000 件、例外 1,000 件、ネットワーク 1,000 件、フレーム 1,000 件、再ビルド 1,000 件、ナビゲーション 500 件、システム 500 件)。フレームは最も早く入れ替わります。60fps では約 17 秒分、10fps のワークロードで計測した場合は 4 分分です。
runtime_statusは保持中のデータと削除されたデータを報告します。また、削除が始まると、すべての診断にその旨の注記が含まれるため、切り詰められたデータがセッション全体の記録として提示されることはありません。 - ダッシュボードはデフォルトで
127.0.0.1にバインドされます。DASHBOARD_HOSTを変更するのは、信頼できるネットワーク上だけにしてください。ランタイムデータは認証なしで提供されます。
セキュリティ
ランタイムデータには機密情報が含まれます。HTTP ヘッダーにはベアラートークンや Cookie が含まれ、URI には API キーが含まれ、開発者が認証情報をログに出力することもあります。キャプチャされたデータはすべて AI モデルに渡され、ダッシュボードを閲覧中のすべてのブラウザーにもストリーミングされます。
シークレットはキャプチャ時に秘匿化されるため、イベントストアに保存されることはなく、どのコンシューマーも保存されていない情報を漏えいさせることはできません。デフォルトでは、Authorization、Proxy-Authorization、Cookie、Set-Cookie、WWW-Authenticate、名前に token、secret、password、credential、api-key、session のいずれかを含むヘッダー、機密性の高いクエリ文字列パラメーター、ログ行やエラーテキスト内の JWT 形式または Bearer 形式の文字列が秘匿化されます。該当したヘッダー名は data.redactedHeaders に表示されるため、黙って一部が欠落した状態のデータを受け取るのではなく、情報が保留されたことを確認できます。FLUTTER_LAMP_REDACT_EXTRA でパターンを追加するか、ローカル限定のセッションで FLUTTER_LAMP_REDACT=off を設定して秘匿化を完全に無効にできます。
VM Service の認証情報は無条件で除去されます。 VM Service URI のパスセグメントは evaluate(監視対象アプリでの任意の Dart コード実行)を認可するもので、アプリが自身の URI をコンソールに出力することがあります。Web ターゲットでは起動時にこれが発生します。このトークンは、キャプチャされたテキスト内のどこに現れても削除されます。また、上記の情報とは異なり、FLUTTER_LAMP_REDACT=off の対象にはなりません。この設定は、自分のアプリのヘッダーやログテキストを読めるようにするためのものであり、サーバーが接続先のアプリにキーを渡せるようにするためのものではありません。
ダッシュボードが他のページに公開されることはありません。 ループバックにバインドしても、WebSocket は保護されません。ブラウザーでは WebSocket が同一オリジンポリシーの対象外となるため、チェックがなければ、開いている任意のページから ws://127.0.0.1:7373/ws に接続して、ランタイムストリーム全体を読み取れてしまいます。ハンドシェイクでは、配信ページに埋め込まれたプロセスごとのトークンが必要です。このトークンはクロスオリジンのスクリプトから読み取れません。また、Origin ヘッダーが存在する場合は、ループバックであることが求められます。ページには X-Frame-Options: DENY が設定され、/health が返すのは稼働状態のみです。VM 自身の認証トークンを含む VM Service URI が返されることはありません。
DASHBOARD_HOST をループバック以外のアドレスに設定すると、警告がログに記録され、ランタイムの証拠データがネットワーク上で公開されます。信頼できるネットワーク上でのみ設定してください。
脆弱性を発見しましたか? SECURITY.md をご覧ください。
ロードマップ
提供済み:VM 接続、ログ、例外(スタックトレース付き)、ネットワーク、フレーム、ウィジェット ツリー、メモリ、タイムライン、ルートの把握、再ビルドの原因特定、状態管理のアクティビティ、 診断、ライブダッシュボード、および実際に問題が発生したアプリに対する診断を確認するため、 記録済みセッションを再生する評価スイートです。
次の予定:より深い相関分析(メモリ/タイムラインと diagnose_runtime の連携)、CPU サンプリング
とリークのヒューリスティクス、ナレッジグラフ、自動修正です。docs/Phases.md と
docs/Observability-Roadmap.md をご覧ください。
開発
npm run build # compile TypeScript → dist/
npm run watch # incremental compile
npm test # node:test suite (engine + collectors + dashboard)
npm test はコンパイル済みの出力を実行するため、先にビルドしてください。テストには
node --test の glob サポートが必要で、Node ≥ 21 が必要です。サーバー自体は Node ≥ 20 で動作します。
ドキュメントは docs/ にあります。
| ドキュメント | 内容 |
|---|---|
| PRD | 課題、ユーザー、原則、対象外事項、制約 |
| アーキテクチャ | データフロー、コンポーネント、イベントモデル、コレクターの追加方法 |
| ルール | すべての変更が準拠すべき必須の制約 |
| フェーズ | ロードマップと進捗状況 |
| AI エージェントの統合 | エージェントが従うべき調査プロトコル |
| 改善計画 | 現状の監査と優先順位付きバックログ |
| 可観測性ロードマップ | アーキテクチャの目標、フェーズ、明示的に採用しない事項 |
| データパス | ランタイムイベントの実際の流れと、観測可能な内容 |
| リリース | バージョンの準備、タグ付け、公開の方法 |
| デザイン | ダッシュボードのデザインシステム — トークン、ステータスの語彙、コンポーネントのルール |
| 実装メモ | 開発中に得られた、わかりにくい点についての知見 |
コントリビュート
Issue や PR を歓迎します。モジュール性を保ち、ハックより公式 API を優先し、重要なロジックを追加する際は
node:test によるチェックも追加してください。
ライセンス
MIT © Chandrabhushan Prakash
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。