diff --git a/README.md b/README.md index 56caf311a..b05f35e2e 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,17 @@ Chrome DevTools for reliable automation, in-depth debugging, and performance ana ## [Tool reference](./docs/tool-reference.md) | [Changelog](./CHANGELOG.md) | [Contributing](./CONTRIBUTING.md) | [Troubleshooting](./docs/troubleshooting.md) | [Design Principles](./docs/design-principles.md) +## Connecting to a running Chrome instance + +If you already have a Chrome instance running with remote debugging enabled (for example started with `--remote-debugging-port=9222`), you can attach `chrome-devtools-mcp` to it instead of launching a new browser. + +- HTTP debugging endpoint (recommended): `--browserUrl http://127.0.0.1:9222` +- WebSocket endpoint (advanced): `--wsEndpoint ws://127.0.0.1:9222/devtools/browser/` + +Quick self-check: `http://127.0.0.1:9222/json/version` should return JSON. + +See example: [`examples/remote-debugging-9222.mjs`](./examples/remote-debugging-9222.mjs). + ## Key features - **Get performance insights**: Uses [Chrome @@ -151,12 +162,23 @@ Restart Claude Code to have the MCP server and skills load (check with `/skills` using the standard config from above. You can also install the Chrome DevTools MCP server using the Codex CLI: ```bash -codex mcp add chrome-devtools -- npx chrome-devtools-mcp@latest +codex mcp add chrome-devtools -- npx -y chrome-devtools-mcp@latest +``` + +Verification: run `codex mcp list` and confirm `chrome-devtools` is listed. + +If you see `error: unexpected argument 'add' found`, your Codex CLI is too old to support `codex mcp add`. +Upgrade Codex, or add the server manually by editing `~/.codex/config.toml`: + +```toml +[mcp_servers.chrome-devtools] +command = "npx" +args = ["-y", "chrome-devtools-mcp@latest"] ``` **On Windows 11** -Configure the Chrome install location and increase the startup timeout by updating `.codex/config.toml` and adding the following `env` and `startup_timeout_ms` parameters: +Configure the Chrome install location and increase the startup timeout by updating `%USERPROFILE%\.codex\config.toml` (usually `C:\Users\\.codex\config.toml`) and adding the following `env` and `startup_timeout_ms` parameters: ``` [mcp_servers.chrome-devtools] diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index e9f51c037..9389f882f 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -38,6 +38,19 @@ Using `.mcp.json` to debug while using a client: ## Specific problems +### Codex: `error: unexpected argument 'add' found` + +Some older Codex CLI versions don't include the `codex mcp add`/`list` subcommands. + +- Run `codex mcp --help` and check whether it shows `add`. +- If it does not, upgrade Codex, or add the server manually by editing `~/.codex/config.toml`: + +```toml +[mcp_servers.chrome-devtools] +command = "npx" +args = ["-y", "chrome-devtools-mcp@latest"] +``` + ### `Error [ERR_MODULE_NOT_FOUND]: Cannot find module ...` This usually indicates either a non-supported Node version is in use or that the @@ -71,6 +84,33 @@ ssh -N -L 127.0.0.1:9222:127.0.0.1:9222 @ Point the MCP connection inside the VM to `http://127.0.0.1:9222`. This allows DevTools to reach the host browser without triggering the Host validation error. +### Connecting to a running Chrome instance (remote debugging, 9222) + +If you want `chrome-devtools-mcp` to attach to an existing Chrome instance, start Chrome with remote debugging enabled, then pass `--browserUrl`. + +1. Start Chrome with a remote debugging port: + - Linux: + + ```sh + google-chrome --remote-debugging-port=9222 + ``` + + - macOS: + ```sh + /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 + ``` + +2. Verify the endpoint is reachable: + - `http://127.0.0.1:9222/json/version` should return JSON + +3. Start the MCP server and point it at the debugging endpoint: + + ```sh + npx --yes chrome-devtools-mcp@latest --browserUrl http://127.0.0.1:9222 + ``` + +See also: `examples/remote-debugging-9222.mjs`. + ### Operating system sandboxes Some MCP clients allow sandboxing the MCP server using macOS Seatbelt or Linux diff --git a/eslint.config.mjs b/eslint.config.mjs index db6ddd675..ef88b7ea8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -32,6 +32,7 @@ export default defineConfig([ 'puppeteer.config.cjs', 'eslint.config.mjs', 'rollup.config.mjs', + 'examples/remote-debugging-9222.mjs', ], }, }, diff --git a/examples/remote-debugging-9222.mjs b/examples/remote-debugging-9222.mjs new file mode 100644 index 000000000..93aa80bc8 --- /dev/null +++ b/examples/remote-debugging-9222.mjs @@ -0,0 +1,55 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +// Example: connect to a Chrome instance that was started with a remote debugging port, +// using the official MCP TypeScript SDK. +// +// 1) Start Chrome manually with remote debugging enabled, e.g.: +// macOS: +// /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 +// Linux: +// google-chrome --remote-debugging-port=9222 +// +// 2) Run this script: +// node examples/remote-debugging-9222.mjs +// +// This starts chrome-devtools-mcp with --browserUrl and connects through MCP stdio. +// +// For SDK details, see: +// https://modelcontextprotocol.io/docs/develop/build-client#typescript + +import {Client} from '@modelcontextprotocol/sdk/client/index.js'; +import {StdioClientTransport} from '@modelcontextprotocol/sdk/client/stdio.js'; + +const DEBUG_URL = process.env.CHROME_DEBUG_URL ?? 'http://127.0.0.1:9222'; + +const transport = new StdioClientTransport({ + command: 'npx', + args: ['--yes', 'chrome-devtools-mcp@latest', '--browserUrl', DEBUG_URL], + env: { + ...process.env, + CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS: 'true', + }, + stderr: 'inherit', +}); + +const client = new Client( + {name: 'remote-debugging-9222', version: '0.0.0'}, + {capabilities: {}}, +); + +try { + await client.connect(transport); + + const {tools} = await client.listTools(); + console.log(`Connected to ${DEBUG_URL}. Found ${tools.length} tools.`); + + for (const tool of tools.slice(0, 10)) { + console.log(`- ${tool.name}`); + } +} finally { + await transport.close(); +}