mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-09-14 19:45:30 +08:00
refactor: replace debug with NodeJS native (#2562)
This commit is contained in:
Generated
+17
-36
@@ -22,7 +22,6 @@
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"@stylistic/eslint-plugin": "^5.4.0",
|
||||
"@toon-format/toon": "^4.1.0",
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/filesystem": "^0.0.36",
|
||||
"@types/node": "^26.0.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
@@ -31,14 +30,13 @@
|
||||
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
||||
"@typescript-eslint/parser": "^8.43.0",
|
||||
"core-js": "3.49.0",
|
||||
"debug": "4.4.3",
|
||||
"eslint": "^10.7.0",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"globals": "^17.0.0",
|
||||
"lighthouse": "13.4.1",
|
||||
"prettier": "^3.6.2",
|
||||
"puppeteer": "25.5.0",
|
||||
"puppeteer": "25.6.0",
|
||||
"rollup": "4.62.4",
|
||||
"rollup-plugin-cleanup": "^3.2.1",
|
||||
"rollup-plugin-license": "^3.6.0",
|
||||
@@ -748,13 +746,13 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@puppeteer/browsers": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.1.0.tgz",
|
||||
"integrity": "sha512-RDLpio3fH/qrj5k4DVY6eyiN8tCS0Zovd/6jW//n605oeqkWcUjn+3k+9ZtZBnbwMpsu0F7xDIiKXvVmG5c5Bw==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.2.0.tgz",
|
||||
"integrity": "sha512-LlBrE8oqGfU7b1Nk2d5Q1SbuPhZxTj0cJEMDPEws28OjNMELlflekmPPuf4FnK03x0ZRjKaYwJElUcKK4kyqJA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"modern-tar": "^0.7.6",
|
||||
"modern-tar": "^0.8.0",
|
||||
"yargs": "^18.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -1468,16 +1466,6 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/debug": {
|
||||
"version": "4.1.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
|
||||
"integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/ms": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/esrecurse": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
|
||||
@@ -1523,13 +1511,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ms": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
|
||||
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "26.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz",
|
||||
@@ -5539,9 +5520,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/modern-tar": {
|
||||
"version": "0.7.7",
|
||||
"resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.7.tgz",
|
||||
"integrity": "sha512-t9VmxaqrmANnEOBhpSDI6HD192Ge48k8vmWqQQL7hSFEqHEYwZbbsu49+aKLWZeRvFs3j1pMhXOqqF4kPlvjkQ==",
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.8.1.tgz",
|
||||
"integrity": "sha512-G/OFF6yTWgdGWS5IvhcrETxsgjsUdotEtHhW2nffB5vP5uCwkhnn38qRO7h6RF4uV0UlqyHx/bq2Vd5Oco4uoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -6064,18 +6045,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer": {
|
||||
"version": "25.5.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.5.0.tgz",
|
||||
"integrity": "sha512-qpp73xblxNr+bF0nSXTodM3v+zcK5IPo/GkjLsdUqRf/qpLJp/1KxBUbstoMMnwnPw9xD6OMei8kmYf6CLWfGw==",
|
||||
"version": "25.6.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.6.0.tgz",
|
||||
"integrity": "sha512-TXUolDddU4AwISjOOrGk2AhJDpbM/ZDt2KvGIqz74EOk+8bKwXFo+acUvP1sQx3hUda7owOeNuuT1UnJT1o0qA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "3.1.0",
|
||||
"@puppeteer/browsers": "3.2.0",
|
||||
"chromium-bidi": "17.0.2",
|
||||
"devtools-protocol": "0.0.1653615",
|
||||
"lilconfig": "^3.1.3",
|
||||
"puppeteer-core": "25.5.0",
|
||||
"puppeteer-core": "25.6.0",
|
||||
"typed-query-selector": "^2.12.2"
|
||||
},
|
||||
"bin": {
|
||||
@@ -6086,13 +6067,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer-core": {
|
||||
"version": "25.5.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.5.0.tgz",
|
||||
"integrity": "sha512-XPNT0dQJtphqQ4I29zxlG4IIPbg1iEHAQKWuQgtMJGXjACV77pZSmJvDi51IIIfd+DTKICcopJwUx4upVQ4XbA==",
|
||||
"version": "25.6.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.6.0.tgz",
|
||||
"integrity": "sha512-GJ67rjZdVQzZmD2Ab0cgttfQN9j387QYMv3t6MN3/4nmjursNt6M5Utj4/T/4y0AwNrSwJzjw6Q/zuWFEIizOg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "3.1.0",
|
||||
"@puppeteer/browsers": "3.2.0",
|
||||
"chromium-bidi": "17.0.2",
|
||||
"devtools-protocol": "0.0.1653615",
|
||||
"typed-query-selector": "^2.12.2",
|
||||
|
||||
+2
-4
@@ -19,7 +19,7 @@
|
||||
"gen": "npm run build && npm run docs:generate && npm run cli:generate && npm run update-metrics && npm run format",
|
||||
"docs:generate": "node scripts/generate-docs.ts",
|
||||
"start": "npm run build && node build/src/bin/chrome-devtools-mcp.js",
|
||||
"start-debug": "DEBUG=mcp:* DEBUG_COLORS=false npm run build && node build/src/bin/chrome-devtools-mcp.js",
|
||||
"start-debug": "NODE_DEBUG=mcp:* npm run build && node build/src/bin/chrome-devtools-mcp.js",
|
||||
"test": "npm run build && node scripts/test.js --test-skip-pattern=THIRD_PARTY_NOTICES",
|
||||
"test:no-build": "node scripts/test.js --test-skip-pattern=THIRD_PARTY_NOTICES",
|
||||
"test:notices": "npm run bundle && node scripts/test.js tests/third_party_notices.test.ts",
|
||||
@@ -62,7 +62,6 @@
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"@stylistic/eslint-plugin": "^5.4.0",
|
||||
"@toon-format/toon": "^4.1.0",
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/filesystem": "^0.0.36",
|
||||
"@types/node": "^26.0.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
@@ -71,14 +70,13 @@
|
||||
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
||||
"@typescript-eslint/parser": "^8.43.0",
|
||||
"core-js": "3.49.0",
|
||||
"debug": "4.4.3",
|
||||
"eslint": "^10.7.0",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"globals": "^17.0.0",
|
||||
"lighthouse": "13.4.1",
|
||||
"prettier": "^3.6.2",
|
||||
"puppeteer": "25.5.0",
|
||||
"puppeteer": "25.6.0",
|
||||
"rollup": "4.62.4",
|
||||
"rollup-plugin-cleanup": "^3.2.1",
|
||||
"rollup-plugin-license": "^3.6.0",
|
||||
|
||||
+3
-1
@@ -16,7 +16,7 @@ import type {
|
||||
Target,
|
||||
} from './third_party/index.js';
|
||||
import {puppeteer} from './third_party/index.js';
|
||||
import {logger} from './utils/logger.js';
|
||||
import {logger, puppeteerLogger} from './utils/logger.js';
|
||||
|
||||
let browser: Browser | undefined;
|
||||
let browserMode: 'launched' | 'connected' | undefined;
|
||||
@@ -66,6 +66,7 @@ export async function ensureBrowserConnected(options: {
|
||||
handleDevToolsAsPage: true,
|
||||
blocklist: options.blocklist,
|
||||
allowlist: options.allowlist,
|
||||
logger: puppeteerLogger,
|
||||
};
|
||||
|
||||
let autoConnect = false;
|
||||
@@ -243,6 +244,7 @@ export async function launch(options: McpLaunchOptions): Promise<Browser> {
|
||||
enableExtensions: options.enableExtensions,
|
||||
blocklist: options.blocklist,
|
||||
allowlist: options.allowlist,
|
||||
logger: puppeteerLogger,
|
||||
});
|
||||
if (options.logFile) {
|
||||
// FIXME: we are probably subscribing too late to catch startup logs. We
|
||||
|
||||
@@ -11,7 +11,7 @@ import net from 'node:net';
|
||||
import type {CallToolResult} from '../third_party/index.js';
|
||||
import {PipeTransport} from '../third_party/index.js';
|
||||
import {getTempFilePath} from '../utils/files.js';
|
||||
import {logger} from '../utils/logger.js';
|
||||
import {logger, puppeteerLogger} from '../utils/logger.js';
|
||||
|
||||
import type {
|
||||
DaemonMessage,
|
||||
@@ -164,7 +164,7 @@ export async function sendCommand(
|
||||
reject(new Error('Timeout waiting for daemon response'));
|
||||
}, timeout);
|
||||
|
||||
const transport = new PipeTransport(socket, socket);
|
||||
const transport = new PipeTransport(socket, socket, puppeteerLogger);
|
||||
transport.onmessage = async (message: string) => {
|
||||
clearTimeout(timer);
|
||||
logger?.('onmessage', message);
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
PipeTransport,
|
||||
StdioClientTransport,
|
||||
} from '../third_party/index.js';
|
||||
import {logger} from '../utils/logger.js';
|
||||
import {logger, puppeteerLogger} from '../utils/logger.js';
|
||||
import {VERSION} from '../version.js';
|
||||
|
||||
import type {DaemonMessage, DaemonStatusResult} from './types.js';
|
||||
@@ -227,7 +227,7 @@ async function startSocketServer() {
|
||||
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
server = createServer(socket => {
|
||||
const transport = new PipeTransport(socket, socket);
|
||||
const transport = new PipeTransport(socket, socket, puppeteerLogger);
|
||||
transport.onmessage = async (message: string) => {
|
||||
logger?.('onmessage', message);
|
||||
const response = await handleRequest(JSON.parse(message));
|
||||
|
||||
Vendored
-2
@@ -17,8 +17,6 @@ export type {Options as YargsOptions} from 'yargs';
|
||||
export {default as yargs} from 'yargs';
|
||||
export {hideBin} from 'yargs/helpers';
|
||||
export {default as semver} from 'semver';
|
||||
export {default as debug} from 'debug';
|
||||
export type {Debugger} from 'debug';
|
||||
export {McpServer} from '@modelcontextprotocol/sdk/server/mcp.js';
|
||||
export {type ShapeOutput} from '@modelcontextprotocol/sdk/server/zod-compat.js';
|
||||
export {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
|
||||
+31
-12
@@ -5,30 +5,24 @@
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
import util from 'node:util';
|
||||
|
||||
import {debug} from '../third_party/index.js';
|
||||
import type {Logger} from '../types.js';
|
||||
|
||||
const mcpDebugNamespace = 'mcp:log';
|
||||
|
||||
const namespacesToEnable = [
|
||||
mcpDebugNamespace,
|
||||
...(process.env['DEBUG'] ? [process.env['DEBUG']] : []),
|
||||
];
|
||||
let logFileStream: fs.WriteStream | undefined;
|
||||
|
||||
const _debugLog = util.debuglog(mcpDebugNamespace);
|
||||
|
||||
export function saveLogsToFile(fileName: string): fs.WriteStream {
|
||||
// Enable overrides everything so we need to add them
|
||||
debug.enable(namespacesToEnable.join(','));
|
||||
|
||||
const logFile = fs.createWriteStream(fileName, {flags: 'a+'});
|
||||
debug.log = function (...chunks: any[]) {
|
||||
logFile.write(`${chunks.join(' ')}\n`);
|
||||
};
|
||||
logFile.on('error', function (error) {
|
||||
console.error(`Error when opening/writing to log file: ${error.message}`);
|
||||
logFile.end();
|
||||
process.exit(1);
|
||||
});
|
||||
logFileStream = logFile;
|
||||
return logFile;
|
||||
}
|
||||
|
||||
@@ -45,4 +39,29 @@ export function flushLogs(
|
||||
});
|
||||
}
|
||||
|
||||
export const logger: Logger = debug(mcpDebugNamespace) as Logger;
|
||||
export const logger: Logger = (...args: unknown[]) => {
|
||||
if (logFileStream) {
|
||||
logFileStream.write(
|
||||
`${new Date().toISOString()} ${mcpDebugNamespace} ${util.format(...args)}\n`,
|
||||
);
|
||||
} else if (_debugLog.enabled) {
|
||||
_debugLog('%s %s', new Date().toISOString(), util.format(...args));
|
||||
}
|
||||
};
|
||||
|
||||
export const puppeteerLogger = (prefix: string) => {
|
||||
if (logFileStream) {
|
||||
return (...args: unknown[]) => {
|
||||
logFileStream!.write(
|
||||
`${new Date().toISOString()} ${prefix} ${util.format(...args)}\n`,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const dbg = util.debuglog(prefix);
|
||||
return dbg.enabled
|
||||
? (...args: unknown[]) => {
|
||||
dbg('%s %s', new Date().toISOString(), util.format(...args));
|
||||
}
|
||||
: undefined;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@ import path from 'node:path';
|
||||
import {afterEach, describe, it} from 'node:test';
|
||||
import {pathToFileURL} from 'node:url';
|
||||
|
||||
import logger from 'debug';
|
||||
import {Locator} from 'puppeteer';
|
||||
import sinon from 'sinon';
|
||||
|
||||
@@ -238,12 +237,7 @@ describe('McpContext', () => {
|
||||
experimentalDevToolsDebugging: false,
|
||||
performanceCrux: false,
|
||||
};
|
||||
const first = await McpContext.from(
|
||||
browser,
|
||||
logger('test'),
|
||||
options,
|
||||
Locator,
|
||||
);
|
||||
const first = await McpContext.from(browser, undefined, options, Locator);
|
||||
const idBeforeReconnect = (await first.newPage()).id;
|
||||
first.dispose();
|
||||
|
||||
@@ -252,7 +246,7 @@ describe('McpContext', () => {
|
||||
// the next page keeps counting up rather than colliding with it.
|
||||
const second = await McpContext.from(
|
||||
browser,
|
||||
logger('test'),
|
||||
undefined,
|
||||
options,
|
||||
Locator,
|
||||
);
|
||||
@@ -275,7 +269,7 @@ describe('McpContext', () => {
|
||||
await withBrowser(async browser => {
|
||||
const context = await McpContext.from(
|
||||
browser,
|
||||
logger('test'),
|
||||
undefined,
|
||||
{
|
||||
experimentalDevToolsDebugging: false,
|
||||
performanceCrux: false,
|
||||
|
||||
@@ -318,65 +318,6 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
-------------------- DEPENDENCY DIVIDER --------------------
|
||||
|
||||
Name: debug
|
||||
URL: git://github.com/debug-js/debug.git
|
||||
Version: <VERSION>
|
||||
License: MIT
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2018-2021 Josh Junon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
and associated documentation files (the 'Software'), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
|
||||
-------------------- DEPENDENCY DIVIDER --------------------
|
||||
|
||||
Name: ms
|
||||
URL: vercel/ms
|
||||
Version: <VERSION>
|
||||
License: MIT
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Vercel, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
-------------------- DEPENDENCY DIVIDER --------------------
|
||||
|
||||
Name: zod
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ import {spawn} from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
|
||||
import type {CallToolResult} from '@modelcontextprotocol/sdk/types.js';
|
||||
import logger from 'debug';
|
||||
|
||||
import type {Browser} from 'puppeteer';
|
||||
import puppeteer, {Locator} from 'puppeteer';
|
||||
import type {
|
||||
@@ -177,7 +177,7 @@ export async function withMcpContext(
|
||||
}
|
||||
context = await McpContext.from(
|
||||
browser,
|
||||
logger('test'),
|
||||
undefined,
|
||||
{
|
||||
experimentalDevToolsDebugging: false,
|
||||
performanceCrux: options.performanceCrux ?? true,
|
||||
|
||||
Reference in New Issue
Block a user