@dynamicu/chromedebug-mcp 2.4.1 ā 2.4.2
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 +11 -1
- package/chrome-extension/icon128.png +0 -0
- package/chrome-extension/icon16.png +0 -0
- package/chrome-extension/icon48.png +0 -0
- package/chrome-extension/manifest.json +3 -3
- package/package.json +1 -1
- package/scripts/package-webstore-extension.js +109 -80
- package/src/services/process-manager.js +14 -2
package/README.md
CHANGED
|
@@ -30,12 +30,22 @@ npm install
|
|
|
30
30
|
|
|
31
31
|
### As MCP Server
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
#### macOS / Linux
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
claude mcp add chromedebug -s user -- chromedebug-mcp
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
#### Windows
|
|
40
|
+
|
|
41
|
+
On Windows, use `cmd /c` to properly execute the server:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
claude mcp add chromedebug -s user -- cmd /c chromedebug-mcp
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Note for Windows Users:** Process cleanup is currently limited on Windows. The server will start successfully but won't clean up orphaned processes from previous sessions. A full cross-platform process management solution is planned for a future release.
|
|
48
|
+
|
|
39
49
|
### Embedded HTTP Server
|
|
40
50
|
|
|
41
51
|
Chrome Debug automatically starts an embedded HTTP server for Chrome extension communication. The server uses ports configured in `config/chrome-pilot-config.json` (default: 3001, 3000, 3002, 3028). The server provides these REST API endpoints:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
|
-
"name": "ChromeDebug MCP Assistant v2.1.
|
|
4
|
-
"version": "2.1.
|
|
5
|
-
"description": "ChromeDebug MCP visual element selector with function tracing [Build: 2025-10-
|
|
3
|
+
"name": "ChromeDebug MCP Assistant v2.1.3",
|
|
4
|
+
"version": "2.1.3",
|
|
5
|
+
"description": "ChromeDebug MCP visual element selector with function tracing [Build: 2025-10-16-v2.1.3]",
|
|
6
6
|
"permissions": [
|
|
7
7
|
"activeTab",
|
|
8
8
|
"scripting",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamicu/chromedebug-mcp",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
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",
|
|
@@ -1,89 +1,118 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Package FREE Chrome extension for Chrome Web Store distribution
|
|
5
|
-
* Creates a .zip file optimized for Chrome Web Store submission
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { createWriteStream, promises as fs } from 'fs';
|
|
9
|
-
import { join, dirname } from 'path';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
|
-
import { execSync } from 'child_process';
|
|
12
2
|
import archiver from 'archiver';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
13
6
|
|
|
14
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
-
const __dirname = dirname(__filename);
|
|
16
|
-
const rootDir = join(__dirname, '..');
|
|
17
|
-
const freeExtensionDir = join(rootDir, 'scripts', 'dist', 'free');
|
|
18
|
-
const outputDir = join(rootDir, 'dist');
|
|
19
|
-
const outputFile = join(outputDir, 'chromedebug-webstore-free.zip');
|
|
20
|
-
|
|
21
|
-
async function packageWebStoreExtension() {
|
|
22
|
-
console.log('š¦ Building and packaging FREE Chrome extension for Web Store...');
|
|
23
|
-
|
|
24
|
-
// Step 1: Build the free version
|
|
25
|
-
console.log('šØ Building free version...');
|
|
26
|
-
try {
|
|
27
|
-
execSync('npm run build:free', {
|
|
28
|
-
cwd: rootDir,
|
|
29
|
-
stdio: 'inherit'
|
|
30
|
-
});
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.error('ā Failed to build free version');
|
|
33
|
-
throw error;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Step 2: Verify the build output exists
|
|
37
|
-
try {
|
|
38
|
-
await fs.access(freeExtensionDir);
|
|
39
|
-
} catch {
|
|
40
|
-
throw new Error(`Build output not found at ${freeExtensionDir}`);
|
|
41
|
-
}
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
42
9
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// Directory might already exist, that's fine
|
|
48
|
-
}
|
|
10
|
+
const projectRoot = path.join(__dirname, '..');
|
|
11
|
+
const extensionDir = path.join(projectRoot, 'chrome-extension');
|
|
12
|
+
const distDir = path.join(projectRoot, 'dist');
|
|
13
|
+
const outputFile = path.join(distDir, 'chromedebug-extension-webstore.zip');
|
|
49
14
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const output = createWriteStream(outputFile);
|
|
54
|
-
const archive = archiver('zip', {
|
|
55
|
-
zlib: { level: 9 }
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
return new Promise((resolve, reject) => {
|
|
59
|
-
output.on('close', () => {
|
|
60
|
-
const sizeKB = (archive.pointer() / 1024).toFixed(2);
|
|
61
|
-
console.log(`ā
Chrome Web Store package created successfully!`);
|
|
62
|
-
console.log(` Size: ${sizeKB} KB`);
|
|
63
|
-
console.log(` Location: ${outputFile}`);
|
|
64
|
-
console.log(` š This is the FREE version for Chrome Web Store`);
|
|
65
|
-
console.log(` š Ready to upload to: https://chrome.google.com/webstore/devconsole`);
|
|
66
|
-
console.log(`\nš Next steps:`);
|
|
67
|
-
console.log(` 1. Go to Chrome Web Store Developer Dashboard`);
|
|
68
|
-
console.log(` 2. Upload this zip file`);
|
|
69
|
-
console.log(` 3. Fill in store listing details`);
|
|
70
|
-
console.log(` 4. Submit for review`);
|
|
71
|
-
resolve();
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
archive.on('error', reject);
|
|
75
|
-
|
|
76
|
-
archive.pipe(output);
|
|
77
|
-
|
|
78
|
-
// Add all files from the free build directory
|
|
79
|
-
// Chrome Web Store expects all files to be in the root of the zip
|
|
80
|
-
archive.directory(freeExtensionDir, false);
|
|
81
|
-
|
|
82
|
-
archive.finalize();
|
|
83
|
-
});
|
|
15
|
+
// Ensure dist directory exists
|
|
16
|
+
if (!fs.existsSync(distDir)) {
|
|
17
|
+
fs.mkdirSync(distDir, { recursive: true });
|
|
84
18
|
}
|
|
85
19
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
20
|
+
// Create output stream
|
|
21
|
+
const output = fs.createWriteStream(outputFile);
|
|
22
|
+
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
23
|
+
|
|
24
|
+
console.log('š¦ Packaging Chrome extension for Web Store...');
|
|
25
|
+
|
|
26
|
+
// Listen for archive events
|
|
27
|
+
output.on('close', () => {
|
|
28
|
+
const sizeKB = (archive.pointer() / 1024).toFixed(2);
|
|
29
|
+
console.log(`ā
Extension packaged successfully!`);
|
|
30
|
+
console.log(` File: ${outputFile}`);
|
|
31
|
+
console.log(` Size: ${sizeKB} KB`);
|
|
32
|
+
console.log(`\nš Ready to upload to Chrome Web Store!`);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
archive.on('error', (err) => {
|
|
36
|
+
throw err;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Pipe archive to output file
|
|
40
|
+
archive.pipe(output);
|
|
41
|
+
|
|
42
|
+
// Files to include in the extension (FREE version for Web Store)
|
|
43
|
+
const filesToInclude = [
|
|
44
|
+
// Manifest (use FREE version and rename to manifest.json)
|
|
45
|
+
{ source: 'manifest.free.json', target: 'manifest.json' },
|
|
46
|
+
|
|
47
|
+
// Background service worker
|
|
48
|
+
'background.js',
|
|
49
|
+
'chrome-session-manager.js',
|
|
50
|
+
'logger.js',
|
|
51
|
+
'extension-config.js',
|
|
52
|
+
'firebase-client.js',
|
|
53
|
+
'firebase-config.js',
|
|
54
|
+
'license-helper.js',
|
|
55
|
+
|
|
56
|
+
// Content scripts (from manifest)
|
|
57
|
+
'content.js',
|
|
58
|
+
'content.css',
|
|
59
|
+
'pako.min.js',
|
|
60
|
+
'web-vitals.iife.js',
|
|
61
|
+
'pii-redactor.js',
|
|
62
|
+
'data-buffer.js',
|
|
63
|
+
'performance-monitor.js',
|
|
64
|
+
'dom-tracker.js',
|
|
65
|
+
'network-tracker.js',
|
|
66
|
+
|
|
67
|
+
// Popup
|
|
68
|
+
'popup.html',
|
|
69
|
+
'popup.js',
|
|
70
|
+
|
|
71
|
+
// Options page
|
|
72
|
+
'options.html',
|
|
73
|
+
'options.js',
|
|
74
|
+
|
|
75
|
+
// Activation manager
|
|
76
|
+
'activation-manager.html',
|
|
77
|
+
'activation-manager.js',
|
|
78
|
+
|
|
79
|
+
// Offscreen
|
|
80
|
+
'offscreen.html',
|
|
81
|
+
'offscreen.js',
|
|
82
|
+
|
|
83
|
+
// Frame capture
|
|
84
|
+
'frame-capture.js',
|
|
85
|
+
|
|
86
|
+
// Icons
|
|
87
|
+
'icon16.png',
|
|
88
|
+
'icon48.png',
|
|
89
|
+
'icon128.png',
|
|
90
|
+
|
|
91
|
+
// Documentation
|
|
92
|
+
'README.md'
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
// Add each file to the archive
|
|
96
|
+
filesToInclude.forEach(file => {
|
|
97
|
+
let sourcePath, targetName;
|
|
98
|
+
|
|
99
|
+
if (typeof file === 'object') {
|
|
100
|
+
// Handle object format { source: 'file.json', target: 'renamed.json' }
|
|
101
|
+
sourcePath = path.join(extensionDir, file.source);
|
|
102
|
+
targetName = file.target;
|
|
103
|
+
} else {
|
|
104
|
+
// Handle simple string format
|
|
105
|
+
sourcePath = path.join(extensionDir, file);
|
|
106
|
+
targetName = file;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (fs.existsSync(sourcePath)) {
|
|
110
|
+
archive.file(sourcePath, { name: targetName });
|
|
111
|
+
console.log(` ā ${targetName}${typeof file === 'object' ? ` (from ${file.source})` : ''}`);
|
|
112
|
+
} else {
|
|
113
|
+
console.warn(` ā Skipping missing file: ${typeof file === 'object' ? file.source : file}`);
|
|
114
|
+
}
|
|
89
115
|
});
|
|
116
|
+
|
|
117
|
+
// Finalize the archive
|
|
118
|
+
archive.finalize();
|
|
@@ -57,18 +57,30 @@ async function safeKillProcess(pid, signal = 'SIGTERM') {
|
|
|
57
57
|
/**
|
|
58
58
|
* Find ChromeDebug MCP processes using Node.js process list instead of shell commands
|
|
59
59
|
* This prevents command injection while maintaining functionality
|
|
60
|
+
*
|
|
61
|
+
* NOTE: Windows support is intentionally limited - the ps command doesn't exist on Windows.
|
|
62
|
+
* Process cleanup is skipped on Windows to allow the server to start. A proper cross-platform
|
|
63
|
+
* solution will be implemented in a future update.
|
|
60
64
|
*/
|
|
61
65
|
async function findChromePilotProcesses() {
|
|
66
|
+
// Skip process cleanup on Windows - ps command doesn't exist
|
|
67
|
+
// This allows the server to start on Windows without crashing
|
|
68
|
+
// TODO: Implement proper Windows process management using tasklist or Node.js process handles
|
|
69
|
+
if (process.platform === 'win32') {
|
|
70
|
+
console.log('[ChromeDebug] Process cleanup skipped on Windows (not yet implemented)');
|
|
71
|
+
return { pidsToKill: [], processDescriptions: [] };
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
const currentPid = process.pid;
|
|
63
75
|
const pidsToKill = [];
|
|
64
76
|
const processDescriptions = [];
|
|
65
|
-
|
|
77
|
+
|
|
66
78
|
try {
|
|
67
79
|
// Security: Use Node.js process list instead of shell commands
|
|
68
80
|
// This approach uses the 'ps-list' module or similar safe approach
|
|
69
81
|
// For now, we'll use a safer implementation with spawn instead of exec
|
|
70
82
|
const { spawn } = await import('child_process');
|
|
71
|
-
|
|
83
|
+
|
|
72
84
|
return new Promise((resolve) => {
|
|
73
85
|
const ps = spawn('ps', ['aux'], { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
74
86
|
let stdout = '';
|