@nimbus21.ai/chrome-devtools-mcp 0.17.4 → 0.17.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,36 @@ import { puppeteer } from './third_party/index.js';
13
13
  // Add stealth plugin
14
14
  puppeteerExtra.use(StealthPlugin());
15
15
  let browser;
16
+ /**
17
+ * Close the browser instance, killing the Chrome process if we launched it.
18
+ * Safe to call multiple times or when no browser exists.
19
+ */
20
+ export async function closeBrowser() {
21
+ if (!browser) {
22
+ return;
23
+ }
24
+ const b = browser;
25
+ browser = undefined;
26
+ try {
27
+ if (b.connected) {
28
+ // browser.close() sends a Browser.close CDP command and kills the process
29
+ // if it was launched by puppeteer. For connected browsers it just disconnects.
30
+ await b.close();
31
+ }
32
+ }
33
+ catch {
34
+ // Best-effort: if close fails, try to kill the process directly
35
+ try {
36
+ const proc = b.process();
37
+ if (proc && !proc.killed) {
38
+ proc.kill('SIGKILL');
39
+ }
40
+ }
41
+ catch {
42
+ // Nothing more we can do
43
+ }
44
+ }
45
+ }
16
46
  function makeTargetFilter() {
17
47
  const ignoredPrefixes = new Set([
18
48
  'chrome://',
package/build/src/main.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import './polyfill.js';
7
7
  import process from 'node:process';
8
- import { ensureBrowserConnected, ensureBrowserLaunched } from './browser.js';
8
+ import { closeBrowser, ensureBrowserConnected, ensureBrowserLaunched } from './browser.js';
9
9
  import { cliOptions, parseArguments } from './cli.js';
10
10
  import { loadIssueDescriptions } from './issue-descriptions.js';
11
11
  import { logger, saveLogsToFile } from './logger.js';
@@ -195,6 +195,43 @@ await loadIssueDescriptions();
195
195
  const transport = new StdioServerTransport();
196
196
  await server.connect(transport);
197
197
  logger('Chrome DevTools MCP Server connected');
198
+ // Graceful shutdown: kill Chrome when the MCP server exits for any reason.
199
+ let shuttingDown = false;
200
+ async function gracefulShutdown(reason) {
201
+ if (shuttingDown) {
202
+ return;
203
+ }
204
+ shuttingDown = true;
205
+ logger(`Shutting down: ${reason}`);
206
+ try {
207
+ context?.dispose();
208
+ }
209
+ catch {
210
+ // best-effort
211
+ }
212
+ try {
213
+ await closeBrowser();
214
+ }
215
+ catch {
216
+ // best-effort
217
+ }
218
+ logger('Shutdown complete');
219
+ process.exit(0);
220
+ }
221
+ // Handle OS signals (container stop, systemd, Ctrl+C)
222
+ for (const signal of ['SIGTERM', 'SIGINT', 'SIGHUP']) {
223
+ process.on(signal, () => {
224
+ void gracefulShutdown(`received ${signal}`);
225
+ });
226
+ }
227
+ // Handle MCP client disconnect (transport/server close)
228
+ server.server.onclose = () => {
229
+ void gracefulShutdown('MCP client disconnected');
230
+ };
231
+ // Handle stdin closing (parent process died)
232
+ process.stdin.on('close', () => {
233
+ void gracefulShutdown('stdin closed');
234
+ });
198
235
  logDisclaimers();
199
236
  void clearcutLogger?.logDailyActiveIfNeeded();
200
237
  void clearcutLogger?.logServerStart(computeFlagUsage(args, cliOptions));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbus21.ai/chrome-devtools-mcp",
3
- "version": "0.17.4",
3
+ "version": "0.17.5",
4
4
  "description": "MCP server for Chrome DevTools with stealth mode support",
5
5
  "type": "module",
6
6
  "bin": "./build/src/index.js",