@dynamicu/chromedebug-mcp 2.5.9 → 2.5.10

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/README.md CHANGED
@@ -27,6 +27,17 @@ npm install @dynamicu/chromedebug-mcp
27
27
 
28
28
  > **Want unlimited recordings and advanced features?** See [Installing PRO Version](#installing-pro-version) below for automated PRO installation.
29
29
 
30
+ ### Chrome Extension Installation
31
+
32
+ Install the Chrome extension to enable visual element selection and recording features:
33
+
34
+ 🌐 **[Install from Chrome Web Store](https://chromewebstore.google.com/detail/chromedebug-mcp-assistant/lemgbmdnephoaniipapgeciebfeakffn)**
35
+
36
+ - ✅ 5 recordings per day (FREE version)
37
+ - ✅ Visual element selection
38
+ - ✅ Full MCP integration
39
+ - ✅ Automatic updates
40
+
30
41
  ### Development Installation
31
42
 
32
43
  ```bash
@@ -117,15 +128,49 @@ When you launch Chrome with `chromedebug-mcp`, you should see:
117
128
 
118
129
  ### As MCP Server
119
130
 
120
- #### macOS / Linux
131
+ #### Quick Setup (Claude Code CLI)
121
132
 
133
+ **macOS / Linux:**
122
134
  ```bash
123
135
  claude mcp add chromedebug -s user -- chromedebug-mcp
124
136
  ```
125
137
 
138
+ **Windows (WSL2):**
139
+ ```bash
140
+ claude mcp add chromedebug -s user -- wsl chromedebug-mcp
141
+ ```
142
+
126
143
  The MCP server will automatically start both the stdio MCP server and HTTP server for Chrome extension integration.
127
144
 
128
- #### Windows
145
+ #### Manual Configuration (Any MCP Client)
146
+
147
+ If you're not using Claude Code CLI or want to configure manually, add this to your MCP settings file:
148
+
149
+ **Location:** `~/.claude/config.json` or your MCP client's configuration file
150
+
151
+ ```json
152
+ {
153
+ "mcpServers": {
154
+ "chromedebug": {
155
+ "command": "chromedebug-mcp"
156
+ }
157
+ }
158
+ }
159
+ ```
160
+
161
+ **For WSL2 users:**
162
+ ```json
163
+ {
164
+ "mcpServers": {
165
+ "chromedebug": {
166
+ "command": "wsl",
167
+ "args": ["chromedebug-mcp"]
168
+ }
169
+ }
170
+ }
171
+ ```
172
+
173
+ #### Windows Setup Details
129
174
 
130
175
  ⚠️ **Important: WSL2 Recommended for Windows Users**
131
176
 
@@ -268,7 +313,7 @@ Chrome Debug includes a Chrome extension that enables visual element selection f
268
313
 
269
314
  Install the FREE version directly from the Chrome Web Store:
270
315
 
271
- 🌐 **[Install from Chrome Web Store](https://chromewebstore.google.com/detail/lemgbmdnephoaniipapgeciebfeakffn?utm_source=item-share-cb)**
316
+ 🌐 **[Install from Chrome Web Store](https://chromewebstore.google.com/detail/chromedebug-mcp-assistant/lemgbmdnephoaniipapgeciebfeakffn)**
272
317
 
273
318
  - ✅ 5 recordings per day
274
319
  - ✅ Full MCP integration
@@ -1,4 +1,4 @@
1
- import { FUNCTIONS_URL } from './firebase-config.module.js';
1
+ import { FUNCTIONS_URL } from './firebase-config.public.js';
2
2
 
3
3
  /**
4
4
  * Firebase License Client
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Firebase Cloud Functions configuration - PUBLIC VERSION
3
+ * For Service Worker (background.js) via importScripts
4
+ *
5
+ * SECURITY NOTE: This API key is intentionally public and restricted:
6
+ * - Restricted by HTTP referrers in Google Cloud Console
7
+ * - Protected by Firebase Security Rules server-side
8
+ * - Standard practice for all web/mobile Firebase apps
9
+ */
10
+
11
+ // Firebase configuration (public, restricted API key)
12
+ const FIREBASE_CONFIG = {
13
+ projectId: 'chrome-debug-mcp',
14
+ apiKey: 'AIzaSyDu4r5k7J4gb76CVN9evBNg3DV6KjworCE',
15
+ authDomain: 'chromedebug.com'
16
+ };
17
+
18
+ // Cloud Functions base URL
19
+ const FUNCTIONS_URL = `https://us-central1-${FIREBASE_CONFIG.projectId}.cloudfunctions.net`;
20
+
21
+ // LemonSqueezy checkout URL (Production)
22
+ const LEMONSQUEEZY_CHECKOUT_URL = 'https://chromedebug.com/buy/996773cb-682b-430f-b9e3-9ce2130bd967';
23
+
24
+ // Make available globally for service worker context
25
+ if (typeof self !== 'undefined') {
26
+ self.FIREBASE_CONFIG = FIREBASE_CONFIG;
27
+ self.FUNCTIONS_URL = FUNCTIONS_URL;
28
+ self.LEMONSQUEEZY_CHECKOUT_URL = LEMONSQUEEZY_CHECKOUT_URL;
29
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Firebase Cloud Functions configuration - PUBLIC VERSION
3
+ * Safe for client-side use and Web Store distribution
4
+ *
5
+ * SECURITY NOTE: This API key is intentionally public and restricted:
6
+ * - Restricted by HTTP referrers in Google Cloud Console
7
+ * - Protected by Firebase Security Rules server-side
8
+ * - Standard practice for all web/mobile Firebase apps
9
+ *
10
+ * This file is committed to the repository and used for:
11
+ * - Web Store extension builds
12
+ * - Development environments
13
+ * - License validation via Firebase Cloud Functions
14
+ */
15
+
16
+ // Firebase configuration (public, restricted API key)
17
+ const FIREBASE_CONFIG = {
18
+ projectId: 'chrome-debug-mcp',
19
+ apiKey: 'AIzaSyDu4r5k7J4gb76CVN9evBNg3DV6KjworCE',
20
+ authDomain: 'chromedebug.com'
21
+ };
22
+
23
+ // Cloud Functions base URL
24
+ const FUNCTIONS_URL = `https://us-central1-${FIREBASE_CONFIG.projectId}.cloudfunctions.net`;
25
+
26
+ // LemonSqueezy checkout URL (Production)
27
+ const LEMONSQUEEZY_CHECKOUT_URL = 'https://chromedebug.com/buy/996773cb-682b-430f-b9e3-9ce2130bd967';
28
+
29
+ // Export for ES6 modules (popup.js, firebase-client.js)
30
+ export { FIREBASE_CONFIG, FUNCTIONS_URL, LEMONSQUEEZY_CHECKOUT_URL };
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "manifest_version": 3,
3
- "name": "ChromeDebug MCP Assistant FREE v2.4.1",
4
- "version": "2.4.1",
5
- "description": "ChromeDebug MCP visual element selector [FREE Edition] [Build: 2025-01-20-v2.4.1]",
3
+ "name": "ChromeDebug MCP Assistant FREE v2.5.0",
4
+ "version": "2.5.0",
5
+ "description": "ChromeDebug MCP visual element selector [FREE Edition] [Build: 2025-10-21-v2.5.0]",
6
6
  "permissions": [
7
7
  "activeTab",
8
8
  "scripting",
@@ -2,14 +2,30 @@
2
2
  const EXTENSION_VERSION = '2.0.4-BUILD-20250119';
3
3
  console.log(`[popup.js] Loaded version: ${EXTENSION_VERSION}`);
4
4
 
5
- // Import Firebase license client
6
- import { FirebaseLicenseClient } from './firebase-client.js';
7
- import { LEMONSQUEEZY_CHECKOUT_URL } from './firebase-config.module.js';
8
-
9
- // Initialize license client
10
- const licenseClient = new FirebaseLicenseClient();
5
+ // Import Firebase license client with graceful fallback
6
+ let FirebaseLicenseClient = null;
7
+ let LEMONSQUEEZY_CHECKOUT_URL = 'https://chromedebug.com/buy/996773cb-682b-430f-b9e3-9ce2130bd967';
8
+ let licenseClient = null;
11
9
  let currentUserId = null;
12
10
 
11
+ // Load Firebase asynchronously to avoid blocking module execution
12
+ (async () => {
13
+ try {
14
+ const firebaseClientModule = await import('./firebase-client.js');
15
+ FirebaseLicenseClient = firebaseClientModule.FirebaseLicenseClient;
16
+
17
+ const firebaseConfigModule = await import('./firebase-config.public.js');
18
+ LEMONSQUEEZY_CHECKOUT_URL = firebaseConfigModule.LEMONSQUEEZY_CHECKOUT_URL;
19
+
20
+ // Initialize license client if Firebase loaded successfully
21
+ licenseClient = new FirebaseLicenseClient();
22
+ console.log('[popup.js] Firebase license client initialized');
23
+ } catch (error) {
24
+ console.warn('[popup.js] Firebase not available - license features disabled:', error);
25
+ // Extension will work without Firebase, just no license validation
26
+ }
27
+ })();
28
+
13
29
  // Global variables for recording functionality
14
30
  let isRecording = false;
15
31
  let recordingTimer = null;
@@ -102,8 +118,24 @@ function stopWorkflowTimer() {
102
118
  }
103
119
  }
104
120
 
105
- // Import configuration - this will be available globally
106
- const CONFIG_PORTS = CHROMEDEBUG_CONFIG?.ports || [3001, 3000, 3002, 3028]; // Fallback to defaults
121
+ // Smart tiered port discovery configuration
122
+ const PORT_TIERS = {
123
+ // Try common ports first with short timeout (fast discovery)
124
+ common: [3000, 3001, 3002, 3028, 3033],
125
+ // Then try extended range if not found
126
+ extended: [3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010,
127
+ 3029, 3030, 3031, 3032, 3034, 3035, 3036],
128
+ // Finally try alternative common development ports
129
+ alternative: [8080, 8081, 8082, 8083, 8084, 8085,
130
+ 9000, 9001, 9002, 9003, 9004, 9005]
131
+ };
132
+
133
+ // All ports in one array for compatibility (used by CONFIG_PORTS references)
134
+ const CONFIG_PORTS = [
135
+ ...PORT_TIERS.common,
136
+ ...PORT_TIERS.extended,
137
+ ...PORT_TIERS.alternative
138
+ ];
107
139
 
108
140
  // Site management functions
109
141
  async function initializeSiteManagement() {
@@ -262,45 +294,122 @@ function testSiteAccess(hostname, mode, allowedSites, restrictedSites) {
262
294
 
263
295
  // Function definitions (outside DOMContentLoaded for proper scope)
264
296
  async function checkServerStatus() {
297
+ console.log('[popup.js] checkServerStatus() called');
265
298
  const statusEl = document.getElementById('serverStatus');
266
299
  const statusTextEl = document.getElementById('statusText');
267
-
268
- const ports = CONFIG_PORTS;
300
+
301
+ if (!statusEl || !statusTextEl) {
302
+ console.error('[popup.js] Status elements not found in DOM');
303
+ return { connected: false, connectedPort: null };
304
+ }
305
+
269
306
  let connected = false;
270
307
  let connectedPort = null;
271
-
272
- for (const port of ports) {
308
+
309
+ // Helper function to try a port with timeout
310
+ const tryPort = async (port, timeout = 1000) => {
273
311
  try {
312
+ const controller = new AbortController();
313
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
314
+
274
315
  const response = await fetch(`http://localhost:${port}/chromedebug/status`, {
275
316
  method: 'GET',
276
- mode: 'cors'
317
+ mode: 'cors',
318
+ signal: controller.signal
277
319
  });
278
-
279
- if (response.ok) {
320
+
321
+ clearTimeout(timeoutId);
322
+ console.log(`[popup.js] Port ${port} responded: ${response.ok}`);
323
+ return response.ok;
324
+ } catch (error) {
325
+ console.log(`[popup.js] Port ${port} failed:`, error.message);
326
+ return false;
327
+ }
328
+ };
329
+
330
+ // Check if we have a cached successful port from previous session
331
+ const cachedPort = await chrome.storage.local.get('lastSuccessfulPort');
332
+ if (cachedPort.lastSuccessfulPort) {
333
+ if (await tryPort(cachedPort.lastSuccessfulPort, 500)) {
334
+ connected = true;
335
+ connectedPort = cachedPort.lastSuccessfulPort;
336
+ console.log(`[popup.js] Connected to cached port ${connectedPort}`);
337
+ }
338
+ }
339
+
340
+ // If cached port didn't work, try tiered discovery
341
+ if (!connected) {
342
+ // Phase 1: Try common ports with short timeout (fast)
343
+ for (const port of PORT_TIERS.common) {
344
+ if (await tryPort(port, 500)) {
280
345
  connected = true;
281
346
  connectedPort = port;
347
+ console.log(`[popup.js] Connected to common port ${connectedPort}`);
282
348
  break;
283
349
  }
284
- } catch (error) {
285
- // Try next port
286
350
  }
287
351
  }
288
-
352
+
353
+ // Phase 2: Try extended range with longer timeout
354
+ if (!connected) {
355
+ for (const port of PORT_TIERS.extended) {
356
+ if (await tryPort(port, 1000)) {
357
+ connected = true;
358
+ connectedPort = port;
359
+ console.log(`[popup.js] Connected to extended port ${connectedPort}`);
360
+ break;
361
+ }
362
+ }
363
+ }
364
+
365
+ // Phase 3: Try alternative ports as last resort
366
+ if (!connected) {
367
+ for (const port of PORT_TIERS.alternative) {
368
+ if (await tryPort(port, 1000)) {
369
+ connected = true;
370
+ connectedPort = port;
371
+ console.log(`[popup.js] Connected to alternative port ${connectedPort}`);
372
+ break;
373
+ }
374
+ }
375
+ }
376
+
377
+ // Cache the successful port for faster connection next time
378
+ if (connected && connectedPort) {
379
+ await chrome.storage.local.set({ lastSuccessfulPort: connectedPort });
380
+ }
381
+
289
382
  if (connected) {
290
383
  statusEl.className = 'server-status connected';
291
- statusTextEl.innerHTML = `Server connected (port ${connectedPort})`;
384
+ statusTextEl.innerHTML = `
385
+ Server connected (port ${connectedPort})
386
+ <div style="margin-top: 4px;">
387
+ <a href="https://www.npmjs.com/package/@dynamicu/chromedebug-mcp" target="_blank" style="font-size: 10px; color: #666; text-decoration: none;">
388
+ 📚 Documentation
389
+ </a>
390
+ </div>
391
+ `;
292
392
  } else {
293
393
  statusEl.className = 'server-status disconnected';
294
394
 
295
395
  // Enhanced disconnected state with install instructions
296
396
  statusTextEl.innerHTML = `
297
- <span style="display: block; margin-bottom: 8px;">Server not installed</span>
397
+ <div style="font-weight: bold; margin-bottom: 8px;">Server Not Running</div>
398
+ <div style="font-size: 11px; color: #666; margin-bottom: 8px; line-height: 1.4;">
399
+ To use ChromeDebug, install and start the MCP server:
400
+ </div>
401
+ <div style="background: #f5f5f5; padding: 8px; border-radius: 4px; font-family: monospace; font-size: 10px; margin-bottom: 8px;">
402
+ <div style="margin-bottom: 4px;"># Install the server</div>
403
+ <div style="color: #1976d2; margin-bottom: 8px;">npm install -g @dynamicu/chromedebug-mcp</div>
404
+ <div style="margin-bottom: 4px;"># Start the server</div>
405
+ <div style="color: #1976d2;">chromedebug-mcp-server</div>
406
+ </div>
298
407
  <div style="display: flex; gap: 5px; align-items: center;">
299
- <button id="copyInstallCmd" style="padding: 4px 8px; font-size: 11px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer; flex-shrink: 0;">
300
- 📋 Copy Install Command
408
+ <button id="copyInstallCmd" style="padding: 4px 8px; font-size: 11px; background: #2196F3; color: white; border: none; border-radius: 3px; cursor: pointer;">
409
+ 📋 Copy Commands
301
410
  </button>
302
- <a href="https://www.npmjs.com/package/@dynamicu/chromedebug-mcp" target="_blank" style="font-size: 11px; white-space: nowrap;">
303
- View Installation Guide
411
+ <a href="https://www.npmjs.com/package/@dynamicu/chromedebug-mcp" target="_blank" style="font-size: 11px; color: #2196F3; text-decoration: none;">
412
+ 📚 Full Documentation
304
413
  </a>
305
414
  </div>
306
415
  `;
@@ -311,10 +420,14 @@ async function checkServerStatus() {
311
420
  if (copyBtn) {
312
421
  copyBtn.addEventListener('click', async (e) => {
313
422
  e.preventDefault();
314
- const installCommand = 'npm install -g @dynamicu/chromedebug-mcp';
423
+ const installCommands = `# Install the server
424
+ npm install -g @dynamicu/chromedebug-mcp
425
+
426
+ # Start the server
427
+ chromedebug-mcp-server`;
315
428
 
316
429
  try {
317
- await navigator.clipboard.writeText(installCommand);
430
+ await navigator.clipboard.writeText(installCommands);
318
431
  const originalText = copyBtn.innerHTML;
319
432
  copyBtn.innerHTML = '✅ Copied!';
320
433
  copyBtn.style.background = '#4CAF50';
@@ -327,7 +440,7 @@ async function checkServerStatus() {
327
440
  console.error('Failed to copy:', err);
328
441
  copyBtn.innerHTML = '❌ Failed';
329
442
  setTimeout(() => {
330
- copyBtn.innerHTML = '📋 Copy Install Command';
443
+ copyBtn.innerHTML = '📋 Copy Commands';
331
444
  }, 2000);
332
445
  }
333
446
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamicu/chromedebug-mcp",
3
- "version": "2.5.9",
3
+ "version": "2.5.10",
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",
@@ -49,8 +49,10 @@ const filesToInclude = [
49
49
  'chrome-session-manager.js',
50
50
  'logger.js',
51
51
  'extension-config.js',
52
+ 'upload-manager.js',
52
53
  'firebase-client.js',
53
- 'firebase-config.js',
54
+ { source: 'firebase-config.public.js', target: 'firebase-config.public.js' },
55
+ { source: 'firebase-config.public-sw.js', target: 'firebase-config.js' }, // For service worker importScripts
54
56
  'license-helper.js',
55
57
 
56
58
  // Content scripts (from manifest)
@@ -78,7 +80,6 @@ const filesToInclude = [
78
80
 
79
81
  // Offscreen
80
82
  'offscreen.html',
81
- 'offscreen.js',
82
83
 
83
84
  // Frame capture
84
85
  'frame-capture.js',