@dynamicu/chromedebug-mcp 2.6.3 → 2.6.6
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/CLAUDE.md +25 -0
- package/chrome-extension/manifest.free.json +3 -4
- package/dist/chromedebug-extension-free.zip +0 -0
- package/package.json +1 -1
- package/scripts/webpack.config.free.cjs +1 -1
- package/scripts/webpack.config.pro.cjs +1 -1
- package/src/cli.js +11 -0
- package/src/index.js +11 -1
- package/src/services/unified-session-manager.js +114 -1
package/CLAUDE.md
CHANGED
|
@@ -23,6 +23,9 @@ npm run server # Run standalone server
|
|
|
23
23
|
npm run single-server # Run with --single-server flag
|
|
24
24
|
npm run cleanup # Clean up stale Chrome processes
|
|
25
25
|
npm run cleanup-force # Force cleanup of all Chrome processes
|
|
26
|
+
|
|
27
|
+
# Persistent server (won't be killed by other instances)
|
|
28
|
+
chromedebug-mcp --persistent # Start a persistent server for manual debugging
|
|
26
29
|
```
|
|
27
30
|
|
|
28
31
|
### Testing
|
|
@@ -235,8 +238,30 @@ Chrome Debug provides a CLI tool that can be used directly:
|
|
|
235
238
|
```bash
|
|
236
239
|
chromedebug-mcp # Runs the MCP server (equivalent to npm start)
|
|
237
240
|
npx chromedebug-mcp # Run without global installation
|
|
241
|
+
|
|
242
|
+
# Persistent server mode
|
|
243
|
+
chromedebug-mcp --persistent # Won't be killed by other instances
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Persistent Server Mode
|
|
247
|
+
|
|
248
|
+
The `--persistent` flag marks a server as persistent, preventing it from being killed when other ChromeDebug instances start. This is useful for:
|
|
249
|
+
|
|
250
|
+
- **Manual debugging servers**: Keep a debug server running while using Claude Code
|
|
251
|
+
- **Multiple projects**: Run persistent servers for different projects simultaneously
|
|
252
|
+
- **Development workflows**: Maintain a stable server instance across multiple Claude Code sessions
|
|
253
|
+
|
|
254
|
+
Example:
|
|
255
|
+
```bash
|
|
256
|
+
# Terminal 1: Start persistent debug server
|
|
257
|
+
chromedebug-mcp --persistent --verbose
|
|
258
|
+
|
|
259
|
+
# Terminal 2: Use Claude Code normally
|
|
260
|
+
# Claude's MCP server will NOT kill the persistent server
|
|
238
261
|
```
|
|
239
262
|
|
|
263
|
+
See `PERSISTENT-FLAG-README.md` for detailed documentation and examples.
|
|
264
|
+
|
|
240
265
|
The package name is `chromedebug-mcp` but the project is commonly referred to as Chrome Debug.
|
|
241
266
|
|
|
242
267
|
## Additional Architecture Notes
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
|
-
"name": "ChromeDebug MCP Assistant FREE v2.6.
|
|
4
|
-
"version": "2.6.
|
|
5
|
-
"description": "ChromeDebug MCP visual element selector [FREE Edition] [Build: 2025-10-
|
|
3
|
+
"name": "ChromeDebug MCP Assistant FREE v2.6.1",
|
|
4
|
+
"version": "2.6.1",
|
|
5
|
+
"description": "ChromeDebug MCP visual element selector [FREE Edition] [Build: 2025-10-28-v2.6.1]",
|
|
6
6
|
"permissions": [
|
|
7
7
|
"activeTab",
|
|
8
8
|
"scripting",
|
|
9
9
|
"tabs",
|
|
10
10
|
"storage",
|
|
11
11
|
"tabCapture",
|
|
12
|
-
"desktopCapture",
|
|
13
12
|
"notifications",
|
|
14
13
|
"offscreen"
|
|
15
14
|
],
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamicu/chromedebug-mcp",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.6",
|
|
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,17 @@ For details: https://github.com/dynamicupgrade/ChromeDebug#windows-setup
|
|
|
81
81
|
verbose: args.verbose
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
+
// Mark as persistent if requested
|
|
85
|
+
if (args.persistent) {
|
|
86
|
+
await sessionManager.markAsPersistent();
|
|
87
|
+
console.error('Session marked as persistent - will not be killed by other instances');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Kill other instances unless --allow-multiple is set
|
|
91
|
+
if (!args.allowMultiple) {
|
|
92
|
+
await sessionManager.killOtherInstances();
|
|
93
|
+
}
|
|
94
|
+
|
|
84
95
|
// Register this process for tracking
|
|
85
96
|
await registerProcess(process.pid, 'mcp-server');
|
|
86
97
|
|
package/src/index.js
CHANGED
|
@@ -152,7 +152,9 @@ class ChromePilotApp {
|
|
|
152
152
|
sessionId: null,
|
|
153
153
|
noCleanup: false,
|
|
154
154
|
verbose: false,
|
|
155
|
-
dbPath: null
|
|
155
|
+
dbPath: null,
|
|
156
|
+
allowMultiple: false,
|
|
157
|
+
persistent: false
|
|
156
158
|
};
|
|
157
159
|
|
|
158
160
|
const argv = process.argv.slice(2);
|
|
@@ -191,6 +193,12 @@ class ChromePilotApp {
|
|
|
191
193
|
case '--verbose':
|
|
192
194
|
args.verbose = true;
|
|
193
195
|
break;
|
|
196
|
+
case '--allow-multiple':
|
|
197
|
+
args.allowMultiple = true;
|
|
198
|
+
break;
|
|
199
|
+
case '--persistent':
|
|
200
|
+
args.persistent = true;
|
|
201
|
+
break;
|
|
194
202
|
case '--help':
|
|
195
203
|
this.showHelp();
|
|
196
204
|
process.exit(0);
|
|
@@ -237,6 +245,8 @@ Options:
|
|
|
237
245
|
--db-path PATH Set custom database file path (default: ~/.chromedebug/chrome-pilot.db)
|
|
238
246
|
--no-cleanup Skip cleanup of dead processes on startup
|
|
239
247
|
--verbose Enable verbose logging including session info
|
|
248
|
+
--allow-multiple Allow multiple ChromeDebug instances (default: kill others on startup)
|
|
249
|
+
--persistent Mark as persistent server (won't be killed by other instances)
|
|
240
250
|
--help Show this help message
|
|
241
251
|
|
|
242
252
|
Session Isolation:
|
|
@@ -31,7 +31,8 @@ export class UnifiedSessionManager {
|
|
|
31
31
|
port: null,
|
|
32
32
|
processes: [],
|
|
33
33
|
locks: [],
|
|
34
|
-
heartbeat: Date.now()
|
|
34
|
+
heartbeat: Date.now(),
|
|
35
|
+
persistent: false // If true, won't be killed by other instances
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
this.heartbeatInterval = null;
|
|
@@ -354,6 +355,18 @@ export class UnifiedSessionManager {
|
|
|
354
355
|
}
|
|
355
356
|
}
|
|
356
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Mark this session as persistent (won't be killed by other instances)
|
|
360
|
+
*/
|
|
361
|
+
async markAsPersistent() {
|
|
362
|
+
this.state.persistent = true;
|
|
363
|
+
await this.updateSessionFile();
|
|
364
|
+
|
|
365
|
+
if (this.verbose) {
|
|
366
|
+
console.error(`Session ${this.sessionId} marked as persistent`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
357
370
|
/**
|
|
358
371
|
* Start heartbeat to keep session alive
|
|
359
372
|
*/
|
|
@@ -446,6 +459,106 @@ export class UnifiedSessionManager {
|
|
|
446
459
|
return sessions;
|
|
447
460
|
}
|
|
448
461
|
|
|
462
|
+
/**
|
|
463
|
+
* Kill all other ChromeDebug instances
|
|
464
|
+
* Uses session files to find PIDs, then kills them gracefully
|
|
465
|
+
* Skips sessions marked as persistent
|
|
466
|
+
* @returns {Array} Array of killed PIDs
|
|
467
|
+
*/
|
|
468
|
+
async killOtherInstances() {
|
|
469
|
+
const sessions = await UnifiedSessionManager.findActiveSessions();
|
|
470
|
+
const currentPid = process.pid;
|
|
471
|
+
const killedPids = [];
|
|
472
|
+
|
|
473
|
+
for (const session of sessions) {
|
|
474
|
+
if (session.pid === currentPid) continue; // Don't kill ourselves
|
|
475
|
+
|
|
476
|
+
// Skip persistent sessions
|
|
477
|
+
if (session.persistent) {
|
|
478
|
+
console.error(`Skipping persistent session: PID ${session.pid} (session ${session.sessionId})`);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
try {
|
|
483
|
+
// Check if process exists
|
|
484
|
+
process.kill(session.pid, 0); // Signal 0 = check existence
|
|
485
|
+
|
|
486
|
+
// Verify this is actually a ChromeDebug process
|
|
487
|
+
const isChromeDebug = await this.isChromeDebugProcess(session.pid);
|
|
488
|
+
if (!isChromeDebug) {
|
|
489
|
+
console.error(`Skipping PID ${session.pid} - not a ChromeDebug process`);
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
console.error(`Killing ChromeDebug instance: PID ${session.pid} (session ${session.sessionId})`);
|
|
494
|
+
|
|
495
|
+
// Send SIGTERM for graceful shutdown
|
|
496
|
+
process.kill(session.pid, 'SIGTERM');
|
|
497
|
+
killedPids.push(session.pid);
|
|
498
|
+
|
|
499
|
+
// Wait 2 seconds, then SIGKILL if still alive
|
|
500
|
+
setTimeout(() => {
|
|
501
|
+
try {
|
|
502
|
+
process.kill(session.pid, 0); // Check if still alive
|
|
503
|
+
console.error(` Process ${session.pid} didn't terminate, sending SIGKILL`);
|
|
504
|
+
process.kill(session.pid, 'SIGKILL');
|
|
505
|
+
} catch (err) {
|
|
506
|
+
// Process already dead, good
|
|
507
|
+
}
|
|
508
|
+
}, 2000);
|
|
509
|
+
|
|
510
|
+
// Clean up session file
|
|
511
|
+
const sessionFile = path.join(this.sessionDir, `${session.sessionId}.json`);
|
|
512
|
+
try {
|
|
513
|
+
await fs.promises.unlink(sessionFile);
|
|
514
|
+
} catch (err) {
|
|
515
|
+
// Ignore errors
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
} catch (error) {
|
|
519
|
+
if (error.code === 'ESRCH') {
|
|
520
|
+
// Process doesn't exist, just clean up the session file
|
|
521
|
+
const sessionFile = path.join(this.sessionDir, `${session.sessionId}.json`);
|
|
522
|
+
try {
|
|
523
|
+
await fs.promises.unlink(sessionFile);
|
|
524
|
+
} catch (err) {
|
|
525
|
+
// Ignore errors
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
// Ignore other errors (permission denied, etc.)
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (killedPids.length > 0) {
|
|
533
|
+
console.error(`Killed ${killedPids.length} other ChromeDebug instance(s)`);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return killedPids;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Verify if a PID belongs to a ChromeDebug process
|
|
541
|
+
* @param {number} pid - Process ID to check
|
|
542
|
+
* @returns {boolean} True if it's a ChromeDebug process
|
|
543
|
+
*/
|
|
544
|
+
async isChromeDebugProcess(pid) {
|
|
545
|
+
try {
|
|
546
|
+
const { execSync } = require('child_process');
|
|
547
|
+
|
|
548
|
+
// Get process command line
|
|
549
|
+
const cmd = execSync(`ps -p ${pid} -o command=`, { encoding: 'utf8' }).trim();
|
|
550
|
+
|
|
551
|
+
// Check if it's a ChromeDebug process (node running chromedebug or chrome-pilot)
|
|
552
|
+
return cmd.includes('chromedebug') ||
|
|
553
|
+
cmd.includes('chrome-pilot') ||
|
|
554
|
+
cmd.includes('ChromePilot') ||
|
|
555
|
+
cmd.includes('ChromeDebug');
|
|
556
|
+
} catch (error) {
|
|
557
|
+
// If we can't determine, be safe and don't kill
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
449
562
|
/**
|
|
450
563
|
* Clean up stale sessions
|
|
451
564
|
*/
|