Skip to content

Commit 1c92ba0

Browse files
authored
fix(cli): enable tools which require --memoryDebugging on the CLI (#2585)
Currently tools that require --memoryDebugging cannot directly be invoked from the CLI. The server needs to be start explicitly with the --memoryDebugging flag first. This PR makes --memoryDebugging a default for the CLI.
1 parent 57adfa9 commit 1c92ba0

4 files changed

Lines changed: 88 additions & 27 deletions

File tree

src/bin/chrome-devtools.ts

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,41 +31,39 @@ import {checkForUpdates} from '../utils/check-for-updates.js';
3131
import {VERSION} from '../version.js';
3232

3333
import {commands} from '../config/cli-options.js';
34-
import {mcpOptions, parseArguments} from '../config/mcp-options.js';
34+
import {
35+
mcpOptions,
36+
parseArguments,
37+
getMcpOptionsForViaCli,
38+
} from '../config/mcp-options.js';
3539

3640
await checkForUpdates(
3741
'Run `npm install -g chrome-devtools-mcp@latest` and `chrome-devtools start` to update and restart the daemon.',
3842
);
3943

44+
const DEFAULT_CLI_ARGS = ['--viaCli'];
45+
4046
async function start(args: string[], sessionId: string) {
41-
const combinedArgs = [...args, ...defaultArgs];
47+
const combinedArgs = [...DEFAULT_CLI_ARGS, ...args];
4248
await startDaemon(combinedArgs, sessionId);
4349
logDisclaimers(parseArguments(VERSION, combinedArgs));
4450
}
4551

46-
const defaultArgs = ['--viaCli', '--experimentalStructuredContent'];
52+
function getCliOptions() {
53+
const options: Partial<typeof mcpOptions> = {
54+
...getMcpOptionsForViaCli(),
55+
};
4756

48-
const startCliOptions = {
49-
...mcpOptions,
50-
} as Partial<typeof mcpOptions>;
57+
// Missing CLI serialization.
58+
delete options.viewport;
5159

52-
// Missing CLI serialization.
53-
delete startCliOptions.viewport;
60+
// Change the defaults for the CLI.
61+
delete options.experimentalStructuredContent;
62+
delete options.experimentalInteropTools;
63+
delete options.experimentalPageIdRouting;
5464

55-
// Change the defaults for the CLI.
56-
delete startCliOptions.experimentalStructuredContent;
57-
delete startCliOptions.experimentalInteropTools;
58-
delete startCliOptions.experimentalPageIdRouting;
59-
if (!('default' in mcpOptions.headless)) {
60-
throw new Error('headless cli option unexpectedly does not have a default');
61-
}
62-
if ('default' in mcpOptions.isolated) {
63-
throw new Error('isolated cli option unexpectedly has a default');
65+
return options;
6466
}
65-
startCliOptions.headless!.default = true;
66-
startCliOptions.isolated!.description =
67-
'If specified, creates a temporary user-data-dir that is automatically cleaned up after the browser is closed. Defaults to true unless userDataDir is provided.';
68-
startCliOptions.categoryExtensions!.default = true;
6967

7068
const y = yargs(hideBin(process.argv))
7169
.locale('en') // Force English to ensure error string matching works in .fail, all custom messages we output are in English anyways
@@ -132,7 +130,7 @@ y.command(
132130
'Start or restart chrome-devtools-mcp',
133131
y =>
134132
y
135-
.options(startCliOptions)
133+
.options(getCliOptions())
136134
.example(
137135
'$0 start --browserUrl http://localhost:9222',
138136
'Start the server connecting to an existing browser',

src/config/cli-options.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ export const commands: Commands = {
223223
},
224224
evaluate_script: {
225225
description:
226-
'Evaluate a JavaScript function inside the currently selected page. Returns the response as JSON, so returned values have to be JSON-serializable.',
226+
'Evaluate a JavaScript function inside the currently selected page or service worker. Returns the response as JSON, so returned values have to be JSON-serializable.',
227227
category: 'Debugging',
228228
args: {
229229
function: {
@@ -260,6 +260,13 @@ export const commands: Commands = {
260260
'Whether to wait for the DOM to settle. Pass false if the script only reads data. Defaults to true.',
261261
required: false,
262262
},
263+
serviceWorkerId: {
264+
name: 'serviceWorkerId',
265+
type: 'string',
266+
description:
267+
"The optional service worker id to evaluate the script in. If provided, 'pageId' should be omitted. Note: 'args' (element UIDs) cannot be used when evaluating in a service worker.",
268+
required: false,
269+
},
263270
},
264271
},
265272
execute_3p_developer_tool: {
@@ -821,7 +828,7 @@ export const commands: Commands = {
821828
},
822829
list_console_messages: {
823830
description:
824-
'List all console messages for the currently selected page since the last navigation.',
831+
'List all console messages for the currently selected page since the last navigation. This includes console messages originating from extensions content scripts.',
825832
category: 'Debugging',
826833
args: {
827834
pageSize: {
@@ -913,7 +920,8 @@ export const commands: Commands = {
913920
},
914921
},
915922
list_pages: {
916-
description: 'Get a list of pages open in the browser.',
923+
description:
924+
'Get a list of pages including extension service workers open in the browser.',
917925
category: 'Navigation automation',
918926
args: {},
919927
},

src/config/mcp-options.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,13 @@ export const mcpOptions = {
163163
},
164164
memoryDebugging: {
165165
type: 'boolean',
166+
default: false,
166167
describe: 'Whether to enable memory debugging tools.',
167168
alias: 'experimentalMemory',
168169
},
169170
experimentalStructuredContent: {
170171
type: 'boolean',
172+
default: false,
171173
describe: 'Whether to output structured formatted content.',
172174
},
173175
experimentalToonFormat: {
@@ -376,6 +378,45 @@ export const mcpOptions = {
376378

377379
export type ParsedArguments = ReturnType<typeof parseArguments>;
378380

381+
export function getMcpOptionsForViaCli(): typeof mcpOptions {
382+
if (!('default' in mcpOptions.headless)) {
383+
throw new Error('headless cli option unexpectedly does not have a default');
384+
}
385+
if (!('default' in mcpOptions.experimentalStructuredContent)) {
386+
throw new Error(
387+
'experimentalStructuredContent cli option unexpectedly does not have a default',
388+
);
389+
}
390+
if ('default' in mcpOptions.isolated) {
391+
throw new Error('isolated cli option unexpectedly has a default');
392+
}
393+
394+
return {
395+
...mcpOptions,
396+
headless: {
397+
...mcpOptions.headless,
398+
default: true,
399+
},
400+
memoryDebugging: {
401+
...mcpOptions.memoryDebugging,
402+
default: true,
403+
},
404+
categoryExtensions: {
405+
...mcpOptions.categoryExtensions,
406+
default: true,
407+
},
408+
experimentalStructuredContent: {
409+
...mcpOptions.experimentalStructuredContent,
410+
default: true,
411+
},
412+
isolated: {
413+
...mcpOptions.isolated,
414+
description:
415+
'If specified, creates a temporary user-data-dir that is automatically cleaned up after the browser is closed. Defaults to true unless userDataDir is provided.',
416+
},
417+
};
418+
}
419+
379420
/**
380421
* Exported only for testing to not trigger process exit.
381422
*/
@@ -384,13 +425,16 @@ export function parser(
384425
argv = process.argv,
385426
env = process.env,
386427
) {
428+
const isViaCli = argv.includes('--viaCli') || argv.includes('--via-cli');
429+
const options = isViaCli ? getMcpOptionsForViaCli() : mcpOptions;
430+
387431
const yargsInstance = yargs(hideBin(argv))
388432
.scriptName('npx chrome-devtools-mcp@latest')
389433
.parserConfiguration({
390434
'strip-aliased': true,
391435
'strip-dashed': true,
392436
})
393-
.options(mcpOptions)
437+
.options(options)
394438
.showHelpOnFail(false, 'Specify --help for available options')
395439
.middleware(args => {
396440
// We can't set default in the options else
@@ -411,7 +455,7 @@ export function parser(
411455
}
412456

413457
const cliOptionsAllowedArgs = [
414-
...Object.keys(mcpOptions),
458+
...Object.keys(options),
415459
// Yargs populated with positional args
416460
'_',
417461
'$0',

tests/cli.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ describe('cli args parsing', () => {
2727
usageStatistics: true,
2828
redactNetworkHeaders: false,
2929
allowUnrestrictedPaths: false,
30+
memoryDebugging: false,
31+
experimentalStructuredContent: false,
3032
};
3133

3234
it('parses with default args', async () => {
@@ -40,6 +42,15 @@ describe('cli args parsing', () => {
4042
});
4143
});
4244

45+
it('parses with viaCli args', async () => {
46+
const args = parseArguments(['--viaCli']);
47+
assert.strictEqual(args.headless, true);
48+
assert.strictEqual(args.memoryDebugging, true);
49+
assert.strictEqual(args.categoryExtensions, true);
50+
assert.strictEqual(args.experimentalStructuredContent, true);
51+
assert.strictEqual(args.viaCli, true);
52+
});
53+
4354
it('parses with browser url', async () => {
4455
const args = parseArguments(['--browserUrl', 'http://localhost:3000']);
4556
assert.deepStrictEqual(args, {

0 commit comments

Comments
 (0)