firefox-devtools-mcp 0.6.0 → 0.6.1

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/dist/index.js CHANGED
@@ -23301,12 +23301,12 @@ ${attemptedPaths.map((p) => ` - ${p}`).join("\n")}`
23301
23301
  * Take a snapshot of the current page
23302
23302
  * Returns text and JSON with snapshotId, no DOM mutations
23303
23303
  */
23304
- async takeSnapshot() {
23304
+ async takeSnapshot(options) {
23305
23305
  const snapshotId = ++this.currentSnapshotId;
23306
23306
  this.resolver.setSnapshotId(snapshotId);
23307
23307
  this.resolver.clear();
23308
23308
  logDebug(`Taking snapshot (ID: ${snapshotId})...`);
23309
- const result = await this.executeInjectedScript(snapshotId);
23309
+ const result = await this.executeInjectedScript(snapshotId, options);
23310
23310
  logDebug(
23311
23311
  `Snapshot executeScript result: hasResult=${!!result}, hasTree=${!!result?.tree}, truncated=${result?.truncated || false}`
23312
23312
  );
@@ -23319,6 +23319,10 @@ ${attemptedPaths.map((p) => ` - ${p}`).join("\n")}`
23319
23319
  logDebug(` ... and ${result.debugLog.length - 20} more`);
23320
23320
  }
23321
23321
  }
23322
+ if (result?.selectorError) {
23323
+ logDebug(`Snapshot generation failed: ${result.selectorError}`);
23324
+ throw new Error(result.selectorError);
23325
+ }
23322
23326
  if (!result?.tree) {
23323
23327
  const errorMsg = "Unknown error";
23324
23328
  logDebug(`Snapshot generation failed: ${errorMsg}`);
@@ -23362,7 +23366,7 @@ ${attemptedPaths.map((p) => ` - ${p}`).join("\n")}`
23362
23366
  /**
23363
23367
  * Execute bundled injected snapshot script
23364
23368
  */
23365
- async executeInjectedScript(snapshotId) {
23369
+ async executeInjectedScript(snapshotId, options) {
23366
23370
  const scriptSource = this.getInjectedScript();
23367
23371
  const result = await this.driver.executeScript(
23368
23372
  `
@@ -23374,10 +23378,11 @@ ${attemptedPaths.map((p) => ` - ${p}`).join("\n")}`
23374
23378
  window.__createSnapshot = __SnapshotInjected.createSnapshot;
23375
23379
  }
23376
23380
  }
23377
- // Call it
23378
- return window.__createSnapshot(arguments[0]);
23381
+ // Call it with options
23382
+ return window.__createSnapshot(arguments[0], arguments[1]);
23379
23383
  `,
23380
- snapshotId
23384
+ snapshotId,
23385
+ options || {}
23381
23386
  );
23382
23387
  return result;
23383
23388
  }
@@ -23649,11 +23654,11 @@ var init_firefox = __esm({
23649
23654
  // ============================================================================
23650
23655
  // Snapshot
23651
23656
  // ============================================================================
23652
- async takeSnapshot() {
23657
+ async takeSnapshot(options) {
23653
23658
  if (!this.snapshot) {
23654
23659
  throw new Error("Not connected");
23655
23660
  }
23656
- return await this.snapshot.takeSnapshot();
23661
+ return await this.snapshot.takeSnapshot(options);
23657
23662
  }
23658
23663
  resolveUidToSelector(uid) {
23659
23664
  if (!this.snapshot) {
@@ -24506,13 +24511,24 @@ async function handleTakeSnapshot(args2) {
24506
24511
  maxLines: requestedMaxLines = DEFAULT_SNAPSHOT_LINES,
24507
24512
  includeAttributes = false,
24508
24513
  includeText = true,
24509
- maxDepth
24514
+ maxDepth,
24515
+ includeAll = false,
24516
+ selector
24510
24517
  } = args2 || {};
24511
24518
  const maxLines = Math.min(Math.max(1, requestedMaxLines), TOKEN_LIMITS.MAX_SNAPSHOT_LINES_CAP);
24512
24519
  const wasCapped = requestedMaxLines > TOKEN_LIMITS.MAX_SNAPSHOT_LINES_CAP;
24513
24520
  const { getFirefox: getFirefox2 } = await init_index().then(() => index_exports);
24514
24521
  const firefox3 = await getFirefox2();
24515
- const snapshot = await firefox3.takeSnapshot();
24522
+ const snapshotOptions = {};
24523
+ if (includeAll) {
24524
+ snapshotOptions.includeAll = includeAll;
24525
+ }
24526
+ if (selector) {
24527
+ snapshotOptions.selector = selector;
24528
+ }
24529
+ const snapshot = await firefox3.takeSnapshot(
24530
+ Object.keys(snapshotOptions).length > 0 ? snapshotOptions : void 0
24531
+ );
24516
24532
  const { formatSnapshotTree: formatSnapshotTree2 } = await Promise.resolve().then(() => (init_formatter(), formatter_exports));
24517
24533
  const options = {
24518
24534
  includeAttributes,
@@ -24526,6 +24542,12 @@ async function handleTakeSnapshot(args2) {
24526
24542
  const truncated = lines.length > maxLines;
24527
24543
  const displayLines = truncated ? lines.slice(0, maxLines) : lines;
24528
24544
  let output = `\u{1F4F8} Snapshot (id=${snapshot.json.snapshotId})`;
24545
+ if (selector) {
24546
+ output += ` [selector: ${selector}]`;
24547
+ }
24548
+ if (includeAll) {
24549
+ output += " [includeAll: true]";
24550
+ }
24529
24551
  if (wasCapped) {
24530
24552
  output += ` [maxLines capped: ${TOKEN_LIMITS.MAX_SNAPSHOT_LINES_CAP}]`;
24531
24553
  }
@@ -24606,6 +24628,14 @@ var init_snapshot2 = __esm({
24606
24628
  maxDepth: {
24607
24629
  type: "number",
24608
24630
  description: "Max tree depth"
24631
+ },
24632
+ includeAll: {
24633
+ type: "boolean",
24634
+ description: "Include all visible elements without relevance filtering. Useful for Vue/Livewire apps (default: false)"
24635
+ },
24636
+ selector: {
24637
+ type: "string",
24638
+ description: 'CSS selector to scope snapshot to specific element (e.g., "#app")'
24609
24639
  }
24610
24640
  }
24611
24641
  }
@@ -1 +1 @@
1
- "use strict";var __SnapshotInjected=(()=>{var h=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var q=(t,r)=>{for(var e in r)h(t,e,{get:r[e],enumerable:!0})},z=(t,r,e,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of V(r))!U.call(t,o)&&o!==e&&h(t,o,{get:()=>r[o],enumerable:!(i=W(r,o))||i.enumerable});return t};var B=t=>z(h({},"__esModule",{value:!0}),t);var rt={};q(rt,{createSnapshot:()=>P});var v=["a","button","input","select","textarea","img","video","audio","iframe"],J=["nav","main","section","article","header","footer","form"],K=["div","span","p","li","ul","ol"];function L(t){if(!t||t.nodeType!==Node.ELEMENT_NODE)return!1;try{let e=window.getComputedStyle(t);if(e.display==="none"||e.visibility==="hidden"||e.opacity==="0")return!1}catch{return!1}let r=t.tagName.toLowerCase();if(v.indexOf(r)!==-1||t.hasAttribute("role")||t.hasAttribute("aria-label")||/^h[1-6]$/.test(r)||J.indexOf(r)!==-1)return!0;if(K.indexOf(r)!==-1){let e=(t.textContent||"").trim();if(e.length>0&&e.length<500||t.id||t.className)return!0}return!1}function M(t){if(t.tabIndex>=0)return!0;let e=t.tagName.toLowerCase();return["a","button","input","select","textarea"].indexOf(e)!==-1}function O(t){let r=t.tagName.toLowerCase();if(v.indexOf(r)!==-1)return!0;let e=t.getAttribute("role");return!!(e&&["button","link","menuitem","tab"].indexOf(e)!==-1||t.hasAttribute("onclick"))}var Q=100;function k(t){if(t.hasAttribute("aria-label"))return t.getAttribute("aria-label")||void 0;let e=t.id;if(e){let o=document.querySelector(`label[for="${e}"]`);if(o?.textContent)return o.textContent.trim()}if(t.hasAttribute("placeholder"))return t.getAttribute("placeholder")||void 0;if(t.hasAttribute("title"))return t.getAttribute("title")||void 0;if(t.hasAttribute("alt"))return t.getAttribute("alt")||void 0;let i=t.tagName.toLowerCase();if(["button","a","h1","h2","h3","h4","h5","h6"].indexOf(i)!==-1)return g(t)}function g(t){let r="";for(let i=0;i<t.childNodes.length;i++){let o=t.childNodes[i];o&&o.nodeType===Node.TEXT_NODE&&(r+=o.textContent||"")}let e=r.trim();if(e)return e.substring(0,Q)}function $(t){let r={},e=!1,i=["disabled","hidden","selected","expanded"];for(let a of i){let n=t.getAttribute(`aria-${a}`);n!==null&&(r[a]=n==="true",e=!0)}let o=["checked","pressed"];for(let a of o){let n=t.getAttribute(`aria-${a}`);n!==null&&(n==="mixed"?r[a]="mixed":r[a]=n==="true",e=!0)}let l=["autocomplete","haspopup","invalid","label","labelledby","describedby","controls"];for(let a of l){let n=t.getAttribute(`aria-${a}`);n&&(r[a]=n,e=!0)}let s=t.getAttribute("aria-level");if(s){let a=parseInt(s,10);isNaN(a)||(r.level=a,e=!0)}return e?r:void 0}function I(t){let r={};try{let e=window.getComputedStyle(t);r.visible=e.display!=="none"&&e.visibility!=="hidden"&&e.opacity!=="0"}catch{r.visible=!1}return r.accessible=r.visible&&!t.getAttribute("aria-hidden"),r.focusable=M(t),r.interactive=O(t),r}var Y=["id","data-testid","data-test-id"];function R(t){let r=[],e=t;for(;e&&e.nodeType===Node.ELEMENT_NODE;){let i=e.nodeName.toLowerCase(),o=!1;for(let n of Y){let u=e.getAttribute(n);if(u){n==="id"?i+="#"+CSS.escape(u):i+=`[${n}="${X(u)}"]`,r.unshift(i),o=!0;break}}if(o)break;let l=e.getAttribute("aria-label"),s=e.getAttribute("role");if(l&&s){i+=`[role="${s}"][aria-label="${X(l)}"]`,r.unshift(i),e=e.parentElement;continue}let a=e.parentElement?.children;if(a&&a.length>1){let n=1;for(let u=0;u<a.length;u++){let d=a[u];if(d){if(d===e)break;d.nodeName===e.nodeName&&n++}}(n>1||a.length>1&&a[0]!==e)&&(i+=`:nth-of-type(${n})`)}if(r.unshift(tt(i)),e=e.parentElement,e&&e.nodeName.toLowerCase()==="body"){r.unshift("body");break}}return r.join(" > ")}function G(t){let r=t.id;if(r)return`//*[@id="${Z(r)}"]`;let e=[],i=t;for(;i&&i.nodeType===Node.ELEMENT_NODE;){let o=i.nodeName.toLowerCase(),l=1,s=i.previousElementSibling;for(;s;)s.nodeName.toLowerCase()===o&&l++,s=s.previousElementSibling;let a=i.parentElement,n=!1;a&&(n=Array.from(a.children).filter(E=>E.nodeName.toLowerCase()===o).length>1);let u=n?`${o}[${l}]`:o;if(e.unshift(u),i=i.parentElement,i&&i.nodeName.toLowerCase()==="html"){e.unshift("html");break}}return"/"+e.join("/")}function X(t){return t.replace(/"/g,'\\"').substring(0,64)}function Z(t){return t.indexOf('"')===-1||t.indexOf("'")===-1?t:`concat(${t.split('"').map((e,i,o)=>i===o.length-1?e?`"${e}"`:"":e?`"${e}",'"'`:`"'"`).filter(e=>e).join(",")})`}function tt(t){return t.length<=64?t:t.substring(0,64)}var et=10,H=1e3;function D(t,r,e=!0){let i=0,o=[],l=!1;function s(n,u){if(u>et||i>=H)return l=!0,null;let d=n.tagName.toLowerCase();if(!(d==="body"||d==="html")&&!L(n))return null;let A=`${r}_${i++}`,j=R(n),F=G(n);o.push({uid:A,css:j,xpath:F});let b=n,N=n.getAttribute("role"),T=k(n),y=g(n),x=b.value,C=b.href,S=b.src,w=$(n),_=I(n),c={uid:A,tag:d,...N&&{role:N},...T&&{name:T},...x&&{value:x},...C&&{href:C},...S&&{src:S},...y&&{text:y},...w&&{aria:w},..._&&{computed:_},children:[]};if(d==="iframe"&&e){try{let f=n,p=f.contentDocument||f.contentWindow?.document;if(p?.body){let m=s(p.body,u+1);m&&(m.isIframe=!0,m.frameSrc=f.src,c.children.push(m))}else c.isIframe=!0,c.frameSrc=f.src,c.crossOrigin=!0}catch{c.isIframe=!0,c.frameSrc=n.src,c.crossOrigin=!0}return c}for(let f=0;f<n.children.length;f++){if(i>=H){l=!0;break}let p=n.children[f];if(!p)continue;let m=s(p,u+1);m&&c.children.push(m)}return c}return{tree:s(t,0),uidMap:o,truncated:l}}function P(t){try{let r=D(document.body,t,!0);if(!r.tree)throw new Error("Failed to generate tree");return r}catch{return{tree:null,uidMap:[],truncated:!1}}}typeof window<"u"&&(window.__createSnapshot=P);return B(rt);})();
1
+ "use strict";var __SnapshotInjected=(()=>{var N=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var Q=(e,n)=>{for(var t in n)N(e,t,{get:n[t],enumerable:!0})},Y=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of J(n))!K.call(e,i)&&i!==t&&N(e,i,{get:()=>n[i],enumerable:!(r=B(n,i))||r.enumerable});return e};var Z=e=>Y(N({},"__esModule",{value:!0}),e);var ue={};Q(ue,{createSnapshot:()=>U});var T=["a","button","input","select","textarea","img","video","audio","iframe"],ee=["nav","main","section","article","header","footer","form"],te=["div","span","p","li","ul","ol"];function y(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return!1;let n=e;for(;n&&n!==document.documentElement;){try{let t=window.getComputedStyle(n),r=parseFloat(t.opacity);if(t.display==="none"||t.visibility==="hidden"||r===0||isNaN(r))return!1}catch{return!1}n=n.parentElement}return!0}function ne(e){let n="";for(let t=0;t<e.childNodes.length;t++){let r=e.childNodes[t];r&&r.nodeType===Node.TEXT_NODE&&(n+=r.textContent||"")}return n.trim()}function re(e){for(let n=0;n<e.children.length;n++){let t=e.children[n];if(t){let r=t.tagName.toLowerCase();if(T.indexOf(r)!==-1||t.hasAttribute("role"))return!0}}return!1}function R(e){if(!e||e.nodeType!==Node.ELEMENT_NODE||!y(e))return!1;let n=e.tagName.toLowerCase();if(T.indexOf(n)!==-1||e.hasAttribute("role")||e.hasAttribute("aria-label")||/^h[1-6]$/.test(n)||ee.indexOf(n)!==-1)return!0;if(te.indexOf(n)!==-1){let t=ne(e);if(t.length>0&&t.length<500||e.id||e.className||re(e))return!0}return!1}function $(e){if(e.tabIndex>=0)return!0;let t=e.tagName.toLowerCase();return["a","button","input","select","textarea"].indexOf(t)!==-1}function D(e){let n=e.tagName.toLowerCase();if(T.indexOf(n)!==-1)return!0;let t=e.getAttribute("role");return!!(t&&["button","link","menuitem","tab"].indexOf(t)!==-1||e.hasAttribute("onclick"))}var ie=100;function X(e){if(e.hasAttribute("aria-label"))return e.getAttribute("aria-label")||void 0;let t=e.id;if(t){let i=document.querySelector(`label[for="${t}"]`);if(i?.textContent)return i.textContent.trim()}if(e.hasAttribute("placeholder"))return e.getAttribute("placeholder")||void 0;if(e.hasAttribute("title"))return e.getAttribute("title")||void 0;if(e.hasAttribute("alt"))return e.getAttribute("alt")||void 0;let r=e.tagName.toLowerCase();if(["button","a","h1","h2","h3","h4","h5","h6"].indexOf(r)!==-1)return x(e)}function x(e){let n="";for(let r=0;r<e.childNodes.length;r++){let i=e.childNodes[r];i&&i.nodeType===Node.TEXT_NODE&&(n+=i.textContent||"")}let t=n.trim();if(t)return t.substring(0,ie)}function W(e){let n={},t=!1,r=["disabled","hidden","selected","expanded"];for(let o of r){let a=e.getAttribute(`aria-${o}`);a!==null&&(n[o]=a==="true",t=!0)}let i=["checked","pressed"];for(let o of i){let a=e.getAttribute(`aria-${o}`);a!==null&&(a==="mixed"?n[o]="mixed":n[o]=a==="true",t=!0)}let l=["autocomplete","haspopup","invalid","label","labelledby","describedby","controls"];for(let o of l){let a=e.getAttribute(`aria-${o}`);a&&(n[o]=a,t=!0)}let u=e.getAttribute("aria-level");if(u){let o=parseInt(u,10);isNaN(o)||(n.level=o,t=!0)}return t?n:void 0}function G(e){let n={};try{let t=window.getComputedStyle(e),r=parseFloat(t.opacity);n.visible=t.display!=="none"&&t.visibility!=="hidden"&&r!==0&&!isNaN(r)}catch{n.visible=!1}return n.accessible=n.visible&&!e.getAttribute("aria-hidden"),n.focusable=$(e),n.interactive=D(e),n}var oe=["id","data-testid","data-test-id"];function P(e){let n=[],t=e;for(;t&&t.nodeType===Node.ELEMENT_NODE;){let r=t.nodeName.toLowerCase(),i=!1;for(let a of oe){let d=t.getAttribute(a);if(d){a==="id"?r+="#"+CSS.escape(d):r+=`[${a}="${H(d)}"]`,n.unshift(r),i=!0;break}}if(i)break;let l=t.getAttribute("aria-label"),u=t.getAttribute("role");if(l&&u){r+=`[role="${u}"][aria-label="${H(l)}"]`,n.unshift(r),t=t.parentElement;continue}let o=t.parentElement?.children;if(o&&o.length>1){let a=1;for(let d=0;d<o.length;d++){let s=o[d];if(s){if(s===t)break;s.nodeName===t.nodeName&&a++}}(a>1||o.length>1&&o[0]!==t)&&(r+=`:nth-of-type(${a})`)}if(n.unshift(se(r)),t=t.parentElement,t&&t.nodeName.toLowerCase()==="body"){n.unshift("body");break}}return n.join(" > ")}function F(e){let n=e.id;if(n)return`//*[@id="${ae(n)}"]`;let t=[],r=e;for(;r&&r.nodeType===Node.ELEMENT_NODE;){let i=r.nodeName.toLowerCase(),l=1,u=r.previousElementSibling;for(;u;)u.nodeName.toLowerCase()===i&&l++,u=u.previousElementSibling;let o=r.parentElement,a=!1;o&&(a=Array.from(o.children).filter(h=>h.nodeName.toLowerCase()===i).length>1);let d=a?`${i}[${l}]`:i;if(t.unshift(d),r=r.parentElement,r&&r.nodeName.toLowerCase()==="html"){t.unshift("html");break}}return"/"+t.join("/")}function H(e){return e.replace(/"/g,'\\"').substring(0,64)}function ae(e){return e.indexOf('"')===-1||e.indexOf("'")===-1?e:`concat(${e.split('"').map((t,r,i)=>r===i.length-1?t?`"${t}"`:"":t?`"${t}",'"'`:`"'"`).filter(t=>t).join(",")})`}function se(e){return e.length<=64?e:e.substring(0,64)}var le=10,j=1e3;function V(e,n,t={}){let{includeAll:r=!1,includeIframes:i=!0}=t,l=0,u=[],o=!1;function a(s,h){if(h>le)return o=!0,{node:null,relevantChildren:[]};if(l>=j)return o=!0,{node:null,relevantChildren:[]};let b=s.tagName.toLowerCase(),C=b==="body"||b==="html",g;r?g=C||y(s):g=C||R(s);let E=[];if(b==="iframe"&&i&&g)try{let c=s,p=c.contentDocument||c.contentWindow?.document;if(p?.body){let f=a(p.body,h+1);f.node&&(f.node.isIframe=!0,f.node.frameSrc=c.src,E.push(f.node))}}catch{}else for(let c=0;c<s.children.length;c++){if(l>=j){o=!0;break}let p=s.children[c];if(!p)continue;let f=a(p,h+1);f.node?E.push(f.node):f.relevantChildren.length>0&&E.push(...f.relevantChildren)}if(!g)return{node:null,relevantChildren:E};let S=`${n}_${l++}`,q=P(s),z=F(s);u.push({uid:S,css:q,xpath:z});let A=s,v=s.getAttribute("role"),O=X(s),_=x(s),w=A.value,M=A.href,L=A.src,I=W(s),k=G(s),m={uid:S,tag:b,...v&&{role:v},...O&&{name:O},...w&&{value:w},...M&&{href:M},...L&&{src:L},..._&&{text:_},...I&&{aria:I},...k&&{computed:k},children:E};if(b==="iframe"&&i)try{let c=s;(c.contentDocument||c.contentWindow?.document)?.body||(m.isIframe=!0,m.frameSrc=c.src,m.crossOrigin=!0)}catch{m.isIframe=!0,m.frameSrc=s.src,m.crossOrigin=!0}return{node:m,relevantChildren:[]}}return{tree:a(e,0).node,uidMap:u,truncated:o}}function U(e,n){try{let t=document.body;if(n?.selector)try{let l=document.querySelector(n.selector);if(!l)return{tree:null,uidMap:[],truncated:!1,selectorError:`Selector "${n.selector}" not found`};t=l}catch{return{tree:null,uidMap:[],truncated:!1,selectorError:`Invalid selector syntax: "${n.selector}"`}}let r={includeIframes:n?.includeIframes??!0};n?.includeAll!==void 0&&(r.includeAll=n.includeAll);let i=V(t,e,r);if(!i.tree)throw new Error("Failed to generate tree");return i}catch{return{tree:null,uidMap:[],truncated:!1}}}typeof window<"u"&&(window.__createSnapshot=U);return Z(ue);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firefox-devtools-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Model Context Protocol (MCP) server for Firefox DevTools automation",
5
5
  "author": "freema",
6
6
  "license": "MIT",