viewgate-mcp 1.0.15 → 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.
- package/dist/index.js +40 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -228,7 +228,7 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
228
228
|
figmaReference: ann.figmaReference,
|
|
229
229
|
backendEndpoints: ann.backendEndpoints || [ann.backendEndpoint].filter(Boolean),
|
|
230
230
|
_ia_fix_instruction: `### 🎨 DESIGN CONTEXT (Figma)
|
|
231
|
-
${ann.figmaReference ? `A design reference is available: ${ann.figmaReference}. Use the 'get_figma_preview' tool to fetch design details and image previews before implementing.` : 'No explicit figma design linked.'}
|
|
231
|
+
${ann.figmaReference ? `A design reference is available: ${Array.isArray(ann.figmaReference) ? (ann.figmaReference[0]?.link || ann.figmaReference[0]) : (ann.figmaReference.link || ann.figmaReference)}. Use the 'get_figma_preview' tool to fetch design details and image previews before implementing.` : 'No explicit figma design linked.'}
|
|
232
232
|
|
|
233
233
|
### 🔬 SURGICAL FIX PROTOCOL (Language: ${data.preferredLanguage || 'en'})
|
|
234
234
|
1. **PRIMARY**: Search for \`data-vg-id="${ann.reference?.vgId}"\`.
|
|
@@ -431,31 +431,54 @@ Instruction: ${ann.message}`
|
|
|
431
431
|
};
|
|
432
432
|
}
|
|
433
433
|
// 2. Parse Figma URL
|
|
434
|
-
|
|
435
|
-
|
|
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[2];
|
|
439
447
|
// Extract node-id if present
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
nodeId =
|
|
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
|
+
}
|
|
459
|
+
}
|
|
460
|
+
catch (e) {
|
|
461
|
+
// Silent fail for nodeId, might just fetch full file
|
|
444
462
|
}
|
|
445
463
|
// 3. Fetch Data from Figma
|
|
446
|
-
//
|
|
447
|
-
const
|
|
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}`;
|
|
448
469
|
const figmaResponse = await fetch(figmaApiUrl, {
|
|
449
470
|
headers: { 'X-Figma-Token': figmaToken }
|
|
450
471
|
});
|
|
451
472
|
if (!figmaResponse.ok) {
|
|
452
|
-
|
|
473
|
+
const errorText = await figmaResponse.text();
|
|
474
|
+
throw new Error(`Figma API returned ${figmaResponse.status}: ${errorText} (URL: ${figmaApiUrl})`);
|
|
453
475
|
}
|
|
454
|
-
const
|
|
476
|
+
const rawData = (await figmaResponse.json());
|
|
455
477
|
// 4. Optionally fetch image preview if a node is specified
|
|
456
478
|
let imageUrl = null;
|
|
457
479
|
if (nodeId) {
|
|
458
|
-
const
|
|
480
|
+
const encodedIds = encodeURIComponent(nodeId);
|
|
481
|
+
const imageResponse = await fetch(`https://api.figma.com/v1/images/${fileKey}?ids=${encodedIds}&scale=2&format=png`, {
|
|
459
482
|
headers: { 'X-Figma-Token': figmaToken }
|
|
460
483
|
});
|
|
461
484
|
if (imageResponse.ok) {
|
|
@@ -463,14 +486,15 @@ Instruction: ${ann.message}`
|
|
|
463
486
|
imageUrl = imageData.images?.[nodeId];
|
|
464
487
|
}
|
|
465
488
|
}
|
|
489
|
+
const nodeInfo = nodeId ? rawData.nodes?.[nodeId] : null;
|
|
466
490
|
return {
|
|
467
491
|
content: [{
|
|
468
492
|
type: "text",
|
|
469
493
|
text: JSON.stringify({
|
|
470
|
-
fileName:
|
|
471
|
-
lastModified:
|
|
494
|
+
fileName: rawData.name || "Unknown File",
|
|
495
|
+
lastModified: rawData.lastModified,
|
|
472
496
|
previewUrl: imageUrl,
|
|
473
|
-
nodeName:
|
|
497
|
+
nodeName: nodeInfo ? (nodeInfo.document?.name || 'Selected Component') : 'Full File',
|
|
474
498
|
note: "Design context successfully retrieved from Figma."
|
|
475
499
|
}, null, 2)
|
|
476
500
|
}]
|