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. 03评估 Dart 表达式读取状态
  4. 04处理多个调试目标连接

适用场景

  1. 01定位工具调用失败原因
  2. 02检查应用异常时的日志
  3. 03只读查看运行中的应用状态

MCP 相关

该技能指导使用 flutter-mcp-toolkit MCP 工具排查 Flutter 应用,包括日志、表达式评估和动态工具调用。

安装

复制下面的命令,在终端中运行。

$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_* 工具(截图、日志、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. 需要日志输出? 调用 get_recent_logs,并设置 count: 100 和级别筛选条件。查找故障时间戳附近的堆栈跟踪或断言消息。
  4. 需要实时状态? 调用 evaluate_dart_expression 并传入有针对性的表达式(例如 MyBloc.instance.state.toString())。请在查看日志之后再执行此操作,而不要用它代替查看日志。
  5. 要与 inspect 串联使用? 顺序为:semantic_snapshot → evaluate_dart_expression → get_recent_logs。快照会提供当前 Widget 树;表达式求值不会改变任何内容;日志则提供后续上下文。
  6. 有多个目标? 如果出现 connection_selection_required,调用 discover_debug_apps,选择 targetId,然后在后续每次调用中传入 connection: {targetId: "..."}。

工具参考

get_recent_logs

从运行中应用的主 isolate 获取近期 print() 和 debugPrint() 输出。

  • count • 整数 • 可选,默认值:50 — 要返回的日志行数。
  • connection • 对象 • 可选 — 连接覆盖项;有多个调试应用正在运行时必填。
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

在运行中应用的主 isolate 中求值 Dart 表达式,并返回其字符串表示形式。

  • expression • 字符串 • 必填 — Dart 表达式(例如 "MyClass.instance.counter")。
  • connection • 对象 • 可选 — 连接覆盖项。
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 始终为字符串。长度较长的 String 会完整返回,最多包含 32,768 个 UTF-16 代码单元(单位 length 和 String.length 计数的就是代码单元,因此非 ASCII 文本可能会编码为更多字节);超过此长度时,truncated: true,并附带 length、returnedLength 以及提示,指出可读取剩余部分的 .substring(...)。List、Map 或对象会以裸类名("_GrowableList")的形式返回,并附带提示——将表达式包装在 .toString() 或 jsonEncode(...) 中以读取其值。会在实时 isolate 中执行任意代码——请避免产生副作用的表达式。仅限调试模式。失败时,请参阅处理手册中的 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}。请始终读取 error.descriptor(而非顶层响应)中的 retryable 和 exitCode。如果提供了 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/Web)。Web 实际捕获:优先使用 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(Web HtmlElementView + CDP 捕获)。
  3. 运行 focus_window(MCP:fmt_focus_window),然后使用 mode: desktop_window 重试 get_screenshots。
  4. 对于 validate-runtime,执行器恢复流程会重试聚焦窗口和捕获一次(desktopCaptureRetried)。如果 desktop_window 仍然失败,validate-runtime 会在检测到平台视图时也使用 flutter_layer 重试一次。读取 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)

**含义:**获取状态锁超时(并发 Agent 争用)。 **原因:**另一个 Agent 或 CLI 调用持有锁;发生死锁。 **恢复方法:**等待后重试;如果问题反复出现,终止其他持有该锁的 Agent 进程。

stateLockConflict (state_lock_conflict)

**含义:**检测到冲突的状态锁。 **原因:**多个 Agent 同时写入。 **恢复方法:**按顺序执行调用;冲突操作完成后重试。

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 与当前应用状态不再匹配。 **原因:**拍摄快照后,热重载或交互更改了 widget 树。 恢复方法:

  1. evaluate_dart_expression(expression: "true") — 验证应用是否可访问。
  2. semantic_snapshot() — 获取新的快照 ID,然后重试原始调用。
bundleBuildFailed (bundle_build_failed)

**含义:**创建或发布 bundle 失败。 恢复方法:flutter-mcp-toolkit doctor --json — 检查构建产物和输出路径。

writeBlocked (write_blocked)

**含义:**由于设置了 --no-overwrite 且目标已存在,写入操作被阻止。无法重试。 **恢复方法:**不使用 --no-overwrite 重试,或选择其他 --output/--name。

doctorCriticalFailed (doctor_critical_failed)

**含义:**一项或多项关键 doctor 检查未通过。 恢复方法:flutter-mcp-toolkit doctor --json — 查看 checks[*] 中 status: "fail" 且 critical: true 的项目;加载 flutter-mcp-toolkit-setup。

interactionFailed (interaction_failed)

**含义:**tap/scroll/swipe/drag/long_press/enter_text/reveal_search/focus_widget 调用被拒绝。 原因:ref 已过期;widget 不可见、不可交互或已禁用;始终未找到目标;工具包桥接未初始化。对于 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)

含义:wait_for 谓词在 timeoutMs 耗尽前未匹配。 **原因:**谓词条件始终未成立;应用状态没有变化;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)会以 interaction_failed 返回,details 中包含工具包的提示。 **恢复方法:**运行 flutter-mcp-toolkit doctor --json

unknown (unknown_error)

**含义:**用于兜底处理任何无法识别的错误代码。 **恢复方法:**运行 flutter-mcp-toolkit doctor --json — 查看 error.details 中的原始原因。

评论

支持 Markdown