@dynamicu/chromedebug-mcp 2.5.14 → 2.6.1

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.
@@ -81,10 +81,10 @@ export class UnifiedSessionManager {
81
81
  this.initialized = true;
82
82
 
83
83
  if (this.verbose) {
84
- console.log(`Session initialized: ${this.sessionId}`);
85
- console.log(` PID: ${this.state.pid}`);
86
- console.log(` Port: ${this.state.port}`);
87
- console.log(` Session file: ${this.sessionFile}`);
84
+ console.error(`Session initialized: ${this.sessionId}`);
85
+ console.error(` PID: ${this.state.pid}`);
86
+ console.error(` Port: ${this.state.port}`);
87
+ console.error(` Session file: ${this.sessionFile}`);
88
88
  }
89
89
 
90
90
  return this.state;
@@ -338,7 +338,7 @@ export class UnifiedSessionManager {
338
338
  await this.updateSessionFile();
339
339
 
340
340
  if (this.verbose) {
341
- console.log(`Registered process: PID ${pid} (${type}) [Session: ${this.sessionId}]`);
341
+ console.error(`Registered process: PID ${pid} (${type}) [Session: ${this.sessionId}]`);
342
342
  }
343
343
  }
344
344
 
@@ -350,7 +350,7 @@ export class UnifiedSessionManager {
350
350
  await this.updateSessionFile();
351
351
 
352
352
  if (this.verbose) {
353
- console.log(`Unregistered process: PID ${pid} [Session: ${this.sessionId}]`);
353
+ console.error(`Unregistered process: PID ${pid} [Session: ${this.sessionId}]`);
354
354
  }
355
355
  }
356
356
 
@@ -365,7 +365,7 @@ export class UnifiedSessionManager {
365
365
  // Handle specific error cases that indicate session cleanup
366
366
  if (error.code === 'ENOENT' || error.message.includes('Session file does not exist')) {
367
367
  if (this.verbose) {
368
- console.log(`Session file removed, stopping heartbeat for session ${this.sessionId}`);
368
+ console.error(`Session file removed, stopping heartbeat for session ${this.sessionId}`);
369
369
  }
370
370
  this.stopHeartbeat();
371
371
  return;
@@ -373,7 +373,7 @@ export class UnifiedSessionManager {
373
373
 
374
374
  // Handle permission errors gracefully
375
375
  if (error.code === 'EPERM' || error.code === 'EACCES' || error.message.includes('Permission denied')) {
376
- console.warn(`Heartbeat permission error for session ${this.sessionId}:`, error.message);
376
+ console.error(`Heartbeat permission error for session ${this.sessionId}:`, error.message);
377
377
  this.stopHeartbeat();
378
378
  return;
379
379
  }
@@ -396,7 +396,7 @@ export class UnifiedSessionManager {
396
396
  this.initialized = false;
397
397
 
398
398
  if (this.verbose) {
399
- console.log(`Heartbeat stopped for session ${this.sessionId}`);
399
+ console.error(`Heartbeat stopped for session ${this.sessionId}`);
400
400
  }
401
401
  }
402
402
  }
@@ -471,7 +471,7 @@ export class UnifiedSessionManager {
471
471
  cleanedCount++;
472
472
 
473
473
  if (this.verbose) {
474
- console.log(`Cleaned up stale session: ${sessionData.sessionId}`);
474
+ console.error(`Cleaned up stale session: ${sessionData.sessionId}`);
475
475
  }
476
476
  }
477
477
  } catch (error) {
@@ -487,7 +487,7 @@ export class UnifiedSessionManager {
487
487
  await this.cleanupStalePortLocks();
488
488
 
489
489
  if (cleanedCount > 0 && this.verbose) {
490
- console.log(`Cleaned up ${cleanedCount} stale sessions`);
490
+ console.error(`Cleaned up ${cleanedCount} stale sessions`);
491
491
  }
492
492
  } catch (error) {
493
493
  // Directory might not exist
@@ -539,7 +539,7 @@ export class UnifiedSessionManager {
539
539
 
540
540
  const cleanup = async (reason) => {
541
541
  if (this.verbose) {
542
- console.log(`Session ${this.sessionId} exiting (${reason}), cleaning up...`);
542
+ console.error(`Session ${this.sessionId} exiting (${reason}), cleaning up...`);
543
543
  }
544
544
  await this.cleanup();
545
545
  };
@@ -617,7 +617,7 @@ export class UnifiedSessionManager {
617
617
  } catch {}
618
618
 
619
619
  if (this.verbose) {
620
- console.log(`Session ${this.sessionId} cleaned up`);
620
+ console.error(`Session ${this.sessionId} cleaned up`);
621
621
  }
622
622
  } catch (error) {
623
623
  console.error(`Error during session cleanup:`, error.message);
@@ -5,32 +5,36 @@
5
5
 
6
6
  import { startHttpServer, startWebSocketServer } from './http-server.js';
7
7
  import { removePortFile } from './port-discovery.js';
8
+ import { interceptStdout } from './logger.js';
8
9
 
9
- console.log('╔════════════════════════════════════════════════════════════════╗');
10
- console.log('║ Chrome Debug HTTP Server ║');
11
- console.log('║ ║');
12
- console.log('║ This server enables Chrome extension features like: ║');
13
- console.log('║ - Frame recording ║');
14
- console.log('║ - Workflow recording ║');
15
- console.log('║ - Visual element selection ║');
16
- console.log('║ ║');
17
- console.log('║ Keep this running while using Chrome Debug through Claude ║');
18
- console.log('╚════════════════════════════════════════════════════════════════╝');
19
- console.log('');
10
+ // CRITICAL: Intercept stdout FIRST to prevent MCP JSON-RPC pollution
11
+ interceptStdout();
12
+
13
+ console.error('╔════════════════════════════════════════════════════════════════╗');
14
+ console.error('║ Chrome Debug HTTP Server ║');
15
+ console.error('║ ║');
16
+ console.error('║ This server enables Chrome extension features like: ║');
17
+ console.error('║ - Frame recording ║');
18
+ console.error('║ - Workflow recording ║');
19
+ console.error('║ - Visual element selection ║');
20
+ console.error('║ ║');
21
+ console.error('║ Keep this running while using Chrome Debug through Claude ║');
22
+ console.error('╚════════════════════════════════════════════════════════════════╝');
23
+ console.error('');
20
24
 
21
25
  async function main() {
22
26
  try {
23
27
  // Start HTTP server
24
28
  const httpPort = await startHttpServer();
25
- console.log(`✓ HTTP server started on port ${httpPort}`);
29
+ console.error(`✓ HTTP server started on port ${httpPort}`);
26
30
 
27
31
  // Start WebSocket server
28
32
  await startWebSocketServer();
29
- console.log('✓ WebSocket server started');
33
+ console.error('✓ WebSocket server started');
30
34
 
31
- console.log('');
32
- console.log('Server is ready! Chrome extension features are now available.');
33
- console.log('Press Ctrl+C to stop the server.');
35
+ console.error('');
36
+ console.error('Server is ready! Chrome extension features are now available.');
37
+ console.error('Press Ctrl+C to stop the server.');
34
38
 
35
39
  } catch (error) {
36
40
  console.error('Failed to start server:', error.message);
@@ -40,7 +44,7 @@ async function main() {
40
44
 
41
45
  // Cleanup on exit
42
46
  process.on('SIGINT', () => {
43
- console.log('\nShutting down server...');
47
+ console.error('\nShutting down server...');
44
48
  removePortFile();
45
49
  process.exit(0);
46
50
  });
@@ -52,18 +52,18 @@ export function getExtensionPath(config = {}) {
52
52
  const resolvedPath = path.resolve(searchPath);
53
53
 
54
54
  if (validateExtensionPath(resolvedPath)) {
55
- console.log(`[ExtensionPath] ✓ Found ChromeDebug extension at: ${resolvedPath}`);
55
+ console.error(`[ExtensionPath] ✓ Found ChromeDebug extension at: ${resolvedPath}`);
56
56
  return resolvedPath;
57
57
  }
58
58
  }
59
59
 
60
- console.warn('[ExtensionPath] ⚠ ChromeDebug extension not found in any standard location');
61
- console.warn('[ExtensionPath] Searched locations:');
62
- searchPaths.filter(Boolean).forEach(p => console.warn(`[ExtensionPath] - ${p}`));
63
- console.warn('[ExtensionPath]');
64
- console.warn('[ExtensionPath] To specify a custom location, use:');
65
- console.warn('[ExtensionPath] • Environment variable: CHROMEDEBUG_EXTENSION_PATH=/path/to/extension');
66
- console.warn('[ExtensionPath] • Config file: Set "extensionPath" in config/chrome-pilot-config.json');
60
+ console.error('[ExtensionPath] ⚠ ChromeDebug extension not found in any standard location');
61
+ console.error('[ExtensionPath] Searched locations:');
62
+ searchPaths.filter(Boolean).forEach(p => console.error(`[ExtensionPath] - ${p}`));
63
+ console.error('[ExtensionPath]');
64
+ console.error('[ExtensionPath] To specify a custom location, use:');
65
+ console.error('[ExtensionPath] • Environment variable: CHROMEDEBUG_EXTENSION_PATH=/path/to/extension');
66
+ console.error('[ExtensionPath] • Config file: Set "extensionPath" in config/chrome-pilot-config.json');
67
67
 
68
68
  return null;
69
69
  }
@@ -114,7 +114,7 @@ export function validateExtensionPath(extensionPath) {
114
114
 
115
115
  // Verify it's the ChromeDebug extension
116
116
  if (!manifest.name?.includes('ChromeDebug')) {
117
- console.warn(`[ExtensionPath] ⚠ Extension at ${extensionPath} is not ChromeDebug (found: ${manifest.name})`);
117
+ console.error(`[ExtensionPath] ⚠ Extension at ${extensionPath} is not ChromeDebug (found: ${manifest.name})`);
118
118
  return false;
119
119
  }
120
120
 
package/src/utils.js CHANGED
@@ -88,7 +88,7 @@ async function handleExistingLock(lockFile, port) {
88
88
  // Try to remove stale lock
89
89
  try {
90
90
  await fs.promises.unlink(lockFile);
91
- console.log(`Cleaned up stale port lock for port ${port}`);
91
+ console.error(`Cleaned up stale port lock for port ${port}`);
92
92
  return true;
93
93
  } catch (cleanupError) {
94
94
  // Another process might have cleaned it up, that's fine
@@ -127,7 +127,7 @@ async function cleanupStaleLocks(lockDir) {
127
127
 
128
128
  if (lockAge > STALE_LOCK_THRESHOLD) {
129
129
  await fs.promises.unlink(lockFile);
130
- console.log(`Cleaned up stale lock file: ${file}`);
130
+ console.error(`Cleaned up stale lock file: ${file}`);
131
131
  }
132
132
  } catch (error) {
133
133
  // Corrupted lock file, remove it
@@ -269,8 +269,8 @@ export function createValidator(schema, target = 'body') {
269
269
 
270
270
  if (error) {
271
271
  // Diagnostic logging for validation failures
272
- console.log(`[Validation] Failed for ${target}:`, JSON.stringify(data, null, 2));
273
- console.log(`[Validation] Errors:`, error.details.map(d => ({ field: d.path.join('.'), message: d.message, value: d.context?.value })));
272
+ console.error(`[Validation] Failed for ${target}:`, JSON.stringify(data, null, 2));
273
+ console.error(`[Validation] Errors:`, error.details.map(d => ({ field: d.path.join('.'), message: d.message, value: d.context?.value })));
274
274
 
275
275
  return res.status(400).json({
276
276
  error: 'Validation failed',