viewgate-mcp 1.0.16 → 1.0.17

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 +38 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -431,35 +431,54 @@ Instruction: ${ann.message}`
431
431
  };
432
432
  }
433
433
  // 2. Parse Figma URL
434
- const fileKeyMatch = url.match(/(?:file|design)\/([a-zA-Z0-9]+)/);
435
- if (!fileKeyMatch) {
434
+ let fileKey = "";
435
+ try {
436
+ if (url.includes("/file/") || url.includes("/design/")) {
437
+ const parts = url.split(/\/(?:file|design)\//)[1].split("/");
438
+ fileKey = parts[0].split(/[?#]/)[0];
439
+ }
440
+ }
441
+ catch (e) {
442
+ throw new Error("Could not parse Figma File Key from URL.");
443
+ }
444
+ if (!fileKey) {
436
445
  throw new Error("Invalid Figma URL format. File key not found.");
437
446
  }
438
- const fileKey = fileKeyMatch[1];
439
447
  // Extract node-id if present
440
- const urlObj = new URL(url.replace(/#/g, '?')); // Handle hash-based node-id
441
- let nodeId = urlObj.searchParams.get('node-id') || urlObj.searchParams.get('m');
442
- if (!nodeId && url.includes('node-id=')) {
443
- nodeId = url.split('node-id=')[1].split('&')[0];
448
+ let nodeId = "";
449
+ try {
450
+ const urlObj = new URL(url.replace(/#/g, "?")); // Handle hash-based node-id
451
+ nodeId = urlObj.searchParams.get("node-id") || urlObj.searchParams.get("m") || "";
452
+ if (!nodeId && url.includes("node-id=")) {
453
+ nodeId = url.split("node-id=")[1].split("&")[0];
454
+ }
455
+ // Normalización y limpieza
456
+ if (nodeId) {
457
+ nodeId = decodeURIComponent(nodeId).replace(/-/g, ":");
458
+ }
444
459
  }
445
- // Figma API expects node-id with : instead of - (which is used in browser URL)
446
- if (nodeId) {
447
- nodeId = nodeId.replace(/%3A/g, ':').replace(/-/g, ':');
460
+ catch (e) {
461
+ // Silent fail for nodeId, might just fetch full file
448
462
  }
449
463
  // 3. Fetch Data from Figma
450
- // First get file info
451
- const figmaApiUrl = `https://api.figma.com/v1/files/${fileKey}${nodeId ? `?ids=${nodeId}` : ''}`;
464
+ // Use /nodes endpoint if nodeId exists, otherwise /files
465
+ const encodedNodeId = nodeId ? encodeURIComponent(nodeId) : "";
466
+ const figmaApiUrl = nodeId
467
+ ? `https://api.figma.com/v1/files/${fileKey}/nodes?ids=${encodedNodeId}`
468
+ : `https://api.figma.com/v1/files/${fileKey}`;
452
469
  const figmaResponse = await fetch(figmaApiUrl, {
453
470
  headers: { 'X-Figma-Token': figmaToken }
454
471
  });
455
472
  if (!figmaResponse.ok) {
456
- throw new Error(`Figma API returned ${figmaResponse.status}: ${await figmaResponse.text()}`);
473
+ const errorText = await figmaResponse.text();
474
+ throw new Error(`Figma API returned ${figmaResponse.status}: ${errorText} (URL: ${figmaApiUrl})`);
457
475
  }
458
- const figmaData = (await figmaResponse.json());
476
+ const rawData = (await figmaResponse.json());
459
477
  // 4. Optionally fetch image preview if a node is specified
460
478
  let imageUrl = null;
461
479
  if (nodeId) {
462
- const imageResponse = await fetch(`https://api.figma.com/v1/images/${fileKey}?ids=${nodeId}&scale=2&format=png`, {
480
+ const encodedIds = encodeURIComponent(nodeId);
481
+ const imageResponse = await fetch(`https://api.figma.com/v1/images/${fileKey}?ids=${encodedIds}&scale=2&format=png`, {
463
482
  headers: { 'X-Figma-Token': figmaToken }
464
483
  });
465
484
  if (imageResponse.ok) {
@@ -467,14 +486,15 @@ Instruction: ${ann.message}`
467
486
  imageUrl = imageData.images?.[nodeId];
468
487
  }
469
488
  }
489
+ const nodeInfo = nodeId ? rawData.nodes?.[nodeId] : null;
470
490
  return {
471
491
  content: [{
472
492
  type: "text",
473
493
  text: JSON.stringify({
474
- fileName: figmaData.name,
475
- lastModified: figmaData.lastModified,
494
+ fileName: rawData.name || "Unknown File",
495
+ lastModified: rawData.lastModified,
476
496
  previewUrl: imageUrl,
477
- nodeName: nodeId ? (figmaData.nodes?.[nodeId]?.document?.name || 'Selected Component') : 'Full File',
497
+ nodeName: nodeInfo ? (nodeInfo.document?.name || 'Selected Component') : 'Full File',
478
498
  note: "Design context successfully retrieved from Figma."
479
499
  }, null, 2)
480
500
  }]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viewgate-mcp",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "viewgate-mcp": "./dist/index.js"