browser-lens-mcp 2.1.0 → 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.
package/README.md
CHANGED
|
@@ -290,34 +290,58 @@ Works with **any design tool** — Figma, Sketch, Adobe XD, Zeplin. Just provide
|
|
|
290
290
|
|
|
291
291
|
---
|
|
292
292
|
|
|
293
|
-
## MCP Prompts (5)
|
|
293
|
+
## MCP Prompts (5) — `/` Commands in IDE
|
|
294
294
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
|
298
|
-
|
|
299
|
-
| `
|
|
300
|
-
| `
|
|
301
|
-
| `
|
|
295
|
+
Type `/` in your IDE chat to see these guided workflows:
|
|
296
|
+
|
|
297
|
+
| Prompt | When to Use | What It Does |
|
|
298
|
+
|--------|-------------|-------------|
|
|
299
|
+
| `/compare_with_figma` | After implementing a UI from Figma | Walks through comparing each element, generates CSS fixes |
|
|
300
|
+
| `/audit_ui` | Before PR review or release | Audits colors, typography, spacing, accessibility — rates 1-10 |
|
|
301
|
+
| `/describe_page` | When you need to explain the current UI to AI | Generates detailed page description with structure, styles, elements |
|
|
302
|
+
| `/suggest_fixes` | After running comparisons | Collects all failing comparisons + a11y issues → prioritized fix list |
|
|
303
|
+
| `/visual_qa` | Final check before shipping | Takes screenshot, compares elements, outputs PASS/NEEDS_WORK/FAIL |
|
|
304
|
+
|
|
305
|
+
**Example usage in Antigravity/Cursor:**
|
|
306
|
+
```
|
|
307
|
+
/compare_with_figma
|
|
308
|
+
→ AI reads current page data, asks for Figma specs, runs comparisons, suggests fixes
|
|
309
|
+
|
|
310
|
+
/audit_ui
|
|
311
|
+
→ AI analyzes colors (too many?), typography (consistent?), spacing (scale?), a11y (issues?)
|
|
312
|
+
```
|
|
302
313
|
|
|
303
314
|
---
|
|
304
315
|
|
|
305
|
-
## MCP Resources (12)
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
|
310
|
-
|
|
311
|
-
| `dom://
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
| `css://
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
316
|
+
## MCP Resources (12) — `@` References in IDE
|
|
317
|
+
|
|
318
|
+
Type `@mcp:browser-lens/` in your IDE to access these data sources directly:
|
|
319
|
+
|
|
320
|
+
| Resource | Shorthand | When to Use | Example |
|
|
321
|
+
|----------|-----------|-------------|---------|
|
|
322
|
+
| `dom://snapshot` | `@browser-lens/dom-snapshot` | Get the full DOM tree structure | "Show me the page structure" |
|
|
323
|
+
| `dom://elements` | `@browser-lens/dom-elements` | List all captured element selectors | "What elements are captured?" |
|
|
324
|
+
| `dom://mutations` | `@browser-lens/mutations-log` | Check recent DOM changes | "What changed since last sync?" |
|
|
325
|
+
| `css://variables` | `@browser-lens/css-variables` | Get all CSS custom properties | "What design tokens exist?" |
|
|
326
|
+
| `css://typography` | `@browser-lens/css-typography` | Get font usage analysis | "What fonts are used?" |
|
|
327
|
+
| `css://colors` | `@browser-lens/css-colors` | Get color palette | "What colors are on this page?" |
|
|
328
|
+
| `layout://responsive` | `@browser-lens/layout-responsive` | Get viewport & breakpoints | "What breakpoint is active?" |
|
|
329
|
+
| `layout://spacing` | `@browser-lens/layout-spacing` | Get spacing analysis | "Is spacing consistent?" |
|
|
330
|
+
| `visual://screenshots` | `@browser-lens/visual-screenshots` | List captured screenshots | "How many screenshots exist?" |
|
|
331
|
+
| `a11y://audit` | `@browser-lens/accessibility-info` | Get accessibility audit | "Any a11y issues?" |
|
|
332
|
+
| `figma://comparisons` | `@browser-lens/comparison-results` | Get comparison results | "How did the last comparison go?" |
|
|
333
|
+
| `browser://page` | `@browser-lens/page-info` | Get page info summary | "Is browser connected?" |
|
|
334
|
+
|
|
335
|
+
**Example usage:**
|
|
336
|
+
```
|
|
337
|
+
@browser-lens/css-colors Tell me the primary colors used on this page
|
|
338
|
+
@browser-lens/dom-snapshot Show me the semantic structure
|
|
339
|
+
@browser-lens/accessibility-info Are there any accessibility issues?
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Resources vs Tools:**
|
|
343
|
+
- **Resources** (`@`) = Read-only data snapshots. Fast, no browser command needed. Use for quick lookups.
|
|
344
|
+
- **Tools** = Actions that can query the browser live, take screenshots, compare with Figma. Use for interactive work.
|
|
321
345
|
|
|
322
346
|
---
|
|
323
347
|
|
|
@@ -334,11 +358,13 @@ IDE ← MCP Server ← WebSocket ← Send result
|
|
|
334
358
|
```
|
|
335
359
|
|
|
336
360
|
**Commands the server can send to the browser:**
|
|
337
|
-
- `screenshot` — Capture
|
|
361
|
+
- `screenshot` — Capture viewport screenshot (cross-origin images auto-replaced with placeholders)
|
|
362
|
+
- `element_screenshot` — Capture a specific element by CSS selector
|
|
338
363
|
- `query_element` — Inspect any element by CSS selector on-demand
|
|
339
364
|
- `fullsync` — Trigger a full data re-capture
|
|
340
365
|
|
|
341
|
-
|
|
366
|
+
**Screenshot CORS handling:**
|
|
367
|
+
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.
|
|
342
368
|
|
|
343
369
|
---
|
|
344
370
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector-script.d.ts","sourceRoot":"","sources":["../../../src/transport/connector-script.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"connector-script.d.ts","sourceRoot":"","sources":["../../../src/transport/connector-script.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAqa3E"}
|
|
@@ -221,47 +221,62 @@ function captureSpacing(){
|
|
|
221
221
|
return{timestamp:Date.now(),elements:entries,inconsistencies:[],spacingScale:Object.keys(Object.assign({},vals.margin,vals.padding)).sort(function(a,b){return parseFloat(a)-parseFloat(b)})};
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
var _ssLastOk=0,_ssFailing=false,_ssAttempts=0;
|
|
225
224
|
function _safeExport(canvas){
|
|
226
225
|
try{return canvas.toDataURL('image/png');}
|
|
227
226
|
catch(e){return null;}
|
|
228
227
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
|
|
229
|
+
function _neutralizeCrossOrigin(root){
|
|
230
|
+
var originals=[];
|
|
231
|
+
root.querySelectorAll('img').forEach(function(img){
|
|
232
|
+
var src=img.src||'';
|
|
233
|
+
if(src&&!src.startsWith(location.origin)&&!src.startsWith('data:')&&!src.startsWith('blob:')){
|
|
234
|
+
var w=img.naturalWidth||img.offsetWidth||100;
|
|
235
|
+
var h=img.naturalHeight||img.offsetHeight||100;
|
|
236
|
+
originals.push({el:img,src:img.src,srcset:img.srcset||''});
|
|
237
|
+
img.srcset='';
|
|
238
|
+
img.src='data:image/svg+xml,'+encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="'+w+'" height="'+h+'"><rect width="100%" height="100%" fill="%2327272a"/><text x="50%" y="50%" fill="%2371717a" font-size="12" text-anchor="middle" dominant-baseline="middle">img</text></svg>');
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
root.querySelectorAll('iframe,video').forEach(function(el){
|
|
242
|
+
originals.push({el:el,vis:el.style.visibility});
|
|
243
|
+
el.style.visibility='hidden';
|
|
244
|
+
});
|
|
245
|
+
return originals;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function _restoreCrossOrigin(originals){
|
|
249
|
+
originals.forEach(function(o){
|
|
250
|
+
if(o.src!==undefined){o.el.src=o.src;if(o.srcset)o.el.srcset=o.srcset;}
|
|
251
|
+
if(o.vis!==undefined)o.el.style.visibility=o.vis;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function _renderScreenshot(target,type,selector){
|
|
256
|
+
var saved=_neutralizeCrossOrigin(target);
|
|
257
|
+
var w=target===document.body?Math.min(window.innerWidth,1440):undefined;
|
|
258
|
+
var h=target===document.body?Math.min(window.innerHeight,900):undefined;
|
|
259
|
+
var opts={scale:1,logging:false,removeContainer:true,imageTimeout:3000,useCORS:false,allowTaint:false,foreignObjectRendering:false};
|
|
260
|
+
if(w)opts.width=w;
|
|
261
|
+
if(h)opts.height=h;
|
|
262
|
+
return html2canvas(target,opts).then(function(canvas){
|
|
263
|
+
_restoreCrossOrigin(saved);
|
|
232
264
|
var dataUrl=_safeExport(canvas);
|
|
233
|
-
if(!dataUrl)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
265
|
+
if(!dataUrl){_restoreCrossOrigin(saved);return null;}
|
|
266
|
+
var result={timestamp:Date.now(),type:type||'viewport',width:canvas.width,height:canvas.height,dataUrl:dataUrl,format:'png'};
|
|
267
|
+
if(selector)result.selector=selector;
|
|
268
|
+
log('Screenshot OK: '+(selector||'viewport')+' '+canvas.width+'x'+canvas.height);
|
|
269
|
+
return result;
|
|
270
|
+
}).catch(function(e){
|
|
271
|
+
_restoreCrossOrigin(saved);
|
|
272
|
+
err('html2canvas render failed',e);
|
|
273
|
+
return null;
|
|
237
274
|
});
|
|
238
275
|
}
|
|
276
|
+
|
|
239
277
|
function captureScreenshot(){
|
|
240
|
-
if(_ssFailing&&_ssAttempts>2&&Date.now()-_ssLastOk<300000)return Promise.resolve(null);
|
|
241
|
-
_ssAttempts++;
|
|
242
278
|
return new Promise(function(resolve){
|
|
243
|
-
function
|
|
244
|
-
log('Attempt 3: minimal capture without images/videos/iframes...');
|
|
245
|
-
_doCapture({useCORS:false,allowTaint:false,foreignObjectRendering:false,ignoreElements:function(el){
|
|
246
|
-
var t=el.tagName;return t==='IMG'||t==='VIDEO'||t==='IFRAME'||t==='CANVAS'||t==='SVG';
|
|
247
|
-
}}).then(resolve).catch(function(e){
|
|
248
|
-
_ssFailing=true;
|
|
249
|
-
log('All screenshot attempts failed. Will retry in 5min.');
|
|
250
|
-
resolve(null);
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
function attempt2(){
|
|
254
|
-
log('Attempt 2: without cross-origin images...');
|
|
255
|
-
_doCapture({useCORS:false,allowTaint:false,foreignObjectRendering:false,ignoreElements:function(el){
|
|
256
|
-
if(el.tagName==='IMG'){var s=el.src||'';if(s&&!s.startsWith(location.origin)&&!s.startsWith('data:'))return true;}
|
|
257
|
-
if(el.tagName==='IFRAME'||el.tagName==='VIDEO')return true;
|
|
258
|
-
return false;
|
|
259
|
-
}}).then(resolve).catch(attempt3);
|
|
260
|
-
}
|
|
261
|
-
function attempt1(){
|
|
262
|
-
_doCapture({useCORS:true,allowTaint:false,foreignObjectRendering:false}).then(resolve).catch(attempt2);
|
|
263
|
-
}
|
|
264
|
-
function run(){try{attempt1();}catch(e){resolve(null);}}
|
|
279
|
+
function run(){_renderScreenshot(document.body,'viewport').then(resolve);}
|
|
265
280
|
try{
|
|
266
281
|
if(typeof html2canvas==='function'){run();}
|
|
267
282
|
else{
|
|
@@ -336,33 +351,12 @@ function captureElementScreenshot(selector){
|
|
|
336
351
|
return new Promise(function(resolve){
|
|
337
352
|
var el=document.querySelector(selector);
|
|
338
353
|
if(!el){resolve(null);return;}
|
|
339
|
-
function
|
|
340
|
-
|
|
341
|
-
var opts={scale:1,logging:false,removeContainer:true,imageTimeout:5000,
|
|
342
|
-
x:rect.left+window.scrollX,y:rect.top+window.scrollY,
|
|
343
|
-
width:Math.ceil(rect.width),height:Math.ceil(rect.height),
|
|
344
|
-
windowWidth:document.documentElement.scrollWidth,
|
|
345
|
-
windowHeight:document.documentElement.scrollHeight,
|
|
346
|
-
useCORS:true,allowTaint:false,foreignObjectRendering:false};
|
|
347
|
-
html2canvas(el,{scale:1,logging:false,removeContainer:true,imageTimeout:5000,useCORS:true,allowTaint:false,foreignObjectRendering:false}).then(function(canvas){
|
|
348
|
-
var dataUrl=_safeExport(canvas);
|
|
349
|
-
if(dataUrl){
|
|
350
|
-
log('Element screenshot OK: '+selector+' '+canvas.width+'x'+canvas.height);
|
|
351
|
-
resolve({timestamp:Date.now(),type:'element',selector:selector,width:canvas.width,height:canvas.height,dataUrl:dataUrl,format:'png'});
|
|
352
|
-
}else{
|
|
353
|
-
html2canvas(el,{scale:1,logging:false,removeContainer:true,useCORS:false,allowTaint:false,foreignObjectRendering:false,ignoreElements:function(e){var t=e.tagName;return t==='IMG'||t==='VIDEO'||t==='IFRAME'||t==='CANVAS';}}).then(function(c2){
|
|
354
|
-
var d2=_safeExport(c2);
|
|
355
|
-
if(d2)resolve({timestamp:Date.now(),type:'element',selector:selector,width:c2.width,height:c2.height,dataUrl:d2,format:'png'});
|
|
356
|
-
else resolve(null);
|
|
357
|
-
}).catch(function(){resolve(null);});
|
|
358
|
-
}
|
|
359
|
-
}).catch(function(){resolve(null);});
|
|
360
|
-
}
|
|
361
|
-
if(typeof html2canvas==='function'){doCapture();}
|
|
354
|
+
function run(){_renderScreenshot(el,'element',selector).then(resolve);}
|
|
355
|
+
if(typeof html2canvas==='function'){run();}
|
|
362
356
|
else{
|
|
363
357
|
var s=document.createElement('script');
|
|
364
358
|
s.src='https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js';
|
|
365
|
-
s.onload=
|
|
359
|
+
s.onload=run;s.onerror=function(){resolve(null);};
|
|
366
360
|
document.head.appendChild(s);
|
|
367
361
|
}
|
|
368
362
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector-script.js","sourceRoot":"","sources":["../../../src/transport/connector-script.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,MAAc;IACjE,OAAO;;;+BAGsB,MAAM;mCACF,QAAQ
|
|
1
|
+
{"version":3,"file":"connector-script.js","sourceRoot":"","sources":["../../../src/transport/connector-script.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,MAAc;IACjE,OAAO;;;+BAGsB,MAAM;mCACF,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+ZtC,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-lens-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
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",
|