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
- **Screenshot CORS handling:**
384
- Cross-origin images (CDN logos, external assets) are temporarily replaced with same-size grey placeholders before capture, then restored. This ensures screenshots always succeed while preserving layout accuracy.
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":"AAiBA,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,CAwCpE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAEvD"}
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
- try {
5
- const res = await fetch(`http://127.0.0.1:${CDP_PORT}/json/version`);
6
- const data = (await res.json());
7
- return data.webSocketDebuggerUrl ?? null;
8
- }
9
- catch {
10
- return null;
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({ browserWSEndpoint: endpoint });
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
- const buf = await el.screenshot({ type: "png" });
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," + Buffer.from(buf).toString("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({ type: "png", fullPage: false });
37
- const viewport = page.viewport();
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," + Buffer.from(buf).toString("base64"),
40
- width: viewport?.width ?? 1440,
41
- height: viewport?.height ?? 900,
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 failed: ${e instanceof Error ? e.message : String(e)}\n`);
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
- browser.disconnect();
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":"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"}
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.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",