Skip to content
Open
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
19 changes: 0 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
"@stylistic/eslint-plugin": "^5.4.0",
"@blackwell-systems/gcf": "^2.2.2",
"@toon-format/toon": "^2.2.0",
"@types/debug": "^4.1.12",
"@types/filesystem": "^0.0.36",
"@types/node": "^26.0.0",
"@types/semver": "^7.7.1",
Expand All @@ -69,7 +68,6 @@
"@typescript-eslint/parser": "^8.43.0",
"chrome-devtools-frontend": "1.0.1661063",
"core-js": "3.49.0",
"debug": "4.4.3",
"eslint": "^9.35.0",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0",
Expand Down
8 changes: 4 additions & 4 deletions src/McpContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class McpContext implements Context {
}
void this.#createMcpPage(page);
} catch (err) {
this.logger?.('Error handling targetcreated', err);
this.logger()?.('Error handling targetcreated', err);
}
};

Expand All @@ -179,7 +179,7 @@ export class McpContext implements Context {
this.#mcpPages.delete(foundPage);
}
} catch (err) {
this.logger?.('Error handling targetdestroyed', err);
this.logger()?.('Error handling targetdestroyed', err);
}
};

Expand Down Expand Up @@ -554,7 +554,7 @@ export class McpContext implements Context {
allPages.push(page);
}
} catch (e) {
this.logger?.('Failed to get page for extension target', e);
this.logger()?.('Failed to get page for extension target', e);
}
}),
);
Expand Down Expand Up @@ -600,7 +600,7 @@ export class McpContext implements Context {
await fs.writeFile(filePath, data);
return {filename: filePath};
} catch (err) {
this.logger?.(err);
this.logger()?.(err);
throw new Error('Could not save a file', {cause: err});
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/McpPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export class McpPage implements ContextPage {
async #initFocusEmulationNoThrow(): Promise<void> {
// We emulate a focused page for all pages to support multi-agent workflows.
void this.pptrPage.emulateFocusedPage(true).catch(error => {
logger?.('Error turning on focused page emulation', error);
logger()?.('Error turning on focused page emulation', error);
});
}

Expand All @@ -195,7 +195,7 @@ export class McpPage implements ContextPage {
const session = await this.pptrPage.createCDPSession();
this.#devtoolsUniverse = await createTargetUniverse(session);
} catch (e) {
logger?.('Failed to initialize DevTools universe', e);
logger()?.('Failed to initialize DevTools universe', e);
}
}

Expand Down Expand Up @@ -327,15 +327,15 @@ export class McpPage implements ContextPage {

resolveCdpRequestId(cdpRequestId: string): number | undefined {
if (!cdpRequestId) {
logger?.('no network request');
logger()?.('no network request');
return;
}
const request = this.networkCollector.find(request => {
// @ts-expect-error id is internal.
return request.id === cdpRequestId;
});
if (!request) {
logger?.('no network request for ' + cdpRequestId);
logger()?.('no network request for ' + cdpRequestId);
return;
}
return this.networkCollector.getIdForResource(request);
Expand Down Expand Up @@ -566,23 +566,23 @@ export class McpPage implements ContextPage {
for (const handle of oldHandles) {
await handle
.dispose()
.catch(e => logger?.('Failed to dispose old handle', e));
.catch(e => logger()?.('Failed to dispose old handle', e));
}
}

const cdpElementIds = await Promise.all(
elementHandles.map(async (elementHandle, index) => {
const backendNodeId = await elementHandle.backendNodeId();
if (!backendNodeId) {
logger?.(
logger()?.(
`No backendNodeId for stashed DOM element with index ${index}`,
);
return `stashed-${index}`;
}
const cdpElementId =
this.textSnapshot?.resolveCdpElementId(backendNodeId);
if (!cdpElementId) {
logger?.(
logger()?.(
`Could not get cdpElementId for backend node ${backendNodeId}`,
);
return `stashed-${index}`;
Expand Down Expand Up @@ -655,10 +655,10 @@ export class McpPage implements ContextPage {

async getDevToolsData(): Promise<DevToolsData> {
try {
logger?.('Getting DevTools UI data');
logger()?.('Getting DevTools UI data');
const devtoolsPage = await this.getDevToolsPage();
if (!devtoolsPage) {
logger?.('No DevTools page detected');
logger()?.('No DevTools page detected');
return {};
}
const {cdpRequestId, cdpBackendNodeId} = await devtoolsPage.evaluate(
Expand All @@ -681,7 +681,7 @@ export class McpPage implements ContextPage {
);
return {cdpBackendNodeId, cdpRequestId};
} catch (err) {
logger?.('error getting devtools data', err);
logger()?.('error getting devtools data', err);
}
return {};
}
Expand Down
4 changes: 2 additions & 2 deletions src/PageCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ class PageEventSubscriber {
inspectorIssue,
)[0];
if (!issue) {
logger?.('No issue mapping for for the issue: ', inspectorIssue.code);
logger()?.('No issue mapping for for the issue: ', inspectorIssue.code);
return;
}

Expand All @@ -277,7 +277,7 @@ class PageEventSubscriber {
},
);
} catch (error) {
logger?.('Error creating a new issue', error);
logger()?.('Error creating a new issue', error);
}
};
}
Expand Down
4 changes: 2 additions & 2 deletions src/TextSnapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export class TextSnapshot {

resolveCdpElementId(cdpBackendNodeId: number): string | undefined {
if (!cdpBackendNodeId) {
logger?.('no cdpBackendNodeId');
logger()?.('no cdpBackendNodeId');
return;
}
// TODO: index by backendNodeId instead.
Expand Down Expand Up @@ -281,7 +281,7 @@ export class TextSnapshot {
collect(node);
}
} catch (e) {
logger?.(
logger()?.(
`Failed to collect descendants for backend node ${backendNodeId}`,
e,
);
Expand Down
6 changes: 3 additions & 3 deletions src/ToolHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,11 @@ export class ToolHandler {
const startTime = Date.now();
let success = false;
try {
logger?.(
logger()?.(
`${this.tool.name} request: ${JSON.stringify(params, null, ' ')}`,
);
const context = await this.getContext();
logger?.(`${this.tool.name} context: resolved`);
logger()?.(`${this.tool.name} context: resolved`);
const response = this.serverArgs.slim
? new SlimMcpResponse(this.serverArgs)
: new McpResponse(this.serverArgs);
Expand Down Expand Up @@ -289,7 +289,7 @@ export class ToolHandler {
}
return result;
} catch (err) {
logger?.(`${this.tool.name} error:`, err, err?.stack);
logger()?.(`${this.tool.name} error:`, err, err?.stack);
let errorText = err && 'message' in err ? err.message : String(err);
if ('cause' in err && err.cause) {
errorText += `\nCause: ${err.cause.message}`;
Expand Down
4 changes: 2 additions & 2 deletions src/WaitForHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export class WaitForHelper {
}
return;
})
.catch(error => logger?.(error));
.catch(error => logger()?.(error));

try {
await action();
Expand All @@ -201,7 +201,7 @@ export class WaitForHelper {
// the correct context
await this.waitForStableDom();
} catch (error) {
logger?.(error);
logger()?.(error);
} finally {
this.#abortController.abort();
}
Expand Down
10 changes: 5 additions & 5 deletions src/bin/chrome-devtools-mcp-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const logFile = args.logFile ? saveLogsToFile(args.logFile) : undefined;

if (process.env['CHROME_DEVTOOLS_MCP_CRASH_ON_UNCAUGHT'] !== 'true') {
process.on('unhandledRejection', (reason, promise) => {
logger?.('Unhandled promise rejection', promise, reason);
logger()?.('Unhandled promise rejection', promise, reason);
});
}

Expand All @@ -43,13 +43,13 @@ async function shutdown(reason: string): Promise<void> {
return;
}
shuttingDown = true;
logger?.(`Shutting down (${reason})`);
logger()?.(`Shutting down (${reason})`);
// Backstop in case browser teardown hangs (e.g. unresponsive Chrome,
// slow beforeunload handlers, many tabs). Exits 0 because we still
// honored the shutdown request; the log line preserves observability.
// Unref'd so it doesn't keep the loop alive on the clean path.
setTimeout(() => {
logger?.('Shutdown timeout exceeded, forcing exit');
logger()?.('Shutdown timeout exceeded, forcing exit');
process.exit(0);
}, 10000).unref();
await closeBrowser();
Expand All @@ -71,13 +71,13 @@ process.on('SIGHUP', () => {
void shutdown('SIGHUP');
});

logger?.(`Starting Chrome DevTools MCP Server v${VERSION}`);
logger()?.(`Starting Chrome DevTools MCP Server v${VERSION}`);
const {server} = await createMcpServer(args, {
logFile,
});
const transport = new StdioServerTransport();
await server.connect(transport);
logger?.('Chrome DevTools MCP Server connected');
logger()?.('Chrome DevTools MCP Server connected');
logDisclaimers(args);
void ClearcutLogger.get()?.logDailyActiveIfNeeded();
void ClearcutLogger.get()?.logServerStart(computeFlagUsage(args, cliOptions));
8 changes: 4 additions & 4 deletions src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export async function ensureBrowserConnected(options: {
);
}

logger?.('Connecting Puppeteer to ', JSON.stringify(connectOptions));
logger()?.('Connecting Puppeteer to ', JSON.stringify(connectOptions));
try {
// Assign mode before browser so a concurrent closeBrowser() never sees
// `browser` set with `browserMode` still undefined (would fall through
Expand All @@ -139,7 +139,7 @@ export async function ensureBrowserConnected(options: {
},
);
}
logger?.('Connected Puppeteer');
logger()?.('Connected Puppeteer');
return browser;
}

Expand Down Expand Up @@ -304,12 +304,12 @@ export async function closeBrowser(): Promise<void> {
}
if (mode === 'launched') {
await b.close().catch(err => {
logger?.('Failed to close browser', err);
logger()?.('Failed to close browser', err);
});
return;
}
await b.disconnect().catch(err => {
logger?.('Failed to disconnect from browser', err);
logger()?.('Failed to disconnect from browser', err);
});
}

Expand Down
14 changes: 7 additions & 7 deletions src/daemon/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ async function waitForDaemonReady(sessionId: string) {

export async function startDaemon(mcpArgs: string[] = [], sessionId: string) {
if (isDaemonRunning(sessionId)) {
logger?.('Daemon is already running');
logger()?.('Daemon is already running');
await waitForDaemonReady(sessionId);
return;
}
Expand All @@ -119,7 +119,7 @@ export async function startDaemon(mcpArgs: string[] = [], sessionId: string) {
fs.unlinkSync(pidFilePath);
}

logger?.('Starting daemon...', ...mcpArgs);
logger()?.('Starting daemon...', ...mcpArgs);
const child = spawn(process.execPath, [DAEMON_SCRIPT_PATH, ...mcpArgs], {
detached: true,
stdio: 'ignore',
Expand Down Expand Up @@ -163,27 +163,27 @@ export async function sendCommand(
const transport = new PipeTransport(socket, socket);
transport.onmessage = async (message: string) => {
clearTimeout(timer);
logger?.('onmessage', message);
logger()?.('onmessage', message);
resolve(JSON.parse(message));
};
socket.on('error', error => {
clearTimeout(timer);
logger?.('Socket error:', error);
logger()?.('Socket error:', error);
reject(error);
});
socket.on('close', () => {
clearTimeout(timer);
logger?.('Socket closed:');
logger()?.('Socket closed:');
reject(new Error('Socket closed'));
});
logger?.('Sending message', command);
logger()?.('Sending message', command);
transport.send(JSON.stringify(command));
});
}

export async function stopDaemon(sessionId: string) {
if (!isDaemonRunning(sessionId)) {
logger?.('Daemon is not running');
logger()?.('Daemon is not running');
return;
}

Expand Down
Loading