@mcp-b/chrome-devtools-mcp 1.7.2 → 1.8.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.
@@ -89,6 +89,7 @@ export class McpContext {
89
89
  #networkConditionsMap = new WeakMap();
90
90
  #cpuThrottlingRateMap = new WeakMap();
91
91
  #geolocationMap = new WeakMap();
92
+ #bypassCSPMap = new WeakMap();
92
93
  #dialog;
93
94
  #nextSnapshotId = 1;
94
95
  #traceResults = [];
@@ -616,6 +617,20 @@ export class McpContext {
616
617
  const page = this.getSelectedPage();
617
618
  return this.#geolocationMap.get(page) ?? null;
618
619
  }
620
+ async setBypassCSP(enabled) {
621
+ const page = this.getSelectedPage();
622
+ await page.setBypassCSP(enabled);
623
+ if (enabled) {
624
+ this.#bypassCSPMap.set(page, true);
625
+ }
626
+ else {
627
+ this.#bypassCSPMap.delete(page);
628
+ }
629
+ }
630
+ getBypassCSP() {
631
+ const page = this.getSelectedPage();
632
+ return this.#bypassCSPMap.get(page) ?? false;
633
+ }
619
634
  setIsRunningPerformanceTrace(x) {
620
635
  this.#isRunningTrace = x;
621
636
  }
@@ -110,6 +110,10 @@ export const navigatePage = defineTool({
110
110
  .boolean()
111
111
  .optional()
112
112
  .describe('Whether to ignore cache on reload.'),
113
+ bypassCSP: zod
114
+ .boolean()
115
+ .optional()
116
+ .describe('Bypass Content-Security-Policy on the page. Useful for injecting scripts into third-party sites during development.'),
113
117
  ...timeoutSchema,
114
118
  },
115
119
  handler: async (request, response, context) => {
@@ -117,6 +121,9 @@ export const navigatePage = defineTool({
117
121
  const options = {
118
122
  timeout: request.params.timeout,
119
123
  };
124
+ if (request.params.bypassCSP !== undefined) {
125
+ await context.setBypassCSP(request.params.bypassCSP);
126
+ }
120
127
  if (!request.params.type && !request.params.url) {
121
128
  throw new Error('Either URL or a type is required.');
122
129
  }
@@ -3,19 +3,26 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { readFile } from 'node:fs/promises';
6
7
  import { zod } from '../third_party/index.js';
7
8
  import { ToolCategory } from './categories.js';
8
9
  import { defineTool } from './ToolDefinition.js';
9
10
  export const evaluateScript = defineTool({
10
11
  name: 'evaluate_script',
11
- description: `Evaluate a JavaScript function inside the currently selected page. Returns the response as JSON
12
- so returned values have to JSON-serializable.`,
12
+ description: `Evaluate a JavaScript function or inject a script file into the currently selected page.
13
+
14
+ When \`function\` is provided, evaluates it and returns the result as JSON (values must be JSON-serializable).
15
+ When \`filePath\` is provided, reads the file from disk and injects it as a <script> tag (useful for large scripts like polyfills that are too big to pass inline).
16
+ Exactly one of \`function\` or \`filePath\` must be provided.`,
13
17
  annotations: {
14
18
  category: ToolCategory.DEBUGGING,
15
19
  readOnlyHint: false,
16
20
  },
17
21
  schema: {
18
- function: zod.string().describe(`A JavaScript function declaration to be executed by the tool in the currently selected page.
22
+ function: zod
23
+ .string()
24
+ .optional()
25
+ .describe(`A JavaScript function declaration to be executed by the tool in the currently selected page.
19
26
  Example without arguments: \`() => {
20
27
  return document.title
21
28
  }\` or \`async () => {
@@ -25,6 +32,10 @@ Example with arguments: \`(el) => {
25
32
  return el.innerText;
26
33
  }\`
27
34
  `),
35
+ filePath: zod
36
+ .string()
37
+ .optional()
38
+ .describe('Absolute path to a local JavaScript file to inject into the page via <script> tag. The file is read server-side so there are no size limits or CSP/mixed-content restrictions. Use this for large scripts (polyfills, bundled tools, etc).'),
28
39
  args: zod
29
40
  .array(zod.object({
30
41
  uid: zod
@@ -32,9 +43,25 @@ Example with arguments: \`(el) => {
32
43
  .describe('The uid of an element on the page from the page content snapshot'),
33
44
  }))
34
45
  .optional()
35
- .describe(`An optional list of arguments to pass to the function.`),
46
+ .describe(`An optional list of arguments to pass to the function. Only used with \`function\`, not \`filePath\`.`),
36
47
  },
37
48
  handler: async (request, response, context) => {
49
+ const { filePath } = request.params;
50
+ // File injection mode
51
+ if (filePath) {
52
+ if (request.params.function) {
53
+ throw new Error('Provide either `function` or `filePath`, not both.');
54
+ }
55
+ const content = await readFile(filePath, 'utf-8');
56
+ const page = context.getSelectedPage();
57
+ await page.addScriptTag({ content });
58
+ response.appendResponseLine(`Injected script from \`${filePath}\` (${content.length} bytes) into page.`);
59
+ return;
60
+ }
61
+ // Function evaluation mode (original behavior)
62
+ if (!request.params.function) {
63
+ throw new Error('Either `function` or `filePath` must be provided.');
64
+ }
38
65
  const args = [];
39
66
  try {
40
67
  const frames = new Set();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/chrome-devtools-mcp",
3
- "version": "1.7.2",
3
+ "version": "1.8.1",
4
4
  "description": "MCP server for Chrome DevTools with WebMCP integration for connecting to website MCP tools",
5
5
  "keywords": [
6
6
  "mcp",