关于 Flutter Lamp
Flutter Lamp 是面向 Flutter 开发者的 MCP 服务,可读取运行中应用的实时状态,辅助定位异常和性能问题。它通过 Dart VM Service Protocol 收集结构化运行数据,并提供证据关联诊断与浏览器仪表板。
主要功能
- 01收集异常、日志和网络请求
- 02分析帧耗时、重建及状态活动
- 03查看路由、组件树和内存
- 04基于证据诊断根因与性能问题
- 05提供实时浏览器仪表板
适用场景
- 01排查运行中应用的异常及触发过程
- 02定位卡顿帧和组件重建热点
- 03查看网络请求与故障时间线
MCP 相关
作为 MCP 服务,它向客户端提供 Flutter 运行时检查和诊断工具。服务连接运行中的 Flutter 应用 Dart VM Service,并可将会话数据提供给浏览器仪表板。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
22收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| uri | string | 是 | VM Service URI,例如 http://127.0.0.1:52719/abcdef=/ 或 ws://... |
详细介绍
💡 Flutter Lamp
让 AI 实时查看正在运行的 Flutter 应用——无需再粘贴日志。
一个 MCP 服务,通过 Dart VM Service Protocol 将 Claude Code、Claude Desktop、Cursor、Codex 和 Gemini 直接连接到正在运行的 Flutter 应用——以结构化数据的形式实时传输异常、日志、网络调用、帧耗时和内存信息, 并提供一个以证据为先的根因诊断引擎和实时浏览器仪表板。
为什么需要它
如今,你通过复制粘贴堆栈跟踪、flutter run
输出和 DevTools 截图来让 AI 帮你调试 Flutter。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
- 💥 实时异常及重建的堆栈跟踪(框架异常 + 未处理异常)
- 📝 控制台与结构化日志(Stdout / Stderr /
dart:developer) - 🌐 通过
dart:io分析捕获网络活动——涵盖 Dio 和package:http,无需拦截器 - 🎞️ 帧耗时,包含卡顿检测、百分位数和构建与光栅化的判定
- 🧭 路由感知——当前屏幕、转场,以及归因到实际发生问题的屏幕的故障
- 🧠 状态管理活动——将 Riverpod、Provider 和 Bloc 的频繁变动与重建风暴关联起来
- 🔁 Widget 重建归因——哪些 Widget 重建、重建频率、所在文件和行号,并将你的代码与包代码分开排名
- 🧬 来自 Inspector 的 Widget 树与选中 Widget 快照
- 🧮 内存(Dart 堆 / 外部内存)和 VM 时间线事件
- 🩺
diagnose_runtime——将证据关联起来,生成摘要 · 根因 · 证据 · 置信度 · 修复方案;置信度低于 70% 时会说**“未知”**,而不是产生幻觉 - 📊 位于
http://127.0.0.1:7373的实时浏览器仪表板——通过 WebSocket 实时传输所有信息,不依赖 AI 连接 - 🧩 附带可复用的
flutter-runtime-diagnosisClaude Code 技能
工具
| 工具 | 用途 | 安全性 |
|---|---|---|
connect_vm | 连接正在运行的应用的 Dart VM Service(ws:// 或 http://)。 | 会修改状态 |
ensure_tcp_device | Android 传输方式;推荐使用无线方式,也可选择切换到 USB。 | 会修改状态 |
runtime_health | 一次调用完成分类诊断——给出判定结果,以及异常、网络、帧和日志、内存摘要。 | 只读 |
what_changed | 提供故障发生前一段时间的证据和时间线。 | 只读 |
get_navigation | 当前路由和最近的路由转换,并列出各路由的失败情况。 | 只读 |
get_rebuilds | 将 Widget 重建热点定位到 Widget、文件和行。 | 只读 |
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 中的 Widget 树快照。 | 只读 |
get_selected_widget | Inspector 中当前选中的 Widget。 | 只读 |
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 注解,客户端可据此自行实施限制。
Agent 不应调用所有工具。推荐流程为
runtime_health → what_changed → 针对性调用 get_* → diagnose_runtime;
参见 AI Agent 集成。
安装
需要 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"]
}
}
}
也可以通过命令行添加:
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 | Dashboard HTTP/WS 端口。 |
DASHBOARD_HOST | 127.0.0.1 | 绑定地址(默认仅限 localhost)。 |
DASHBOARD_DISABLE | — | 设置为 1 以停用 Dashboard。 |
FLUTTER_LAMP_REDACT | on | 设置为 off 以保留原始凭据值。 |
FLUTTER_LAMP_REDACT_EXTRA | — | 以逗号分隔的额外请求头名称匹配模式,将对其进行脱敏。 |
使用方法
-
以 debug/profile 模式运行 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 查看实时 Dashboard——它与 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 切回。
实时 Dashboard
零依赖的深色 UI(原生 HTTP + WebSocket,无需构建步骤),实时流式传输运行时数据:
概览——会话报告:健康状况、FPS、内存、最差帧、MCP 活动,以及可链接到相关事件的发现(最差帧发现会打开筛选到该帧的时间线) · 日志(搜索 / 筛选 / 自动滚动) · 网络(可展开的请求头和耗时) · 异常 (可展开的堆栈跟踪) · 时间线 · 性能(实时画布图表) · MCP——连接的 Agent、它调用的每个工具,以及延迟、错误和响应大小 · 检查器——现有哪些检查链接,哪些仅支持拉取 · 诊断——测得的拓扑、各采集器的健康状况,以及此目标完全无法观测的内容。
控件:暂停/恢复 · 清除视图 · 导出 JSON · 各标签页搜索 · 自动重新连接。
该 UI 会区分看起来相似但含义不同的状态:0 MB 表示测量结果,尚未采样 表示没有测量结果;空标签页会说明是筛选器隐藏了行、采集器无法观测此目标,还是采集器正在监测但尚未发现内容。断开连接前采集的读数会明确标注,不会让人误以为它们是实时数据。
工作原理
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
所有数据都流经一个事件存储。添加新的运行时数据源,只需实现 Collector 接口并注册即可——其他层无需更改。
设计原则:仅使用官方 Flutter/Dart API,使用结构化 JSON 而非文本,不抓取 DevTools 数据,也绝不声称证据无法支持的原因。
限制
- 仅限调试/性能分析构建。 发布构建中无法使用 VM Service、Inspector 和
dart:ioHTTP 性能分析。 - 网络数据按需拉取。 Dart 不会为
dart:ioHTTP 提供推送流,因此只有在运行get_network或diagnose_runtime时才会获取请求,而不是持续流式传输。 - 异常不一定总能被观测到。 要触发
Debug.PauseException,应用必须启用异常暂停。只有在结构化错误报告开启时,widget inspector 才会发布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 标头中包含 Bearer 令牌和 Cookie,URI 中包含 API 密钥,开发者也会将凭据打印到日志中;所有捕获的数据都会交给大模型,并且会流式传输给任何正在查看仪表板的浏览器。
捕获时会对机密信息进行脱敏,因此它们永远不会进入事件存储,也就没有任何使用方能泄露从未存储过的信息。默认脱敏内容包括: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 Agent 集成 | Agent 应遵循的调查协议 |
| 改进计划 | 当前审查结果和优先级待办事项 |
| 可观测性路线图 | 架构目标、阶段和明确排除项 |
| 数据路径 | 运行时事件的实际流向,以及可观测内容 |
| 发布 | 如何筹备、标记和发布版本 |
| 设计 | 仪表盘设计系统——设计令牌、状态术语、组件规则 |
| 实现说明 | 构建过程中的非显而易见经验 |
贡献
欢迎提交问题和 PR。请保持模块化,优先使用官方 API 而非投机性方案,并为任何非简单逻辑添加 node:test 检查。
许可证
MIT © Chandrabhushan Prakash
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。