关于 flutter-mcp-toolkit-debug
flutter-mcp-toolkit-debug 是面向 Flutter 应用调试的技能,用于排查工具错误、查看运行日志和读取实时状态。它提供按错误代码组织的恢复步骤,并说明多应用连接和诊断工具的使用顺序。
主要功能
- 01按错误代码排查故障
- 02读取应用运行日志
- 03评估 Dart 表达式读取状态
- 04处理多个调试目标连接
适用场景
- 01定位工具调用失败原因
- 02检查应用异常时的日志
- 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。
分类流程
- 是否返回了错误信封? 首先读取
error.code,然后读取error.descriptor.retryable。在下方的错误信封处理手册中查找该错误代码。 - 错误是否可重试? 运行
flutter-mcp-toolkit doctor --json。如果 doctor 失败,请加载flutter-mcp-toolkit-setup。 - 需要日志输出? 调用
get_recent_logs,并设置count: 100和级别筛选条件。查找故障时间戳附近的堆栈跟踪或断言消息。 - 需要实时状态? 调用
evaluate_dart_expression并传入有针对性的表达式(例如MyBloc.instance.state.toString())。请在查看日志之后再执行此操作,而不要用它代替查看日志。 - 要与 inspect 串联使用? 顺序为:
semantic_snapshot→evaluate_dart_expression→get_recent_logs。快照会提供当前 Widget 树;表达式求值不会改变任何内容;日志则提供后续上下文。 - 有多个目标? 如果出现
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)时:
- 调用
discover_debug_apps()— 读取每个运行中应用的targets[*].targetId。 - 按端口或主机名识别目标。
- 调用
connect_debug_app(connection: {targetId: "ws://127.0.0.1:<port>/<token>/ws"})固定会话。 - 在该会话后续的每次工具调用中传入相同的
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 状态。 恢复:
flutter-mcp-toolkit doctor --json- 如果 doctor 检查通过,则重试一次;如果再次出现,请提交错误报告并附上
error.details。
connectFailed (connect_failed)
含义: 与 VM Service WebSocket 的连接失败。 原因: 端口错误、令牌过期、应用未运行。 恢复:
flutter-mcp-toolkit exec --name get_vm --args '{"connection":{"uri":"ws://127.0.0.1:8181/<token>/ws"}}'- 从 Flutter 输出中的
app.debugPort.wsUri获取准确的 URI。
vmNotConnected (vm_not_connected)
含义: 在建立连接前调用了依赖 VM 的命令。 恢复:
flutter-mcp-toolkit exec --name status --args '{}'- 然后运行
flutter-mcp-toolkit doctor --json。
connectionSelectionRequired (connection_selection_required)
含义: 存在多个调试目标;需要指定明确的目标。 原因: 同时有多个 Flutter 应用以调试模式运行。 恢复:
flutter-mcp-toolkit exec --name discover_debug_apps --args '{}'- 从
details.availableTargets中选择正确的targetId。 - 使用
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 拒绝了热重载。 原因: 修改的文件中有编译错误;隔离区处于异常状态。 恢复:
flutter-mcp-toolkit exec --name get_app_errors --args '{}'- 修复编译错误,然后重试。
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 窗口竞态等)。 恢复方法:
flutter-mcp-toolkit doctor --json— 单独检查visual_capture_permission_denied。- 检查
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(macOSAppKitView),或运行flutter run -d chrome(WebHtmlElementView+ CDP 捕获)。 - 运行
focus_window(MCP:fmt_focus_window),然后使用mode: desktop_window重试get_screenshots。 - 对于
validate-runtime,执行器恢复流程会重试聚焦窗口和捕获一次(desktopCaptureRetried)。如果desktop_window仍然失败,validate-runtime 会在检测到平台视图时也使用flutter_layer重试一次。读取data.summary中的capturePlatformViewsDetected、captureFocusAttempted和captureFallbackUsed。
visualCapturePermissionDenied (visual_capture_permission_denied)
含义: 未授予 macOS 屏幕录制权限。 恢复方法:
flutter-mcp-toolkit permissions request --kind visual_capture- 或打开“系统设置” →“隐私与安全性” →“屏幕录制”。
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 树。
恢复方法:
evaluate_dart_expression(expression: "true")— 验证应用是否可访问。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 指明了持有焦点的对象)。
恢复方法:
- 读取
error.details.hint— 拒绝信息会说明具体原因和下一步操作,该提示也会出现在error.recovery.summary中。 - 否则,调用
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 太短。
恢复方法:
semantic_snapshot()— 验证预期的组件状态。- 增大
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 中的原始原因。