flutter开发工具mcp
赋予AI代理在运行时检查、分析和调试Flutter应用程序的能力。
MCP(模型上下文协议)服务器,连接AI编码助手,如 光标, 克劳德代码, 帆板运动,以及 GitHub Copilot 通过Dart VM服务协议运行Flutter应用程序。
不要在IDE和DevTools之间切换,只需告诉你的AI助手:
*“找到我正在运行的Flutter应用程序并连接到它”* *“当我滚动浏览提要时,跟踪小部件会重建”* *拍摄内存快照,我将修复泄漏,然后进行比较*
┌─────────────────┐ stdio ┌──────────────────────┐ WebSocket ┌─────────────────┐
│ AI Agent │◄──────────────►│ flutter-devtools-mcp │◄─────────────►│ Flutter App │
│ (Cursor/Claude) │ │ (MCP Server) │ VM Service │ (--profile) │
└─────────────────┘ └──────────────────────┘ └─────────────────┘特性
自动发现
- 自动查找您计算机上正在运行的Flutter应用程序
- 无需手动复制URI——只需说“连接到我的Flutter应用程序”
- 扫描进程、临时文件和常用端口
小部件树检查
- 获取具有源文件位置的任何屏幕的完整小部件层次结构
- 过滤器仅显示项目的小部件(跳过框架内部)
- 深入检查单个小部件的约束、大小和状态
- 递归扩展整个树,而不仅仅是第一级
小部件重建跟踪
- 准确跟踪哪些小部件重建以及重建次数
- 每个重建小部件的源文件和行号
- 严重性额定输出(绿色/黄色/橙色/红色)
- 减少不必要重建的可行建议
性能分析
- 在与应用程序交互时启动/停止分析会话
- 具有jank检测的逐帧分析
- 具有严重性评级的CPU热点识别
- 构建/布局/涂漆阶段分解
- 人工智能生成的解决性能问题的建议
内存分析
- 堆使用情况概述及利用率百分比
- 应用程序和框架类与VM内部分离
- 自动检测可疑的分配模式
- 为确保准确性,快照前可选择强制GC
快照比较(差异之前/之后)
- 随时保存命名内存快照
- 比较两个快照,看看到底发生了什么变化
- 显示哪些类随着字节和实例增量而增长/收缩
- 结论:你的修复真的提高了记忆力吗?
网络流量检查器
- 实时捕获HTTP请求和响应
- 方法、URL、状态代码、响应时间、有效载荷大小
- 标记慢速请求(>2s)和大型响应(>500KB)
- 跟踪失败请求时出错
- 注: 依赖于
dart:ioHttpClient时间线事件。可能无法捕获来自某些GraphQL客户端(Ferry、gql_http_link)或绕过的自定义http实现的流量dart:io仪器。
调试操作
- 热重新加载 --在不丢失状态的情况下注入代码更改
- 热重启 --完全重启,无需重建
- 截图 --捕获当前屏幕
- 调试油漆 --切换小部件边界可视化
- 表达式求值 --在实时应用程序中运行Dart表达式
快速开始
先决条件
- Node.js>=18
- 运行在中的Flutter应用程序 调试 或 个人资料 模式
安装
在本地克隆和构建:
git clone https://github.com/draganbajic/flutter-devtools-mcp.git
cd flutter-devtools-mcp
npm install
npm run build配置
光标
添加到您的 .cursor/mcp.json:
{
"mcpServers": {
"flutter-devtools": {
"command": "node",
"args": ["/path/to/flutter-devtools-mcp/dist/index.js"]
}
}
}克劳德桌面版
添加到您的 claude_desktop_config.json:
{
"mcpServers": {
"flutter-devtools": {
"command": "node",
"args": ["/path/to/flutter-devtools-mcp/dist/index.js"]
}
}
}VS代码(GitHub副本)
添加到您的 .vscode/mcp.json:
{
"servers": {
"flutter-devtools": {
"command": "node",
"args": ["/path/to/flutter-devtools-mcp/dist/index.js"]
}
}
}用法
- 启动Flutter应用程序 在调试或配置文件模式下:
flutter run --profile- 让您的AI代理发现并连接:
“找到我正在运行的Flutter应用程序并连接到它”
或者使用终端中打印的VM服务URI手动连接:
“连接到我的Flutter应用程序http://127.0.0.1:50000/AbCdEf=/"
- 开始检查:
“显示小部件树”
“滚动列表时,跟踪小部件重建”
“在我进行更改之前,先拍摄内存快照”
“开始分析,我会四处导航……好吧,停下来”
“在我拉取刷新时捕获网络流量”
工具参考(21个工具)
发现与连接
| 工具 | 说明 |
|---|---|
discover_apps | 自动查找正在运行的Flutter应用程序并连接 |
connect | 通过VM服务URI连接到Flutter应用程序 |
disconnect | 断开与应用程序的连接 |
get_app_info | VM信息、隔离、平台详细信息、扩展 |
小部件检查
| 工具 | 说明 |
|---|---|
get_widget_tree | 带有源位置和项目筛选的小部件层次结构 |
inspect_widget | 深入检查小部件的属性、约束、呈现信息 |
重建跟踪
| 工具 | 说明 |
|---|---|
start_tracking_rebuilds | 开始跟踪重建哪些小部件 |
stop_tracking_rebuilds | 获取报告:小部件名称、重建计数、源位置 |
性能分析
| 工具 | 说明 |
|---|---|
start_profiling | 开始时间线分析会话 |
stop_profiling | 获取分析:帧、jank、热点、相位分解 |
内存分析
| 工具 | 说明 |
|---|---|
get_memory_snapshot | 带有应用程序类分解和泄漏检测的堆配置文件 |
save_snapshot | 保存命名快照以供以后比较 |
compare_snapshots | 区分两个快照:什么增长了,什么缩小了,判决 |
list_snapshots | 列出所有已保存的快照 |
网络
| 工具 | 说明 |
|---|---|
start_network_capture | 开始捕获HTTP流量 |
stop_network_capture | 报告:URL、状态代码、时间、大小、错误 |
调试操作
| 工具 | 说明 |
|---|---|
hot_reload | 触发热重新加载 |
hot_restart | 触发热重启 |
take_screenshot | 将当前屏幕捕获为PNG格式 |
toggle_debug_paint | 切换调试绘制覆盖 |
evaluate_expression | 在运行中的应用程序中计算Dart表达式 |
示例输出
小部件重建报告
═══════════════════════════════════════════════════════════
WIDGET REBUILD REPORT
═══════════════════════════════════════════════════════════
📊 SUMMARY
───────────────────────────────────────────────────────────
Tracked for 6.2s
Total rebuilds: 1,847
Unique widgets rebuilt: 34
Average rebuilds per widget: 54.3
🔥 TOP REBUILDING WIDGETS
───────────────────────────────────────────────────────────
🔴 312x | OrderCard [order_card.dart:15]
🔴 287x | Text [order_card.dart:43]
🔴 284x | StatusBadge [order_card.dart:48]
🟠 94x | SummaryCard [summary_card.dart:11]
🟠 74x | DashboardScreen [dashboard_screen.dart:18]
🟡 28x | SliverAppBar [dashboard_screen.dart:58]
🟢 4x | Navigator [app_router.dart:31]
💡 RECOMMENDATIONS
───────────────────────────────────────────────────────────
• OrderCard rebuilt 312x [order_card.dart:15]
→ Check if it depends on a Provider that changes too
frequently. Consider using context.select() instead
of context.watch() or adding a const constructor.快照比较
═══════════════════════════════════════════════════════════
SNAPSHOT COMPARISON
"before-fix" → "after-fix"
═══════════════════════════════════════════════════════════
📊 HEAP OVERVIEW
───────────────────────────────────────────────────────────
🟢 Heap usage: 182.84 MB → 94.12 MB (-88.72 MB, -48.5%)
Capacity: 199.52 MB → 128.00 MB (-71.52 MB)
📉 SHRANK (top 5)
───────────────────────────────────────────────────────────
🔻 -42.30 MB | -3,412 inst | _Uint8List
🔻 -18.20 MB | -847 inst | _ImageInfo
🔻 -6.40 MB | -624 inst | StreamSubscription
💡 VERDICT
───────────────────────────────────────────────────────────
✅ Memory improved by 88.72 MB (-48.5%). Nice work!性能分析
═══════════════════════════════════════════════════════════
FLUTTER PERFORMANCE ANALYSIS REPORT
═══════════════════════════════════════════════════════════
📊 SUMMARY
───────────────────────────────────────────────────────────
Profiled for 8.0s, captured 481 frames
Average frame time: 8.94ms (target: 16.7ms)
⚠️ 38 janky frames detected (7.9% of total)
Worst frame: 94.32ms (5.6x target)
🔧 PHASE BREAKDOWN
───────────────────────────────────────────────────────────
Build: avg 3.12ms | max 38.40ms | 962 calls
Layout: avg 1.94ms | max 22.10ms | 481 calls
Paint: avg 2.08ms | max 14.80ms | 481 calls
🔥 CPU HOTSPOTS
───────────────────────────────────────────────────────────
🔴 Build [CRITICAL]
Total: 3001.4ms | Avg: 3.1ms | Max: 38.4ms | Calls: 962
💡 RECOMMENDATIONS
───────────────────────────────────────────────────────────
• HIGH: Excessive widget rebuilds detected (962 builds for
481 frames). Check for unnecessary setState calls, missing
const widgets, or improper use of context.watch().控件树
Widget Tree (68 widgets, 42 from project, depth: 18)
────────────────────────────────────────────────────────────
RootWidget (1 children)
MyApp ★ (1 children) [main.dart:12]
MaterialApp ★ (1 children) [app.dart:45]
Navigator ★ (2 children) [app_router.dart:31]
DashboardScreen ★ (1 children) [dashboard_screen.dart:18]
Scaffold ★ (2 children) [dashboard_screen.dart:42]
CustomScrollView ★ (3 children) [dashboard_screen.dart:56]
SliverList ★ (1 children) [dashboard_screen.dart:71]
OrderCard ★ (2 children) [order_card.dart:15]
Row ★ (3 children) [order_card.dart:34]
CachedNetworkImage ★ [order_card.dart:36]
Text ★ [order_card.dart:43]
StatusBadge ★ [order_card.dart:48]
BottomNavigationBar ★ (4 children) [dashboard_screen.dart:95]配置文件模式与调试模式
为了获得准确的性能数据,请始终使用配置文件模式:
flutter run --profile调试模式包括断言和调试检查的开销,这些开销会使性能看起来比实际情况更差。MCP服务器在这两种模式下都能工作,但对调试模式下的分析数据应该持保留态度。
运作原理
此MCP服务器通过以下方式与您的Flutter应用程序通信 Dart VM服务协议 --Flutter DevTools在底层使用的协议相同。当您在调试或配置文件模式下运行Flutter应用程序时,它会公开一个WebSocket端点,该端点支持JSON-RPC 2.0命令,用于:
- 隔离管理和检查
- 小部件树遍历(通过Flutter服务扩展)
- 小部件重建跟踪(
trackRebuildDirtyWidgets) - 时间线和CPU分析
- 内存分配跟踪
- HTTP流量记录
- 代码评估
- 热重新加载/重新启动
MCP服务器将这些低级协议调用封装到AI代理友好的工具中,这些工具具有结构化的输出、严重性评级和可操作的建议,因此AI可以对应用程序的运行时行为进行推理,并提出具体的修复建议。
路线图
- \[x\] 自动发现正在运行的Flutter应用程序
- \[x\] 小部件重建源位置跟踪
- \[x\] 网络流量检查
- \[x\] 快照比较之前/之后
- \[\]连续监控模式(实时监视jank)
- \[\]具有性能基线的集成测试运行器
- \[\]着色器编译错误检测
- \[\]将报告导出为markdown/HTML
- \[\]npm发布
npx flutter-devtools-mcp
贡献
欢迎投稿!请打开问题或PR。
许可证
麻省理工学院
