mcpField
F
flutter-mcp-toolkit-debug

flutter-mcp-toolkit-debug

github.com/arenukvern開発39461 回インストール2 週間前に更新
リポジトリ

flutter-mcp-toolkit-debug について

flutter-mcp-toolkit-debug は、Flutter アプリの障害調査、実行ログの確認、実行中の状態の読み取りに使うスキルです。エラーコード別の復旧手順に加え、複数アプリ接続時の操作順も説明します。

主な機能

  1. 01エラーコード別の切り分け
  2. 02アプリ実行ログの取得
  3. 03Dart 式による状態の評価
  4. 04複数のデバッグ対象への接続

活用シーン

  1. 01ツール呼び出し失敗の原因調査
  2. 02予期しない動作のログ確認
  3. 03実行中アプリの状態を変更せずに確認

MCP 対応

ログ、式の評価、動的ツール呼び出しなど、Flutter アプリのデバッグに使う flutter-mcp-toolkit の MCP ツールを案内します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/arenukvern/mcp_flutter --skill flutter-mcp-toolkit-debug

インストール後、Claude Code で/flutter-mcp-toolkit-debugを入力して読み込まれたか確認します。

詳細

使用するタイミング

何かが壊れ、その原因を把握する必要がある場合にこのスキルを使用します。

  • ツール呼び出しがエラーエンベロープ(ok: false)を返した場合。
  • アプリが予期しない動作をし、実行時ログの出力が必要な場合。
  • ライブアプリの状態を変更せずに調べる必要がある場合(AgentState.instance.value を読み取ります)。
  • 以前の control アクション(tap、hot_reload、navigate)がエラーなく完了したものの、結果が正しくない場合。

次の用途にはこのスキルを使用しないでください。

  • 現在画面に表示されている内容の読み取り — flutter-mcp-toolkit-inspect を使用してください。
  • ツールキット自体への接続失敗 — flutter-mcp-toolkit-setup を読み込んでください。

レジストリとバンドルされたツール

  • バンドルされた fmt_* ツール(screenshot、logs、evaluate など)は、ホスト上の AgentRegistry を介して MCP サーバー上で実行されます。
  • アプリに登録されたサーフェスは、MCPToolkitBinding.addEntries / AgentCallEntry の後に表示されます。fmt_list_client_tools_and_resources で検出し、次に fmt_client_tool / fmt_client_resource を使用してください。

トリアージの流れ

  1. エラーエンベロープが返された場合:まず error.code を読み、次に error.descriptor.retryable を確認します。以下のエラーエンベロープのプレイブックでコードを調べてください。
  2. 再試行可能なエラーの場合:flutter-mcp-toolkit doctor --json を実行します。doctor が失敗した場合は flutter-mcp-toolkit-setup を読み込んでください。
  3. ログ出力が必要な場合:count: 100 とレベルフィルターを指定して get_recent_logs を呼び出します。失敗した時刻付近にあるスタックトレースやアサーションメッセージを探してください。
  4. ライブ状態が必要な場合:対象を絞った式(例:MyBloc.instance.state.toString())を指定して evaluate_dart_expression を呼び出します。ログを確認した後に実行し、ログの代わりにはしないでください。
  5. inspect と連携する場合:順序は semantic_snapshot → evaluate_dart_expression → get_recent_logs です。スナップショットで式の評価前の現在のウィジェットツリーを確認できます。式の評価で状態は変更されず、ログからは後続の状況を把握できます。
  6. 複数のターゲットがある場合:connection_selection_required が発生したら、discover_debug_apps を呼び出して targetId を選び、その後のすべての呼び出しに connection: {targetId: "..."} を渡します。

ツールリファレンス

get_recent_logs

実行中のアプリのメインアイソレートから、最近の print() および debugPrint() の出力を取得します。

  • count • integer • 省略可能、デフォルト:50 — 返すログ行数です。
  • connection • object • 省略可能 — 接続のオーバーライドです。複数のデバッグアプリが実行中の場合は必須です。
get_recent_logs(count: 100)
get_recent_logs(count: 50, connection: {targetId: "ws://127.0.0.1:8181/<token>/ws"})

戻り値:{"logs": ["[INFO] page loaded", "[ERROR] assertion failed: ..."], "count": 50}

読み取り専用で、コードは実行されません。アプリの起動またはホットリスタート以降にバッファーされた行のみを返します。失敗した場合は、プレイブックの getRecentLogsFailed を参照してください。

evaluate_dart_expression

実行中のアプリのメインアイソレートで Dart 式を評価し、その文字列表現を返します。

  • expression • string • 必須 — Dart 式(例:"MyClass.instance.counter")。
  • connection • object • 省略可能 — 接続のオーバーライドです。
evaluate_dart_expression(expression: "Navigator.of(context).canPop()")
evaluate_dart_expression(expression: "AgentState.instance.value.toString()")

戻り値:{"result": "42", "kind": "Int", "classRef": "_Smi", "truncated": false} — result は常に文字列です。長い文字列は、最大32,768 UTF-16 コード単位まで全体が返されます(単位の length と String.length はこの単位で数えられるため、ASCII 以外のテキストはより多くのバイトにエンコードされる場合があります)。それを超えると truncated: true とともに length、returnedLength、残りを読み取る .substring(...) を示すヒントが返されます。List、Map、オブジェクトはヒント付きでクラス名のみ("_GrowableList")が返されます。値を読み取るには、式を .toString() または jsonEncode(...) で囲んでください。ライブアイソレート内で任意のコードを実行するため、副作用のある式は避けてください。デバッグモードでのみ使用できます。失敗した場合は、プレイブックの evaluateExpressionFailed を参照してください。

接続/マルチアプリのフロー

discover_debug_apps が複数のエントリーを返した場合(または、いずれかの呼び出しが connection_selection_required を返した場合):

  1. discover_debug_apps() を呼び出し、実行中の各アプリについて targets[*].targetId を確認します。
  2. ポートまたはホスト名でターゲットを特定します。
  3. connect_debug_app(connection: {targetId: "ws://127.0.0.1:<port>/<token>/ws"}) を呼び出して、セッションを固定します。
  4. セッション中の後続のすべてのツール呼び出しに、同じ connection オブジェクトを渡します。

接続のオーバーライドパターン — すべての呼び出しで connection を渡します:

get_recent_logs(count: 50, connection: {targetId: "ws://127.0.0.1:8182/<token>/ws"})
evaluate_dart_expression(expression: "x.toString()", connection: {targetId: "ws://127.0.0.1:8182/<token>/ws"})

ターゲットが変わった場合(アプリの再起動、ポートの変更など)は、discover_debug_apps を再実行して新しい targetId を取得します。古い URI は connect_failed を返します。

エラーエンベロープの対処ガイド

エラーが発生すると、必ず {code, message, details, descriptor, recovery} が返されます。retryable と exitCode は、トップレベルのエンベロープではなく、必ず error.descriptor を確認してください。error.recovery.fix_command が指定されている場合は、そのコマンドを直接実行します。

unexpectedExecutorError(unexpected_executor_error)

意味: コマンド実行ツールで未処理の例外が発生しました。 原因: サーバーのバグ、予期しない nil、復旧不能な VM の状態。 復旧方法:

  1. flutter-mcp-toolkit doctor --json
  2. doctor が成功した場合は一度だけ再試行します。再発した場合は、error.details を添えてバグを報告してください。
connectFailed(connect_failed)

意味: VM Service WebSocket への接続に失敗しました。 原因: ポートが誤っている、トークンが古い、アプリが実行されていない。 復旧方法:

  1. flutter-mcp-toolkit exec --name get_vm --args '{"connection":{"uri":"ws://127.0.0.1:8181/<token>/ws"}}'
  2. Flutter の出力にある app.debugPort.wsUri から正確な URI を取得します。
vmNotConnected(vm_not_connected)

意味: 接続が確立する前に、VM に依存するコマンドが呼び出されました。 復旧方法:

  1. flutter-mcp-toolkit exec --name status --args '{}'
  2. 続けて flutter-mcp-toolkit doctor --json を実行します。
connectionSelectionRequired(connection_selection_required)

意味: デバッグターゲットが複数存在するため、明示的なターゲットの指定が必要です。 原因: Flutter アプリがデバッグモードで同時に複数実行されています。 復旧方法:

  1. flutter-mcp-toolkit exec --name discover_debug_apps --args '{}'
  2. details.availableTargets から正しい targetId を選択します。
  3. connection: {targetId: "<chosen_id>"} を指定して、元の呼び出しを再試行します。
discoverDebugAppsFailed(discover_debug_apps_failed)

意味: ローカルの VM Service ポートの検出スキャンに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

getVmFailed(get_vm_failed)

意味: VM Service への get_vm RPC 呼び出しに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

getExtensionRpcsFailed(get_extension_rpcs_failed)

意味: 登録済みの拡張 RPC の一覧表示に失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

hotReloadFailed(hot_reload_failed)

意味: Dart コンパイラーまたは VM によってホットリロードが拒否されました。 原因: 変更したファイルにコンパイルエラーがある、アイソレートの状態が不正。 復旧方法:

  1. flutter-mcp-toolkit exec --name get_app_errors --args '{}'
  2. コンパイルエラーを修正してから、再試行します。
hotRestartFailed(hot_restart_failed)

意味: ホットリスタート全体に失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json を実行します。VM に到達できない場合は、手動でアプリを再起動してください。

getActivePortsFailed(get_active_ports_failed)

意味: アクティブなデバッグポートのスキャンに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

getAppErrorsFailed(get_app_errors_failed)

意味: ツールキットブリッジからのアプリエラーの取得に失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

getScreenshotsFailed (get_screenshots_failed)

意味: スクリーンショットのキャプチャに失敗しました(モードが正しくない、ホストウィンドウが利用できない、Simulator ウィンドウの競合状態など)。 復旧方法:

  1. flutter-mcp-toolkit doctor --json — visual_capture_permission_denied を個別に確認します。
  2. get_view_details またはスクリーンショットのペイロードで captureHints を確認します。強いシグナル(platformViewsDetected):UiKitView、AppKitView、AndroidView、HtmlElementView — desktop_window または auto を使用します(macOS アプリ、iOS Simulator、または CDP を使用する任意のホスト上の Chrome/ウェブ)。ウェブの実キャプチャでは、まず macOS ScreenCaptureKit を使用し、次に Chrome CDP を使用します(captureBackend: cdp)。ポートを上書きするには --web-browser-debugging-port を指定します。弱いシグナル(weakSignalsDetected):Texture のみ — macOS ホストでは desktop_window を優先しますが、auto は切り替わりません。プラットフォームビューのない WGPU/カスタムエンジンでは、アプリで MCPToolkitBinding.captureHintsContributor を設定します。画像のみを返す get_screenshots ツールも、meta 内のルーティング JSON と先頭のテキストブロックを返します。ショーケースを実行するには、make showcase-stop の後に make showcase(macOS AppKitView)または flutter run -d chrome(ウェブ HtmlElementView + CDP キャプチャ)を実行します。
  3. focus_window(MCP:fmt_focus_window)を実行し、その後 mode: desktop_window を指定して get_screenshots を再試行します。
  4. validate-runtime では、エグゼキューターがフォーカスとキャプチャを1回再試行します(desktopCaptureRetried)。desktop_window が引き続き失敗する場合、プラットフォームビューが検出されていても、validate-runtime は flutter_layer で1回再試行します。data.summary の capturePlatformViewsDetected、captureFocusAttempted、captureFallbackUsed を確認します。
visualCapturePermissionDenied (visual_capture_permission_denied)

意味: macOS の画面収録権限が付与されていません。 復旧方法:

  1. flutter-mcp-toolkit permissions request --kind visual_capture
  2. または、システム設定 → プライバシーとセキュリティ → 画面収録を開きます。
visualCaptureUnsupported (visual_capture_unsupported)

意味: このプラットフォームまたはキャプチャモードでは、ビジュアルキャプチャがサポートされていません。再試行できません。 復旧方法: flutter-mcp-toolkit permissions status && flutter-mcp-toolkit doctor --json

getViewDetailsFailed (get_view_details_failed)

意味: FlutterView の寸法の取得に失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

debugDumpFailed (debug_dump_failed)

意味: VM のデバッグダンプ RPC(レンダーツリー、セマンティクス、レイヤー)に失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

dynamicRegistryDisabled (dynamic_registry_disabled)

意味: 動的ツール/リソースの呼び出しが行われましたが、動的レジストリが無効になっています。再試行できません。 復旧方法: flutter-mcp-toolkit --dynamics exec --name status --args '{}' — 有効にするには --dynamics フラグを渡します。

dynamicRegistryListFailed (dynamic_registry_list_failed)

意味: レジストリから動的ツール/リソースを一覧表示できませんでした。 復旧方法: flutter-mcp-toolkit doctor --json

missingToolName (missing_tool_name)

意味: ツール名を指定せずに動的ツールが呼び出されました。再試行できません。 復旧方法: 呼び出しに tool_name パラメーターを含めます。flutter-mcp-toolkit schema --name fmt_client_tool

dynamicToolFailed (dynamic_tool_failed)

意味: 動的ツールの呼び出しに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

missingResourceUri (missing_resource_uri)

意味: URI を指定せずに動的リソースの読み取りが呼び出されました。再試行できません。 復旧方法: uri パラメーターを含めます。flutter-mcp-toolkit schema --name fmt_client_resource

dynamicResourceFailed (dynamic_resource_failed)

意味: 動的リソースの読み取りに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

sessionManagerNotConfigured (session_manager_not_configured)

意味: セッションコマンドが呼び出されましたが、セッションマネージャーが接続されていません。再試行できません。 復旧方法: flutter-mcp-toolkit doctor --json — サーバー設定の問題です。flutter-mcp-toolkit-setup を再読み込みします。

sessionNotFound (session_not_found)

意味: 要求されたセッション ID が存在しません。再試行できません。 復旧方法: アクティブなセッションを一覧表示し、参照する前に新しいセッションを開始します。

invalidCommand (invalid_command)

意味: コマンド名または引数のスキーマが無効です。再試行できません。 復旧方法: flutter-mcp-toolkit schema --name <command_name>

stateStoreReadFailed (state_store_read_failed)

意味: 永続状態ストアからの読み取りに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json — 状態ディレクトリのファイルシステム権限を確認します。

stateStoreWriteFailed (state_store_write_failed)

意味: 永続状態ストアへの書き込みに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json — ディスク容量と権限を確認します。

stateLockTimeout (state_lock_timeout)

意味: 状態ロックの取得がタイムアウトしました(エージェント間の競合)。 原因: 別のエージェントまたは CLI 呼び出しがロックを保持しています。デッドロックが発生しています。 復旧方法: 待ってから再試行します。繰り返し発生する場合は、ロックを保持している他のエージェントプロセスを終了します。

stateLockConflict (state_lock_conflict)

意味: 競合する状態ロックが検出されました。 原因: 複数のエージェントが同時に書き込みを行っています。 復旧方法: 呼び出しを直列化し、競合する操作の完了後に再試行します。

diagnoseFailed (diagnose_failed)

意味: 複合 diagnose コマンドが失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

explainErrorsFailed (explain_errors_failed)

意味: エラー説明コマンドが失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json

unsupportedSummaryProvider (unsupported_summary_provider)

意味: 認識されない要約プロバイダーが要求されました。再試行できません。 復旧方法: flutter-mcp-toolkit schema --name diagnose — 使用可能な provider の値を確認します。

snapshotNotFound (snapshot_not_found)

意味: 参照されたスナップショット ID が存在しません。再試行できません。 復旧方法: flutter-mcp-toolkit snapshot create --name <snapshot_id> --args '{}'

snapshotInvalid (snapshot_invalid)

意味: スナップショットのペイロードの形式が不正か、検証に失敗しました。再試行できません。 復旧方法: スナップショットを作り直します。破損したファイルは再利用しないでください。

staleSnapshot (stale_snapshot)

意味: 指定された snapshotId が現在のアプリの状態と一致しなくなっています。 原因: スナップショット取得後にホットリロードまたは操作が行われ、ウィジェットツリーが変更されました。 復旧方法:

  1. evaluate_dart_expression(expression: "true") — アプリに到達できることを確認します。
  2. semantic_snapshot() — 新しいスナップショット ID を取得し、元の呼び出しを再試行します。
bundleBuildFailed (bundle_build_failed)

意味: バンドルの作成または公開に失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json — ビルド成果物と出力パスを確認します。

writeBlocked (write_blocked)

意味: --no-overwrite が設定されていて、対象がすでに存在するため、書き込みがブロックされました。再試行できません。 復旧方法: --no-overwrite を付けずに再試行するか、別の --output/--name を指定します。

doctorCriticalFailed (doctor_critical_failed)

意味: 1 つ以上の重要な doctor チェックに失敗しました。 復旧方法: flutter-mcp-toolkit doctor --json — status: "fail" かつ critical: true の checks[*] を読み取り、flutter-mcp-toolkit-setup を読み込みます。

interactionFailed (interaction_failed)

意味: tap/scroll/swipe/drag/long_press/enter_text/reveal_search/focus_widget の呼び出しが拒否されました。 原因: ref が古い、ウィジェットが表示されていない・操作できない・無効になっている、対象が見つからない、またはツールキットブリッジが初期化されていません。focus_widget の場合:focus_not_exposed(その ref に対してフォーカス可能な要素が応答していません — FocusNode のないタップ専用ボタンなど)、または focus_refused(フォーカスが別の場所に移動しました。details.focusedNow にフォーカスを保持している要素が示されます)。 復旧方法:

  1. error.details.hint を読み取ります — 拒否の原因と次の手順が示されており、error.recovery.summary にも同じヒントが含まれます。
  2. それ以外の場合は semantic_snapshot() で新しい ref を取得してから、再試行します。
semanticSnapshotFailed (semantic_snapshot_failed)

意味: semantic_snapshot の実行に失敗しました。 対処方法: flutter-mcp-toolkit doctor --json — MCPToolkitBinding.initialize() が呼び出されていることを確認してください。

evaluateExpressionFailed (evaluate_expression_failed)

意味: evaluate_dart_expression の実行に失敗しました。 原因: 式の構文エラー、実行時に例外がスローされた、または isolate に到達できません。 対処方法: 式を簡潔にし、構文を確認してください。flutter-mcp-toolkit doctor --json も実行してください。

getRecentLogsFailed (get_recent_logs_failed)

意味: get_recent_logs の取得に失敗しました。 対処方法: flutter-mcp-toolkit doctor --json — ツールキットが初期化されていることを確認してください。

invalidPredicate (invalid_predicate)

意味: wait_for が受け取った述語では、要求された観測をタイムアウト時間内に完了できません。 原因: stableWindowMs が実効 timeoutMs 以上です。 対処方法: timeoutMs を stableWindowMs より大きく設定してください。timeoutMs を省略すると、デフォルトの 5000 ms が使用されます。

waitTimeout (wait_timeout)

意味: timeoutMs が経過する前に wait_for の述語が一致しませんでした。 原因: 述語の条件が真にならない、アプリの状態が変化しない、または timeoutMs が短すぎます。 対処方法:

  1. semantic_snapshot() — 期待されるウィジェットの状態を確認してください。
  2. timeoutMs を延長するか、述語を調整してください。
waitForFailed (wait_for_failed)

意味: wait_for の実行に失敗しました(述語の形式が不正、またはツールキットエラー)。 対処方法: flutter-mcp-toolkit schema --name wait_for

pressKeyFailed (press_key_failed)

意味: press_key の実行に失敗しました。 対処方法: flutter-mcp-toolkit schema --name press_key

handleDialogFailed (handle_dialog_failed)

意味: handle_dialog(ダイアログの閉じる/承認)の実行に失敗しました。 原因: ダイアログが表示されていない、またはすでに閉じられています。 対処方法: 呼び出す前に semantic_snapshot() でダイアログが表示されていることを確認してください。

navigateFailed (navigate_failed)

意味: navigate の push/pop/popUntil に失敗しました。 対処方法: flutter-mcp-toolkit schema --name navigate

navigatorNotRegistered (navigator_not_registered)

意味: navigate が呼び出されましたが、アプリで GlobalKey<NavigatorState> が登録されていません。再試行できません。 原因: ホストアプリで MCPToolkitBinding.instance.navigatorKey が設定されていません。 対処方法: アプリの main.dart で MCPToolkitBinding.instance.navigatorKey = navigatorKey を代入し、ホットリスタートしてください。

fillFormFailed (fill_form_failed)

意味: fill_form のオーケストレーションに失敗しました(トランスポートまたはフィールドごとのエラー)。 対処方法: flutter-mcp-toolkit schema --name fill_form

hoverFailed (hover_failed)

意味: hover の実行に失敗しました。 対処方法: flutter-mcp-toolkit doctor --json

focusWidgetFailed (focus_widget_failed)

意味: focus_widget がアプリに到達できませんでした。アプリ自体が報告する拒否(focus_not_exposed、focus_refused)は、ツールキットのヒントを details に含む interaction_failed として返されます。 対処方法: flutter-mcp-toolkit doctor --json

unknown (unknown_error)

意味: 認識できないエラーコードに対するフォールバックです。 対処方法: flutter-mcp-toolkit doctor --json — 生の原因を確認するには error.details を調べてください。

コメント