faux-studio 0.3.7 → 0.3.8

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.
Files changed (2) hide show
  1. package/dist/index.js +52 -24
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11007,18 +11007,36 @@ async function isCdpAlive(port) {
11007
11007
  try {
11008
11008
  const controller = new AbortController();
11009
11009
  const timeout = setTimeout(() => controller.abort(), 2e3);
11010
- const res = await fetch(`http://127.0.0.1:${port}/json/list`, {
11010
+ const res = await fetch(`http://127.0.0.1:${port}/json/version`, {
11011
11011
  signal: controller.signal
11012
11012
  });
11013
11013
  clearTimeout(timeout);
11014
11014
  if (!res.ok) return { alive: false, isFigma: false };
11015
- const targets = await res.json();
11016
- const isFigma = targets.some((t) => t.url?.startsWith("views://"));
11017
- return { alive: true, isFigma };
11015
+ return { alive: true, isFigma: isPortOwnedByFigma(port) };
11018
11016
  } catch {
11019
11017
  return { alive: false, isFigma: false };
11020
11018
  }
11021
11019
  }
11020
+ function isPortOwnedByFigma(port) {
11021
+ try {
11022
+ if (process.platform === "win32") {
11023
+ const output = execSync(
11024
+ `netstat -ano | findstr "LISTENING" | findstr ":${port} "`,
11025
+ { encoding: "utf-8" }
11026
+ );
11027
+ const pid2 = output.trim().split(/\s+/).pop();
11028
+ if (!pid2) return false;
11029
+ const tasks = execSync(`tasklist /FI "PID eq ${pid2}" /NH`, { encoding: "utf-8" });
11030
+ return tasks.includes("Figma");
11031
+ }
11032
+ const pid = execSync(`lsof -iTCP:${port} -sTCP:LISTEN -t`, { encoding: "utf-8" }).trim().split("\n")[0];
11033
+ if (!pid) return false;
11034
+ const comm = execSync(`ps -p ${pid} -o comm=`, { encoding: "utf-8" }).trim();
11035
+ return comm.endsWith("Figma") || comm.endsWith("/Figma");
11036
+ } catch {
11037
+ return false;
11038
+ }
11039
+ }
11022
11040
  function isPortAvailable(port) {
11023
11041
  return new Promise((resolve) => {
11024
11042
  const server2 = createServer();
@@ -11041,7 +11059,7 @@ async function listTargets(port) {
11041
11059
  }
11042
11060
  var FIGMA_DESIGN_URL_RE = /figma\.com\/(file|design)\//;
11043
11061
  function findFigmaDesignTarget(targets) {
11044
- return targets.find((t) => t.type === "page" && FIGMA_DESIGN_URL_RE.test(t.url)) || targets.find((t) => t.type === "page" && t.url.startsWith("views://")) || null;
11062
+ return targets.find((t) => t.type === "page" && FIGMA_DESIGN_URL_RE.test(t.url)) || targets.find((t) => t.type === "page") || null;
11045
11063
  }
11046
11064
  async function probeCdpPorts() {
11047
11065
  for (const port of KNOWN_CDP_PORTS) {
@@ -25470,23 +25488,29 @@ var RESOURCES = [
25470
25488
  description: "All variable collections and their variables (colors, spacing, typography tokens)",
25471
25489
  mimeType: "application/json",
25472
25490
  script: `
25473
- const collections = figma.variables.getLocalVariableCollections();
25474
- return collections.map(c => ({
25475
- id: c.id,
25476
- name: c.name,
25477
- modes: c.modes,
25478
- variableCount: c.variableIds.length,
25479
- variables: c.variableIds.map(vid => {
25480
- const v = figma.variables.getVariableById(vid);
25481
- if (!v) return null;
25482
- return {
25491
+ const collections = await figma.variables.getLocalVariableCollectionsAsync();
25492
+ const result = [];
25493
+ for (const c of collections) {
25494
+ const variables = [];
25495
+ for (const vid of c.variableIds) {
25496
+ const v = await figma.variables.getVariableByIdAsync(vid);
25497
+ if (!v) continue;
25498
+ variables.push({
25483
25499
  id: v.id,
25484
25500
  name: v.name,
25485
25501
  resolvedType: v.resolvedType,
25486
25502
  valuesByMode: v.valuesByMode,
25487
- };
25488
- }).filter(Boolean),
25489
- }));
25503
+ });
25504
+ }
25505
+ result.push({
25506
+ id: c.id,
25507
+ name: c.name,
25508
+ modes: c.modes,
25509
+ variableCount: c.variableIds.length,
25510
+ variables,
25511
+ });
25512
+ }
25513
+ return result;
25490
25514
  `
25491
25515
  },
25492
25516
  {
@@ -25495,7 +25519,7 @@ var RESOURCES = [
25495
25519
  description: "Local components and component sets in the file",
25496
25520
  mimeType: "application/json",
25497
25521
  script: `
25498
- const nodes = figma.root.findAllWithCriteria({ types: ['COMPONENT', 'COMPONENT_SET'] });
25522
+ const nodes = figma.currentPage.findAllWithCriteria({ types: ['COMPONENT', 'COMPONENT_SET'] });
25499
25523
  return nodes.map(c => ({
25500
25524
  id: c.id,
25501
25525
  name: c.name,
@@ -25511,9 +25535,9 @@ var RESOURCES = [
25511
25535
  description: "Text styles, paint styles, and effect styles defined in the file",
25512
25536
  mimeType: "application/json",
25513
25537
  script: `
25514
- const textStyles = figma.getLocalTextStyles();
25515
- const paintStyles = figma.getLocalPaintStyles();
25516
- const effectStyles = figma.getLocalEffectStyles();
25538
+ const textStyles = await figma.getLocalTextStylesAsync();
25539
+ const paintStyles = await figma.getLocalPaintStylesAsync();
25540
+ const effectStyles = await figma.getLocalEffectStylesAsync();
25517
25541
  return {
25518
25542
  textStyles: textStyles.map(s => ({
25519
25543
  id: s.id, name: s.name, fontSize: s.fontSize, fontName: s.fontName,
@@ -25567,7 +25591,7 @@ Resources provide quick read-only access to Figma state without tool calls:
25567
25591
  - Create components for reusable UI patterns.`;
25568
25592
  function createMcpServer(deps) {
25569
25593
  const server2 = new Server(
25570
- { name: "faux-studio", version: "0.3.7" },
25594
+ { name: "faux-studio", version: "0.3.8" },
25571
25595
  {
25572
25596
  capabilities: { tools: { listChanged: true }, resources: {}, logging: {} },
25573
25597
  instructions: INSTRUCTIONS
@@ -25723,7 +25747,11 @@ Run the \`login\` tool to re-authenticate.` : `Error: ${message}`
25723
25747
  throw new Error(`Unknown resource: ${uri}`);
25724
25748
  }
25725
25749
  log(`Reading resource: ${uri}`);
25726
- const result = await deps.executeScript(resource.script);
25750
+ const wrapped = `
25751
+ const __res = await (async () => {${resource.script}})();
25752
+ return { success: true, result: __res };
25753
+ `;
25754
+ const result = await deps.executeScript(wrapped);
25727
25755
  const text = result === void 0 || result === null ? "{}" : typeof result === "string" ? result : JSON.stringify(result, null, 2);
25728
25756
  return {
25729
25757
  contents: [{ uri, mimeType: resource.mimeType, text }]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "faux-studio",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "AI-powered Figma design via MCP — connect any AI client to Figma Desktop",
5
5
  "type": "module",
6
6
  "bin": {