Skip to content

Commit 6425fc1

Browse files
author
Yevhenii Hyzyla
committed
feat: add disconnect_browser tool
1 parent 32dc50d commit 6425fc1

5 files changed

Lines changed: 50 additions & 0 deletions

File tree

src/McpContext.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import os from 'node:os';
99
import path from 'node:path';
1010
import {fileURLToPath, pathToFileURL} from 'node:url';
1111

12+
import {disconnectBrowser} from './browser.js';
1213
import type {TargetUniverse} from './DevtoolsUtils.js';
1314
import {UniverseManager} from './DevtoolsUtils.js';
1415
import {HeapSnapshotManager} from './HeapSnapshotManager.js';
@@ -146,6 +147,11 @@ export class McpContext implements Context {
146147
this.#isolatedContexts.clear();
147148
}
148149

150+
async disconnect(): Promise<void> {
151+
this.dispose();
152+
await disconnectBrowser();
153+
}
154+
149155
static async from(
150156
browser: Browser,
151157
logger: Debugger,

src/browser.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,16 @@ export async function ensureBrowserLaunched(
270270
return browser;
271271
}
272272

273+
export async function disconnectBrowser(): Promise<void> {
274+
const current = browser;
275+
browser = undefined;
276+
if (current?.connected) {
277+
try {
278+
await current.disconnect();
279+
} catch (err) {
280+
logger('Error while disconnecting browser', err);
281+
}
282+
}
283+
}
284+
273285
export type Channel = 'stable' | 'canary' | 'beta' | 'dev';

src/tools/ToolDefinition.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ export type Context = Readonly<{
179179
isCruxEnabled(): boolean;
180180
recordedTraces(): TraceResult[];
181181
storeTraceRecording(result: TraceResult): void;
182+
disconnect(): Promise<void>;
182183
getPageById(pageId: number): ContextPage;
183184
newPage(
184185
background?: boolean,

src/tools/connection.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {ToolCategory} from './categories.js';
8+
import {defineTool} from './ToolDefinition.js';
9+
10+
export const disconnectBrowser = defineTool({
11+
name: 'disconnect_browser',
12+
description:
13+
'Release the current connection to Chrome without exiting the MCP server. ' +
14+
'The next tool call will reconnect using the original startup options ' +
15+
'(autoConnect, --browserUrl, --wsEndpoint, or launch). ' +
16+
'Useful for revoking remote-debugging permission cleanly or resetting MCP state.',
17+
annotations: {
18+
category: ToolCategory.NAVIGATION,
19+
readOnlyHint: false,
20+
},
21+
schema: {},
22+
blockedByDialog: false,
23+
handler: async (_request, response, context) => {
24+
await context.disconnect();
25+
response.appendResponseLine(
26+
'Browser connection released. The next tool call will reconnect.',
27+
);
28+
},
29+
});

src/tools/tools.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import type {ParsedArguments} from '../bin/chrome-devtools-mcp-cli-options.js';
88

9+
import * as connectionTools from './connection.js';
910
import * as consoleTools from './console.js';
1011
import * as emulationTools from './emulation.js';
1112
import * as extensionTools from './extensions.js';
@@ -28,6 +29,7 @@ export const createTools = (args: ParsedArguments) => {
2829
const rawTools = args.slim
2930
? Object.values(slimTools)
3031
: [
32+
...Object.values(connectionTools),
3133
...Object.values(consoleTools),
3234
...Object.values(emulationTools),
3335
...Object.values(extensionTools),

0 commit comments

Comments
 (0)