browser-lens-mcp 4.0.0 → 4.0.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
CHANGED
|
@@ -380,8 +380,83 @@ IDE ← MCP Server ← WebSocket ← Send result
|
|
|
380
380
|
- `query_element` — Inspect any element by CSS selector on-demand
|
|
381
381
|
- `fullsync` — Trigger a full data re-capture
|
|
382
382
|
|
|
383
|
-
|
|
384
|
-
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Screenshots (CDP — 100% Reliable)
|
|
386
|
+
|
|
387
|
+
Screenshots use **Chrome DevTools Protocol (CDP)** via `puppeteer-core` — captures exactly what you see in the browser. No CORS issues, no CSP restrictions, works on any page.
|
|
388
|
+
|
|
389
|
+
### Setup: Launch browser with remote debugging
|
|
390
|
+
|
|
391
|
+
<details open>
|
|
392
|
+
<summary><strong>Brave Browser (Mac)</strong></summary>
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
/Applications/Brave\ Browser.app/Contents/MacOS/Brave\ Browser --remote-debugging-port=9222
|
|
396
|
+
```
|
|
397
|
+
</details>
|
|
398
|
+
|
|
399
|
+
<details>
|
|
400
|
+
<summary><strong>Google Chrome (Mac)</strong></summary>
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
|
|
404
|
+
```
|
|
405
|
+
</details>
|
|
406
|
+
|
|
407
|
+
<details>
|
|
408
|
+
<summary><strong>Google Chrome (Linux)</strong></summary>
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
google-chrome --remote-debugging-port=9222
|
|
412
|
+
```
|
|
413
|
+
</details>
|
|
414
|
+
|
|
415
|
+
<details>
|
|
416
|
+
<summary><strong>Microsoft Edge (Mac)</strong></summary>
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
/Applications/Microsoft\ Edge.app/Contents/MacOS/Microsoft\ Edge --remote-debugging-port=9222
|
|
420
|
+
```
|
|
421
|
+
</details>
|
|
422
|
+
|
|
423
|
+
<details>
|
|
424
|
+
<summary><strong>Tip: Create a shell alias</strong></summary>
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
# Add to ~/.zshrc or ~/.bashrc
|
|
428
|
+
alias brave-debug='/Applications/Brave\ Browser.app/Contents/MacOS/Brave\ Browser --remote-debugging-port=9222'
|
|
429
|
+
alias chrome-debug='/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222'
|
|
430
|
+
|
|
431
|
+
# Then just run
|
|
432
|
+
brave-debug
|
|
433
|
+
```
|
|
434
|
+
</details>
|
|
435
|
+
|
|
436
|
+
**Verify CDP is running:**
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
curl http://127.0.0.1:9222/json/version
|
|
440
|
+
# Should show: {"Browser":"Brave/...","webSocketDebuggerUrl":"ws://..."}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Screenshot tools
|
|
444
|
+
|
|
445
|
+
| Tool | What it does |
|
|
446
|
+
|------|-------------|
|
|
447
|
+
| `trigger_screenshot` | Capture full viewport — returns PNG image directly |
|
|
448
|
+
| `screenshot_element` | Capture specific element by CSS selector (e.g. `header`, `.hero-btn`) |
|
|
449
|
+
|
|
450
|
+
### Screenshot fallback chain
|
|
451
|
+
|
|
452
|
+
```
|
|
453
|
+
trigger_screenshot / screenshot_element
|
|
454
|
+
├─ 1. CDP (puppeteer-core) ← primary, 100% reliable
|
|
455
|
+
├─ 2. WS command → bookmarklet → html2canvas (simple pages)
|
|
456
|
+
└─ 3. Return cached screenshot if available
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
CDP auto-scans ports 9222, 9229, 9333. Set `MCP_BROWSER_LENS_CDP_PORT` for custom port.
|
|
385
460
|
|
|
386
461
|
---
|
|
387
462
|
|
|
@@ -391,8 +466,26 @@ Cross-origin images (CDN logos, external assets) are temporarily replaced with s
|
|
|
391
466
|
|----------|---------|-------------|
|
|
392
467
|
| `MCP_BROWSER_LENS_PORT` | `3202` | HTTP server port |
|
|
393
468
|
| `MCP_BROWSER_LENS_WS_PORT` | `3203` | WebSocket server port |
|
|
469
|
+
| `MCP_BROWSER_LENS_CDP_PORT` | `9222` | Chrome DevTools Protocol port for screenshots |
|
|
394
470
|
| `MCP_BROWSER_LENS_STORE_PATH` | `.store/browser.json` | Custom store path |
|
|
395
471
|
|
|
472
|
+
**Full config example:**
|
|
473
|
+
|
|
474
|
+
```json
|
|
475
|
+
{
|
|
476
|
+
"mcpServers": {
|
|
477
|
+
"browser-lens": {
|
|
478
|
+
"command": "npx",
|
|
479
|
+
"args": ["-y", "browser-lens-mcp@latest"],
|
|
480
|
+
"env": {
|
|
481
|
+
"MCP_BROWSER_LENS_PORT": "3300",
|
|
482
|
+
"MCP_BROWSER_LENS_WS_PORT": "3301",
|
|
483
|
+
"MCP_BROWSER_LENS_CDP_PORT": "9222"
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
396
489
|
---
|
|
397
490
|
|
|
398
491
|
## License
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdp-capture.d.ts","sourceRoot":"","sources":["../../../src/transport/cdp-capture.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cdp-capture.d.ts","sourceRoot":"","sources":["../../../src/transport/cdp-capture.ts"],"names":[],"mappings":"AAgCA,wBAAsB,oBAAoB,CACxC,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA+EpE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAEvD"}
|
|
@@ -1,53 +1,86 @@
|
|
|
1
1
|
import puppeteer from "puppeteer-core";
|
|
2
2
|
const CDP_PORT = parseInt(process.env.MCP_BROWSER_LENS_CDP_PORT ?? "9222", 10);
|
|
3
|
+
const CANDIDATE_PORTS = [CDP_PORT, 9222, 9229, 9333];
|
|
3
4
|
async function findBrowserEndpoint() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
for (const port of [...new Set(CANDIDATE_PORTS)]) {
|
|
6
|
+
try {
|
|
7
|
+
const res = await fetch(`http://127.0.0.1:${port}/json/version`, {
|
|
8
|
+
signal: AbortSignal.timeout(2000),
|
|
9
|
+
});
|
|
10
|
+
const data = (await res.json());
|
|
11
|
+
if (data.webSocketDebuggerUrl) {
|
|
12
|
+
process.stderr.write(`[mcp-browser-lens] CDP found on :${port} (${data.Browser ?? "unknown"})\n`);
|
|
13
|
+
return data.webSocketDebuggerUrl;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
11
19
|
}
|
|
20
|
+
return null;
|
|
12
21
|
}
|
|
13
22
|
export async function cdpCaptureScreenshot(selector) {
|
|
14
23
|
const endpoint = await findBrowserEndpoint();
|
|
15
|
-
if (!endpoint)
|
|
24
|
+
if (!endpoint) {
|
|
25
|
+
process.stderr.write(`[mcp-browser-lens] CDP not available. Launch browser with --remote-debugging-port=9222\n`);
|
|
16
26
|
return null;
|
|
27
|
+
}
|
|
17
28
|
let browser;
|
|
18
29
|
try {
|
|
19
|
-
browser = await puppeteer.connect({
|
|
30
|
+
browser = await puppeteer.connect({
|
|
31
|
+
browserWSEndpoint: endpoint,
|
|
32
|
+
defaultViewport: null,
|
|
33
|
+
});
|
|
20
34
|
const pages = await browser.pages();
|
|
21
|
-
if (pages.length === 0)
|
|
35
|
+
if (pages.length === 0) {
|
|
36
|
+
process.stderr.write(`[mcp-browser-lens] CDP: no pages open\n`);
|
|
22
37
|
return null;
|
|
38
|
+
}
|
|
23
39
|
const page = pages[pages.length - 1];
|
|
40
|
+
process.stderr.write(`[mcp-browser-lens] CDP: capturing ${selector ?? "viewport"} from ${page.url()}\n`);
|
|
24
41
|
if (selector) {
|
|
25
42
|
const el = await page.$(selector);
|
|
26
|
-
if (!el)
|
|
43
|
+
if (!el) {
|
|
44
|
+
process.stderr.write(`[mcp-browser-lens] CDP: element '${selector}' not found\n`);
|
|
27
45
|
return null;
|
|
28
|
-
|
|
46
|
+
}
|
|
47
|
+
const buf = (await el.screenshot({ type: "png" }));
|
|
29
48
|
const box = await el.boundingBox();
|
|
49
|
+
const b64 = Buffer.from(buf).toString("base64");
|
|
50
|
+
process.stderr.write(`[mcp-browser-lens] CDP: element screenshot ${box?.width ?? 0}x${box?.height ?? 0} (${b64.length} bytes b64)\n`);
|
|
30
51
|
return {
|
|
31
|
-
dataUrl: "data:image/png;base64," +
|
|
52
|
+
dataUrl: "data:image/png;base64," + b64,
|
|
32
53
|
width: Math.round(box?.width ?? 0),
|
|
33
54
|
height: Math.round(box?.height ?? 0),
|
|
34
55
|
};
|
|
35
56
|
}
|
|
36
|
-
const buf = await page.screenshot({
|
|
37
|
-
|
|
57
|
+
const buf = (await page.screenshot({
|
|
58
|
+
type: "png",
|
|
59
|
+
fullPage: false,
|
|
60
|
+
}));
|
|
61
|
+
const b64 = Buffer.from(buf).toString("base64");
|
|
62
|
+
const metrics = await page.evaluate(() => ({
|
|
63
|
+
width: window.innerWidth,
|
|
64
|
+
height: window.innerHeight,
|
|
65
|
+
}));
|
|
66
|
+
process.stderr.write(`[mcp-browser-lens] CDP: viewport screenshot ${metrics.width}x${metrics.height} (${b64.length} bytes b64)\n`);
|
|
38
67
|
return {
|
|
39
|
-
dataUrl: "data:image/png;base64," +
|
|
40
|
-
width:
|
|
41
|
-
height:
|
|
68
|
+
dataUrl: "data:image/png;base64," + b64,
|
|
69
|
+
width: metrics.width,
|
|
70
|
+
height: metrics.height,
|
|
42
71
|
};
|
|
43
72
|
}
|
|
44
73
|
catch (e) {
|
|
45
|
-
process.stderr.write(`[mcp-browser-lens] CDP screenshot
|
|
74
|
+
process.stderr.write(`[mcp-browser-lens] CDP screenshot error: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
46
75
|
return null;
|
|
47
76
|
}
|
|
48
77
|
finally {
|
|
49
|
-
if (browser)
|
|
50
|
-
|
|
78
|
+
if (browser) {
|
|
79
|
+
try {
|
|
80
|
+
browser.disconnect();
|
|
81
|
+
}
|
|
82
|
+
catch { /* already disconnected */ }
|
|
83
|
+
}
|
|
51
84
|
}
|
|
52
85
|
}
|
|
53
86
|
export async function isCdpAvailable() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdp-capture.js","sourceRoot":"","sources":["../../../src/transport/cdp-capture.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAEvC,MAAM,QAAQ,GAAG,QAAQ,CACvB,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,MAAM,EAC/C,EAAE,CACH,CAAC;AAEF,KAAK,UAAU,mBAAmB;IAChC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"cdp-capture.js","sourceRoot":"","sources":["../../../src/transport/cdp-capture.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-lens-mcp",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"description": "MCP server that connects to your browser for real-time DOM, CSS, layout inspection, screenshot capture, and Figma design comparison — your IDE's AI agent sees exactly what users see",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|