@dynamicu/chromedebug-mcp 2.6.6 → 2.6.7

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.
@@ -0,0 +1,101 @@
1
+ {
2
+ "serverPorts": {
3
+ "httpServer": {
4
+ "preferredPorts": [
5
+ 3001,
6
+ 3000,
7
+ 3002,
8
+ 3028,
9
+ 3029,
10
+ 3030,
11
+ 3031,
12
+ 3032,
13
+ 3033,
14
+ 3034,
15
+ 3035,
16
+ 3036,
17
+ 8080,
18
+ 8081,
19
+ 8082,
20
+ 8083,
21
+ 8084,
22
+ 8085,
23
+ 8086,
24
+ 8087,
25
+ 8088,
26
+ 8089,
27
+ 8090,
28
+ 9000,
29
+ 9001,
30
+ 9002,
31
+ 9003,
32
+ 9004,
33
+ 9005,
34
+ 9006,
35
+ 9007,
36
+ 9008,
37
+ 9009,
38
+ 9010
39
+ ],
40
+ "description": "Ports to try for HTTP server discovery, in priority order"
41
+ },
42
+ "mcpServer": {
43
+ "preferredPorts": [
44
+ 3028,
45
+ 3023,
46
+ 3002,
47
+ 3003,
48
+ 3004,
49
+ 3005,
50
+ 3029,
51
+ 3030,
52
+ 3031,
53
+ 3032,
54
+ 3033,
55
+ 3034,
56
+ 3035,
57
+ 3036,
58
+ 8080,
59
+ 8081,
60
+ 8082,
61
+ 8083,
62
+ 8084,
63
+ 8085,
64
+ 8086,
65
+ 8087,
66
+ 8088,
67
+ 8089,
68
+ 8090,
69
+ 9000,
70
+ 9001,
71
+ 9002,
72
+ 9003,
73
+ 9004,
74
+ 9005,
75
+ 9006,
76
+ 9007,
77
+ 9008,
78
+ 9009,
79
+ 9010
80
+ ],
81
+ "description": "Ports to try for MCP server discovery, in priority order"
82
+ },
83
+ "discoveryRange": {
84
+ "start": 3000,
85
+ "end": 9010,
86
+ "description": "Port range for automatic discovery when preferred ports are not available"
87
+ }
88
+ },
89
+ "chromeExtension": {
90
+ "serverDiscovery": {
91
+ "timeoutMs": 3000,
92
+ "description": "Timeout for server discovery requests in milliseconds"
93
+ },
94
+ "portScanOrder": "httpFirst",
95
+ "description": "Order to try ports: 'httpFirst' tries HTTP ports first, 'mcpFirst' tries MCP ports first, 'sequential' tries all ports in numerical order"
96
+ },
97
+ "logging": {
98
+ "level": "info",
99
+ "description": "Logging level: debug, info, warn, error"
100
+ }
101
+ }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamicu/chromedebug-mcp",
3
- "version": "2.6.6",
3
+ "version": "2.6.7",
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",
@@ -14,7 +14,7 @@ import archiver from 'archiver';
14
14
  const __filename = fileURLToPath(import.meta.url);
15
15
  const __dirname = dirname(__filename);
16
16
  const rootDir = join(__dirname, '..');
17
- const proExtensionDir = join(rootDir, 'scripts', 'dist', 'pro');
17
+ const proExtensionDir = join(rootDir, 'dist', 'pro');
18
18
  const outputDir = join(rootDir, 'dist');
19
19
  const outputFile = join(outputDir, 'chromedebug-extension-pro.zip');
20
20
 
@@ -67,6 +67,9 @@ module.exports = {
67
67
  { from: 'chrome-extension/frame-capture.js', to: 'frame-capture.js' },
68
68
  { from: 'chrome-extension/chrome-session-manager.js', to: 'chrome-session-manager.js' },
69
69
 
70
+ // Browser-only recording mode files
71
+ { from: 'chrome-extension/browser-recording-manager.js', to: 'browser-recording-manager.js' },
72
+
70
73
  // Copy README
71
74
  { from: 'chrome-extension/README.md', to: 'README.md' }
72
75
  ]
@@ -69,6 +69,9 @@ module.exports = {
69
69
  { from: 'chrome-extension/frame-capture.js', to: 'frame-capture.js' },
70
70
  { from: 'chrome-extension/chrome-session-manager.js', to: 'chrome-session-manager.js' },
71
71
 
72
+ // Browser-only recording mode files
73
+ { from: 'chrome-extension/browser-recording-manager.js', to: 'browser-recording-manager.js' },
74
+
72
75
  // Copy Pro features
73
76
  { from: 'chrome-extension/pro/function-tracker.js', to: 'pro/function-tracker.js' },
74
77
  { from: 'chrome-extension/pro/enhanced-capture.js', to: 'pro/enhanced-capture.js' },
@@ -1981,10 +1981,10 @@ export class ChromeController {
1981
1981
  async storeWorkflowRecording(sessionId, url, title, includeLogs, actions, logs, name = null, screenshotSettings = null, functionTraces = null) {
1982
1982
  try {
1983
1983
  const { database } = await import('./database.js');
1984
-
1984
+
1985
1985
  // Store the workflow recording
1986
1986
  const workflowId = database.storeWorkflowRecording(sessionId, url, title, includeLogs, name, screenshotSettings);
1987
-
1987
+
1988
1988
  // Merge function traces into actions if provided
1989
1989
  let allActions = [...actions];
1990
1990
  if (functionTraces && functionTraces.length > 0) {
@@ -1994,23 +1994,23 @@ export class ChromeController {
1994
1994
  // Sort all actions by timestamp to maintain chronological order
1995
1995
  allActions.sort((a, b) => a.timestamp - b.timestamp);
1996
1996
  }
1997
-
1997
+
1998
1998
  // Store actions with proper indexing
1999
1999
  const indexedActions = allActions.map((action, index) => ({
2000
2000
  ...action,
2001
2001
  index: index
2002
2002
  }));
2003
-
2003
+
2004
2004
  const actionsResult = database.storeWorkflowActions(workflowId, indexedActions);
2005
-
2005
+
2006
2006
  // Store logs if provided
2007
2007
  if (includeLogs && logs && logs.length > 0) {
2008
2008
  const logsResult = database.storeWorkflowLogs(workflowId, logs);
2009
2009
  logger.debug(`Stored ${logsResult.storedCount} logs for workflow ${sessionId}`);
2010
2010
  }
2011
-
2011
+
2012
2012
  logger.debug(`Stored workflow recording ${sessionId} with ${actionsResult.storedCount} actions (including ${functionTraces ? functionTraces.length : 0} function traces)`);
2013
-
2013
+
2014
2014
  return {
2015
2015
  success: true,
2016
2016
  sessionId: sessionId,
package/src/database.js CHANGED
@@ -1414,6 +1414,8 @@ class ChromePilotDatabase {
1414
1414
  return action[camelCaseName] || action[snakeCaseName] || null;
1415
1415
  };
1416
1416
 
1417
+ const screenshotDataToStore = action.screenshot_data || null;
1418
+
1417
1419
  stmt.run(
1418
1420
  workflowId,
1419
1421
  action.index,
@@ -1425,7 +1427,7 @@ class ChromePilotDatabase {
1425
1427
  action.text || null,
1426
1428
  action.placeholder || null,
1427
1429
  action.timestamp,
1428
- action.screenshot_data || null,
1430
+ screenshotDataToStore,
1429
1431
  action.component || null, // For function traces
1430
1432
  action.args ? JSON.stringify(action.args) : null, // Store args as JSON string
1431
1433
  action.stack || null, // For function traces
@@ -1436,6 +1438,7 @@ class ChromePilotDatabase {
1436
1438
  safeJsonStringify(getEnhancedFieldData(action, 'elementState', 'element_state'), 2048), // 2KB limit
1437
1439
  safeJsonStringify(getEnhancedFieldData(action, 'performanceMetrics', 'performance_metrics'), 1024) // 1KB limit
1438
1440
  );
1441
+
1439
1442
  storedCount++;
1440
1443
  }
1441
1444
 
@@ -1452,6 +1455,7 @@ class ChromePilotDatabase {
1452
1455
  `);
1453
1456
  updateStmt.run(storedCount, workflowId);
1454
1457
 
1458
+ logger.debug('[SCREENSHOT-DEBUG] database.storeWorkflowActions - EXIT');
1455
1459
  return { success: true, storedCount };
1456
1460
  }
1457
1461
 
@@ -1560,7 +1564,7 @@ class ChromePilotDatabase {
1560
1564
  text: action.text,
1561
1565
  placeholder: action.placeholder,
1562
1566
  timestamp: action.timestamp,
1563
- screenshot_data: action.screenshot_data
1567
+ screenshot: action.screenshot_data // Map screenshot_data to screenshot for consistency
1564
1568
  };
1565
1569
 
1566
1570
  // Add function trace fields if they exist
@@ -286,18 +286,19 @@ async function startHttpServer(chromeController = null, targetPort = null) {
286
286
  });
287
287
 
288
288
  // Protected workflow recording endpoints
289
- app.post('/chromedebug/workflow-recording',
289
+ app.post('/chromedebug/workflow-recording',
290
290
  authenticate,
291
291
  authorize(PERMISSIONS.WORKFLOW_WRITE),
292
292
  createValidator(workflowRecordingSchema),
293
293
  async (req, res) => {
294
294
  const { sessionId, url, title, includeLogs, actions, logs, functionTraces, name, screenshotSettings } = req.body;
295
+
295
296
  logger.info('[HTTP Server] Received workflow recording with name:', name);
296
297
  logger.info('[HTTP Server] Function traces count:', functionTraces ? functionTraces.length : 0);
297
298
  if (!sessionId || !actions) {
298
299
  return res.status(400).json({ error: 'sessionId and actions are required' });
299
300
  }
300
-
301
+
301
302
  try {
302
303
  const result = await activeController.storeWorkflowRecording(sessionId, url, title, includeLogs, actions, logs, name, screenshotSettings, functionTraces);
303
304
  res.json(result);
@@ -20,8 +20,35 @@ export const workflowRecordingSchema = Joi.object({
20
20
  Joi.object({
21
21
  type: Joi.string().required(),
22
22
  timestamp: Joi.number().required(),
23
- data: Joi.object().optional()
24
- })
23
+ data: Joi.object().optional(),
24
+ // Screenshot field - base64 encoded image data
25
+ screenshot_data: Joi.string().max(10485760).optional(), // 10MB max for base64 string
26
+ // Click/interaction fields
27
+ selector: Joi.string().optional(),
28
+ x: Joi.number().optional(),
29
+ y: Joi.number().optional(),
30
+ value: Joi.string().optional(),
31
+ text: Joi.string().optional(),
32
+ placeholder: Joi.string().optional(),
33
+ index: Joi.number().optional(),
34
+ // Enhanced click tracking fields
35
+ element_html: Joi.string().max(10240).optional(),
36
+ elementHTML: Joi.string().max(10240).optional(), // camelCase variant
37
+ component_data: Joi.string().max(3072).optional(),
38
+ componentData: Joi.string().max(3072).optional(), // camelCase variant
39
+ event_handlers: Joi.string().max(2048).optional(),
40
+ eventHandlers: Joi.string().max(2048).optional(), // camelCase variant
41
+ element_state: Joi.string().max(2048).optional(),
42
+ elementState: Joi.string().max(2048).optional(), // camelCase variant
43
+ performance_metrics: Joi.string().max(1024).optional(),
44
+ performanceMetrics: Joi.string().max(1024).optional(), // camelCase variant
45
+ // Function trace fields
46
+ component: Joi.string().optional(),
47
+ args: Joi.alternatives().try(Joi.array(), Joi.string()).optional(),
48
+ stack: Joi.string().optional(),
49
+ // Attached logs
50
+ logs: Joi.array().optional()
51
+ }).unknown(true) // Allow additional fields for future extensibility
25
52
  ).required(),
26
53
  logs: Joi.array().items(
27
54
  Joi.object({
@@ -42,10 +69,13 @@ export const workflowRecordingSchema = Joi.object({
42
69
  ).optional(),
43
70
  name: Joi.any().optional(),
44
71
  screenshotSettings: Joi.object({
45
- width: Joi.number().integer().min(100).max(4000).optional(),
46
- height: Joi.number().integer().min(100).max(4000).optional(),
47
- quality: Joi.number().min(10).max(100).optional()
48
- }).optional()
72
+ width: Joi.number().integer().min(100).max(4000).optional().allow(null),
73
+ height: Joi.number().integer().min(100).max(4000).optional().allow(null),
74
+ quality: Joi.number().min(10).max(100).optional().allow(null),
75
+ format: Joi.string().valid('png', 'jpeg').optional().allow(null),
76
+ enabled: Joi.boolean().optional().allow(null),
77
+ maxWidth: Joi.number().integer().optional().allow(null)
78
+ }).optional().allow(null)
49
79
  });
50
80
 
51
81
  // Frame batch schema