Skip to content

Commit bd895f4

Browse files
revert: support experimental allowlist for navigate tool calls (#1935)
This reverts commit d502557.
1 parent 4f8eb7a commit bd895f4

6 files changed

Lines changed: 58 additions & 270 deletions

File tree

package-lock.json

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

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@
8080
"sinon": "^22.0.0",
8181
"typescript": "^6.0.2",
8282
"typescript-eslint": "^8.43.0",
83-
"urlpattern-polyfill": "^10.1.0",
8483
"yargs": "18.0.0"
8584
},
8685
"engines": {

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,6 @@ export const cliOptions = {
181181
describe:
182182
'Whether to include all kinds of pages such as webviews or background pages as pages.',
183183
},
184-
experimentalNavigationAllowlist: {
185-
type: 'boolean',
186-
describe: 'Whether to enable navigation allowlist tool parameter.',
187-
hidden: true,
188-
},
189184
experimentalInteropTools: {
190185
type: 'boolean',
191186
describe: 'Whether to enable interoperability tools',

src/third_party/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import 'urlpattern-polyfill';
87
import 'core-js/modules/es.promise.with-resolvers.js';
98
import 'core-js/modules/es.set.union.v2.js';
109
import 'core-js/proposals/iterator-helpers.js';

src/tools/pages.ts

Lines changed: 58 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -5,76 +5,17 @@
55
*/
66

77
import {logger} from '../logger.js';
8-
import type {CdpPage, Dialog, HTTPRequest} from '../third_party/index.js';
8+
import type {CdpPage, Dialog} from '../third_party/index.js';
99
import {zod} from '../third_party/index.js';
1010

1111
import {ToolCategory} from './categories.js';
12-
import type {ContextPage} from './ToolDefinition.js';
1312
import {
1413
CLOSE_PAGE_ERROR,
1514
definePageTool,
1615
defineTool,
1716
timeoutSchema,
1817
} from './ToolDefinition.js';
1918

20-
async function navigateWithInterception(
21-
page: ContextPage,
22-
action: () => Promise<unknown>,
23-
allowListString?: string,
24-
timeout?: number,
25-
): Promise<void> {
26-
const allowList = allowListString
27-
? allowListString.split(',').map((p: string) => new URLPattern(p.trim()))
28-
: undefined;
29-
30-
const requestHandler = (interceptedRequest: HTTPRequest) => {
31-
if (!interceptedRequest.isNavigationRequest()) {
32-
void interceptedRequest.continue();
33-
return;
34-
}
35-
const requestUrl = interceptedRequest.url();
36-
const isAllowed = allowList!.some((pattern: URLPattern) =>
37-
pattern.test(requestUrl),
38-
);
39-
40-
if (isAllowed) {
41-
void interceptedRequest.continue();
42-
} else {
43-
logger?.(`Blocking request to: ${requestUrl}`);
44-
void interceptedRequest.abort('blockedbyclient');
45-
}
46-
};
47-
48-
const cleanupInterception = async () => {
49-
if (allowList) {
50-
page.pptrPage.off('request', requestHandler);
51-
await page.pptrPage.setRequestInterception(false).catch(error => {
52-
logger?.(`Failed to disable request interception`, error);
53-
});
54-
}
55-
};
56-
57-
if (allowList) {
58-
await page.pptrPage.setRequestInterception(true);
59-
page.pptrPage.on('request', requestHandler);
60-
}
61-
62-
try {
63-
await page.waitForEventsAfterAction(
64-
async () => {
65-
try {
66-
await action();
67-
} finally {
68-
await cleanupInterception();
69-
}
70-
},
71-
{timeout},
72-
);
73-
} finally {
74-
await cleanupInterception();
75-
}
76-
}
77-
7819
export const listPages = defineTool(args => {
7920
return {
8021
name: 'list_pages',
@@ -179,16 +120,6 @@ export const newPage = defineTool(args => {
179120
'Pages in the same browser context share cookies and storage. ' +
180121
'Pages in different browser contexts are fully isolated.',
181122
),
182-
...(args?.experimentalNavigationAllowlist
183-
? {
184-
allowList: zod
185-
.string()
186-
.optional()
187-
.describe(
188-
'Optional comma-separated list of URL patterns to allow. If provided, all other navigations will be blocked.',
189-
),
190-
}
191-
: {}),
192123
...timeoutSchema,
193124
},
194125
blockedByDialog: false,
@@ -199,15 +130,9 @@ export const newPage = defineTool(args => {
199130
request.params.isolatedContext,
200131
);
201132

202-
await navigateWithInterception(
203-
page,
204-
() =>
205-
page.pptrPage.goto(request.params.url, {
206-
timeout: request.params.timeout,
207-
}),
208-
request.params.allowList,
209-
request.params.timeout,
210-
);
133+
await page.pptrPage.goto(request.params.url, {
134+
timeout: request.params.timeout,
135+
});
211136

212137
response.setIncludePages(true);
213138
response.setListThirdPartyDeveloperTools();
@@ -247,16 +172,7 @@ export const navigatePage = definePageTool(args => {
247172
.describe(
248173
'A JavaScript script to be executed on each new document before any other scripts for the next navigation.',
249174
),
250-
...(args?.experimentalNavigationAllowlist
251-
? {
252-
allowList: zod
253-
.string()
254-
.optional()
255-
.describe(
256-
'Optional comma-separated list of URL patterns to allow. If provided, all other navigations will be blocked.',
257-
),
258-
}
259-
: {}),
175+
260176
...timeoutSchema,
261177
},
262178
blockedByDialog: false,
@@ -301,71 +217,60 @@ export const navigatePage = definePageTool(args => {
301217
page.pptrPage.on('dialog', dialogHandler);
302218

303219
try {
304-
await navigateWithInterception(
305-
page,
306-
async () => {
307-
switch (request.params.type) {
308-
case 'url':
309-
if (!request.params.url) {
310-
throw new Error(
311-
'A URL is required for navigation of type=url.',
312-
);
313-
}
314-
try {
315-
await page.pptrPage.goto(request.params.url, options);
316-
response.appendResponseLine(
317-
`Successfully navigated to ${request.params.url}.`,
318-
);
319-
} catch (error) {
320-
response.appendResponseLine(
321-
`Unable to navigate in the selected page: ${error.message}.`,
322-
);
323-
}
324-
break;
325-
case 'back':
326-
try {
327-
await page.pptrPage.goBack(options);
328-
response.appendResponseLine(
329-
`Successfully navigated back to ${page.pptrPage.url()}.`,
330-
);
331-
} catch (error) {
332-
response.appendResponseLine(
333-
`Unable to navigate back in the selected page: ${error.message}.`,
334-
);
335-
}
336-
break;
337-
case 'forward':
338-
try {
339-
await page.pptrPage.goForward(options);
340-
response.appendResponseLine(
341-
`Successfully navigated forward to ${page.pptrPage.url()}.`,
342-
);
343-
} catch (error) {
344-
response.appendResponseLine(
345-
`Unable to navigate forward in the selected page: ${error.message}.`,
346-
);
347-
}
348-
break;
349-
case 'reload':
350-
try {
351-
await page.pptrPage.reload({
352-
...options,
353-
ignoreCache: request.params.ignoreCache,
354-
});
355-
response.appendResponseLine(
356-
`Successfully reloaded the page.`,
357-
);
358-
} catch (error) {
359-
response.appendResponseLine(
360-
`Unable to reload the selected page: ${error.message}.`,
361-
);
362-
}
363-
break;
220+
switch (request.params.type) {
221+
case 'url':
222+
if (!request.params.url) {
223+
throw new Error('A URL is required for navigation of type=url.');
364224
}
365-
},
366-
request.params.allowList,
367-
request.params.timeout,
368-
);
225+
try {
226+
await page.pptrPage.goto(request.params.url, options);
227+
response.appendResponseLine(
228+
`Successfully navigated to ${request.params.url}.`,
229+
);
230+
} catch (error) {
231+
response.appendResponseLine(
232+
`Unable to navigate in the selected page: ${error.message}.`,
233+
);
234+
}
235+
break;
236+
case 'back':
237+
try {
238+
await page.pptrPage.goBack(options);
239+
response.appendResponseLine(
240+
`Successfully navigated back to ${page.pptrPage.url()}.`,
241+
);
242+
} catch (error) {
243+
response.appendResponseLine(
244+
`Unable to navigate back in the selected page: ${error.message}.`,
245+
);
246+
}
247+
break;
248+
case 'forward':
249+
try {
250+
await page.pptrPage.goForward(options);
251+
response.appendResponseLine(
252+
`Successfully navigated forward to ${page.pptrPage.url()}.`,
253+
);
254+
} catch (error) {
255+
response.appendResponseLine(
256+
`Unable to navigate forward in the selected page: ${error.message}.`,
257+
);
258+
}
259+
break;
260+
case 'reload':
261+
try {
262+
await page.pptrPage.reload({
263+
...options,
264+
ignoreCache: request.params.ignoreCache,
265+
});
266+
response.appendResponseLine(`Successfully reloaded the page.`);
267+
} catch (error) {
268+
response.appendResponseLine(
269+
`Unable to reload the selected page: ${error.message}.`,
270+
);
271+
}
272+
break;
273+
}
369274
} finally {
370275
page.pptrPage.off('dialog', dialogHandler);
371276
if (initScriptId) {

0 commit comments

Comments
 (0)