@dynamicu/chromedebug-mcp 2.6.3 → 2.6.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamicu/chromedebug-mcp",
3
- "version": "2.6.3",
3
+ "version": "2.6.4",
4
4
  "description": "ChromeDebug MCP - MCP server that provides full control over a Chrome browser instance for debugging and automation with AI assistants like Claude Code",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -81,6 +81,11 @@ For details: https://github.com/dynamicupgrade/ChromeDebug#windows-setup
81
81
  verbose: args.verbose
82
82
  });
83
83
 
84
+ // Kill other instances unless --allow-multiple is set
85
+ if (!args.allowMultiple) {
86
+ await sessionManager.killOtherInstances();
87
+ }
88
+
84
89
  // Register this process for tracking
85
90
  await registerProcess(process.pid, 'mcp-server');
86
91
 
package/src/index.js CHANGED
@@ -152,7 +152,8 @@ class ChromePilotApp {
152
152
  sessionId: null,
153
153
  noCleanup: false,
154
154
  verbose: false,
155
- dbPath: null
155
+ dbPath: null,
156
+ allowMultiple: false
156
157
  };
157
158
 
158
159
  const argv = process.argv.slice(2);
@@ -191,6 +192,9 @@ class ChromePilotApp {
191
192
  case '--verbose':
192
193
  args.verbose = true;
193
194
  break;
195
+ case '--allow-multiple':
196
+ args.allowMultiple = true;
197
+ break;
194
198
  case '--help':
195
199
  this.showHelp();
196
200
  process.exit(0);
@@ -237,6 +241,7 @@ Options:
237
241
  --db-path PATH Set custom database file path (default: ~/.chromedebug/chrome-pilot.db)
238
242
  --no-cleanup Skip cleanup of dead processes on startup
239
243
  --verbose Enable verbose logging including session info
244
+ --allow-multiple Allow multiple ChromeDebug instances (default: kill others on startup)
240
245
  --help Show this help message
241
246
 
242
247
  Session Isolation:
@@ -446,6 +446,99 @@ export class UnifiedSessionManager {
446
446
  return sessions;
447
447
  }
448
448
 
449
+ /**
450
+ * Kill all other ChromeDebug instances
451
+ * Uses session files to find PIDs, then kills them gracefully
452
+ * @returns {Array} Array of killed PIDs
453
+ */
454
+ async killOtherInstances() {
455
+ const sessions = await UnifiedSessionManager.findActiveSessions();
456
+ const currentPid = process.pid;
457
+ const killedPids = [];
458
+
459
+ for (const session of sessions) {
460
+ if (session.pid === currentPid) continue; // Don't kill ourselves
461
+
462
+ try {
463
+ // Check if process exists
464
+ process.kill(session.pid, 0); // Signal 0 = check existence
465
+
466
+ // Verify this is actually a ChromeDebug process
467
+ const isChromeDebug = await this.isChromeDebugProcess(session.pid);
468
+ if (!isChromeDebug) {
469
+ console.error(`Skipping PID ${session.pid} - not a ChromeDebug process`);
470
+ continue;
471
+ }
472
+
473
+ console.error(`Killing ChromeDebug instance: PID ${session.pid} (session ${session.sessionId})`);
474
+
475
+ // Send SIGTERM for graceful shutdown
476
+ process.kill(session.pid, 'SIGTERM');
477
+ killedPids.push(session.pid);
478
+
479
+ // Wait 2 seconds, then SIGKILL if still alive
480
+ setTimeout(() => {
481
+ try {
482
+ process.kill(session.pid, 0); // Check if still alive
483
+ console.error(` Process ${session.pid} didn't terminate, sending SIGKILL`);
484
+ process.kill(session.pid, 'SIGKILL');
485
+ } catch (err) {
486
+ // Process already dead, good
487
+ }
488
+ }, 2000);
489
+
490
+ // Clean up session file
491
+ const sessionFile = path.join(this.sessionDir, `${session.sessionId}.json`);
492
+ try {
493
+ await fs.promises.unlink(sessionFile);
494
+ } catch (err) {
495
+ // Ignore errors
496
+ }
497
+
498
+ } catch (error) {
499
+ if (error.code === 'ESRCH') {
500
+ // Process doesn't exist, just clean up the session file
501
+ const sessionFile = path.join(this.sessionDir, `${session.sessionId}.json`);
502
+ try {
503
+ await fs.promises.unlink(sessionFile);
504
+ } catch (err) {
505
+ // Ignore errors
506
+ }
507
+ }
508
+ // Ignore other errors (permission denied, etc.)
509
+ }
510
+ }
511
+
512
+ if (killedPids.length > 0) {
513
+ console.error(`Killed ${killedPids.length} other ChromeDebug instance(s)`);
514
+ }
515
+
516
+ return killedPids;
517
+ }
518
+
519
+ /**
520
+ * Verify if a PID belongs to a ChromeDebug process
521
+ * @param {number} pid - Process ID to check
522
+ * @returns {boolean} True if it's a ChromeDebug process
523
+ */
524
+ async isChromeDebugProcess(pid) {
525
+ try {
526
+ const { execSync } = await import('child_process');
527
+
528
+ // Get process command line
529
+ const cmd = execSync(`ps -p ${pid} -o command=`, { encoding: 'utf8' }).trim();
530
+
531
+ // Check if it's a ChromeDebug process (node running chromedebug or chrome-pilot)
532
+ return cmd.includes('chromedebug') ||
533
+ cmd.includes('chrome-pilot') ||
534
+ cmd.includes('ChromePilot') ||
535
+ cmd.includes('ChromeDebug');
536
+ } catch (error) {
537
+ // If we can't determine, be safe and don't kill
538
+ return false;
539
+ }
540
+ }
541
+
449
542
  /**
450
543
  * Clean up stale sessions
451
544
  */