From d332f6b3c7f3e987e5154b3516a3ca330814cea5 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 13 Mar 2026 15:21:27 -0700 Subject: [PATCH 1/6] feat(mcp): include request body in network tool output Adds `includeBody` option to `browser_network_requests` MCP tool and `--body` flag to the `network` CLI command to include POST/PUT/PATCH request bodies in the network log output. --- .../src/tools/backend/network.ts | 10 ++++- .../src/tools/cli-daemon/commands.ts | 3 +- tests/mcp/cli-devtools.spec.ts | 20 ++++++++++ tests/mcp/network.spec.ts | 40 +++++++++++++++++++ 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/packages/playwright-core/src/tools/backend/network.ts b/packages/playwright-core/src/tools/backend/network.ts index 2e3040528678e..4aa02cf629ab1 100644 --- a/packages/playwright-core/src/tools/backend/network.ts +++ b/packages/playwright-core/src/tools/backend/network.ts @@ -28,6 +28,7 @@ const requests = defineTabTool({ description: 'Returns all network requests since loading the page', inputSchema: z.object({ includeStatic: z.boolean().default(false).describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), + includeBody: z.boolean().default(false).describe('Whether to include request body. Defaults to false.'), filename: z.string().optional().describe('Filename to save the network requests to. If not provided, requests are returned as text.'), }), type: 'readOnly', @@ -39,7 +40,7 @@ const requests = defineTabTool({ for (const request of requests) { if (!params.includeStatic && !isFetch(request) && isSuccessfulResponse(request)) continue; - text.push(await renderRequest(request)); + text.push(await renderRequest(request, params.includeBody)); } await response.addResult('Network', text.join('\n'), { prefix: 'network', ext: 'log', suggestedFilename: params.filename }); }, @@ -71,7 +72,7 @@ export function isFetch(request: playwright.Request): boolean { return ['fetch', 'xhr'].includes(request.resourceType()); } -export async function renderRequest(request: playwright.Request): Promise { +export async function renderRequest(request: playwright.Request, includeBody = false): Promise { const response = request.existingResponse(); const result: string[] = []; @@ -80,6 +81,11 @@ export async function renderRequest(request: playwright.Request): Promise [${response.status()}] ${response.statusText()}`); else if (request.failure()) result.push(`=> [FAILED] ${request.failure()?.errorText ?? 'Unknown error'}`); + if (includeBody) { + const postData = request.postData(); + if (postData) + result.push(`\n Request body: ${postData}`); + } return result.join(' '); } diff --git a/packages/playwright-core/src/tools/cli-daemon/commands.ts b/packages/playwright-core/src/tools/cli-daemon/commands.ts index 98e691f02f579..0512e0dc2e803 100644 --- a/packages/playwright-core/src/tools/cli-daemon/commands.ts +++ b/packages/playwright-core/src/tools/cli-daemon/commands.ts @@ -743,10 +743,11 @@ const networkRequests = declareCommand({ args: z.object({}), options: z.object({ static: z.boolean().optional().describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), + body: z.boolean().optional().describe('Whether to include request body. Defaults to false.'), clear: z.boolean().optional().describe('Whether to clear the network list'), }), toolName: ({ clear }) => clear ? 'browser_network_clear' : 'browser_network_requests', - toolParams: ({ static: includeStatic, clear }) => clear ? ({}) : ({ includeStatic }), + toolParams: ({ static: includeStatic, body: includeBody, clear }) => clear ? ({}) : ({ includeStatic, includeBody }), }); const tracingStart = declareCommand({ diff --git a/tests/mcp/cli-devtools.spec.ts b/tests/mcp/cli-devtools.spec.ts index 8bdd8e3397004..63a5028c4001e 100644 --- a/tests/mcp/cli-devtools.spec.ts +++ b/tests/mcp/cli-devtools.spec.ts @@ -64,6 +64,26 @@ test('network --static', async ({ cli, server }) => { expect(attachments[0].data.toString()).toContain(`[GET] ${`${server.PREFIX}/`} => [200] OK`); }); +test('network --body', async ({ cli, server }) => { + server.setContent('/', ` + + `, 'text/html'); + server.setContent('/api', '{}', 'application/json'); + await cli('open', server.PREFIX); + await cli('click', 'e2'); + + { + const { attachments } = await cli('network'); + expect(attachments[0].data.toString()).not.toContain('Request body:'); + } + + { + const { attachments } = await cli('network', '--body'); + expect(attachments[0].data.toString()).toContain(`[POST] ${server.PREFIX}/api => [200] OK`); + expect(attachments[0].data.toString()).toContain('Request body: {"key":"value"}'); + } +}); + test('network --clear', async ({ cli, server }) => { await cli('open', server.PREFIX); await cli('eval', '() => fetch("/hello-world")'); diff --git a/tests/mcp/network.spec.ts b/tests/mcp/network.spec.ts index 9bfdbe337beb9..52e9293824bbc 100644 --- a/tests/mcp/network.spec.ts +++ b/tests/mcp/network.spec.ts @@ -60,3 +60,43 @@ test('browser_network_requests', async ({ client, server }) => { expect(response.result).toContain(`[GET] ${`${server.PREFIX}/image.png`} => [404]`); } }); + +test('browser_network_requests includes request payload', async ({ client, server }) => { + server.setContent('/', ` + + `, 'text/html'); + + server.setContent('/api', '{}', 'application/json'); + + await client.callTool({ + name: 'browser_navigate', + arguments: { + url: server.PREFIX, + }, + }); + + await client.callTool({ + name: 'browser_click', + arguments: { + element: 'Click me button', + ref: 'e2', + }, + }); + + { + const response = parseResponse(await client.callTool({ + name: 'browser_network_requests', + })); + expect(response.result).toContain(`[POST] ${server.PREFIX}/api => [200] OK`); + expect(response.result).not.toContain(`Request body:`); + } + + { + const response = parseResponse(await client.callTool({ + name: 'browser_network_requests', + arguments: { includeBody: true }, + })); + expect(response.result).toContain(`[POST] ${server.PREFIX}/api => [200] OK`); + expect(response.result).toContain(`Request body: {"key":"value"}`); + } +}); From 9660b2cac04b68b3bb3a77ea21fe5a366f1e14c1 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 13 Mar 2026 16:00:36 -0700 Subject: [PATCH 2/6] add filter option --- .../src/tools/backend/network.ts | 7 +++++++ .../src/tools/cli-daemon/commands.ts | 3 ++- tests/mcp/cli-devtools.spec.ts | 12 +++++++++++ tests/mcp/network.spec.ts | 21 +++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/tools/backend/network.ts b/packages/playwright-core/src/tools/backend/network.ts index 4aa02cf629ab1..d565aef9493ab 100644 --- a/packages/playwright-core/src/tools/backend/network.ts +++ b/packages/playwright-core/src/tools/backend/network.ts @@ -29,6 +29,7 @@ const requests = defineTabTool({ inputSchema: z.object({ includeStatic: z.boolean().default(false).describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), includeBody: z.boolean().default(false).describe('Whether to include request body. Defaults to false.'), + filter: z.string().optional().describe('Only return requests whose URL matches this regexp (e.g. "/api/.*user").'), filename: z.string().optional().describe('Filename to save the network requests to. If not provided, requests are returned as text.'), }), type: 'readOnly', @@ -36,10 +37,16 @@ const requests = defineTabTool({ handle: async (tab, params, response) => { const requests = await tab.requests(); + const filter = params.filter ? new RegExp(params.filter) : undefined; const text: string[] = []; for (const request of requests) { if (!params.includeStatic && !isFetch(request) && isSuccessfulResponse(request)) continue; + if (filter) { + filter.lastIndex = 0; + if (!filter.test(request.url())) + continue; + } text.push(await renderRequest(request, params.includeBody)); } await response.addResult('Network', text.join('\n'), { prefix: 'network', ext: 'log', suggestedFilename: params.filename }); diff --git a/packages/playwright-core/src/tools/cli-daemon/commands.ts b/packages/playwright-core/src/tools/cli-daemon/commands.ts index 0512e0dc2e803..4da4ae8a30bac 100644 --- a/packages/playwright-core/src/tools/cli-daemon/commands.ts +++ b/packages/playwright-core/src/tools/cli-daemon/commands.ts @@ -744,10 +744,11 @@ const networkRequests = declareCommand({ options: z.object({ static: z.boolean().optional().describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), body: z.boolean().optional().describe('Whether to include request body. Defaults to false.'), + filter: z.string().optional().describe('Only return requests whose URL matches this regexp (e.g. "/api/.*user").'), clear: z.boolean().optional().describe('Whether to clear the network list'), }), toolName: ({ clear }) => clear ? 'browser_network_clear' : 'browser_network_requests', - toolParams: ({ static: includeStatic, body: includeBody, clear }) => clear ? ({}) : ({ includeStatic, includeBody }), + toolParams: ({ static: includeStatic, body: includeBody, filter, clear }) => clear ? ({}) : ({ includeStatic, includeBody, filter }), }); const tracingStart = declareCommand({ diff --git a/tests/mcp/cli-devtools.spec.ts b/tests/mcp/cli-devtools.spec.ts index 63a5028c4001e..011fc4fd1abb9 100644 --- a/tests/mcp/cli-devtools.spec.ts +++ b/tests/mcp/cli-devtools.spec.ts @@ -64,6 +64,18 @@ test('network --static', async ({ cli, server }) => { expect(attachments[0].data.toString()).toContain(`[GET] ${`${server.PREFIX}/`} => [200] OK`); }); +test('network --filter', async ({ cli, server }) => { + server.setContent('/', ``, 'text/html'); + await cli('open', server.PREFIX); + + const { attachments } = await cli('network', '--filter=/api/', '--static'); + expect(attachments[0].data.toString()).toContain(`${server.PREFIX}/api/users`); + expect(attachments[0].data.toString()).toContain(`${server.PREFIX}/api/orders`); + expect(attachments[0].data.toString()).not.toContain(`${server.PREFIX}/static/image.png`); +}); + test('network --body', async ({ cli, server }) => { server.setContent('/', ` diff --git a/tests/mcp/network.spec.ts b/tests/mcp/network.spec.ts index 52e9293824bbc..9f5bb01e13ce0 100644 --- a/tests/mcp/network.spec.ts +++ b/tests/mcp/network.spec.ts @@ -61,6 +61,27 @@ test('browser_network_requests', async ({ client, server }) => { } }); +test('browser_network_requests filter', async ({ client, server }) => { + server.setContent('/', ``, 'text/html'); + + await client.callTool({ + name: 'browser_navigate', + arguments: { url: server.PREFIX }, + }); + + { + const response = parseResponse(await client.callTool({ + name: 'browser_network_requests', + arguments: { filter: '/api/', includeStatic: true }, + })); + expect(response.result).toContain(`${server.PREFIX}/api/users`); + expect(response.result).toContain(`${server.PREFIX}/api/orders`); + expect(response.result).not.toContain(`${server.PREFIX}/static/image.png`); + } +}); + test('browser_network_requests includes request payload', async ({ client, server }) => { server.setContent('/', ` From a3eb8d07e3e7a8525d322fb8b7e910e213a441ea Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 13 Mar 2026 16:33:26 -0700 Subject: [PATCH 3/6] rename to request body --- packages/playwright-core/src/tools/backend/network.ts | 4 ++-- packages/playwright-core/src/tools/cli-daemon/commands.ts | 4 ++-- tests/mcp/network.spec.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/playwright-core/src/tools/backend/network.ts b/packages/playwright-core/src/tools/backend/network.ts index d565aef9493ab..197d7e267c3da 100644 --- a/packages/playwright-core/src/tools/backend/network.ts +++ b/packages/playwright-core/src/tools/backend/network.ts @@ -28,7 +28,7 @@ const requests = defineTabTool({ description: 'Returns all network requests since loading the page', inputSchema: z.object({ includeStatic: z.boolean().default(false).describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), - includeBody: z.boolean().default(false).describe('Whether to include request body. Defaults to false.'), + includeRequestBody: z.boolean().default(false).describe('Whether to include request body. Defaults to false.'), filter: z.string().optional().describe('Only return requests whose URL matches this regexp (e.g. "/api/.*user").'), filename: z.string().optional().describe('Filename to save the network requests to. If not provided, requests are returned as text.'), }), @@ -47,7 +47,7 @@ const requests = defineTabTool({ if (!filter.test(request.url())) continue; } - text.push(await renderRequest(request, params.includeBody)); + text.push(await renderRequest(request, params.includeRequestBody)); } await response.addResult('Network', text.join('\n'), { prefix: 'network', ext: 'log', suggestedFilename: params.filename }); }, diff --git a/packages/playwright-core/src/tools/cli-daemon/commands.ts b/packages/playwright-core/src/tools/cli-daemon/commands.ts index 4da4ae8a30bac..378b2cd5475bd 100644 --- a/packages/playwright-core/src/tools/cli-daemon/commands.ts +++ b/packages/playwright-core/src/tools/cli-daemon/commands.ts @@ -743,12 +743,12 @@ const networkRequests = declareCommand({ args: z.object({}), options: z.object({ static: z.boolean().optional().describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), - body: z.boolean().optional().describe('Whether to include request body. Defaults to false.'), + ['request-body']: z.boolean().optional().describe('Whether to include request body. Defaults to false.'), filter: z.string().optional().describe('Only return requests whose URL matches this regexp (e.g. "/api/.*user").'), clear: z.boolean().optional().describe('Whether to clear the network list'), }), toolName: ({ clear }) => clear ? 'browser_network_clear' : 'browser_network_requests', - toolParams: ({ static: includeStatic, body: includeBody, filter, clear }) => clear ? ({}) : ({ includeStatic, includeBody, filter }), + toolParams: ({ static: includeStatic, 'request-body': includeRequestBody, filter, clear }) => clear ? ({}) : ({ includeStatic, includeRequestBody, filter }), }); const tracingStart = declareCommand({ diff --git a/tests/mcp/network.spec.ts b/tests/mcp/network.spec.ts index 9f5bb01e13ce0..9d8952e1c6c9a 100644 --- a/tests/mcp/network.spec.ts +++ b/tests/mcp/network.spec.ts @@ -115,7 +115,7 @@ test('browser_network_requests includes request payload', async ({ client, serve { const response = parseResponse(await client.callTool({ name: 'browser_network_requests', - arguments: { includeBody: true }, + arguments: { includeRequestBody: true }, })); expect(response.result).toContain(`[POST] ${server.PREFIX}/api => [200] OK`); expect(response.result).toContain(`Request body: {"key":"value"}`); From 674fd41aa68c4aca1f77bac26716cd4f411885e8 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 13 Mar 2026 16:36:56 -0700 Subject: [PATCH 4/6] copilot instructions --- .github/copilot-instructions.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000000000..231189577e90c --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,9 @@ +## PR Review Guidelines + +When reviewing pull requests: + +- Only comment on semantically meaningful issues: bugs, incorrect logic, security problems, or API contract violations. +- Skip style, formatting, naming, and whitespace observations unless they cause functional problems. +- Keep each comment short — one or two sentences maximum. +- Do not write long descriptions or summaries of what the code does. +- Do not suggest refactors or improvements unrelated to the PR's stated goal. From 704a31b475cfaaa58baa8013179bfc02474a0c90 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 13 Mar 2026 16:43:42 -0700 Subject: [PATCH 5/6] --include-headers option --- .../src/tools/backend/network.ts | 17 +++++++--- .../src/tools/cli-daemon/commands.ts | 3 +- tests/mcp/cli-devtools.spec.ts | 25 ++++++++++++-- tests/mcp/network.spec.ts | 34 +++++++++++++++++++ 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/packages/playwright-core/src/tools/backend/network.ts b/packages/playwright-core/src/tools/backend/network.ts index 197d7e267c3da..aac87277b30e7 100644 --- a/packages/playwright-core/src/tools/backend/network.ts +++ b/packages/playwright-core/src/tools/backend/network.ts @@ -29,6 +29,7 @@ const requests = defineTabTool({ inputSchema: z.object({ includeStatic: z.boolean().default(false).describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), includeRequestBody: z.boolean().default(false).describe('Whether to include request body. Defaults to false.'), + includeRequestHeaders: z.boolean().default(false).describe('Whether to include request headers. Defaults to false.'), filter: z.string().optional().describe('Only return requests whose URL matches this regexp (e.g. "/api/.*user").'), filename: z.string().optional().describe('Filename to save the network requests to. If not provided, requests are returned as text.'), }), @@ -47,7 +48,7 @@ const requests = defineTabTool({ if (!filter.test(request.url())) continue; } - text.push(await renderRequest(request, params.includeRequestBody)); + text.push(await renderRequest(request, params.includeRequestBody, params.includeRequestHeaders)); } await response.addResult('Network', text.join('\n'), { prefix: 'network', ext: 'log', suggestedFilename: params.filename }); }, @@ -79,21 +80,27 @@ export function isFetch(request: playwright.Request): boolean { return ['fetch', 'xhr'].includes(request.resourceType()); } -export async function renderRequest(request: playwright.Request, includeBody = false): Promise { +export async function renderRequest(request: playwright.Request, includeBody = false, includeHeaders = false): Promise { const response = request.existingResponse(); const result: string[] = []; result.push(`[${request.method().toUpperCase()}] ${request.url()}`); if (response) - result.push(`=> [${response.status()}] ${response.statusText()}`); + result.push(` => [${response.status()}] ${response.statusText()}`); else if (request.failure()) - result.push(`=> [FAILED] ${request.failure()?.errorText ?? 'Unknown error'}`); + result.push(` => [FAILED] ${request.failure()?.errorText ?? 'Unknown error'}`); + if (includeHeaders) { + const headers = request.headers(); + const headerLines = Object.entries(headers).map(([k, v]) => ` ${k}: ${v}`).join('\n'); + if (headerLines) + result.push(`\n Request headers:\n${headerLines}`); + } if (includeBody) { const postData = request.postData(); if (postData) result.push(`\n Request body: ${postData}`); } - return result.join(' '); + return result.join(''); } const networkStateSet = defineTool({ diff --git a/packages/playwright-core/src/tools/cli-daemon/commands.ts b/packages/playwright-core/src/tools/cli-daemon/commands.ts index 378b2cd5475bd..3aa473958d16e 100644 --- a/packages/playwright-core/src/tools/cli-daemon/commands.ts +++ b/packages/playwright-core/src/tools/cli-daemon/commands.ts @@ -744,11 +744,12 @@ const networkRequests = declareCommand({ options: z.object({ static: z.boolean().optional().describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), ['request-body']: z.boolean().optional().describe('Whether to include request body. Defaults to false.'), + ['request-headers']: z.boolean().optional().describe('Whether to include request headers. Defaults to false.'), filter: z.string().optional().describe('Only return requests whose URL matches this regexp (e.g. "/api/.*user").'), clear: z.boolean().optional().describe('Whether to clear the network list'), }), toolName: ({ clear }) => clear ? 'browser_network_clear' : 'browser_network_requests', - toolParams: ({ static: includeStatic, 'request-body': includeRequestBody, filter, clear }) => clear ? ({}) : ({ includeStatic, includeRequestBody, filter }), + toolParams: ({ static: includeStatic, 'request-body': includeRequestBody, 'request-headers': includeRequestHeaders, filter, clear }) => clear ? ({}) : ({ includeStatic, includeRequestBody, includeRequestHeaders, filter }), }); const tracingStart = declareCommand({ diff --git a/tests/mcp/cli-devtools.spec.ts b/tests/mcp/cli-devtools.spec.ts index 011fc4fd1abb9..12086d8d26be9 100644 --- a/tests/mcp/cli-devtools.spec.ts +++ b/tests/mcp/cli-devtools.spec.ts @@ -76,7 +76,7 @@ test('network --filter', async ({ cli, server }) => { expect(attachments[0].data.toString()).not.toContain(`${server.PREFIX}/static/image.png`); }); -test('network --body', async ({ cli, server }) => { +test('network --request-body', async ({ cli, server }) => { server.setContent('/', ` `, 'text/html'); @@ -90,12 +90,33 @@ test('network --body', async ({ cli, server }) => { } { - const { attachments } = await cli('network', '--body'); + const { attachments } = await cli('network', '--request-body'); expect(attachments[0].data.toString()).toContain(`[POST] ${server.PREFIX}/api => [200] OK`); expect(attachments[0].data.toString()).toContain('Request body: {"key":"value"}'); } }); +test('network --request-headers', async ({ cli, server }) => { + server.setContent('/', ` + + `, 'text/html'); + server.setContent('/api', '{}', 'application/json'); + await cli('open', server.PREFIX); + await cli('click', 'e2'); + + { + const { attachments } = await cli('network'); + expect(attachments[0].data.toString()).not.toContain('Request headers:'); + } + + { + const { attachments } = await cli('network', '--request-headers'); + expect(attachments[0].data.toString()).toContain(`[GET] ${server.PREFIX}/api => [200] OK`); + expect(attachments[0].data.toString()).toContain('Request headers:'); + expect(attachments[0].data.toString()).toContain('x-custom-header: test-value'); + } +}); + test('network --clear', async ({ cli, server }) => { await cli('open', server.PREFIX); await cli('eval', '() => fetch("/hello-world")'); diff --git a/tests/mcp/network.spec.ts b/tests/mcp/network.spec.ts index 9d8952e1c6c9a..b5c3f11cda862 100644 --- a/tests/mcp/network.spec.ts +++ b/tests/mcp/network.spec.ts @@ -82,6 +82,40 @@ test('browser_network_requests filter', async ({ client, server }) => { } }); +test('browser_network_requests includes request headers', async ({ client, server }) => { + server.setContent('/', ` + + `, 'text/html'); + server.setContent('/api', '{}', 'application/json'); + + await client.callTool({ + name: 'browser_navigate', + arguments: { url: server.PREFIX }, + }); + + await client.callTool({ + name: 'browser_click', + arguments: { element: 'Click me button', ref: 'e2' }, + }); + + { + const response = parseResponse(await client.callTool({ + name: 'browser_network_requests', + })); + expect(response.result).not.toContain('Request headers:'); + } + + { + const response = parseResponse(await client.callTool({ + name: 'browser_network_requests', + arguments: { includeRequestHeaders: true }, + })); + expect(response.result).toContain(`[GET] ${server.PREFIX}/api => [200] OK`); + expect(response.result).toContain('Request headers:'); + expect(response.result).toContain('x-custom-header: test-value'); + } +}); + test('browser_network_requests includes request payload', async ({ client, server }) => { server.setContent('/', ` From 7dfdaf26a0e0c3796fcf42f733b30b5eff255f6d Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 13 Mar 2026 16:50:10 -0700 Subject: [PATCH 6/6] drop include prefix --- packages/playwright-core/src/tools/backend/network.ts | 10 +++++----- .../playwright-core/src/tools/cli-daemon/commands.ts | 2 +- tests/mcp/network.spec.ts | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/playwright-core/src/tools/backend/network.ts b/packages/playwright-core/src/tools/backend/network.ts index aac87277b30e7..4097422b63357 100644 --- a/packages/playwright-core/src/tools/backend/network.ts +++ b/packages/playwright-core/src/tools/backend/network.ts @@ -27,9 +27,9 @@ const requests = defineTabTool({ title: 'List network requests', description: 'Returns all network requests since loading the page', inputSchema: z.object({ - includeStatic: z.boolean().default(false).describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), - includeRequestBody: z.boolean().default(false).describe('Whether to include request body. Defaults to false.'), - includeRequestHeaders: z.boolean().default(false).describe('Whether to include request headers. Defaults to false.'), + static: z.boolean().default(false).describe('Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.'), + requestBody: z.boolean().default(false).describe('Whether to include request body. Defaults to false.'), + requestHeaders: z.boolean().default(false).describe('Whether to include request headers. Defaults to false.'), filter: z.string().optional().describe('Only return requests whose URL matches this regexp (e.g. "/api/.*user").'), filename: z.string().optional().describe('Filename to save the network requests to. If not provided, requests are returned as text.'), }), @@ -41,14 +41,14 @@ const requests = defineTabTool({ const filter = params.filter ? new RegExp(params.filter) : undefined; const text: string[] = []; for (const request of requests) { - if (!params.includeStatic && !isFetch(request) && isSuccessfulResponse(request)) + if (!params.static && !isFetch(request) && isSuccessfulResponse(request)) continue; if (filter) { filter.lastIndex = 0; if (!filter.test(request.url())) continue; } - text.push(await renderRequest(request, params.includeRequestBody, params.includeRequestHeaders)); + text.push(await renderRequest(request, params.requestBody, params.requestHeaders)); } await response.addResult('Network', text.join('\n'), { prefix: 'network', ext: 'log', suggestedFilename: params.filename }); }, diff --git a/packages/playwright-core/src/tools/cli-daemon/commands.ts b/packages/playwright-core/src/tools/cli-daemon/commands.ts index 3aa473958d16e..f410a7856090e 100644 --- a/packages/playwright-core/src/tools/cli-daemon/commands.ts +++ b/packages/playwright-core/src/tools/cli-daemon/commands.ts @@ -749,7 +749,7 @@ const networkRequests = declareCommand({ clear: z.boolean().optional().describe('Whether to clear the network list'), }), toolName: ({ clear }) => clear ? 'browser_network_clear' : 'browser_network_requests', - toolParams: ({ static: includeStatic, 'request-body': includeRequestBody, 'request-headers': includeRequestHeaders, filter, clear }) => clear ? ({}) : ({ includeStatic, includeRequestBody, includeRequestHeaders, filter }), + toolParams: ({ static: s, 'request-body': requestBody, 'request-headers': requestHeaders, filter, clear }) => clear ? ({}) : ({ static: s, requestBody, requestHeaders, filter }), }); const tracingStart = declareCommand({ diff --git a/tests/mcp/network.spec.ts b/tests/mcp/network.spec.ts index b5c3f11cda862..94ee4cad6e06f 100644 --- a/tests/mcp/network.spec.ts +++ b/tests/mcp/network.spec.ts @@ -52,7 +52,7 @@ test('browser_network_requests', async ({ client, server }) => { const response = parseResponse(await client.callTool({ name: 'browser_network_requests', arguments: { - includeStatic: true, + static: true, }, })); expect(response.result).toContain(`[GET] ${`${server.PREFIX}/`} => [200] OK`); @@ -74,7 +74,7 @@ test('browser_network_requests filter', async ({ client, server }) => { { const response = parseResponse(await client.callTool({ name: 'browser_network_requests', - arguments: { filter: '/api/', includeStatic: true }, + arguments: { filter: '/api/', static: true }, })); expect(response.result).toContain(`${server.PREFIX}/api/users`); expect(response.result).toContain(`${server.PREFIX}/api/orders`); @@ -108,7 +108,7 @@ test('browser_network_requests includes request headers', async ({ client, serve { const response = parseResponse(await client.callTool({ name: 'browser_network_requests', - arguments: { includeRequestHeaders: true }, + arguments: { requestHeaders: true }, })); expect(response.result).toContain(`[GET] ${server.PREFIX}/api => [200] OK`); expect(response.result).toContain('Request headers:'); @@ -149,7 +149,7 @@ test('browser_network_requests includes request payload', async ({ client, serve { const response = parseResponse(await client.callTool({ name: 'browser_network_requests', - arguments: { includeRequestBody: true }, + arguments: { requestBody: true }, })); expect(response.result).toContain(`[POST] ${server.PREFIX}/api => [200] OK`); expect(response.result).toContain(`Request body: {"key":"value"}`);