refactor: clean up McpContext getters (#2340)

This commit is contained in:
Alex Rudenko
2026-07-10 09:46:31 +02:00
committed by GitHub
parent 8a4ddb3256
commit 5b33debf1a
8 changed files with 82 additions and 86 deletions
-42
View File
@@ -304,37 +304,6 @@ export class McpContext implements Context {
await this.validatePath(outputPath);
return outputPath;
}
resolveCdpRequestId(page: McpPage, cdpRequestId: string): number | undefined {
if (!cdpRequestId) {
this.logger?.('no network request');
return;
}
const request = page.networkCollector.find(request => {
// @ts-expect-error id is internal.
return request.id === cdpRequestId;
});
if (!request) {
this.logger?.('no network request for ' + cdpRequestId);
return;
}
return page.networkCollector.getIdForResource(request);
}
getNetworkRequests(
page: McpPage,
includePreservedRequests?: boolean,
): HTTPRequest[] {
return page.networkCollector.getData(includePreservedRequests);
}
getConsoleData(
page: McpPage,
includePreservedMessages?: boolean,
): Array<ConsoleMessage | Error | DevTools.AggregatedIssue | UncaughtError> {
return page.consoleCollector.getData(includePreservedMessages);
}
getDevToolsUniverse(page: McpPage): TargetUniverse | null {
return this.#devtoolsUniverseManager.get(page.pptrPage);
}
@@ -345,13 +314,6 @@ export class McpContext implements Context {
return (message as WithSymbolId<typeof message>)[stableIdSymbol] ?? -1;
}
getConsoleMessageById(
page: McpPage,
id: number,
): ConsoleMessage | Error | DevTools.AggregatedIssue | UncaughtError {
return page.consoleCollector.getById(id);
}
async newPage(
background?: boolean,
isolatedContextName?: string,
@@ -384,10 +346,6 @@ export class McpContext implements Context {
await page.pptrPage.close({runBeforeUnload: false});
}
getNetworkRequestById(page: McpPage, reqid: number): HTTPRequest {
return page.networkCollector.getById(reqid);
}
async restoreEmulation(page: McpPage) {
const currentSetting = page.emulationSettings;
await this.emulate(currentSetting, page);
+40
View File
@@ -9,6 +9,7 @@ import {
ConsoleCollector,
NetworkCollector,
type ListenerMap,
type UncaughtError,
} from './PageCollector.js';
import {TextSnapshot} from './TextSnapshot.js';
import type {
@@ -18,6 +19,9 @@ import type {
WebMCPTool,
Protocol,
Page,
ConsoleMessage,
HTTPRequest,
DevTools,
} from './third_party/index.js';
import {takeSnapshot} from './tools/snapshot.js';
import type {ToolGroups} from './tools/thirdPartyDeveloper.js';
@@ -119,6 +123,42 @@ export class McpPage implements ContextPage {
return this.pptrPage.webmcp.tools();
}
resolveCdpRequestId(cdpRequestId: string): number | undefined {
if (!cdpRequestId) {
logger?.('no network request');
return;
}
const request = this.networkCollector.find(request => {
// @ts-expect-error id is internal.
return request.id === cdpRequestId;
});
if (!request) {
logger?.('no network request for ' + cdpRequestId);
return;
}
return this.networkCollector.getIdForResource(request);
}
getNetworkRequests(includePreservedRequests?: boolean): HTTPRequest[] {
return this.networkCollector.getData(includePreservedRequests);
}
getConsoleData(
includePreservedMessages?: boolean,
): Array<ConsoleMessage | Error | DevTools.AggregatedIssue | UncaughtError> {
return this.consoleCollector.getData(includePreservedMessages);
}
getConsoleMessageById(
id: number,
): ConsoleMessage | Error | DevTools.AggregatedIssue | UncaughtError {
return this.consoleCollector.getById(id);
}
getNetworkRequestById(reqid: number): HTTPRequest {
return this.networkCollector.getById(reqid);
}
get networkConditions(): string | null {
return this.emulationSettings.networkConditions ?? null;
}
+5 -12
View File
@@ -610,8 +610,7 @@ export class McpResponse implements Response {
if (!this.#page) {
throw new Error(`Response must have an McpPage`);
}
const request = context.getNetworkRequestById(
this.#page,
const request = this.#page.getNetworkRequestById(
this.#attachedNetworkRequestId,
);
const formatter = await NetworkFormatter.from(request, {
@@ -634,8 +633,7 @@ export class McpResponse implements Response {
throw new Error(`Response must have an McpPage`);
}
const message = context.getConsoleMessageById(
this.#page,
const message = this.#page.getConsoleMessageById(
this.#attachedConsoleMessageId,
);
const consoleMessageStableId = this.#attachedConsoleMessageId;
@@ -650,10 +648,7 @@ export class McpResponse implements Response {
} else if (message instanceof DevTools.AggregatedIssue) {
const formatter = new IssueFormatter(message, {
id: consoleMessageStableId,
requestIdResolver: context.resolveCdpRequestId.bind(
context,
this.#page,
),
requestIdResolver: this.#page.resolveCdpRequestId.bind(this.#page),
elementIdResolver: this.#page.textSnapshot?.resolveCdpElementId.bind(
this.#page.textSnapshot,
),
@@ -707,8 +702,7 @@ export class McpResponse implements Response {
if (!page) {
throw new Error(`Response must have an McpPage`);
}
messages = context.getConsoleData(
page,
messages = page.getConsoleData(
this.#consoleDataOptions.includePreservedMessages,
);
}
@@ -764,8 +758,7 @@ export class McpResponse implements Response {
if (!this.#page) {
throw new Error(`Response must have an McpPage`);
}
let requests = context.getNetworkRequests(
this.#page,
let requests = this.#page.getNetworkRequests(
this.#networkRequestsOptions?.includePreservedRequests,
);
+6 -7
View File
@@ -232,13 +232,7 @@ export type Context = Readonly<{
timeout?: number,
mcpPage?: ContextPage,
): Promise<Element>;
/**
* Returns a reqid for a cdpRequestId.
*/
resolveCdpRequestId(
page: ContextPage,
cdpRequestId: string,
): number | undefined;
getScreenRecorder(): {recorder: ScreenRecorder; filePath: string} | null;
setScreenRecorder(
data: {recorder: ScreenRecorder; filePath: string} | null,
@@ -312,6 +306,11 @@ export type ContextPage = Readonly<{
getAXNodeByUid(uid: string): TextSnapshotNode | undefined;
getElementByUid(uid: string): Promise<ElementHandle<Element>>;
/**
* Returns a reqid for a cdpRequestId.
*/
resolveCdpRequestId(cdpRequestId: string): number | undefined;
getDialog(): Dialog | undefined;
clearDialog(): void;
throwIfDialogOpen(): void;
+4 -4
View File
@@ -72,11 +72,11 @@ export const listNetworkRequests = definePageTool({
},
blockedByDialog: false,
verifyFilesSchema: [],
handler: async (request, response, context) => {
handler: async (request, response) => {
const data = await request.page.getDevToolsData();
response.attachDevToolsData(data);
const reqid = data?.cdpRequestId
? context.resolveCdpRequestId(request.page, data.cdpRequestId)
? request.page.resolveCdpRequestId(data.cdpRequestId)
: undefined;
response.setIncludeNetworkRequests(true, {
pageSize: request.params.pageSize,
@@ -117,7 +117,7 @@ export const getNetworkRequest = definePageTool({
},
blockedByDialog: true,
verifyFilesSchema: ['requestFilePath', 'responseFilePath'],
handler: async (request, response, context) => {
handler: async (request, response) => {
if (request.params.reqid) {
response.attachNetworkRequest(request.params.reqid, {
requestFilePath: request.params.requestFilePath,
@@ -127,7 +127,7 @@ export const getNetworkRequest = definePageTool({
const data = await request.page.getDevToolsData();
response.attachDevToolsData(data);
const reqid = data?.cdpRequestId
? context.resolveCdpRequestId(request.page, data.cdpRequestId)
? request.page.resolveCdpRequestId(data.cdpRequestId)
: undefined;
if (reqid) {
response.attachNetworkRequest(reqid, {
+9 -3
View File
@@ -207,7 +207,9 @@ describe('McpContext', () => {
stableId: 123,
});
sinon.stub(context, 'getNetworkRequests').returns([mockRequest]);
sinon
.stub(context.getSelectedMcpPage(), 'getNetworkRequests')
.returns([mockRequest]);
sinon.stub(context, 'getNetworkRequestStableId').returns(123);
response.setIncludeNetworkRequests(true);
@@ -223,7 +225,9 @@ describe('McpContext', () => {
stableId: 456,
});
sinon.stub(context, 'getNetworkRequestById').returns(mockRequest);
sinon
.stub(context.getSelectedMcpPage(), 'getNetworkRequestById')
.returns(mockRequest);
sinon.stub(context, 'getNetworkRequestStableId').returns(456);
response.attachNetworkRequest(456);
@@ -247,7 +251,9 @@ describe('McpContext', () => {
} as unknown as HTTPResponse,
});
sinon.stub(context, 'getNetworkRequestById').returns(mockRequest);
sinon
.stub(context.getSelectedMcpPage(), 'getNetworkRequestById')
.returns(mockRequest);
sinon.stub(context, 'getNetworkRequestStableId').returns(789);
// Use os.tmpdir() so validatePath passes on all platforms (macOS tmpdir
+17 -17
View File
@@ -462,7 +462,7 @@ describe('McpResponse', () => {
it('add network requests when setting is true', async t => {
await withMcpContext(async (response, context) => {
response.setIncludeNetworkRequests(true);
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [getMockRequest({stableId: 1}), getMockRequest({stableId: 2})];
};
const {content, structuredContent} = await response.handle(
@@ -479,7 +479,7 @@ describe('McpResponse', () => {
it('does not include network requests when setting is false', async t => {
await withMcpContext(async (response, context) => {
response.setIncludeNetworkRequests(false);
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [getMockRequest()];
};
const {content, structuredContent} = await response.handle(
@@ -511,10 +511,10 @@ describe('McpResponse', () => {
postData: JSON.stringify({request: 'body'}),
response: httpResponse,
});
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [request];
};
context.getNetworkRequestById = () => {
context.getSelectedMcpPage().getNetworkRequestById = () => {
return request;
};
response.attachNetworkRequest(1);
@@ -535,10 +535,10 @@ describe('McpResponse', () => {
await withMcpContext(async (response, context) => {
response.setIncludeNetworkRequests(true);
const request = getMockRequest();
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [request];
};
context.getNetworkRequestById = () => {
context.getSelectedMcpPage().getNetworkRequestById = () => {
return request;
};
response.attachNetworkRequest(1);
@@ -602,7 +602,7 @@ describe('McpResponse', () => {
};
mockAggregatedIssue.getDescription.returns(mockDescription);
response.setIncludeConsoleData(true);
context.getConsoleData = () => {
context.getSelectedMcpPage().getConsoleData = () => {
return [mockAggregatedIssue];
};
@@ -627,7 +627,7 @@ describe('McpResponse', () => {
};
mockAggregatedIssue.getDescription.returns(mockDescription);
response.attachConsoleMessage(1);
context.getConsoleMessageById = () => {
context.getSelectedMcpPage().getConsoleMessageById = () => {
return mockAggregatedIssue;
};
@@ -646,7 +646,7 @@ describe('McpResponse network request filtering', () => {
response.setIncludeNetworkRequests(true, {
resourceTypes: ['script', 'stylesheet'],
});
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [
getMockRequest({resourceType: 'script'}),
getMockRequest({resourceType: 'image'}),
@@ -670,7 +670,7 @@ describe('McpResponse network request filtering', () => {
response.setIncludeNetworkRequests(true, {
resourceTypes: ['image'],
});
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [
getMockRequest({resourceType: 'script'}),
getMockRequest({resourceType: 'image'}),
@@ -693,7 +693,7 @@ describe('McpResponse network request filtering', () => {
response.setIncludeNetworkRequests(true, {
resourceTypes: ['font'],
});
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [
getMockRequest({resourceType: 'script'}),
getMockRequest({resourceType: 'image'}),
@@ -714,7 +714,7 @@ describe('McpResponse network request filtering', () => {
it('shows all requests when no filters are provided', async t => {
await withMcpContext(async (response, context) => {
response.setIncludeNetworkRequests(true);
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [
getMockRequest({resourceType: 'script'}),
getMockRequest({resourceType: 'image'}),
@@ -740,7 +740,7 @@ describe('McpResponse network request filtering', () => {
response.setIncludeNetworkRequests(true, {
resourceTypes: [],
});
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return [
getMockRequest({resourceType: 'script'}),
getMockRequest({resourceType: 'image'}),
@@ -765,7 +765,7 @@ describe('McpResponse network pagination', () => {
it('returns all requests when pagination is not provided', async t => {
await withMcpContext(async (response, context) => {
const requests = Array.from({length: 5}, () => getMockRequest());
context.getNetworkRequests = () => requests;
context.getSelectedMcpPage().getNetworkRequests = () => requests;
response.setIncludeNetworkRequests(true);
const {content, structuredContent} = await response.handle(
'test',
@@ -786,7 +786,7 @@ describe('McpResponse network pagination', () => {
const requests = Array.from({length: 30}, (_, idx) =>
getMockRequest({method: `GET-${idx}`}),
);
context.getNetworkRequests = () => {
context.getSelectedMcpPage().getNetworkRequests = () => {
return requests;
};
response.setIncludeNetworkRequests(true, {pageSize: 10});
@@ -809,7 +809,7 @@ describe('McpResponse network pagination', () => {
const requests = Array.from({length: 25}, (_, idx) =>
getMockRequest({method: `GET-${idx}`}),
);
context.getNetworkRequests = () => requests;
context.getSelectedMcpPage().getNetworkRequests = () => requests;
response.setIncludeNetworkRequests(true, {
pageSize: 10,
pageIdx: 1,
@@ -831,7 +831,7 @@ describe('McpResponse network pagination', () => {
it('handles invalid page number by showing first page', async t => {
await withMcpContext(async (response, context) => {
const requests = Array.from({length: 5}, () => getMockRequest());
context.getNetworkRequests = () => requests;
context.getSelectedMcpPage().getNetworkRequests = () => requests;
response.setIncludeNetworkRequests(true, {
pageSize: 2,
pageIdx: 10, // Invalid page number
+1 -1
View File
@@ -403,7 +403,7 @@ describe('console', () => {
`);
page.textSnapshot = await TextSnapshot.create(page);
await issuePromise;
const messages = context.getConsoleData(page);
const messages = page.getConsoleData();
let issueMsg;
for (const message of messages) {
if (message instanceof DevTools.AggregatedIssue) {