@dynamicu/chromedebug-mcp 2.2.0

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.
Files changed (95) hide show
  1. package/CLAUDE.md +344 -0
  2. package/LICENSE +21 -0
  3. package/README.md +250 -0
  4. package/chrome-extension/README.md +41 -0
  5. package/chrome-extension/background.js +3917 -0
  6. package/chrome-extension/chrome-session-manager.js +706 -0
  7. package/chrome-extension/content.css +181 -0
  8. package/chrome-extension/content.js +3022 -0
  9. package/chrome-extension/data-buffer.js +435 -0
  10. package/chrome-extension/dom-tracker.js +411 -0
  11. package/chrome-extension/extension-config.js +78 -0
  12. package/chrome-extension/firebase-client.js +278 -0
  13. package/chrome-extension/firebase-config.js +32 -0
  14. package/chrome-extension/firebase-config.module.js +22 -0
  15. package/chrome-extension/firebase-config.module.template.js +27 -0
  16. package/chrome-extension/firebase-config.template.js +36 -0
  17. package/chrome-extension/frame-capture.js +407 -0
  18. package/chrome-extension/icon128.png +1 -0
  19. package/chrome-extension/icon16.png +1 -0
  20. package/chrome-extension/icon48.png +1 -0
  21. package/chrome-extension/license-helper.js +181 -0
  22. package/chrome-extension/logger.js +23 -0
  23. package/chrome-extension/manifest.json +73 -0
  24. package/chrome-extension/network-tracker.js +510 -0
  25. package/chrome-extension/offscreen.html +10 -0
  26. package/chrome-extension/options.html +203 -0
  27. package/chrome-extension/options.js +282 -0
  28. package/chrome-extension/pako.min.js +2 -0
  29. package/chrome-extension/performance-monitor.js +533 -0
  30. package/chrome-extension/pii-redactor.js +405 -0
  31. package/chrome-extension/popup.html +532 -0
  32. package/chrome-extension/popup.js +2446 -0
  33. package/chrome-extension/upload-manager.js +323 -0
  34. package/chrome-extension/web-vitals.iife.js +1 -0
  35. package/config/api-keys.json +11 -0
  36. package/config/chrome-pilot-config.json +45 -0
  37. package/package.json +126 -0
  38. package/scripts/cleanup-processes.js +109 -0
  39. package/scripts/config-manager.js +280 -0
  40. package/scripts/generate-extension-config.js +53 -0
  41. package/scripts/setup-security.js +64 -0
  42. package/src/capture/architecture.js +426 -0
  43. package/src/capture/error-handling-tests.md +38 -0
  44. package/src/capture/error-handling-types.ts +360 -0
  45. package/src/capture/index.js +508 -0
  46. package/src/capture/interfaces.js +625 -0
  47. package/src/capture/memory-manager.js +713 -0
  48. package/src/capture/types.js +342 -0
  49. package/src/chrome-controller.js +2658 -0
  50. package/src/cli.js +19 -0
  51. package/src/config-loader.js +303 -0
  52. package/src/database.js +2178 -0
  53. package/src/firebase-license-manager.js +462 -0
  54. package/src/firebase-privacy-guard.js +397 -0
  55. package/src/http-server.js +1516 -0
  56. package/src/index-direct.js +157 -0
  57. package/src/index-modular.js +219 -0
  58. package/src/index-monolithic-backup.js +2230 -0
  59. package/src/index.js +305 -0
  60. package/src/legacy/chrome-controller-old.js +1406 -0
  61. package/src/legacy/index-express.js +625 -0
  62. package/src/legacy/index-old.js +977 -0
  63. package/src/legacy/routes.js +260 -0
  64. package/src/legacy/shared-storage.js +101 -0
  65. package/src/logger.js +10 -0
  66. package/src/mcp/handlers/chrome-tool-handler.js +306 -0
  67. package/src/mcp/handlers/element-tool-handler.js +51 -0
  68. package/src/mcp/handlers/frame-tool-handler.js +957 -0
  69. package/src/mcp/handlers/request-handler.js +104 -0
  70. package/src/mcp/handlers/workflow-tool-handler.js +636 -0
  71. package/src/mcp/server.js +68 -0
  72. package/src/mcp/tools/index.js +701 -0
  73. package/src/middleware/auth.js +371 -0
  74. package/src/middleware/security.js +267 -0
  75. package/src/port-discovery.js +258 -0
  76. package/src/routes/admin.js +182 -0
  77. package/src/services/browser-daemon.js +494 -0
  78. package/src/services/chrome-service.js +375 -0
  79. package/src/services/failover-manager.js +412 -0
  80. package/src/services/git-safety-service.js +675 -0
  81. package/src/services/heartbeat-manager.js +200 -0
  82. package/src/services/http-client.js +195 -0
  83. package/src/services/process-manager.js +318 -0
  84. package/src/services/process-tracker.js +574 -0
  85. package/src/services/profile-manager.js +449 -0
  86. package/src/services/project-manager.js +415 -0
  87. package/src/services/session-manager.js +497 -0
  88. package/src/services/session-registry.js +491 -0
  89. package/src/services/unified-session-manager.js +678 -0
  90. package/src/shared-storage-old.js +267 -0
  91. package/src/standalone-server.js +53 -0
  92. package/src/utils/extension-path.js +145 -0
  93. package/src/utils.js +187 -0
  94. package/src/validation/log-transformer.js +125 -0
  95. package/src/validation/schemas.js +391 -0
package/src/cli.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawn } from 'child_process';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
+ const indexPath = join(__dirname, 'index.js');
11
+
12
+ const child = spawn('node', [indexPath], {
13
+ stdio: 'inherit',
14
+ env: process.env
15
+ });
16
+
17
+ child.on('exit', (code) => {
18
+ process.exit(code);
19
+ });
@@ -0,0 +1,303 @@
1
+ // Configuration loader for Chrome Debug
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { ProjectManager } from './services/project-manager.js';
6
+
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+
9
+ // Default configuration
10
+ const DEFAULT_CONFIG = {
11
+ serverPorts: {
12
+ httpServer: {
13
+ preferredPorts: [
14
+ // Original range (maintain backward compatibility)
15
+ 3001, 3000, 3002, 3028,
16
+ // Extended original range
17
+ 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036,
18
+ // Safer fallback ranges (avoid common service conflicts)
19
+ 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090,
20
+ 9000, 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009, 9010
21
+ ],
22
+ description: "Ports to try for HTTP server discovery, in priority order"
23
+ },
24
+ mcpServer: {
25
+ preferredPorts: [
26
+ // Original range (maintain backward compatibility)
27
+ 3028, 3023, 3002, 3003, 3004, 3005,
28
+ // Extended original range
29
+ 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036,
30
+ // Safer fallback ranges (avoid common service conflicts)
31
+ 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090,
32
+ 9000, 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009, 9010
33
+ ],
34
+ description: "Ports to try for MCP server discovery, in priority order"
35
+ },
36
+ discoveryRange: {
37
+ start: 3000,
38
+ end: 9010,
39
+ description: "Port range for automatic discovery when preferred ports are not available"
40
+ }
41
+ },
42
+ chromeExtension: {
43
+ serverDiscovery: {
44
+ timeoutMs: 3000,
45
+ description: "Timeout for server discovery requests in milliseconds"
46
+ },
47
+ portScanOrder: "httpFirst",
48
+ description: "Order to try ports: 'httpFirst' tries HTTP ports first, 'mcpFirst' tries MCP ports first, 'sequential' tries all ports in numerical order"
49
+ },
50
+ logging: {
51
+ level: "info",
52
+ description: "Logging level: debug, info, warn, error"
53
+ }
54
+ };
55
+
56
+ class ConfigLoader {
57
+ constructor() {
58
+ this.config = null;
59
+ this.configPath = null;
60
+ this.projectManager = new ProjectManager();
61
+ this._determineConfigPath();
62
+ }
63
+
64
+ /**
65
+ * Determines the appropriate config path based on project mode
66
+ */
67
+ _determineConfigPath() {
68
+ try {
69
+ // Try project-local config first
70
+ const projectInfo = this.projectManager.detectProject();
71
+ if (projectInfo) {
72
+ try {
73
+ // Initialize project structure synchronously if possible
74
+ const projectConfigPath = path.join(projectInfo.projectDir, '.chromedebug', 'config', 'config.json');
75
+
76
+ // Ensure config directory exists
77
+ const configDir = path.dirname(projectConfigPath);
78
+ if (!fs.existsSync(configDir)) {
79
+ fs.mkdirSync(configDir, { recursive: true });
80
+ }
81
+
82
+ this.configPath = projectConfigPath;
83
+ console.log(`[ConfigLoader] Using project-local config: ${projectConfigPath}`);
84
+ return;
85
+ } catch (error) {
86
+ console.warn('[ConfigLoader] Project structure not ready, using global config:', error.message);
87
+ }
88
+ }
89
+ } catch (error) {
90
+ console.warn('[ConfigLoader] Failed project detection, using global config:', error.message);
91
+ }
92
+
93
+ // Fallback to global config
94
+ this.configPath = path.join(__dirname, '../config/chromedebug-config.json');
95
+ console.log(`[ConfigLoader] Using global config: ${this.configPath}`);
96
+ }
97
+
98
+ // Load configuration from file
99
+ loadConfig() {
100
+ if (this.config) return this.config;
101
+
102
+ try {
103
+ if (fs.existsSync(this.configPath)) {
104
+ const configData = fs.readFileSync(this.configPath, 'utf8');
105
+ this.config = { ...DEFAULT_CONFIG, ...JSON.parse(configData) };
106
+ console.log(`Configuration loaded from: ${this.configPath}`);
107
+ } else {
108
+ console.log('No configuration file found, using defaults');
109
+ this.config = DEFAULT_CONFIG;
110
+
111
+ // If we're in project mode and global config exists, copy it first
112
+ if (this.isProjectLocalConfig() && this.hasGlobalConfig()) {
113
+ this.copyGlobalConfigToProject();
114
+ } else {
115
+ this.createDefaultConfigFile();
116
+ }
117
+ }
118
+ } catch (error) {
119
+ console.warn(`Error loading configuration: ${error.message}`);
120
+ console.log('Using default configuration');
121
+ this.config = DEFAULT_CONFIG;
122
+ }
123
+
124
+ return this.config;
125
+ }
126
+
127
+ /**
128
+ * Checks if current config path is project-local
129
+ * @returns {boolean} True if using project-local config
130
+ */
131
+ isProjectLocalConfig() {
132
+ return this.configPath && this.configPath.includes('.chromedebug');
133
+ }
134
+
135
+ /**
136
+ * Checks if global config file exists
137
+ * @returns {boolean} True if global config exists
138
+ */
139
+ hasGlobalConfig() {
140
+ const globalConfigPath = path.join(__dirname, '../config/chromedebug-config.json');
141
+ return fs.existsSync(globalConfigPath);
142
+ }
143
+
144
+ /**
145
+ * Copies global config to project-local config
146
+ */
147
+ copyGlobalConfigToProject() {
148
+ try {
149
+ const globalConfigPath = path.join(__dirname, '../config/chromedebug-config.json');
150
+ const globalConfigData = fs.readFileSync(globalConfigPath, 'utf8');
151
+ const globalConfig = JSON.parse(globalConfigData);
152
+
153
+ // Merge with defaults and write to project config
154
+ this.config = { ...DEFAULT_CONFIG, ...globalConfig };
155
+ fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
156
+
157
+ console.log(`[ConfigLoader] Copied global config to project: ${this.configPath}`);
158
+ } catch (error) {
159
+ console.warn(`[ConfigLoader] Failed to copy global config: ${error.message}`);
160
+ this.createDefaultConfigFile();
161
+ }
162
+ }
163
+
164
+ // Create default configuration file
165
+ createDefaultConfigFile() {
166
+ try {
167
+ const configDir = path.dirname(this.configPath);
168
+ if (!fs.existsSync(configDir)) {
169
+ fs.mkdirSync(configDir, { recursive: true });
170
+ }
171
+
172
+ fs.writeFileSync(this.configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
173
+ console.log(`Default configuration file created at: ${this.configPath}`);
174
+ } catch (error) {
175
+ console.warn(`Could not create default configuration file: ${error.message}`);
176
+ }
177
+ }
178
+
179
+ // Get HTTP server ports in priority order
180
+ getHttpServerPorts() {
181
+ const config = this.loadConfig();
182
+ return [...config.serverPorts.httpServer.preferredPorts];
183
+ }
184
+
185
+ // Get MCP server ports in priority order
186
+ getMcpServerPorts() {
187
+ const config = this.loadConfig();
188
+ return [...config.serverPorts.mcpServer.preferredPorts];
189
+ }
190
+
191
+ // Get combined port list for Chrome extension based on scan order
192
+ getExtensionPortList() {
193
+ const config = this.loadConfig();
194
+ const httpPorts = this.getHttpServerPorts();
195
+ const mcpPorts = this.getMcpServerPorts();
196
+
197
+ let combinedPorts = [];
198
+
199
+ switch (config.chromeExtension.portScanOrder) {
200
+ case 'httpFirst':
201
+ // HTTP ports first, then MCP ports, avoiding duplicates
202
+ combinedPorts = [...httpPorts];
203
+ mcpPorts.forEach(port => {
204
+ if (!combinedPorts.includes(port)) {
205
+ combinedPorts.push(port);
206
+ }
207
+ });
208
+ break;
209
+
210
+ case 'mcpFirst':
211
+ // MCP ports first, then HTTP ports, avoiding duplicates
212
+ combinedPorts = [...mcpPorts];
213
+ httpPorts.forEach(port => {
214
+ if (!combinedPorts.includes(port)) {
215
+ combinedPorts.push(port);
216
+ }
217
+ });
218
+ break;
219
+
220
+ case 'sequential':
221
+ // All ports in numerical order
222
+ const allPorts = [...new Set([...httpPorts, ...mcpPorts])];
223
+ combinedPorts = allPorts.sort((a, b) => a - b);
224
+ break;
225
+
226
+ default:
227
+ // Default to httpFirst
228
+ combinedPorts = [...httpPorts];
229
+ mcpPorts.forEach(port => {
230
+ if (!combinedPorts.includes(port)) {
231
+ combinedPorts.push(port);
232
+ }
233
+ });
234
+ }
235
+
236
+ // Add discovery range if enabled
237
+ const discoveryRange = config.serverPorts.discoveryRange;
238
+ if (discoveryRange.start && discoveryRange.end) {
239
+ for (let port = discoveryRange.start; port <= discoveryRange.end; port++) {
240
+ if (!combinedPorts.includes(port)) {
241
+ combinedPorts.push(port);
242
+ }
243
+ }
244
+ }
245
+
246
+ return combinedPorts;
247
+ }
248
+
249
+ // Get server discovery timeout
250
+ getDiscoveryTimeout() {
251
+ const config = this.loadConfig();
252
+ return config.chromeExtension.serverDiscovery.timeoutMs;
253
+ }
254
+
255
+ // Get logging level
256
+ getLoggingLevel() {
257
+ const config = this.loadConfig();
258
+ return config.logging.level;
259
+ }
260
+
261
+ // Update configuration
262
+ updateConfig(updates) {
263
+ const config = this.loadConfig();
264
+ const newConfig = { ...config, ...updates };
265
+
266
+ try {
267
+ fs.writeFileSync(this.configPath, JSON.stringify(newConfig, null, 2));
268
+ this.config = newConfig;
269
+ console.log('Configuration updated successfully');
270
+ return true;
271
+ } catch (error) {
272
+ console.error(`Error updating configuration: ${error.message}`);
273
+ return false;
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Gets configuration mode information
279
+ * @returns {object} Configuration mode info
280
+ */
281
+ getConfigInfo() {
282
+ return {
283
+ mode: this.isProjectLocalConfig() ? 'project' : 'global',
284
+ configPath: this.configPath,
285
+ isProjectLocal: this.isProjectLocalConfig(),
286
+ projectInfo: this.projectManager.projectInfo,
287
+ hasGlobalConfig: this.hasGlobalConfig(),
288
+ configExists: fs.existsSync(this.configPath)
289
+ };
290
+ }
291
+
292
+ /**
293
+ * Gets the current config file path
294
+ * @returns {string} Config file path
295
+ */
296
+ getConfigPath() {
297
+ return this.configPath;
298
+ }
299
+ }
300
+
301
+ // Export singleton instance
302
+ export const configLoader = new ConfigLoader();
303
+ export default configLoader;