diff --git a/package-lock.json b/package-lock.json index e67822c4a..f002fcfd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { - "name": "chrome-devtools-mcp", - "version": "0.20.3", + "name": "@holepunchto/electron-devtools-mcp", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "chrome-devtools-mcp", - "version": "0.20.3", + "name": "@holepunchto/electron-devtools-mcp", + "version": "0.1.0", + "hasInstallScript": true, "license": "Apache-2.0", "bin": { "chrome-devtools": "build/src/bin/chrome-devtools.js", @@ -35,6 +36,7 @@ "eslint-plugin-import": "^2.32.0", "globals": "^17.0.0", "lighthouse": "13.0.3", + "patch-package": "^8.0.1", "prettier": "^3.6.2", "puppeteer": "24.39.1", "rollup": "4.59.1", @@ -2797,6 +2799,13 @@ "win32" ] }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -3347,6 +3356,19 @@ "balanced-match": "^1.0.0" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -3491,6 +3513,22 @@ "devtools-protocol": "*" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cjs-module-lexer": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", @@ -4890,6 +4928,19 @@ "node": ">=16.0.0" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -4929,6 +4980,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -5023,6 +5084,21 @@ "node": ">= 0.8" } }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -5933,6 +6009,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", @@ -6265,6 +6351,26 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -6285,6 +6391,29 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "dev": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/jwa": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", @@ -6318,6 +6447,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/legacy-javascript": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/legacy-javascript/-/legacy-javascript-0.0.1.tgz", @@ -6653,6 +6792,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", @@ -7166,6 +7332,53 @@ "node": ">= 0.8" } }, + "node_modules/patch-package": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^10.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.2.4", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8189,6 +8402,16 @@ "node": ">=4.2" } }, + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -8701,6 +8924,29 @@ "tldts-core": "^7.0.23" } }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -8944,6 +9190,16 @@ "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -9305,6 +9561,22 @@ "node": ">=10" } }, + "node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yargs": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", diff --git a/package.json b/package.json index 29277b2c5..9b3c4ecf0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "chrome-devtools-mcp", - "version": "0.20.3", - "description": "MCP server for Chrome DevTools", + "name": "@holepunchto/electron-devtools-mcp", + "version": "0.1.0", + "description": "MCP server for Electron DevTools (based on chrome-devtools-mcp)", "type": "module", "bin": { "chrome-devtools-mcp": "./build/src/bin/chrome-devtools-mcp.js", @@ -24,6 +24,7 @@ "test:no-build": "node scripts/test.mjs", "test:only": "npm run build && node scripts/test.mjs --test-only", "test:update-snapshots": "npm run build && node scripts/test.mjs --test-update-snapshots", + "postinstall": "patch-package", "prepare": "node --experimental-strip-types scripts/prepare.ts", "verify-server-json-version": "node --experimental-strip-types scripts/verify-server-json-version.ts", "update-lighthouse": "node --experimental-strip-types scripts/update-lighthouse.ts", @@ -67,6 +68,7 @@ "eslint-plugin-import": "^2.32.0", "globals": "^17.0.0", "lighthouse": "13.0.3", + "patch-package": "^8.0.1", "prettier": "^3.6.2", "puppeteer": "24.39.1", "rollup": "4.59.1", diff --git a/patches/puppeteer-core+24.39.1.patch b/patches/puppeteer-core+24.39.1.patch new file mode 100644 index 000000000..b8fe41b13 --- /dev/null +++ b/patches/puppeteer-core+24.39.1.patch @@ -0,0 +1,48 @@ +diff --git a/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Browser.js b/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Browser.js +index 945e493..04bb0f2 100644 +--- a/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Browser.js ++++ b/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Browser.js +@@ -244,10 +244,15 @@ class CdpBrowser extends Browser_js_1.Browser { + return page; + } + async _hasDevToolsTarget(pageTargetId) { +- const response = await this.#connection.send('Target.getDevToolsTarget', { +- targetId: pageTargetId, +- }); +- return response.targetId; ++ try { ++ const response = await this.#connection.send('Target.getDevToolsTarget', { ++ targetId: pageTargetId, ++ }); ++ return response.targetId; ++ } catch { ++ // Electron doesn't support Target.getDevToolsTarget ++ return undefined; ++ } + } + async installExtension(path) { + const { id } = await this.#connection.send('Extensions.loadUnpacked', { path }); +diff --git a/node_modules/puppeteer-core/lib/esm/puppeteer/cdp/Browser.js b/node_modules/puppeteer-core/lib/esm/puppeteer/cdp/Browser.js +index 8ed5f49..14ba887 100644 +--- a/node_modules/puppeteer-core/lib/esm/puppeteer/cdp/Browser.js ++++ b/node_modules/puppeteer-core/lib/esm/puppeteer/cdp/Browser.js +@@ -241,10 +241,15 @@ export class CdpBrowser extends BrowserBase { + return page; + } + async _hasDevToolsTarget(pageTargetId) { +- const response = await this.#connection.send('Target.getDevToolsTarget', { +- targetId: pageTargetId, +- }); +- return response.targetId; ++ try { ++ const response = await this.#connection.send('Target.getDevToolsTarget', { ++ targetId: pageTargetId, ++ }); ++ return response.targetId; ++ } catch { ++ // Electron doesn't support Target.getDevToolsTarget ++ return undefined; ++ } + } + async installExtension(path) { + const { id } = await this.#connection.send('Extensions.loadUnpacked', { path }); diff --git a/src/bin/chrome-devtools-mcp-cli-options.ts b/src/bin/chrome-devtools-mcp-cli-options.ts index b4792629c..ab28164a9 100644 --- a/src/bin/chrome-devtools-mcp-cli-options.ts +++ b/src/bin/chrome-devtools-mcp-cli-options.ts @@ -25,7 +25,7 @@ export const cliOptions = { type: 'string', description: 'Connect to a running, debuggable Chrome instance (e.g. `http://127.0.0.1:9222`). For more details see: https://github.com/ChromeDevTools/chrome-devtools-mcp#connecting-to-a-running-chrome-instance.', - alias: 'u', + alias: ['u', 'cdp-url'], conflicts: ['wsEndpoint', 'categoryExtensions'], coerce: (url: string | undefined) => { if (!url) { diff --git a/src/browser.ts b/src/browser.ts index 7deea75b4..e68dc2459 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -57,10 +57,30 @@ export async function ensureBrowserConnected(options: { return browser; } + // Detect Electron by checking /json/version — Electron doesn't support + // Target.getDevToolsTarget which handleDevToolsAsPage relies on. + let isElectron = false; + const detectURL = options.browserURL || (options.wsEndpoint ? undefined : undefined); + if (options.browserURL) { + try { + const res = await fetch(`${options.browserURL}/json/version`, { + signal: AbortSignal.timeout(2000), + }); + const info = (await res.json()) as {Browser?: string; 'User-Agent'?: string}; + const ua = info['User-Agent'] || ''; + if (/electron/i.test(ua) || (info.Browser && /electron/i.test(info.Browser))) { + isElectron = true; + logger('Detected Electron browser, disabling handleDevToolsAsPage'); + } + } catch { + // Can't detect, assume Chrome + } + } + const connectOptions: Parameters[0] = { targetFilter: makeTargetFilter(enableExtensions), defaultViewport: null, - handleDevToolsAsPage: true, + handleDevToolsAsPage: !isElectron, }; let autoConnect = false; @@ -270,4 +290,11 @@ export async function ensureBrowserLaunched( return browser; } +export function disconnectBrowser(): void { + if (browser?.connected) { + browser.disconnect(); + } + browser = undefined; +} + export type Channel = 'stable' | 'canary' | 'beta' | 'dev'; diff --git a/src/tools/connect.ts b/src/tools/connect.ts new file mode 100644 index 000000000..f290fe4e5 --- /dev/null +++ b/src/tools/connect.ts @@ -0,0 +1,76 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {disconnectBrowser, ensureBrowserConnected} from '../browser.js'; +import {zod} from '../third_party/index.js'; + +import {ToolCategory} from './categories.js'; +import {defineTool} from './ToolDefinition.js'; + +export const connect = defineTool({ + name: 'connect', + description: + 'Connect to a different browser/Electron instance by CDP port. Disconnects from the current instance first.', + schema: { + port: zod + .number() + .describe('The remote debugging port to connect to (e.g. 9222, 9223)'), + }, + annotations: { + title: 'Connect to CDP instance', + category: ToolCategory.NAVIGATION, + readOnlyHint: false, + }, + handler: async ({params}, response) => { + disconnectBrowser(); + try { + await ensureBrowserConnected({ + browserURL: `http://127.0.0.1:${params.port}`, + devtools: false, + }); + response.appendResponseLine( + `Connected to CDP instance on port ${params.port}`, + ); + } catch (err) { + response.appendResponseLine( + `Failed to connect to port ${params.port}: ${(err as Error).message}`, + ); + } + }, +}); + +export const listInstances = defineTool({ + name: 'list_instances', + description: + 'Scan for running browser/Electron instances on CDP ports 9222-9231', + schema: {}, + annotations: { + title: 'List CDP instances', + category: ToolCategory.NAVIGATION, + readOnlyHint: true, + }, + handler: async (_args, response) => { + const found: Array<{port: number; browser: string}> = []; + for (let port = 9222; port < 9232; port++) { + try { + const res = await fetch(`http://127.0.0.1:${port}/json/version`, { + signal: AbortSignal.timeout(500), + }); + const info = (await res.json()) as {Browser: string}; + found.push({port, browser: info.Browser}); + } catch { + // not running on this port + } + } + if (found.length === 0) { + response.appendResponseLine( + 'No CDP instances found on ports 9222-9231', + ); + } else { + response.appendResponseLine(JSON.stringify(found, null, 2)); + } + }, +}); diff --git a/src/tools/tools.ts b/src/tools/tools.ts index d448552b0..615dd70fc 100644 --- a/src/tools/tools.ts +++ b/src/tools/tools.ts @@ -6,6 +6,7 @@ import type {ParsedArguments} from '../bin/chrome-devtools-mcp-cli-options.js'; +import * as connectTools from './connect.js'; import * as consoleTools from './console.js'; import * as emulationTools from './emulation.js'; import * as extensionTools from './extensions.js'; @@ -26,6 +27,7 @@ export const createTools = (args: ParsedArguments) => { const rawTools = args.slim ? Object.values(slimTools) : [ + ...Object.values(connectTools), ...Object.values(consoleTools), ...Object.values(emulationTools), ...Object.values(extensionTools),