豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 755eeef

Browse files
authored
chore: support structured network (#774)
This PR adds a structured variant of the network responses and refactors the code accordingly.
1 parent a3de5e4 commit 755eeef

File tree

9 files changed

+590
-453
lines changed

9 files changed

+590
-453
lines changed

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/McpResponse.ts

Lines changed: 64 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,7 @@ import {
1010
formatConsoleEventShort,
1111
formatConsoleEventVerbose,
1212
} from './formatters/consoleFormatter.js';
13-
import {
14-
getFormattedHeaderValue,
15-
getFormattedResponseBody,
16-
getFormattedRequestBody,
17-
getShortDescriptionForRequest,
18-
getStatusFromRequest,
19-
} from './formatters/networkFormatter.js';
13+
import {NetworkFormatter} from './formatters/NetworkFormatter.js';
2014
import {SnapshotFormatter} from './formatters/SnapshotFormatter.js';
2115
import type {McpContext} from './McpContext.js';
2216
import {DevTools} from './third_party/index.js';
@@ -215,22 +209,17 @@ export class McpResponse implements Response {
215209
}
216210
}
217211

218-
const bodies: {
219-
requestBody?: string;
220-
responseBody?: string;
221-
} = {};
222-
212+
let detailedNetworkRequest: NetworkFormatter | undefined;
223213
if (this.#attachedNetworkRequestId) {
224214
const request = context.getNetworkRequestById(
225215
this.#attachedNetworkRequestId,
226216
);
227-
228-
bodies.requestBody = await getFormattedRequestBody(request);
229-
230-
const response = request.response();
231-
if (response) {
232-
bodies.responseBody = await getFormattedResponseBody(response);
233-
}
217+
const formatter = await NetworkFormatter.from(request, {
218+
requestId: this.#attachedNetworkRequestId,
219+
requestIdResolver: req => context.getNetworkRequestStableId(req),
220+
fetchData: true,
221+
});
222+
detailedNetworkRequest = formatter;
234223
}
235224

236225
let consoleData: ConsoleMessageData | undefined;
@@ -341,25 +330,61 @@ export class McpResponse implements Response {
341330
).filter(item => item !== null);
342331
}
343332

333+
let networkRequests: NetworkFormatter[] | undefined;
334+
if (this.#networkRequestsOptions?.include) {
335+
let requests = context.getNetworkRequests(
336+
this.#networkRequestsOptions?.includePreservedRequests,
337+
);
338+
339+
// Apply resource type filtering if specified
340+
if (this.#networkRequestsOptions.resourceTypes?.length) {
341+
const normalizedTypes = new Set(
342+
this.#networkRequestsOptions.resourceTypes,
343+
);
344+
requests = requests.filter(request => {
345+
const type = request.resourceType();
346+
return normalizedTypes.has(type);
347+
});
348+
}
349+
350+
if (requests.length) {
351+
const data = this.#dataWithPagination(
352+
requests,
353+
this.#networkRequestsOptions.pagination,
354+
);
355+
356+
networkRequests = await Promise.all(
357+
data.items.map(request =>
358+
NetworkFormatter.from(request, {
359+
requestId: context.getNetworkRequestStableId(request),
360+
selectedInDevToolsUI:
361+
context.getNetworkRequestStableId(request) ===
362+
this.#networkRequestsOptions?.networkRequestIdInDevToolsUI,
363+
fetchData: false,
364+
}),
365+
),
366+
);
367+
}
368+
}
369+
344370
return this.format(toolName, context, {
345-
bodies,
346371
consoleData,
347372
consoleListData,
348373
snapshot,
374+
detailedNetworkRequest,
375+
networkRequests,
349376
});
350377
}
351378

352379
format(
353380
toolName: string,
354381
context: McpContext,
355382
data: {
356-
bodies: {
357-
requestBody?: string;
358-
responseBody?: string;
359-
};
360383
consoleData: ConsoleMessageData | undefined;
361384
consoleListData: ConsoleMessageData[] | undefined;
362385
snapshot: SnapshotFormatter | string | undefined;
386+
detailedNetworkRequest?: NetworkFormatter;
387+
networkRequests?: NetworkFormatter[];
363388
},
364389
): {content: Array<TextContent | ImageContent>; structuredContent: object} {
365390
const response = [`# ${toolName} response`];
@@ -407,6 +432,8 @@ Call ${handleDialog.name} to handle it before continuing.`);
407432
snapshot?: object;
408433
snapshotFilePath?: string;
409434
tabId?: string;
435+
networkRequest?: object;
436+
networkRequests?: object[];
410437
} = {};
411438

412439
if (this.#tabId) {
@@ -424,7 +451,11 @@ Call ${handleDialog.name} to handle it before continuing.`);
424451
}
425452
}
426453

427-
response.push(...this.#formatNetworkRequestData(context, data.bodies));
454+
if (data.detailedNetworkRequest) {
455+
response.push(data.detailedNetworkRequest.toStringDetailed());
456+
structuredContent.networkRequest =
457+
data.detailedNetworkRequest.toJSONDetailed();
458+
}
428459
response.push(...this.#formatConsoleData(context, data.consoleData));
429460

430461
if (this.#networkRequestsOptions?.include) {
@@ -445,20 +476,17 @@ Call ${handleDialog.name} to handle it before continuing.`);
445476

446477
response.push('## Network requests');
447478
if (requests.length) {
448-
const data = this.#dataWithPagination(
479+
const paginationData = this.#dataWithPagination(
449480
requests,
450481
this.#networkRequestsOptions.pagination,
451482
);
452-
response.push(...data.info);
453-
for (const request of data.items) {
454-
response.push(
455-
getShortDescriptionForRequest(
456-
request,
457-
context.getNetworkRequestStableId(request),
458-
context.getNetworkRequestStableId(request) ===
459-
this.#networkRequestsOptions?.networkRequestIdInDevToolsUI,
460-
),
461-
);
483+
response.push(...paginationData.info);
484+
if (data.networkRequests) {
485+
structuredContent.networkRequests = [];
486+
for (const formatter of data.networkRequests) {
487+
response.push(formatter.toString());
488+
structuredContent.networkRequests.push(formatter.toJSON());
489+
}
462490
}
463491
} else {
464492
response.push('No requests found.');
@@ -539,65 +567,6 @@ Call ${handleDialog.name} to handle it before continuing.`);
539567
return response;
540568
}
541569

542-
#formatNetworkRequestData(
543-
context: McpContext,
544-
data: {
545-
requestBody?: string;
546-
responseBody?: string;
547-
},
548-
): string[] {
549-
const response: string[] = [];
550-
const id = this.#attachedNetworkRequestId;
551-
if (!id) {
552-
return response;
553-
}
554-
555-
const httpRequest = context.getNetworkRequestById(id);
556-
response.push(`## Request ${httpRequest.url()}`);
557-
response.push(`Status: ${getStatusFromRequest(httpRequest)}`);
558-
response.push(`### Request Headers`);
559-
for (const line of getFormattedHeaderValue(httpRequest.headers())) {
560-
response.push(line);
561-
}
562-
563-
if (data.requestBody) {
564-
response.push(`### Request Body`);
565-
response.push(data.requestBody);
566-
}
567-
568-
const httpResponse = httpRequest.response();
569-
if (httpResponse) {
570-
response.push(`### Response Headers`);
571-
for (const line of getFormattedHeaderValue(httpResponse.headers())) {
572-
response.push(line);
573-
}
574-
}
575-
576-
if (data.responseBody) {
577-
response.push(`### Response Body`);
578-
response.push(data.responseBody);
579-
}
580-
581-
const httpFailure = httpRequest.failure();
582-
if (httpFailure) {
583-
response.push(`### Request failed with`);
584-
response.push(httpFailure.errorText);
585-
}
586-
587-
const redirectChain = httpRequest.redirectChain();
588-
if (redirectChain.length) {
589-
response.push(`### Redirect chain`);
590-
let indent = 0;
591-
for (const request of redirectChain.reverse()) {
592-
response.push(
593-
`${' '.repeat(indent)}${getShortDescriptionForRequest(request, context.getNetworkRequestStableId(request))}`,
594-
);
595-
indent++;
596-
}
597-
}
598-
return response;
599-
}
600-
601570
resetResponseLineForTesting() {
602571
this.#textResponseLines = [];
603572
}

0 commit comments

Comments
 (0)