viewgate-mcp 1.0.12 → 1.0.14
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 +89 -0
- package/package.json +40 -40
package/dist/index.js
CHANGED
|
@@ -142,6 +142,17 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
142
142
|
type: "object",
|
|
143
143
|
properties: {},
|
|
144
144
|
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "get_figma_preview",
|
|
148
|
+
description: "Fetches design metadata and image previews from a Figma URL using the project's centralized access token. Use this to understand the UX requirements without needing local Figma configuration. The Figma token must be configured in the ViewGate dashboard under Settings > Integrations.",
|
|
149
|
+
inputSchema: {
|
|
150
|
+
type: "object",
|
|
151
|
+
properties: {
|
|
152
|
+
url: { type: "string", description: "The Figma design or file URL" }
|
|
153
|
+
},
|
|
154
|
+
required: ["url"]
|
|
155
|
+
}
|
|
145
156
|
}
|
|
146
157
|
],
|
|
147
158
|
};
|
|
@@ -390,6 +401,84 @@ Instruction: ${ann.message}`
|
|
|
390
401
|
};
|
|
391
402
|
}
|
|
392
403
|
}
|
|
404
|
+
case "get_figma_preview": {
|
|
405
|
+
try {
|
|
406
|
+
const args = request.params.arguments;
|
|
407
|
+
const url = args.url;
|
|
408
|
+
// 1. Get Figma Token from Backend Config
|
|
409
|
+
const configResponse = await fetch(`${BACKEND_URL}/api/mcp/config`, {
|
|
410
|
+
headers: {
|
|
411
|
+
'x-api-key': apiKey,
|
|
412
|
+
...(personalKey ? { 'x-personal-key': personalKey } : {})
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
if (!configResponse.ok) {
|
|
416
|
+
throw new Error(`Failed to fetch project configuration: ${configResponse.status}`);
|
|
417
|
+
}
|
|
418
|
+
const configData = (await configResponse.json());
|
|
419
|
+
const figmaToken = configData?.settings?.figmaToken;
|
|
420
|
+
if (!figmaToken) {
|
|
421
|
+
return {
|
|
422
|
+
content: [{
|
|
423
|
+
type: "text",
|
|
424
|
+
text: "Figma integration is not fully configured. Please add a Figma Access Token in the ViewGate Dashboard (Settings > Integrations)."
|
|
425
|
+
}],
|
|
426
|
+
isError: true
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
// 2. Parse Figma URL
|
|
430
|
+
const fileKeyMatch = url.match(/(file|design)\/([a-zA-Z0-9]+)/);
|
|
431
|
+
if (!fileKeyMatch) {
|
|
432
|
+
throw new Error("Invalid Figma URL format. File key not found.");
|
|
433
|
+
}
|
|
434
|
+
const fileKey = fileKeyMatch[2];
|
|
435
|
+
// Extract node-id if present
|
|
436
|
+
const urlObj = new URL(url.replace(/#/g, '?')); // Handle hash-based node-id
|
|
437
|
+
let nodeId = urlObj.searchParams.get('node-id') || urlObj.searchParams.get('m');
|
|
438
|
+
if (!nodeId && url.includes('node-id=')) {
|
|
439
|
+
nodeId = url.split('node-id=')[1].split('&')[0].replace('%3A', ':');
|
|
440
|
+
}
|
|
441
|
+
// 3. Fetch Data from Figma
|
|
442
|
+
// First get file info
|
|
443
|
+
const figmaApiUrl = `https://api.figma.com/v1/files/${fileKey}${nodeId ? `?ids=${nodeId}` : ''}`;
|
|
444
|
+
const figmaResponse = await fetch(figmaApiUrl, {
|
|
445
|
+
headers: { 'X-Figma-Token': figmaToken }
|
|
446
|
+
});
|
|
447
|
+
if (!figmaResponse.ok) {
|
|
448
|
+
throw new Error(`Figma API returned ${figmaResponse.status}: ${await figmaResponse.text()}`);
|
|
449
|
+
}
|
|
450
|
+
const figmaData = (await figmaResponse.json());
|
|
451
|
+
// 4. Optionally fetch image preview if a node is specified
|
|
452
|
+
let imageUrl = null;
|
|
453
|
+
if (nodeId) {
|
|
454
|
+
const imageResponse = await fetch(`https://api.figma.com/v1/images/${fileKey}?ids=${nodeId}&scale=2&format=png`, {
|
|
455
|
+
headers: { 'X-Figma-Token': figmaToken }
|
|
456
|
+
});
|
|
457
|
+
if (imageResponse.ok) {
|
|
458
|
+
const imageData = await imageResponse.json();
|
|
459
|
+
imageUrl = imageData.images?.[nodeId];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
content: [{
|
|
464
|
+
type: "text",
|
|
465
|
+
text: JSON.stringify({
|
|
466
|
+
fileName: figmaData.name,
|
|
467
|
+
lastModified: figmaData.lastModified,
|
|
468
|
+
previewUrl: imageUrl,
|
|
469
|
+
nodeName: nodeId ? (figmaData.nodes?.[nodeId]?.document?.name || 'Selected Component') : 'Full File',
|
|
470
|
+
note: "Design context successfully retrieved from Figma."
|
|
471
|
+
}, null, 2)
|
|
472
|
+
}]
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
return {
|
|
477
|
+
content: [{ type: "text", text: `Error fetching Figma preview: ${error.message}` }],
|
|
478
|
+
isError: true
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
}
|
|
393
482
|
default:
|
|
394
483
|
throw new Error("Unknown tool");
|
|
395
484
|
}
|
package/package.json
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "viewgate-mcp",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"main": "dist/index.js",
|
|
5
|
-
"bin": {
|
|
6
|
-
"viewgate-mcp": "./dist/index.js"
|
|
7
|
-
},
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
11
|
-
"type": "module",
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "tsc",
|
|
14
|
-
"watch": "tsc -w",
|
|
15
|
-
"start": "node dist/index.js",
|
|
16
|
-
"dev": "tsx watch src/index.ts",
|
|
17
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [],
|
|
20
|
-
"author": "",
|
|
21
|
-
"license": "ISC",
|
|
22
|
-
"description": "",
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
25
|
-
"cors": "^2.8.6",
|
|
26
|
-
"dotenv": "^17.3.1",
|
|
27
|
-
"express": "^5.2.1",
|
|
28
|
-
"node-fetch": "^3.3.2"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@types/cors": "^2.8.19",
|
|
32
|
-
"@types/express": "^5.0.6",
|
|
33
|
-
"@types/node": "^25.5.0",
|
|
34
|
-
"@types/node-fetch": "^2.6.13",
|
|
35
|
-
"nodemon": "^3.1.14",
|
|
36
|
-
"ts-node": "^10.9.2",
|
|
37
|
-
"tsx": "^4.21.0",
|
|
38
|
-
"typescript": "^5.9.3"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "viewgate-mcp",
|
|
3
|
+
"version": "1.0.14",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"viewgate-mcp": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"type": "module",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"watch": "tsc -w",
|
|
15
|
+
"start": "node dist/index.js",
|
|
16
|
+
"dev": "tsx watch src/index.ts",
|
|
17
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "ISC",
|
|
22
|
+
"description": "",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
25
|
+
"cors": "^2.8.6",
|
|
26
|
+
"dotenv": "^17.3.1",
|
|
27
|
+
"express": "^5.2.1",
|
|
28
|
+
"node-fetch": "^3.3.2"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/cors": "^2.8.19",
|
|
32
|
+
"@types/express": "^5.0.6",
|
|
33
|
+
"@types/node": "^25.5.0",
|
|
34
|
+
"@types/node-fetch": "^2.6.13",
|
|
35
|
+
"nodemon": "^3.1.14",
|
|
36
|
+
"ts-node": "^10.9.2",
|
|
37
|
+
"tsx": "^4.21.0",
|
|
38
|
+
"typescript": "^5.9.3"
|
|
39
|
+
}
|
|
40
|
+
}
|