豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The CLI acts as a client to a background `chrome-devtools-mcp` daemon (uses Unix

- **Automatic Start**: The first time you call a tool (e.g., `list_pages`), the CLI automatically starts the MCP server and the browser in the background if they aren't already running.
- **Persistence**: The same background instance is reused for subsequent commands, preserving the browser state (open pages, cookies, etc.).
- **Manual Control**: You can explicitly manage the background process using `start`, `stop`, and `status`. The `start` command forwards all subsequent arguments to the underlying MCP server (e.g., `--headless`, `--userDataDir`) but not all args are supported. Run `chrome-devtools start --help` for supported args. Headless and isolated are enabled by default.
- **Manual Control**: You can explicitly manage the background process using `start`, `stop`, and `status`. The `start` command forwards all subsequent arguments to the underlying MCP server (e.g., `--headless`, `--userDataDir`) but not all args are supported. Run `chrome-devtools start --help` for supported args. Headless is enabled by default. Isolated is enabled by default unless `--userDataDir` is provided.

```sh
# Check if the daemon is running
Expand Down
6 changes: 4 additions & 2 deletions src/bin/chrome-devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ if (!('default' in cliOptions.headless)) {
throw new Error('headless cli option unexpectedly does not have a default');
}
if ('default' in cliOptions.isolated) {
throw new Error('headless cli option unexpectedly does not have a default');
throw new Error('isolated cli option unexpectedly has a default');
}
startCliOptions.headless!.default = true;
startCliOptions.isolated!.description =
'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.';

const y = yargs(hideBin(process.argv))
.scriptName('chrome-devtools')
Expand Down Expand Up @@ -92,7 +94,7 @@ y.command(
await stopDaemon();
}
// Defaults but we do not want to affect the yargs conflict resolution.
if (argv.isolated === undefined) {
if (argv.isolated === undefined && argv.userDataDir === undefined) {
argv.isolated = true;
}
if (argv.headless === undefined) {
Expand Down
25 changes: 25 additions & 0 deletions tests/e2e/chrome-devtools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import assert from 'node:assert';
import {spawn} from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import {describe, it, afterEach, beforeEach} from 'node:test';

Expand Down Expand Up @@ -93,6 +95,29 @@ describe('chrome-devtools', () => {
await assertDaemonIsNotRunning();
});

it('can start the daemon with userDataDir', async () => {
const userDataDir = path.join(
os.tmpdir(),
`chrome-devtools-test-${crypto.randomUUID()}`,
);
fs.mkdirSync(userDataDir, {recursive: true});

const startResult = await runCli(['start', '--userDataDir', userDataDir]);
assert.strictEqual(
startResult.status,
0,
`start command failed: ${startResult.stderr}`,
);
assert.ok(
!startResult.stderr.includes(
'Arguments userDataDir and isolated are mutually exclusive',
),
`unexpected conflict error: ${startResult.stderr}`,
);

await assertDaemonIsRunning();
});

it('can invoke list_pages', async () => {
await assertDaemonIsNotRunning();

Expand Down