flutter-devtools-mcp 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +71 -39
- package/README.zh-CN.md +105 -137
- package/docs/README.md +1 -1
- package/docs/performance-metrics-guide.md +10 -20
- package/docs/performance-session-simple-design.md +15 -33
- package/package.json +2 -8
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -15,7 +15,8 @@ Connect AI agents to running Flutter apps for runtime inspection, profiling, and
|
|
|
15
15
|
|
|
16
16
|
- Auto-discover and connect to running Flutter apps
|
|
17
17
|
- Inspect widget tree and locate rebuild hotspots with source references
|
|
18
|
-
- Run session-based performance collection (frames,
|
|
18
|
+
- Run session-based performance collection (frames, jank@16.67ms, rebuilds, hot functions Self>20ms, GC Top5, scroll FPS, image decode, isolate, network, memory)
|
|
19
|
+
- Generate rule-engine `.ai.md` reports (runtime summary → findings → P0/P1/P2)
|
|
19
20
|
- Save and compare memory snapshots
|
|
20
21
|
- Execute debug actions (hot reload/restart, evaluate expression, screenshot)
|
|
21
22
|
|
|
@@ -24,27 +25,26 @@ Connect AI agents to running Flutter apps for runtime inspection, profiling, and
|
|
|
24
25
|
### Prerequisites
|
|
25
26
|
|
|
26
27
|
- Node.js >= 18
|
|
27
|
-
- A Flutter app running in `debug` or `profile` mode (recommended: `profile`)
|
|
28
|
+
- A Flutter app running in `debug` or `profile` mode (recommended: `profile` for metrics; use `debug` when you need rebuild tracking)
|
|
28
29
|
|
|
29
|
-
### Install
|
|
30
|
+
### Install via npm (recommended)
|
|
31
|
+
|
|
32
|
+
No local clone required:
|
|
30
33
|
|
|
31
34
|
```bash
|
|
32
|
-
|
|
33
|
-
cd flutter-devtools-mcp
|
|
34
|
-
npm install
|
|
35
|
-
npm run build
|
|
35
|
+
npx -y flutter-devtools-mcp
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
### MCP config
|
|
38
|
+
### MCP config (npx)
|
|
39
39
|
|
|
40
|
-
#### Cursor (`.cursor/mcp.json`)
|
|
40
|
+
#### Cursor (`.cursor/mcp.json` or Settings → MCP)
|
|
41
41
|
|
|
42
42
|
```json
|
|
43
43
|
{
|
|
44
44
|
"mcpServers": {
|
|
45
45
|
"flutter-devtools": {
|
|
46
|
-
"command": "
|
|
47
|
-
"args": ["
|
|
46
|
+
"command": "npx",
|
|
47
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -56,8 +56,8 @@ npm run build
|
|
|
56
56
|
{
|
|
57
57
|
"mcpServers": {
|
|
58
58
|
"flutter-devtools": {
|
|
59
|
-
"command": "
|
|
60
|
-
"args": ["
|
|
59
|
+
"command": "npx",
|
|
60
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -69,8 +69,8 @@ npm run build
|
|
|
69
69
|
{
|
|
70
70
|
"servers": {
|
|
71
71
|
"flutter-devtools": {
|
|
72
|
-
"command": "
|
|
73
|
-
"args": ["
|
|
72
|
+
"command": "npx",
|
|
73
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -78,12 +78,34 @@ npm run build
|
|
|
78
78
|
|
|
79
79
|
#### CodeBuddy (`.codebuddy/mcp.json`)
|
|
80
80
|
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"flutter-devtools": {
|
|
85
|
+
"command": "npx",
|
|
86
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Local build (optional)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
git clone https://github.com/treexi/flutter-devtools-ext.git
|
|
96
|
+
cd flutter-devtools-ext/flutter-devtools-mcp
|
|
97
|
+
npm install
|
|
98
|
+
npm run build
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then point MCP at the built entry:
|
|
102
|
+
|
|
81
103
|
```json
|
|
82
104
|
{
|
|
83
105
|
"mcpServers": {
|
|
84
106
|
"flutter-devtools": {
|
|
85
107
|
"command": "node",
|
|
86
|
-
"args": ["/path/to/flutter-devtools-mcp/dist/index.js"]
|
|
108
|
+
"args": ["/absolute/path/to/flutter-devtools-mcp/dist/index.js"]
|
|
87
109
|
}
|
|
88
110
|
}
|
|
89
111
|
}
|
|
@@ -95,6 +117,7 @@ Start your app:
|
|
|
95
117
|
|
|
96
118
|
```bash
|
|
97
119
|
flutter run --profile
|
|
120
|
+
# or: flutter run --debug # needed for rebuild tracking
|
|
98
121
|
```
|
|
99
122
|
|
|
100
123
|
Then ask your AI assistant:
|
|
@@ -103,7 +126,7 @@ Then ask your AI assistant:
|
|
|
103
126
|
Connect Flutter app, collect performance data for 30s (scenario: home feed scroll), and provide optimization suggestions based on code.
|
|
104
127
|
```
|
|
105
128
|
|
|
106
|
-
The AI calls `collect_performance_session` (blocking for 30s), then reads `filesToInspect` and returns P0/P1/P2 suggestions.
|
|
129
|
+
The AI calls `collect_performance_session` (blocking for ~30s), then reads `filesToInspect` and returns P0/P1/P2 suggestions.
|
|
107
130
|
|
|
108
131
|
Design docs:
|
|
109
132
|
|
|
@@ -112,25 +135,12 @@ Design docs:
|
|
|
112
135
|
- Doc index: [`docs/README.md`](docs/README.md)
|
|
113
136
|
- Image URL sample: [`examples/app_network_image_README.md`](examples/app_network_image_README.md)
|
|
114
137
|
|
|
115
|
-
## 4)
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
# Android debug regression
|
|
119
|
-
npm run test:regression:android
|
|
120
|
-
|
|
121
|
-
# Android profile regression (default duration)
|
|
122
|
-
npm run test:regression:android:profile
|
|
123
|
-
|
|
124
|
-
# Android profile regression (30s)
|
|
125
|
-
npm run test:regression:android:profile:30s
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## 5) Tool List (22)
|
|
138
|
+
## 4) Tool List (22)
|
|
129
139
|
|
|
130
140
|
### Performance Session
|
|
131
141
|
| Tool | Description |
|
|
132
142
|
|------|-------------|
|
|
133
|
-
| `collect_performance_session` | Block for N seconds (default 30), return JSON
|
|
143
|
+
| `collect_performance_session` | Block for N seconds (default 30), return JSON + `.ai.md`: frames/jank, rebuilds (debug), hot functions (Self>20ms), GC Top5, scroll FPS, image decode, isolate, memory, network |
|
|
134
144
|
|
|
135
145
|
### Discovery & Connection
|
|
136
146
|
| Tool | Description |
|
|
@@ -181,14 +191,35 @@ npm run test:regression:android:profile:30s
|
|
|
181
191
|
| `toggle_debug_paint` | Toggle debug paint |
|
|
182
192
|
| `evaluate_expression` | Evaluate Dart expression |
|
|
183
193
|
|
|
184
|
-
##
|
|
194
|
+
## 5) Recommendations and Limitations
|
|
185
195
|
|
|
186
196
|
- Prefer `profile` mode for accurate performance metrics: `flutter run --profile`
|
|
187
|
-
- `debug` mode adds overhead; use it for trend checks
|
|
197
|
+
- `debug` mode adds overhead; use it for trend checks and **rebuild tracking**
|
|
188
198
|
- Rebuild tracking extension is unavailable in `profile` mode (auto-degraded)
|
|
189
|
-
- Network capture depends on `dart:io` `HttpClient` timeline events
|
|
190
|
-
- `projectTopFunctions`
|
|
191
|
-
-
|
|
199
|
+
- Network capture depends on `dart:io` `HttpClient` timeline events (and HttpProfile when available)
|
|
200
|
+
- Hot functions (`projectTopFunctions`) track app `lib/` methods; on Android profile hit rate can be low — use 30~60s and keep interacting
|
|
201
|
+
- Jank budget is fixed at **16.67ms** (60 FPS)
|
|
202
|
+
- To attribute image decode to a **URL + ms**, use the shared loader sample: [`examples/app_network_image.dart`](./examples/app_network_image.dart) (writes `args.ms`)
|
|
203
|
+
|
|
204
|
+
## 6) Publish (GitHub Actions → npm)
|
|
205
|
+
|
|
206
|
+
1. Repo Settings → Secrets → Actions: create **`NPM_TOKEN`**
|
|
207
|
+
- [npm Access Tokens](https://www.npmjs.com/settings/~/tokens) → **Granular Access Token**
|
|
208
|
+
- Packages: Read and write
|
|
209
|
+
- Enable **Bypass two-factor authentication** (required for CI)
|
|
210
|
+
- Prefer enabling 2FA on the npm account first
|
|
211
|
+
2. Bump & tag:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cd flutter-devtools-mcp
|
|
215
|
+
npm version patch
|
|
216
|
+
git push origin main --tags
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
3. GitHub → Releases → publish the tag (e.g. `v0.3.1`), or run workflow **Publish npm** manually.
|
|
220
|
+
Workflow: [`.github/workflows/publish-npm.yml`](../.github/workflows/publish-npm.yml)
|
|
221
|
+
|
|
222
|
+
Tag version (without `v`) must match `package.json` `version`.
|
|
192
223
|
|
|
193
224
|
## 7) Roadmap
|
|
194
225
|
|
|
@@ -197,12 +228,13 @@ npm run test:regression:android:profile:30s
|
|
|
197
228
|
- [x] Network traffic inspection
|
|
198
229
|
- [x] Before/after snapshot comparison
|
|
199
230
|
- [x] Session-based performance collection (`collect_performance_session`)
|
|
200
|
-
- [
|
|
231
|
+
- [x] npm publish for `npx flutter-devtools-mcp`
|
|
232
|
+
- [ ] Continuous monitoring mode
|
|
201
233
|
- [ ] Integration test runner with performance baselines
|
|
202
234
|
- [ ] Shader compilation jank detection
|
|
203
|
-
- [ ] npm publish for `npx flutter-devtools-mcp`
|
|
204
235
|
|
|
205
236
|
## 8) License
|
|
206
237
|
|
|
207
238
|
MIT
|
|
208
239
|
|
|
240
|
+
Flutter and Dart are trademarks of Google LLC. This project is an independent, unofficial tool that talks to apps over the Dart VM Service; it is not affiliated with, endorsed by, or part of Google or the official Flutter DevTools.
|
package/README.zh-CN.md
CHANGED
|
@@ -15,97 +15,101 @@
|
|
|
15
15
|
|
|
16
16
|
- 自动发现并连接 Flutter 进程(无需手抄 VM URI)
|
|
17
17
|
- 查看 Widget 树、定位重建热点(含源码位置)
|
|
18
|
-
- 采集性能会话(帧、
|
|
18
|
+
- 采集性能会话(帧、jank@16.67ms、重建、耗时函数 Self>20ms、GC Top5、滚动 FPS、图片解码、Isolate、网络、内存)
|
|
19
|
+
- 生成规则引擎 `.ai.md` 报告(运行时摘要 → 问题清单 → P0/P1/P2)
|
|
19
20
|
- 做快照对比(内存前后变化)
|
|
20
21
|
- 执行调试动作(hot reload/restart、表达式求值、截图等)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
23
|
## 2. 快速开始
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
25
|
### 2.1 前置条件
|
|
29
26
|
|
|
30
27
|
- Node.js >= 18
|
|
31
|
-
- Flutter App 运行在 `debug` 或 `profile`
|
|
32
|
-
|
|
28
|
+
- Flutter App 运行在 `debug` 或 `profile` 模式(指标建议 `profile`;需要重建追踪用 `debug`)
|
|
33
29
|
|
|
30
|
+
### 2.2 用 npm 安装(推荐)
|
|
34
31
|
|
|
35
|
-
|
|
32
|
+
无需本地 clone / build:
|
|
36
33
|
|
|
37
34
|
```bash
|
|
38
|
-
|
|
39
|
-
cd flutter-devtools-mcp
|
|
40
|
-
npm install
|
|
41
|
-
npm run build
|
|
35
|
+
npx -y flutter-devtools-mcp
|
|
42
36
|
```
|
|
43
37
|
|
|
38
|
+
### 2.3 MCP 配置(npx)
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
### 2.3 MCP 配置
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
#### Cursor (`.cursor/mcp.json`)
|
|
40
|
+
#### Cursor(`.cursor/mcp.json` 或 Settings → MCP)
|
|
51
41
|
|
|
52
42
|
```json
|
|
53
43
|
{
|
|
54
44
|
"mcpServers": {
|
|
55
45
|
"flutter-devtools": {
|
|
56
|
-
"command": "
|
|
57
|
-
"args": ["
|
|
46
|
+
"command": "npx",
|
|
47
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
58
48
|
}
|
|
59
49
|
}
|
|
60
50
|
}
|
|
61
51
|
```
|
|
62
52
|
|
|
63
|
-
|
|
64
|
-
|
|
65
53
|
#### Claude Desktop (`claude_desktop_config.json`)
|
|
66
54
|
|
|
67
55
|
```json
|
|
68
56
|
{
|
|
69
57
|
"mcpServers": {
|
|
70
58
|
"flutter-devtools": {
|
|
71
|
-
"command": "
|
|
72
|
-
"args": ["
|
|
59
|
+
"command": "npx",
|
|
60
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
73
61
|
}
|
|
74
62
|
}
|
|
75
63
|
}
|
|
76
64
|
```
|
|
77
65
|
|
|
78
|
-
|
|
79
|
-
|
|
80
66
|
#### VS Code / Copilot (`.vscode/mcp.json`)
|
|
81
67
|
|
|
82
68
|
```json
|
|
83
69
|
{
|
|
84
70
|
"servers": {
|
|
85
71
|
"flutter-devtools": {
|
|
86
|
-
"command": "
|
|
87
|
-
"args": ["
|
|
72
|
+
"command": "npx",
|
|
73
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
88
74
|
}
|
|
89
75
|
}
|
|
90
76
|
}
|
|
91
77
|
```
|
|
92
78
|
|
|
93
|
-
|
|
94
|
-
|
|
95
79
|
#### CodeBuddy (`.codebuddy/mcp.json`)
|
|
96
80
|
|
|
97
81
|
```json
|
|
98
82
|
{
|
|
99
83
|
"mcpServers": {
|
|
100
84
|
"flutter-devtools": {
|
|
101
|
-
"command": "
|
|
102
|
-
"args": ["
|
|
85
|
+
"command": "npx",
|
|
86
|
+
"args": ["-y", "flutter-devtools-mcp"]
|
|
103
87
|
}
|
|
104
88
|
}
|
|
105
89
|
}
|
|
106
90
|
```
|
|
107
91
|
|
|
92
|
+
### 2.4 本地构建(可选)
|
|
108
93
|
|
|
94
|
+
```bash
|
|
95
|
+
git clone https://github.com/treexi/flutter-devtools-ext.git
|
|
96
|
+
cd flutter-devtools-ext/flutter-devtools-mcp
|
|
97
|
+
npm install
|
|
98
|
+
npm run build
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
然后 MCP 指向:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"flutter-devtools": {
|
|
107
|
+
"command": "node",
|
|
108
|
+
"args": ["/absolute/path/to/flutter-devtools-mcp/dist/index.js"]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
109
113
|
|
|
110
114
|
## 3. 推荐主流程:30s 性能会话
|
|
111
115
|
|
|
@@ -113,6 +117,7 @@ npm run build
|
|
|
113
117
|
|
|
114
118
|
```bash
|
|
115
119
|
flutter run --profile
|
|
120
|
+
# 或:flutter run --debug # 需要重建追踪时
|
|
116
121
|
```
|
|
117
122
|
|
|
118
123
|
然后在 AI 中直接说:
|
|
@@ -121,140 +126,99 @@ flutter run --profile
|
|
|
121
126
|
连接 Flutter App,开始采集性能数据 30s,场景:首页滚动,结合代码给优化方案
|
|
122
127
|
```
|
|
123
128
|
|
|
124
|
-
AI 会调用 `collect_performance_session
|
|
129
|
+
AI 会调用 `collect_performance_session`(阻塞约 30s)并返回结构化结果,随后结合 `filesToInspect` 源码给出 P0/P1/P2 优化建议。
|
|
125
130
|
|
|
126
131
|
**文档:**
|
|
127
132
|
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
131
|
-
- 图片 URL
|
|
132
|
-
|
|
133
|
+
- 指标怎么读:[`docs/performance-metrics-guide.md`](docs/performance-metrics-guide.md)
|
|
134
|
+
- 产品与数据结构:[`docs/performance-session-simple-design.md`](docs/performance-session-simple-design.md)
|
|
135
|
+
- 文档索引:[`docs/README.md`](docs/README.md)
|
|
136
|
+
- 图片 URL 埋点样板:[`examples/app_network_image_README.md`](examples/app_network_image_README.md)
|
|
133
137
|
|
|
138
|
+
## 4. Demo App
|
|
134
139
|
|
|
135
|
-
|
|
140
|
+
仓库内 [`../flutter-simple`](../flutter-simple) 是带故意性能问题的 Demo(高频 setState、网络图、后台 isolate)。
|
|
136
141
|
|
|
137
142
|
```bash
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
# Android profile 回归(默认时长)
|
|
142
|
-
npm run test:regression:android:profile
|
|
143
|
-
|
|
144
|
-
# Android profile 回归(30s)
|
|
145
|
-
npm run test:regression:android:profile:30s
|
|
143
|
+
cd ../flutter-simple
|
|
144
|
+
flutter run --debug -d <device>
|
|
146
145
|
```
|
|
147
146
|
|
|
148
|
-
|
|
147
|
+
然后用 MCP `collect_performance_session` 采集即可。
|
|
149
148
|
|
|
150
149
|
## 5. 工具清单(22)
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
154
151
|
### Performance Session
|
|
155
152
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
|
159
|
-
| `collect_performance_session` | 阻塞采集 N 秒(默认 30),返回 JSON:帧/jank、耗时函数(Self>20ms 异常)、重建(debug)、GC、滚动FPS、图片解码、Isolate、内存、网络;并生成带「开发者结论」的 `.ai.md` |
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
153
|
+
| Tool | Description |
|
|
154
|
+
|------|-------------|
|
|
155
|
+
| `collect_performance_session` | 阻塞采集 N 秒(默认 30),返回 JSON + `.ai.md`:帧/jank、重建(debug)、耗时函数(Self>20ms)、GC Top5、滚动 FPS、图片解码、Isolate、内存、网络 |
|
|
163
156
|
|
|
164
157
|
### Discovery & Connection
|
|
165
158
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `get_app_info` | 获取 VM / isolate / 平台信息与扩展能力 |
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
159
|
+
| Tool | Description |
|
|
160
|
+
|------|-------------|
|
|
161
|
+
| `discover_apps` | 自动发现并连接运行中的 Flutter App |
|
|
162
|
+
| `connect` | 通过 VM Service URI 手动连接 |
|
|
163
|
+
| `disconnect` | 断开连接 |
|
|
164
|
+
| `get_app_info` | 获取 VM / isolate / 平台信息与扩展能力 |
|
|
176
165
|
|
|
177
166
|
### Widget Inspection
|
|
178
167
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
|
182
|
-
| `
|
|
183
|
-
| `inspect_widget` | 深度查看 widget 属性/约束/render 信息 |
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
168
|
+
| Tool | Description |
|
|
169
|
+
|------|-------------|
|
|
170
|
+
| `get_widget_tree` | 获取 Widget 层级(含源码位置与项目过滤) |
|
|
171
|
+
| `inspect_widget` | 深度查看 widget 属性/约束/render 信息 |
|
|
187
172
|
|
|
188
173
|
### Rebuild Tracking
|
|
189
174
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
|
193
|
-
| `
|
|
194
|
-
| `stop_tracking_rebuilds` | 输出重建报告(次数、源码位置、建议) |
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
175
|
+
| Tool | Description |
|
|
176
|
+
|------|-------------|
|
|
177
|
+
| `start_tracking_rebuilds` | 开始追踪重建 |
|
|
178
|
+
| `stop_tracking_rebuilds` | 输出重建报告(次数、源码位置、建议) |
|
|
198
179
|
|
|
199
180
|
### Performance Profiling
|
|
200
181
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
|
204
|
-
| `
|
|
205
|
-
| `stop_profiling` | 输出帧、jank、hotspot、build/layout/paint 分析 |
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
182
|
+
| Tool | Description |
|
|
183
|
+
|------|-------------|
|
|
184
|
+
| `start_profiling` | 开始 timeline profiling |
|
|
185
|
+
| `stop_profiling` | 输出帧、jank、hotspot、build/layout/paint 分析 |
|
|
209
186
|
|
|
210
187
|
### Memory Analysis
|
|
211
188
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
| --------------------- | ---------------- |
|
|
189
|
+
| Tool | Description |
|
|
190
|
+
|------|-------------|
|
|
215
191
|
| `get_memory_snapshot` | 获取堆快照(含类分布、疑似异常) |
|
|
216
|
-
| `save_snapshot`
|
|
217
|
-
| `compare_snapshots`
|
|
218
|
-
| `list_snapshots`
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
192
|
+
| `save_snapshot` | 保存命名快照 |
|
|
193
|
+
| `compare_snapshots` | 对比两个快照差异 |
|
|
194
|
+
| `list_snapshots` | 列出所有快照 |
|
|
222
195
|
|
|
223
196
|
### Network
|
|
224
197
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
|
228
|
-
| `
|
|
229
|
-
| `stop_network_capture` | 输出 URL、状态码、耗时、体积、错误等统计 |
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
198
|
+
| Tool | Description |
|
|
199
|
+
|------|-------------|
|
|
200
|
+
| `start_network_capture` | 开始抓取 HTTP 流量 |
|
|
201
|
+
| `stop_network_capture` | 输出 URL、状态码、耗时、体积、错误等统计 |
|
|
233
202
|
|
|
234
203
|
### Debug Actions
|
|
235
204
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
|
239
|
-
| `
|
|
240
|
-
| `
|
|
241
|
-
| `
|
|
242
|
-
| `
|
|
243
|
-
| `evaluate_expression` | 执行 Dart 表达式 |
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
205
|
+
| Tool | Description |
|
|
206
|
+
|------|-------------|
|
|
207
|
+
| `hot_reload` | 触发 Hot Reload |
|
|
208
|
+
| `hot_restart` | 触发 Hot Restart |
|
|
209
|
+
| `take_screenshot` | 截图 |
|
|
210
|
+
| `toggle_debug_paint` | 切换 Debug Paint |
|
|
211
|
+
| `evaluate_expression` | 执行 Dart 表达式 |
|
|
247
212
|
|
|
248
213
|
## 6. 使用建议与限制
|
|
249
214
|
|
|
250
215
|
- 推荐在 `profile` 模式采集性能数据:`flutter run --profile`
|
|
251
|
-
- `debug`
|
|
216
|
+
- `debug` 有额外检查开销;需要 **重建追踪** 时用 debug
|
|
252
217
|
- `profile` 下不支持 Widget 重建追踪扩展(会自动降级)
|
|
253
|
-
- 网络采集基于 `dart:io` `HttpClient`
|
|
254
|
-
-
|
|
255
|
-
-
|
|
256
|
-
|
|
257
|
-
|
|
218
|
+
- 网络采集基于 `dart:io` `HttpClient` / HttpProfile,部分封装可能不完整
|
|
219
|
+
- 耗时函数(`projectTopFunctions`)为业务 `lib/` 方法;Android profile 下命中率可能偏低,建议 30~60s 并持续操作
|
|
220
|
+
- 掉帧预算固定 **16.67ms**(60FPS)
|
|
221
|
+
- 图片解码若要带 **URL + ms**,请用统一入口样板:[`examples/app_network_image.dart`](./examples/app_network_image.dart)(写入 `args.ms`)
|
|
258
222
|
|
|
259
223
|
## 7. 路线图
|
|
260
224
|
|
|
@@ -263,30 +227,34 @@ npm run test:regression:android:profile:30s
|
|
|
263
227
|
- [x] 支持网络流量检查
|
|
264
228
|
- [x] 支持前后快照对比
|
|
265
229
|
- [x] 支持会话式性能采集(`collect_performance_session`)
|
|
230
|
+
- [x] 发布到 npm(支持 `npx flutter-devtools-mcp`)
|
|
266
231
|
- [ ] 持续监控模式(实时卡顿监视)
|
|
267
232
|
- [ ] 集成测试运行器(含性能基线对比)
|
|
268
233
|
- [ ] Shader 编译卡顿检测
|
|
269
|
-
- [x] 发布到 npm(支持 `npx flutter-devtools-mcp`)
|
|
270
|
-
|
|
271
|
-
|
|
272
234
|
|
|
273
235
|
## 8. 发版(GitHub Actions → npm)
|
|
274
236
|
|
|
275
|
-
1. 仓库 Settings → Secrets and variables → Actions,新增 **`NPM_TOKEN
|
|
237
|
+
1. 仓库 Settings → Secrets and variables → Actions,新增 **`NPM_TOKEN`**
|
|
238
|
+
- 打开 [npm Access Tokens](https://www.npmjs.com/settings/~/tokens)
|
|
239
|
+
- 账号建议先开 [2FA](https://www.npmjs.com/settings/~/account/security)(Authorization and writing)
|
|
240
|
+
- 创建 **Granular Access Token**:Packages **Read and write**,勾选 **Bypass two-factor authentication**(CI 必须)
|
|
241
|
+
- Secret 名必须是 `NPM_TOKEN`
|
|
276
242
|
2. 改版本并提交:
|
|
277
243
|
```bash
|
|
278
244
|
cd flutter-devtools-mcp
|
|
279
|
-
npm version patch # 0.3.
|
|
245
|
+
npm version patch # 例如 0.3.1 → 0.3.2
|
|
280
246
|
git push origin main --tags
|
|
281
247
|
```
|
|
282
|
-
3. GitHub → **Releases** →
|
|
283
|
-
→ 自动跑 [`.github/workflows/publish-npm.yml`](../.github/workflows/publish-npm.yml)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
> Tag 版本(去掉前缀 `v`)必须与 `package.json` 的 `version` 一致。
|
|
287
|
-
|
|
248
|
+
3. GitHub → **Releases** → 用对应 tag(如 `v0.3.2`)发布
|
|
249
|
+
→ 自动跑 [`.github/workflows/publish-npm.yml`](../.github/workflows/publish-npm.yml)
|
|
250
|
+
或在 Actions 里对 **Publish npm** 手动 Run workflow
|
|
288
251
|
|
|
252
|
+
> `ENEEDAUTH`:未配置 / 空的 `NPM_TOKEN`
|
|
253
|
+
> `403 … bypass 2fa`:请按上面重建 **Granular + Bypass 2FA** token
|
|
254
|
+
> Tag(去掉 `v`)必须与 `package.json` 的 `version` 一致
|
|
289
255
|
|
|
290
256
|
## 9. License
|
|
291
257
|
|
|
292
|
-
MIT
|
|
258
|
+
MIT
|
|
259
|
+
|
|
260
|
+
Flutter / Dart 为 Google LLC 商标。本项目为独立的非官方工具,通过 Dart VM Service 连接运行中的 App,与 Google 或官方 Flutter DevTools **无隶属或背书关系**。
|
package/docs/README.md
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
| [performance-session-simple-design.md](./performance-session-simple-design.md) | 产品 / 实现 | `collect_performance_session` 交互、参数、数据结构 |
|
|
7
7
|
| [performance-audit-requirements.md](./performance-audit-requirements.md) | 规划 | 重型 MD/HTML 审计(P2,非当前主路径) |
|
|
8
8
|
| [../examples/app_network_image_README.md](../examples/app_network_image_README.md) | 业务接入 | 统一图片入口,解码带 URL |
|
|
9
|
-
| [../README.zh-CN.md](../README.zh-CN.md) | 全员 |
|
|
9
|
+
| [../README.zh-CN.md](../README.zh-CN.md) | 全员 | 安装(npx)、快速开始、工具表、发版 |
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## 1. 推荐用法(两分钟)
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
# 1) 性能主采(帧 /
|
|
12
|
+
# 1) 性能主采(帧 / 耗时函数 / GC / 图片解码更准)
|
|
13
13
|
flutter run --profile
|
|
14
14
|
|
|
15
15
|
# 2) AI 对话
|
|
@@ -56,7 +56,7 @@ flutter run --profile
|
|
|
56
56
|
| **滚动段 FPS / 段 jank** | 2s 窗口分段 | 滑动 <50FPS 或段 jank 高 | 列表滑动卡顿 |
|
|
57
57
|
| **Build / Layout / Paint max** | Timeline 阶段 | 单阶段经常 >8~16ms | 卡在 build / 布局 / 绘制哪一段 |
|
|
58
58
|
|
|
59
|
-
**限制**:Android profile 下 Timeline 帧事件偶发偏少 → 摘要可能 ⚪无数据,此时以
|
|
59
|
+
**限制**:Android profile 下 Timeline 帧事件偶发偏少 → 摘要可能 ⚪无数据,此时以 **耗时函数 / 图片解码** 为准。
|
|
60
60
|
|
|
61
61
|
### 3.2 归因:卡在哪
|
|
62
62
|
|
|
@@ -64,7 +64,7 @@ flutter run --profile
|
|
|
64
64
|
|------|------|------------|------|
|
|
65
65
|
| **耗时函数 Top(lib/)** | VM `getCpuSamples` + 路径过滤;**Self >20ms → 🔴异常** | 哪个业务方法占时间 | 比框架 `drawFrame` 有用;框架热点不进开发者结论 |
|
|
66
66
|
| **Widget 重建 Top** | inspector 扩展 | 哪个组件重建过多、文件:行号 | **仅 debug**;profile 固定 ⚪无数据 |
|
|
67
|
-
| **filesToInspect** | 重建 +
|
|
67
|
+
| **filesToInspect** | 重建 + 耗时函数 文件 | 该打开哪些源码 | AI/人工优先读这些文件 |
|
|
68
68
|
|
|
69
69
|
### 3.3 尖刺:偶发卡一下
|
|
70
70
|
|
|
@@ -102,7 +102,7 @@ flutter run --profile
|
|
|
102
102
|
**能发现:**
|
|
103
103
|
|
|
104
104
|
1. **卡顿尖刺来自 GC**:最长经常 >16~32ms,或 >8ms 很多次
|
|
105
|
-
2. **分配偏勤(间接)**:次数极高 → 短命对象多(临时 List
|
|
105
|
+
2. **分配偏勤(间接)**:次数极高 → 短命对象多(临时 List、字符串、闭包、解码缓冲);需结合耗时函数/重建
|
|
106
106
|
3. **交叉验证**:与 setState / 热循环 / 大图同时出现时,GC 高往往是副作用
|
|
107
107
|
|
|
108
108
|
**发现不了:**
|
|
@@ -131,7 +131,8 @@ flutter run --profile
|
|
|
131
131
|
**推荐**:全站网络图走统一入口 [`AppNetworkImage`](../examples/app_network_image.dart):
|
|
132
132
|
|
|
133
133
|
- Timeline 事件名:`app.imageDecode`
|
|
134
|
-
- arguments:`url
|
|
134
|
+
- arguments:`url`(必填),**`ms`(必填,Stopwatch 耗时)**,`width` / `height` / `bytes`(可选)
|
|
135
|
+
- 跨 `await` 时 B/E 常丢时长,样板用 instant + `args.ms`;MCP 优先读该字段
|
|
135
136
|
|
|
136
137
|
报告示例:
|
|
137
138
|
|
|
@@ -162,11 +163,12 @@ flutter run --profile
|
|
|
162
163
|
|
|
163
164
|
---
|
|
164
165
|
|
|
165
|
-
## 7.
|
|
166
|
+
## 7. 耗时函数为什么曾为空 / 怎么读
|
|
166
167
|
|
|
167
168
|
- 过滤规则:业务 `lib/` / `package:<app>/`,排除 Flutter SDK、`dart:ui` 等误归一路径
|
|
168
169
|
- Android profile 下 Self 时间常落在框架叶子;业务方法靠采样 + 路径/符号命中
|
|
169
170
|
- Demo 可用 `Timeline` / `@pragma('vm:never-inline')` 提高命中率
|
|
171
|
+
- **Self >20ms → 报告标 🔴异常**
|
|
170
172
|
- **看 `projectTopFunctions`,不要看框架 `topFunctions` 当根因**
|
|
171
173
|
|
|
172
174
|
---
|
|
@@ -176,7 +178,7 @@ flutter run --profile
|
|
|
176
178
|
```text
|
|
177
179
|
1. 开发者结论里的 P0
|
|
178
180
|
2. 🔴 行:图片解码(带 URL)/ 高 jank / 滚动最差段
|
|
179
|
-
3.
|
|
181
|
+
3. 耗时函数 Top → 打开 filesToInspect
|
|
180
182
|
4. 🟡 GC / 内存 → 当旁证,回到分配与重建
|
|
181
183
|
5. debug 补采重建(若怀疑 setState 风暴)
|
|
182
184
|
```
|
|
@@ -190,18 +192,6 @@ flutter run --profile
|
|
|
190
192
|
| [performance-session-simple-design.md](./performance-session-simple-design.md) | 产品形态、工具参数、数据结构、AI 话术 |
|
|
191
193
|
| [performance-audit-requirements.md](./performance-audit-requirements.md) | 重型 MD/HTML 审计(P2 规划,非当前主路径) |
|
|
192
194
|
| [../examples/app_network_image_README.md](../examples/app_network_image_README.md) | 图片统一入口接入 |
|
|
193
|
-
| [../README.zh-CN.md](../README.zh-CN.md) |
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
## 10. 回归
|
|
198
|
-
|
|
199
|
-
```bash
|
|
200
|
-
cd flutter-devtools-mcp
|
|
201
|
-
npm run build
|
|
202
|
-
npm run test:regression:android:profile
|
|
203
|
-
# 或 30s:
|
|
204
|
-
npm run test:regression:android:profile:30s
|
|
205
|
-
```
|
|
195
|
+
| [../README.zh-CN.md](../README.zh-CN.md) | 安装、MCP 配置(npx)、工具清单、发版 |
|
|
206
196
|
|
|
207
197
|
报告默认落在 Flutter 工程下:`performance-sessions/*.json` + `*.ai.md`。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Flutter 性能采集会话 —
|
|
1
|
+
# Flutter 性能采集会话 — 方案设计
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **产品形态**:用户一句话完成一次采集;MCP 负责采数据;AI 负责结合代码出优化方案。
|
|
4
4
|
> **优先级**:本方案为 P0;[`performance-audit-requirements.md`](./performance-audit-requirements.md) 中的重型报告降为 P2 可选。
|
|
5
5
|
> **指标怎么读(开发者)**:见 [`performance-metrics-guide.md`](./performance-metrics-guide.md)。
|
|
6
6
|
|
|
@@ -61,9 +61,9 @@ sequenceDiagram
|
|
|
61
61
|
|
|
62
62
|
| 角色 | 职责 | 不做 |
|
|
63
63
|
|------|------|------|
|
|
64
|
-
| **你** | `flutter run
|
|
65
|
-
| **MCP** | 连接 VM
|
|
66
|
-
| **AI** | 解析人话 →
|
|
64
|
+
| **你** | `flutter run`;一句话触发采集;App 内操作约 30s | 不调 MCP 工具名 |
|
|
65
|
+
| **MCP** | 连接 VM;并行采集;时长到后输出结构化 JSON + `.ai.md` | 不调 LLM;不读源码 |
|
|
66
|
+
| **AI** | 解析人话 → 调工具;返回后读代码 → 写优化方案 | 不代替你在 App 里操作 |
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
@@ -84,7 +84,7 @@ AI **必须依次**:
|
|
|
84
84
|
|
|
85
85
|
## 5. MCP 工具设计
|
|
86
86
|
|
|
87
|
-
### 5.1
|
|
87
|
+
### 5.1 连接类(采集前)
|
|
88
88
|
|
|
89
89
|
| 工具 | 用途 |
|
|
90
90
|
|------|------|
|
|
@@ -337,10 +337,11 @@ interface PerformanceSessionResult {
|
|
|
337
337
|
## 9. 前置条件
|
|
338
338
|
|
|
339
339
|
```bash
|
|
340
|
-
#
|
|
340
|
+
# 终端:启动 App(推荐 profile;需要重建追踪用 debug)
|
|
341
341
|
flutter run --profile
|
|
342
342
|
|
|
343
|
-
# Cursor
|
|
343
|
+
# Cursor / Claude:MCP 用 npx(见 README.zh-CN §2.3)
|
|
344
|
+
# command: npx , args: ["-y", "flutter-devtools-mcp"]
|
|
344
345
|
# 工作区:打开 Flutter 项目根目录(AI 才能读 lib/)
|
|
345
346
|
```
|
|
346
347
|
|
|
@@ -351,37 +352,18 @@ flutter run --profile
|
|
|
351
352
|
| 情况 | AI 回复要点 |
|
|
352
353
|
|------|-------------|
|
|
353
354
|
| 未发现 App | 提示先 `flutter run`,或粘贴 VM URI |
|
|
354
|
-
|
|
|
355
|
-
| 未 start 就 stop | 提示先执行第一轮话术 |
|
|
356
|
-
| 采集 < 5s | 警告数据可能不足,建议重新采 30s |
|
|
355
|
+
| 采集时长过短 | 警告数据可能不足,建议重新采 30s |
|
|
357
356
|
| 网络为空 | 说明可能未走 dart:io,其他维度仍给方案 |
|
|
357
|
+
| profile 无重建 | 说明平台限制,需要时 debug 补采 |
|
|
358
358
|
|
|
359
359
|
---
|
|
360
360
|
|
|
361
361
|
## 11. 验收标准
|
|
362
362
|
|
|
363
|
-
1.
|
|
364
|
-
2.
|
|
365
|
-
3.
|
|
366
|
-
4.
|
|
367
|
-
5. 原有 21 个工具行为不变
|
|
368
|
-
|
|
369
|
-
---
|
|
370
|
-
|
|
371
|
-
## 13. 回归命令(当前)
|
|
372
|
-
|
|
373
|
-
```bash
|
|
374
|
-
# Android debug 回归
|
|
375
|
-
npm run test:regression:android
|
|
376
|
-
|
|
377
|
-
# Android profile 回归(默认时长)
|
|
378
|
-
npm run test:regression:android:profile
|
|
379
|
-
|
|
380
|
-
# Android profile 回归(30s)
|
|
381
|
-
npm run test:regression:android:profile:30s
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
> 说明:profile 模式不支持 Widget 重建追踪;帧数偶发偏低时,以 `vm-samples` + 网络 + AI 规则分析为准。
|
|
363
|
+
1. 一句话术后,`collect_performance_session` 阻塞约 30s 并返回合法 JSON + `.ai.md`
|
|
364
|
+
2. JSON 含运行时摘要字段、`filesToInspect`、`projectTopFunctions`(耗时函数)等
|
|
365
|
+
3. AI 能根据 `filesToInspect` 打开对应 dart 文件并输出 P0/P1 方案
|
|
366
|
+
4. 原有独立工具行为不变(加上会话工具共 22 个)
|
|
385
367
|
|
|
386
368
|
---
|
|
387
369
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flutter-devtools-mcp",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "MCP server that connects AI agents to Flutter
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "MCP server that connects AI agents to running Flutter apps via the Dart VM Service for runtime inspection, profiling, and debugging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -20,12 +20,6 @@
|
|
|
20
20
|
"start": "node dist/index.js",
|
|
21
21
|
"dev": "tsx src/index.ts",
|
|
22
22
|
"prepublishOnly": "npm run build",
|
|
23
|
-
"test:regression": "node scripts/regression-performance-session.mjs",
|
|
24
|
-
"test:regression:spawn": "node scripts/regression-performance-session.mjs --spawn",
|
|
25
|
-
"test:regression:android": "FLUTTER_DEVICE=android node scripts/regression-performance-session.mjs --spawn",
|
|
26
|
-
"test:regression:android:profile": "FLUTTER_DEVICE=android FLUTTER_RUN_MODE=profile node scripts/regression-performance-session.mjs --spawn",
|
|
27
|
-
"test:regression:android:profile:30s": "FLUTTER_DEVICE=android FLUTTER_RUN_MODE=profile REGRESSION_DURATION_SEC=30 node scripts/regression-performance-session.mjs --spawn",
|
|
28
|
-
"test:regression:ios": "FLUTTER_DEVICE=ios node scripts/regression-performance-session.mjs --spawn",
|
|
29
23
|
"prepare": "npm run build"
|
|
30
24
|
},
|
|
31
25
|
"keywords": [
|