flutter-devtools-mcp 0.3.1
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 +21 -0
- package/README.md +208 -0
- package/README.zh-CN.md +292 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/services/ai-analysis.d.ts +6 -0
- package/dist/services/ai-analysis.d.ts.map +1 -0
- package/dist/services/ai-analysis.js +728 -0
- package/dist/services/ai-analysis.js.map +1 -0
- package/dist/services/collect-progress.d.ts +6 -0
- package/dist/services/collect-progress.d.ts.map +1 -0
- package/dist/services/collect-progress.js +23 -0
- package/dist/services/collect-progress.js.map +1 -0
- package/dist/services/cpu-profiler-service.d.ts +42 -0
- package/dist/services/cpu-profiler-service.d.ts.map +1 -0
- package/dist/services/cpu-profiler-service.js +208 -0
- package/dist/services/cpu-profiler-service.js.map +1 -0
- package/dist/services/cpu-symbol-filter.d.ts +10 -0
- package/dist/services/cpu-symbol-filter.d.ts.map +1 -0
- package/dist/services/cpu-symbol-filter.js +90 -0
- package/dist/services/cpu-symbol-filter.js.map +1 -0
- package/dist/services/http-profile-parser.d.ts +4 -0
- package/dist/services/http-profile-parser.d.ts.map +1 -0
- package/dist/services/http-profile-parser.js +71 -0
- package/dist/services/http-profile-parser.js.map +1 -0
- package/dist/services/json-parse-aggregate.d.ts +30 -0
- package/dist/services/json-parse-aggregate.d.ts.map +1 -0
- package/dist/services/json-parse-aggregate.js +155 -0
- package/dist/services/json-parse-aggregate.js.map +1 -0
- package/dist/services/network-aggregate.d.ts +50 -0
- package/dist/services/network-aggregate.d.ts.map +1 -0
- package/dist/services/network-aggregate.js +185 -0
- package/dist/services/network-aggregate.js.map +1 -0
- package/dist/services/network-capture-service.d.ts +50 -0
- package/dist/services/network-capture-service.d.ts.map +1 -0
- package/dist/services/network-capture-service.js +187 -0
- package/dist/services/network-capture-service.js.map +1 -0
- package/dist/services/network-capture.d.ts +2 -0
- package/dist/services/network-capture.d.ts.map +1 -0
- package/dist/services/network-capture.js +2 -0
- package/dist/services/network-capture.js.map +1 -0
- package/dist/services/performance-session.d.ts +41 -0
- package/dist/services/performance-session.d.ts.map +1 -0
- package/dist/services/performance-session.js +697 -0
- package/dist/services/performance-session.js.map +1 -0
- package/dist/services/performance-thresholds.d.ts +17 -0
- package/dist/services/performance-thresholds.d.ts.map +1 -0
- package/dist/services/performance-thresholds.js +19 -0
- package/dist/services/performance-thresholds.js.map +1 -0
- package/dist/services/profiler.d.ts +71 -0
- package/dist/services/profiler.d.ts.map +1 -0
- package/dist/services/profiler.js +314 -0
- package/dist/services/profiler.js.map +1 -0
- package/dist/services/rebuild-business-resolver.d.ts +24 -0
- package/dist/services/rebuild-business-resolver.d.ts.map +1 -0
- package/dist/services/rebuild-business-resolver.js +599 -0
- package/dist/services/rebuild-business-resolver.js.map +1 -0
- package/dist/services/rebuild-tracker-service.d.ts +45 -0
- package/dist/services/rebuild-tracker-service.d.ts.map +1 -0
- package/dist/services/rebuild-tracker-service.js +196 -0
- package/dist/services/rebuild-tracker-service.js.map +1 -0
- package/dist/services/session-types.d.ts +240 -0
- package/dist/services/session-types.d.ts.map +1 -0
- package/dist/services/session-types.js +180 -0
- package/dist/services/session-types.js.map +1 -0
- package/dist/services/threshold-alerts.d.ts +49 -0
- package/dist/services/threshold-alerts.d.ts.map +1 -0
- package/dist/services/threshold-alerts.js +258 -0
- package/dist/services/threshold-alerts.js.map +1 -0
- package/dist/services/timeline-cpu-parser.d.ts +28 -0
- package/dist/services/timeline-cpu-parser.d.ts.map +1 -0
- package/dist/services/timeline-cpu-parser.js +174 -0
- package/dist/services/timeline-cpu-parser.js.map +1 -0
- package/dist/services/timeline-extras.d.ts +61 -0
- package/dist/services/timeline-extras.d.ts.map +1 -0
- package/dist/services/timeline-extras.js +449 -0
- package/dist/services/timeline-extras.js.map +1 -0
- package/dist/services/vm-service-client.d.ts +123 -0
- package/dist/services/vm-service-client.d.ts.map +1 -0
- package/dist/services/vm-service-client.js +418 -0
- package/dist/services/vm-service-client.js.map +1 -0
- package/dist/tools/connection.d.ts +4 -0
- package/dist/tools/connection.d.ts.map +1 -0
- package/dist/tools/connection.js +127 -0
- package/dist/tools/connection.js.map +1 -0
- package/dist/tools/debug-actions.d.ts +4 -0
- package/dist/tools/debug-actions.d.ts.map +1 -0
- package/dist/tools/debug-actions.js +210 -0
- package/dist/tools/debug-actions.js.map +1 -0
- package/dist/tools/discover.d.ts +4 -0
- package/dist/tools/discover.d.ts.map +1 -0
- package/dist/tools/discover.js +183 -0
- package/dist/tools/discover.js.map +1 -0
- package/dist/tools/memory.d.ts +4 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +145 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/network.d.ts +4 -0
- package/dist/tools/network.d.ts.map +1 -0
- package/dist/tools/network.js +265 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/performance-session.d.ts +4 -0
- package/dist/tools/performance-session.d.ts.map +1 -0
- package/dist/tools/performance-session.js +105 -0
- package/dist/tools/performance-session.js.map +1 -0
- package/dist/tools/profiling.d.ts +5 -0
- package/dist/tools/profiling.d.ts.map +1 -0
- package/dist/tools/profiling.js +142 -0
- package/dist/tools/profiling.js.map +1 -0
- package/dist/tools/rebuild-tracker.d.ts +4 -0
- package/dist/tools/rebuild-tracker.d.ts.map +1 -0
- package/dist/tools/rebuild-tracker.js +228 -0
- package/dist/tools/rebuild-tracker.js.map +1 -0
- package/dist/tools/snapshot-diff.d.ts +4 -0
- package/dist/tools/snapshot-diff.d.ts.map +1 -0
- package/dist/tools/snapshot-diff.js +235 -0
- package/dist/tools/snapshot-diff.js.map +1 -0
- package/dist/tools/widget-tree.d.ts +4 -0
- package/dist/tools/widget-tree.d.ts.map +1 -0
- package/dist/tools/widget-tree.js +156 -0
- package/dist/tools/widget-tree.js.map +1 -0
- package/docs/README.md +9 -0
- package/docs/performance-audit-requirements.md +403 -0
- package/docs/performance-metrics-guide.md +207 -0
- package/docs/performance-session-simple-design.md +399 -0
- package/examples/app_network_image.dart +242 -0
- package/examples/app_network_image_README.md +51 -0
- package/package.json +69 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
function formatBytes(bytes) {
|
|
3
|
+
if (bytes === 0)
|
|
4
|
+
return "0 B";
|
|
5
|
+
const units = ["B", "KB", "MB"];
|
|
6
|
+
const k = 1024;
|
|
7
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
8
|
+
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${units[i]}`;
|
|
9
|
+
}
|
|
10
|
+
function formatDuration(ms) {
|
|
11
|
+
if (ms < 1)
|
|
12
|
+
return "<1ms";
|
|
13
|
+
if (ms < 1000)
|
|
14
|
+
return `${Math.round(ms)}ms`;
|
|
15
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
16
|
+
}
|
|
17
|
+
export function registerNetworkTools(server, client) {
|
|
18
|
+
let capturing = false;
|
|
19
|
+
let requests = new Map();
|
|
20
|
+
let captureStartTime = 0;
|
|
21
|
+
const httpListener = (event) => {
|
|
22
|
+
if (!event)
|
|
23
|
+
return;
|
|
24
|
+
const kind = event.extensionKind ?? event.kind;
|
|
25
|
+
const data = event.extensionData ?? event;
|
|
26
|
+
if (kind === "dart:io.httpClient.request.start" || kind === "HttpClientRequest") {
|
|
27
|
+
const id = data?.id?.toString() ?? data?.isolateId ?? `req_${Date.now()}`;
|
|
28
|
+
requests.set(id, {
|
|
29
|
+
id,
|
|
30
|
+
method: data?.method ?? "GET",
|
|
31
|
+
uri: data?.uri ?? data?.url ?? "unknown",
|
|
32
|
+
startTime: Date.now(),
|
|
33
|
+
requestSize: data?.contentLength ?? data?.requestSize,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (kind === "dart:io.httpClient.request.finish" || kind === "HttpClientResponse") {
|
|
37
|
+
const id = data?.id?.toString() ?? data?.isolateId;
|
|
38
|
+
const req = id ? requests.get(id) : undefined;
|
|
39
|
+
if (req) {
|
|
40
|
+
req.endTime = Date.now();
|
|
41
|
+
req.statusCode = data?.statusCode ?? data?.status;
|
|
42
|
+
req.responseSize =
|
|
43
|
+
data?.contentLength ?? data?.responseSize ?? data?.compressionState?.length;
|
|
44
|
+
req.contentType = data?.contentType ?? data?.headers?.["content-type"];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (kind === "dart:io.httpClient.request.error") {
|
|
48
|
+
const id = data?.id?.toString();
|
|
49
|
+
const req = id ? requests.get(id) : undefined;
|
|
50
|
+
if (req) {
|
|
51
|
+
req.endTime = Date.now();
|
|
52
|
+
req.error = data?.error ?? data?.message ?? "Unknown error";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (kind === "Extension" &&
|
|
56
|
+
data?.extensionKind?.includes("http")) {
|
|
57
|
+
const extData = data.extensionData;
|
|
58
|
+
if (extData?.method && extData?.uri) {
|
|
59
|
+
const id = extData.id?.toString() ?? `ext_${Date.now()}`;
|
|
60
|
+
const existing = requests.get(id);
|
|
61
|
+
if (!existing) {
|
|
62
|
+
requests.set(id, {
|
|
63
|
+
id,
|
|
64
|
+
method: extData.method,
|
|
65
|
+
uri: extData.uri,
|
|
66
|
+
startTime: extData.startTime ?? Date.now(),
|
|
67
|
+
endTime: extData.endTime,
|
|
68
|
+
statusCode: extData.statusCode ?? extData.status,
|
|
69
|
+
responseSize: extData.responseSize ?? extData.contentLength,
|
|
70
|
+
contentType: extData.contentType,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
server.tool("start_network_capture", "Start capturing HTTP network traffic from the running Flutter app. After starting, use the app to trigger API calls, then call stop_network_capture to see all requests with timing, status codes, and sizes.", {}, async () => {
|
|
77
|
+
if (!client.connected) {
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: "text",
|
|
82
|
+
text: "Not connected. Use the `connect` tool first.",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
isError: true,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (capturing) {
|
|
89
|
+
return {
|
|
90
|
+
content: [
|
|
91
|
+
{
|
|
92
|
+
type: "text",
|
|
93
|
+
text: "Already capturing network traffic. Call stop_network_capture first.",
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
isError: true,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
requests = new Map();
|
|
100
|
+
captureStartTime = Date.now();
|
|
101
|
+
capturing = true;
|
|
102
|
+
client.on("stream:Extension", httpListener);
|
|
103
|
+
client.on("stream:Logging", httpListener);
|
|
104
|
+
client.on("event", httpListener);
|
|
105
|
+
try {
|
|
106
|
+
await client
|
|
107
|
+
.callServiceExtension("ext.dart.io.httpEnableTimelineLogging", undefined, {
|
|
108
|
+
enabled: true,
|
|
109
|
+
})
|
|
110
|
+
.catch(() => { });
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Extension may not be available
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: "✅ Network capture started. Use the app to trigger API calls, then call `stop_network_capture` to see the results.",
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
server.tool("stop_network_capture", "Stop capturing network traffic and get a detailed report of all HTTP requests including method, URL, status code, response time, and payload size.", {
|
|
125
|
+
sortBy: z
|
|
126
|
+
.enum(["time", "duration", "size"])
|
|
127
|
+
.default("time")
|
|
128
|
+
.describe("Sort requests by: time (chronological), duration (slowest first), size (largest first)"),
|
|
129
|
+
}, async ({ sortBy }) => {
|
|
130
|
+
if (!capturing) {
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: "text",
|
|
135
|
+
text: "Not capturing network traffic. Call start_network_capture first.",
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
isError: true,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
capturing = false;
|
|
142
|
+
client.off("stream:Extension", httpListener);
|
|
143
|
+
client.off("stream:Logging", httpListener);
|
|
144
|
+
client.off("event", httpListener);
|
|
145
|
+
try {
|
|
146
|
+
await client
|
|
147
|
+
.callServiceExtension("ext.dart.io.httpEnableTimelineLogging", undefined, {
|
|
148
|
+
enabled: false,
|
|
149
|
+
})
|
|
150
|
+
.catch(() => { });
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Best effort
|
|
154
|
+
}
|
|
155
|
+
const durationMs = Date.now() - captureStartTime;
|
|
156
|
+
const allRequests = Array.from(requests.values());
|
|
157
|
+
if (allRequests.length === 0) {
|
|
158
|
+
return {
|
|
159
|
+
content: [
|
|
160
|
+
{
|
|
161
|
+
type: "text",
|
|
162
|
+
text: [
|
|
163
|
+
`Captured for ${(durationMs / 1000).toFixed(1)}s — no HTTP requests detected.`,
|
|
164
|
+
"",
|
|
165
|
+
"This can happen if:",
|
|
166
|
+
"• The app didn't make any network calls during capture",
|
|
167
|
+
"• HTTP timeline logging is not supported in this Flutter version",
|
|
168
|
+
"• The app uses a custom HTTP client that doesn't go through dart:io",
|
|
169
|
+
"",
|
|
170
|
+
"Try making the app load data (pull to refresh, navigate to a new screen).",
|
|
171
|
+
].join("\n"),
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const sorted = [...allRequests];
|
|
177
|
+
switch (sortBy) {
|
|
178
|
+
case "duration":
|
|
179
|
+
sorted.sort((a, b) => {
|
|
180
|
+
const durA = a.endTime ? a.endTime - a.startTime : 0;
|
|
181
|
+
const durB = b.endTime ? b.endTime - b.startTime : 0;
|
|
182
|
+
return durB - durA;
|
|
183
|
+
});
|
|
184
|
+
break;
|
|
185
|
+
case "size":
|
|
186
|
+
sorted.sort((a, b) => (b.responseSize ?? 0) - (a.responseSize ?? 0));
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
sorted.sort((a, b) => a.startTime - b.startTime);
|
|
190
|
+
}
|
|
191
|
+
const completedRequests = sorted.filter((r) => r.endTime);
|
|
192
|
+
const failedRequests = sorted.filter((r) => r.error);
|
|
193
|
+
const pendingRequests = sorted.filter((r) => !r.endTime && !r.error);
|
|
194
|
+
const totalSize = sorted.reduce((sum, r) => sum + (r.responseSize ?? 0), 0);
|
|
195
|
+
const durations = completedRequests.map((r) => r.endTime - r.startTime);
|
|
196
|
+
const avgDuration = durations.length > 0
|
|
197
|
+
? durations.reduce((a, b) => a + b, 0) / durations.length
|
|
198
|
+
: 0;
|
|
199
|
+
const maxDuration = durations.length > 0 ? Math.max(...durations) : 0;
|
|
200
|
+
const output = [
|
|
201
|
+
"═══════════════════════════════════════════════════════════",
|
|
202
|
+
" NETWORK TRAFFIC REPORT",
|
|
203
|
+
"═══════════════════════════════════════════════════════════",
|
|
204
|
+
"",
|
|
205
|
+
"📊 SUMMARY",
|
|
206
|
+
"───────────────────────────────────────────────────────────",
|
|
207
|
+
`Captured for ${(durationMs / 1000).toFixed(1)}s`,
|
|
208
|
+
`Total requests: ${allRequests.length}`,
|
|
209
|
+
`Completed: ${completedRequests.length} | Failed: ${failedRequests.length} | Pending: ${pendingRequests.length}`,
|
|
210
|
+
`Total response size: ${formatBytes(totalSize)}`,
|
|
211
|
+
`Average response time: ${formatDuration(avgDuration)}`,
|
|
212
|
+
`Slowest request: ${formatDuration(maxDuration)}`,
|
|
213
|
+
"",
|
|
214
|
+
"📡 REQUESTS",
|
|
215
|
+
"───────────────────────────────────────────────────────────",
|
|
216
|
+
];
|
|
217
|
+
for (const req of sorted) {
|
|
218
|
+
const duration = req.endTime
|
|
219
|
+
? formatDuration(req.endTime - req.startTime)
|
|
220
|
+
: "pending...";
|
|
221
|
+
const status = req.error
|
|
222
|
+
? `❌ ${req.error}`
|
|
223
|
+
: req.statusCode
|
|
224
|
+
? req.statusCode >= 400
|
|
225
|
+
? `🔴 ${req.statusCode}`
|
|
226
|
+
: req.statusCode >= 300
|
|
227
|
+
? `🟡 ${req.statusCode}`
|
|
228
|
+
: `🟢 ${req.statusCode}`
|
|
229
|
+
: "⏳";
|
|
230
|
+
const size = req.responseSize
|
|
231
|
+
? formatBytes(req.responseSize)
|
|
232
|
+
: "-";
|
|
233
|
+
output.push(`${status} ${req.method.padEnd(6)} ${duration.padStart(8)} | ${size.padStart(8)} | ${req.uri}`);
|
|
234
|
+
}
|
|
235
|
+
const slowRequests = completedRequests.filter((r) => r.endTime - r.startTime > 2000);
|
|
236
|
+
const largeResponses = completedRequests.filter((r) => (r.responseSize ?? 0) > 500000);
|
|
237
|
+
const errors = failedRequests;
|
|
238
|
+
if (slowRequests.length > 0 ||
|
|
239
|
+
largeResponses.length > 0 ||
|
|
240
|
+
errors.length > 0) {
|
|
241
|
+
output.push("");
|
|
242
|
+
output.push("⚠️ CONCERNS");
|
|
243
|
+
output.push("───────────────────────────────────────────────────────────");
|
|
244
|
+
for (const req of slowRequests.slice(0, 3)) {
|
|
245
|
+
const dur = formatDuration(req.endTime - req.startTime);
|
|
246
|
+
output.push(`• SLOW: ${req.method} ${req.uri} took ${dur}`);
|
|
247
|
+
}
|
|
248
|
+
for (const req of largeResponses.slice(0, 3)) {
|
|
249
|
+
output.push(`• LARGE: ${req.method} ${req.uri} returned ${formatBytes(req.responseSize)}`);
|
|
250
|
+
}
|
|
251
|
+
for (const req of errors.slice(0, 3)) {
|
|
252
|
+
output.push(`• ERROR: ${req.method} ${req.uri} — ${req.error}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
content: [
|
|
257
|
+
{
|
|
258
|
+
type: "text",
|
|
259
|
+
text: output.join("\n"),
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/tools/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { PerformanceSession } from "../services/performance-session.js";
|
|
3
|
+
export declare function registerPerformanceSessionTools(server: McpServer, session: PerformanceSession): void;
|
|
4
|
+
//# sourceMappingURL=performance-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-session.d.ts","sourceRoot":"","sources":["../../src/tools/performance-session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAwB,MAAM,oCAAoC,CAAC;AAG9F,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,kBAAkB,QAmI5B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { formatSessionSummary } from "../services/performance-session.js";
|
|
3
|
+
import { PERFORMANCE_SESSIONS_DIR } from "../services/session-types.js";
|
|
4
|
+
export function registerPerformanceSessionTools(server, session) {
|
|
5
|
+
server.tool("collect_performance_session", `采集指定时长的 Flutter 性能数据并返回结构化 JSON,供 AI 结合源码给出优化方案。
|
|
6
|
+
|
|
7
|
+
重要:durationSec 仅为「录制窗口」(默认还会 +2s 预热)。工具返回前还需收尾(Timeline/CPU/报告),Android 真机总耗时常为 录制+30s~+120s,期间会输出 [perf] 进度。
|
|
8
|
+
|
|
9
|
+
推荐话术:用户说「连接 Flutter App,开始采集性能数据 30s」时:
|
|
10
|
+
1. 先 discover_apps / connect(adb 转发口需用真实 VM URI,非 302 端口)
|
|
11
|
+
2. 调用本工具并告知用户「录制 30s,请保持 App 前台;收尾可能再需 1~2 分钟」
|
|
12
|
+
3. 工具返回后读取 filesToInspect,按 hintsForAnalysis 输出 P0/P1/P2
|
|
13
|
+
|
|
14
|
+
采集项:帧率/jank、Widget 重建(含行号)、CPU Top 函数、网络;内存默认关闭(enableMemory=true 开启)。`, {
|
|
15
|
+
scenario: z
|
|
16
|
+
.string()
|
|
17
|
+
.default("manual-session")
|
|
18
|
+
.describe("场景标识,如 home-list-scroll"),
|
|
19
|
+
durationSec: z
|
|
20
|
+
.number()
|
|
21
|
+
.min(5)
|
|
22
|
+
.max(120)
|
|
23
|
+
.default(30)
|
|
24
|
+
.describe("录制窗口(秒);不含收尾分析时间。总耗时见返回 progressLog / wallClockSec"),
|
|
25
|
+
enableNetwork: z.boolean().default(true),
|
|
26
|
+
enableCpuProfile: z.boolean().default(true),
|
|
27
|
+
enableMemory: z
|
|
28
|
+
.boolean()
|
|
29
|
+
.default(false)
|
|
30
|
+
.describe("是否调用 getAllocationProfile(gc:true);默认 false 以缩短 Android 收尾"),
|
|
31
|
+
topN: z.number().min(5).max(50).default(15),
|
|
32
|
+
saveToFile: z
|
|
33
|
+
.boolean()
|
|
34
|
+
.default(false)
|
|
35
|
+
.describe(`是否保存 JSON/AI 报告到 Flutter 工程下的 ${PERFORMANCE_SESSIONS_DIR}/`),
|
|
36
|
+
outputDir: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe(`覆盖默认输出目录;未指定时使用 {projectRoot}/${PERFORMANCE_SESSIONS_DIR}`),
|
|
40
|
+
generateAiReport: z
|
|
41
|
+
.boolean()
|
|
42
|
+
.default(true)
|
|
43
|
+
.describe("是否生成 P0/P1/P2 规则引擎分析报告"),
|
|
44
|
+
projectRoot: z
|
|
45
|
+
.string()
|
|
46
|
+
.optional()
|
|
47
|
+
.describe("Flutter 工程根目录(读取源码 + 默认将报告保存到该目录下的 performance-sessions/)"),
|
|
48
|
+
}, async ({ scenario, durationSec, enableNetwork, enableCpuProfile, enableMemory, topN, saveToFile, outputDir, generateAiReport, projectRoot, }) => {
|
|
49
|
+
try {
|
|
50
|
+
const { result, savedPath } = await session.collect({
|
|
51
|
+
scenario,
|
|
52
|
+
durationSec,
|
|
53
|
+
enableNetwork,
|
|
54
|
+
enableCpuProfile,
|
|
55
|
+
enableMemory,
|
|
56
|
+
topN,
|
|
57
|
+
saveToFile,
|
|
58
|
+
outputDir,
|
|
59
|
+
generateAiReport,
|
|
60
|
+
projectRoot,
|
|
61
|
+
});
|
|
62
|
+
const summary = formatSessionSummary(result);
|
|
63
|
+
const json = JSON.stringify(result, null, 2);
|
|
64
|
+
const rec = result.recordingWindowSec ?? durationSec;
|
|
65
|
+
const wall = result.wallClockSec ?? result.durationSec;
|
|
66
|
+
const text = [
|
|
67
|
+
`✅ 性能采集完成(录制 ${rec}s,总耗时 ${wall}s,场景:${scenario})`,
|
|
68
|
+
"",
|
|
69
|
+
"── 采集进度 ──",
|
|
70
|
+
...(result.progressLog?.map((p) => `- ${p}`) ?? ["- (无进度日志)"]),
|
|
71
|
+
"",
|
|
72
|
+
"── 中文摘要 ──",
|
|
73
|
+
summary,
|
|
74
|
+
];
|
|
75
|
+
if (result.aiAnalysis) {
|
|
76
|
+
text.push("", "── AI 优化方案(规则引擎)──", result.aiAnalysis);
|
|
77
|
+
}
|
|
78
|
+
text.push("", "── PerformanceSessionResult JSON ──", json);
|
|
79
|
+
if (savedPath) {
|
|
80
|
+
text.push("", `已保存: ${savedPath}`);
|
|
81
|
+
if (result.aiAnalysis) {
|
|
82
|
+
text.push(`AI 分析: ${savedPath.replace(/\.json$/, ".ai.md")}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (result.durationSec < 5) {
|
|
86
|
+
text.push("", "⚠️ 采集时长过短,数据可能不足。");
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: "text", text: text.join("\n") }],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return {
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
96
|
+
type: "text",
|
|
97
|
+
text: `采集失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
isError: true,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=performance-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-session.js","sourceRoot":"","sources":["../../src/tools/performance-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { FlutterVmServiceClient } from "../services/vm-service-client.js";
|
|
3
|
+
import { Profiler } from "../services/profiler.js";
|
|
4
|
+
export declare function registerProfilingTools(server: McpServer, client: FlutterVmServiceClient, profiler: Profiler): void;
|
|
5
|
+
//# sourceMappingURL=profiling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiling.d.ts","sourceRoot":"","sources":["../../src/tools/profiling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,sBAAsB,EAC9B,QAAQ,EAAE,QAAQ,QAuKnB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
export function registerProfilingTools(server, client, profiler) {
|
|
2
|
+
server.tool("start_profiling", "Start a performance profiling session. After starting, interact with the app (scroll, tap, navigate) to generate activity, then call stop_profiling to get the analysis. The app should be running in profile mode (`flutter run --profile`) for accurate results.", {}, async () => {
|
|
3
|
+
if (!client.connected) {
|
|
4
|
+
return {
|
|
5
|
+
content: [
|
|
6
|
+
{
|
|
7
|
+
type: "text",
|
|
8
|
+
text: "Not connected. Use the `connect` tool first.",
|
|
9
|
+
},
|
|
10
|
+
],
|
|
11
|
+
isError: true,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
if (profiler.isActive) {
|
|
15
|
+
return {
|
|
16
|
+
content: [
|
|
17
|
+
{
|
|
18
|
+
type: "text",
|
|
19
|
+
text: "A profiling session is already active. Call stop_profiling first.",
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
isError: true,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
await profiler.start();
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: "text",
|
|
31
|
+
text: "✅ Profiling started. Interact with the app now (scroll, tap, navigate), then call `stop_profiling` to get the analysis.",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: `Failed to start profiling: ${error instanceof Error ? error.message : String(error)}`,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
isError: true,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
server.tool("stop_profiling", "Stop the current profiling session and get a detailed performance analysis including frame timing, jank detection, CPU hotspots, build/layout/paint phase analysis, and actionable recommendations.", {}, async () => {
|
|
49
|
+
if (!client.connected) {
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
text: "Not connected. Use the `connect` tool first.",
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
isError: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (!profiler.isActive) {
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: "text",
|
|
65
|
+
text: "No active profiling session. Call start_profiling first.",
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
isError: true,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const result = await profiler.stop();
|
|
73
|
+
const output = [
|
|
74
|
+
"═══════════════════════════════════════════════════════════",
|
|
75
|
+
" FLUTTER PERFORMANCE ANALYSIS REPORT",
|
|
76
|
+
"═══════════════════════════════════════════════════════════",
|
|
77
|
+
"",
|
|
78
|
+
"📊 SUMMARY",
|
|
79
|
+
"───────────────────────────────────────────────────────────",
|
|
80
|
+
...result.summary,
|
|
81
|
+
"",
|
|
82
|
+
"📈 FRAME ANALYSIS",
|
|
83
|
+
"───────────────────────────────────────────────────────────",
|
|
84
|
+
`Total frames: ${result.frameAnalysis.totalFrames}`,
|
|
85
|
+
`Average frame time: ${result.frameAnalysis.averageFrameTimeMs.toFixed(2)}ms`,
|
|
86
|
+
`P90 frame time: ${result.frameAnalysis.p90FrameTimeMs.toFixed(2)}ms`,
|
|
87
|
+
`P99 frame time: ${result.frameAnalysis.p99FrameTimeMs.toFixed(2)}ms`,
|
|
88
|
+
`Max frame time: ${result.frameAnalysis.maxFrameTimeMs.toFixed(2)}ms`,
|
|
89
|
+
`Jank frames: ${result.frameAnalysis.jankFrames} (${result.frameAnalysis.jankPercentage.toFixed(1)}%)`,
|
|
90
|
+
`Target: ${result.frameAnalysis.targetFrameTimeMs.toFixed(1)}ms (${Math.round(1000 / result.frameAnalysis.targetFrameTimeMs)}fps)`,
|
|
91
|
+
"",
|
|
92
|
+
"🔧 PHASE BREAKDOWN",
|
|
93
|
+
"───────────────────────────────────────────────────────────",
|
|
94
|
+
`Build: avg ${result.buildPhaseAnalysis.avgBuildTimeMs.toFixed(2)}ms | max ${result.buildPhaseAnalysis.maxBuildTimeMs.toFixed(2)}ms | ${result.buildPhaseAnalysis.buildCount} calls`,
|
|
95
|
+
`Layout: avg ${result.layoutPhaseAnalysis.avgLayoutTimeMs.toFixed(2)}ms | max ${result.layoutPhaseAnalysis.maxLayoutTimeMs.toFixed(2)}ms | ${result.layoutPhaseAnalysis.layoutCount} calls`,
|
|
96
|
+
`Paint: avg ${result.paintPhaseAnalysis.avgPaintTimeMs.toFixed(2)}ms | max ${result.paintPhaseAnalysis.maxPaintTimeMs.toFixed(2)}ms | ${result.paintPhaseAnalysis.paintCount} calls`,
|
|
97
|
+
"",
|
|
98
|
+
];
|
|
99
|
+
if (result.cpuHotspots.length > 0) {
|
|
100
|
+
output.push("🔥 CPU HOTSPOTS");
|
|
101
|
+
output.push("───────────────────────────────────────────────────────────");
|
|
102
|
+
for (const h of result.cpuHotspots.slice(0, 10)) {
|
|
103
|
+
const severityIcon = h.severity === "critical"
|
|
104
|
+
? "🔴"
|
|
105
|
+
: h.severity === "high"
|
|
106
|
+
? "🟠"
|
|
107
|
+
: h.severity === "medium"
|
|
108
|
+
? "🟡"
|
|
109
|
+
: "🟢";
|
|
110
|
+
output.push(`${severityIcon} ${h.name} [${h.severity.toUpperCase()}]`);
|
|
111
|
+
output.push(` Total: ${h.totalDurationMs.toFixed(1)}ms | Avg: ${h.avgDurationMs.toFixed(1)}ms | Max: ${h.maxDurationMs.toFixed(1)}ms | Calls: ${h.callCount}`);
|
|
112
|
+
}
|
|
113
|
+
output.push("");
|
|
114
|
+
}
|
|
115
|
+
output.push("💡 RECOMMENDATIONS");
|
|
116
|
+
output.push("───────────────────────────────────────────────────────────");
|
|
117
|
+
for (const rec of result.recommendations) {
|
|
118
|
+
output.push(`• ${rec}`);
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: output.join("\n"),
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
content: [
|
|
132
|
+
{
|
|
133
|
+
type: "text",
|
|
134
|
+
text: `Failed to stop profiling: ${error instanceof Error ? error.message : String(error)}`,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
isError: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=profiling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiling.js","sourceRoot":"","sources":["../../src/tools/profiling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { FlutterVmServiceClient } from "../services/vm-service-client.js";
|
|
3
|
+
export declare function registerRebuildTrackerTools(server: McpServer, client: FlutterVmServiceClient): void;
|
|
4
|
+
//# sourceMappingURL=rebuild-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuild-tracker.d.ts","sourceRoot":"","sources":["../../src/tools/rebuild-tracker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAU1E,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,sBAAsB,QAkS/B"}
|