Skip to content

Commit 3f4284d

Browse files
authored
Merge branch 'ChromeDevTools:main' into feat-computed-css
2 parents c723efb + fefc8ad commit 3f4284d

18 files changed

Lines changed: 245 additions & 133 deletions

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
# Chrome DevTools MCP
1+
# Chrome DevTools for Agents
22

33
[![npm chrome-devtools-mcp package](https://img.shields.io/npm/v/chrome-devtools-mcp.svg)](https://npmjs.org/package/chrome-devtools-mcp)
44

5-
`chrome-devtools-mcp` lets your coding agent (such as Gemini, Claude, Cursor or Copilot)
5+
Chrome DevTools for Agents (`chrome-devtools-mcp`) lets your coding agent (such as Gemini, Claude, Cursor or Copilot)
66
control and inspect a live Chrome browser. It acts as a Model-Context-Protocol
77
(MCP) server, giving your AI coding assistant access to the full power of
88
Chrome DevTools for reliable automation, in-depth debugging, and performance analysis.
9+
A [CLI](docs/cli.md) is also provided for use without MCP.
910

1011
## [Tool reference](./docs/tool-reference.md) | [MCP tools guide](./docs/mcp-tools-user-guide.md) | [Changelog](./CHANGELOG.md) | [Contributing](./CONTRIBUTING.md) | [Troubleshooting](./docs/troubleshooting.md) | [Design Principles](./docs/design-principles.md)
1112

@@ -630,6 +631,11 @@ The Chrome DevTools MCP server supports the following configuration option:
630631
Exposes a "slim" set of 3 tools covering navigation, script execution and screenshots only. Useful for basic browser tasks.
631632
- **Type:** boolean
632633

634+
- **`--redactNetworkHeaders`/ `--redact-network-headers`**
635+
If true, redacts some of the network headers considered senstive before returning to the client.
636+
- **Type:** boolean
637+
- **Default:** `false`
638+
633639
<!-- END AUTO GENERATED OPTIONS -->
634640

635641
Pass them via the `args` property in the JSON configuration. For example:

SECURITY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
## Security policy
22

33
The Chrome DevTools MCP project takes security very seriously. Please use [Chromium’s process to report security issues](https://www.chromium.org/Home/chromium-security/reporting-security-bugs/).
4+
5+
### Scope
6+
7+
In general, it is the expectation that the AI agent or client using this MCP server validates any input before sending it. The server provides powerful capabilities for browser automation and inspection, and it is the responsibility of the calling agent to ensure these are used safely and as intended.
8+
9+
Several tools in this project have the ability to perform actions such as writing files to disk (e.g., via browser downloads or screenshots) or dynamically loading Chrome extensions. These are intentional, documented features and are not vulnerabilities.

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"@types/yargs": "^17.0.33",
6262
"@typescript-eslint/eslint-plugin": "^8.43.0",
6363
"@typescript-eslint/parser": "^8.43.0",
64-
"chrome-devtools-frontend": "1.0.1611825",
64+
"chrome-devtools-frontend": "1.0.1613625",
6565
"core-js": "3.49.0",
6666
"debug": "4.4.3",
6767
"eslint": "^9.35.0",

scripts/post-build.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ function main(): void {
2626

2727
// Create i18n mock
2828
const i18nDir = path.join(BUILD_DIR, devtoolsFrontEndCorePath, 'i18n');
29+
fs.mkdirSync(i18nDir, {recursive: true});
2930
const localesFile = path.join(i18nDir, 'locales.js');
3031
const localesContent = `
3132
export const LOCALES = [

scripts/test.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ async function runNodeTestBatch(testTimeoutMs, testFiles, label) {
122122
...process.env,
123123
CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS: true,
124124
CHROME_DEVTOOLS_MCP_CRASH_ON_UNCAUGHT: true,
125+
CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS: true,
125126
},
126127
});
127128
child.on('close', code => {

src/McpResponse.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ export class McpResponse implements Response {
189189
#tabId?: string;
190190
#args: ParsedArguments;
191191
#page?: McpPage;
192+
#redactNetworkHeaders = true;
192193

193194
constructor(args: ParsedArguments) {
194195
this.#args = args;
@@ -198,6 +199,10 @@ export class McpResponse implements Response {
198199
this.#page = page;
199200
}
200201

202+
setRedactNetworkHeaders(value: boolean): void {
203+
this.#redactNetworkHeaders = value;
204+
}
205+
201206
attachDevToolsData(data: DevToolsData): void {
202207
this.#devToolsData = data;
203208
}
@@ -429,6 +434,7 @@ export class McpResponse implements Response {
429434
requestFilePath: this.#attachedNetworkRequestOptions?.requestFilePath,
430435
responseFilePath: this.#attachedNetworkRequestOptions?.responseFilePath,
431436
saveFile: (data, filename) => context.saveFile(data, filename),
437+
redactNetworkHeaders: this.#redactNetworkHeaders,
432438
});
433439
detailedNetworkRequest = formatter;
434440
}
@@ -572,6 +578,7 @@ export class McpResponse implements Response {
572578
this.#networkRequestsOptions?.networkRequestIdInDevToolsUI,
573579
fetchData: false,
574580
saveFile: (data, filename) => context.saveFile(data, filename),
581+
redactNetworkHeaders: this.#redactNetworkHeaders,
575582
}),
576583
),
577584
);

src/bin/chrome-devtools-mcp-cli-options.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ export const cliOptions = {
261261
'Set by Chrome DevTools CLI if the MCP server is started via the CLI client (this arg exists for usage stats)',
262262
hidden: true,
263263
},
264+
redactNetworkHeaders: {
265+
type: 'boolean',
266+
describe:
267+
'If true, redacts some of the network headers considered senstive before returning to the client.',
268+
default: false,
269+
},
264270
} satisfies Record<string, YargsOptions>;
265271

266272
export type ParsedArguments = ReturnType<typeof parseArguments>;

src/formatters/NetworkFormatter.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66

77
import {isUtf8} from 'node:buffer';
88

9-
import type {HTTPRequest, HTTPResponse} from '../third_party/index.js';
9+
import {
10+
DevTools,
11+
type HTTPRequest,
12+
type HTTPResponse,
13+
} from '../third_party/index.js';
1014

1115
const BODY_CONTEXT_SIZE_LIMIT = 10000;
1216

@@ -21,6 +25,7 @@ export interface NetworkFormatterOptions {
2125
data: Uint8Array<ArrayBufferLike>,
2226
filename: string,
2327
) => Promise<{filename: string}>;
28+
redactNetworkHeaders: boolean;
2429
}
2530

2631
interface NetworkRequestConcise {
@@ -150,6 +155,20 @@ export class NetworkFormatter {
150155
};
151156
}
152157

158+
#redactNetworkHeaders(
159+
headers: Record<string, string>,
160+
): Record<string, string> {
161+
const headersList = Object.entries(headers).map(item => {
162+
return {name: item[0], value: item[1]};
163+
});
164+
const redacted =
165+
DevTools.NetworkRequestFormatter.sanitizeHeaders(headersList);
166+
return redacted.reduce<Record<string, string>>((acc, item) => {
167+
acc[item.name] = item.value;
168+
return acc;
169+
}, {});
170+
}
171+
153172
toJSONDetailed(): NetworkRequestDetailed {
154173
const redirectChain = this.#request.redirectChain();
155174
const formattedRedirectChain = redirectChain.reverse().map(request => {
@@ -159,16 +178,24 @@ export class NetworkFormatter {
159178
const formatter = new NetworkFormatter(request, {
160179
requestId: id,
161180
saveFile: this.#options.saveFile,
181+
redactNetworkHeaders: this.#options.redactNetworkHeaders,
162182
});
163183
return formatter.toJSON();
164184
});
165185

186+
const responseHeaders = this.#request.response()?.headers();
187+
166188
return {
167189
...this.toJSON(),
168-
requestHeaders: this.#request.headers(),
190+
requestHeaders: this.#options.redactNetworkHeaders
191+
? this.#redactNetworkHeaders(this.#request.headers())
192+
: this.#request.headers(),
169193
requestBody: this.#requestBody,
170194
requestBodyFilePath: this.#requestBodyFilePath,
171-
responseHeaders: this.#request.response()?.headers(),
195+
responseHeaders:
196+
this.#options.redactNetworkHeaders && responseHeaders
197+
? this.#redactNetworkHeaders(responseHeaders)
198+
: this.#request.response()?.headers(),
172199
responseBody: this.#responseBody,
173200
responseBodyFilePath: this.#responseBodyFilePath,
174201
failure: this.#request.failure()?.errorText,

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ export async function createMcpServer(
192192
const response = serverArgs.slim
193193
? new SlimMcpResponse(serverArgs)
194194
: new McpResponse(serverArgs);
195+
196+
response.setRedactNetworkHeaders(serverArgs.redactNetworkHeaders);
195197
if ('pageScoped' in tool && tool.pageScoped) {
196198
const page =
197199
serverArgs.experimentalPageIdRouting &&

0 commit comments

Comments
 (0)