@seed-design/mcp 0.0.21 → 0.0.23
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/bin/index.mjs +108 -27
- package/package.json +2 -2
- package/src/bin/index.ts +22 -3
- package/src/config.ts +47 -0
- package/src/tools.ts +75 -22
- package/src/websocket.ts +1 -1
package/bin/index.mjs
CHANGED
|
@@ -4,8 +4,10 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
4
4
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
5
|
import { v4 } from 'uuid';
|
|
6
6
|
import WebSocket$1 from 'ws';
|
|
7
|
-
import { createRestNormalizer,
|
|
7
|
+
import { createRestNormalizer, figma, react, getFigmaColorVariableNames } from '@seed-design/figma';
|
|
8
8
|
import { z } from 'zod';
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import path from 'node:path';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Custom logging module that writes to stderr instead of stdout
|
|
@@ -56,7 +58,7 @@ function createFigmaWebSocketClient(serverUrl) {
|
|
|
56
58
|
ws.on("open", ()=>{
|
|
57
59
|
logger.info("Connected to Figma socket server");
|
|
58
60
|
// Reset channel on new connection
|
|
59
|
-
|
|
61
|
+
joinChannel("local-default");
|
|
60
62
|
});
|
|
61
63
|
ws.on("message", (data)=>{
|
|
62
64
|
try {
|
|
@@ -261,8 +263,9 @@ function createFigmaWebSocketClient(serverUrl) {
|
|
|
261
263
|
};
|
|
262
264
|
}
|
|
263
265
|
|
|
264
|
-
function registerTools(server, figmaClient) {
|
|
266
|
+
function registerTools(server, figmaClient, config = {}) {
|
|
265
267
|
const { joinChannel, sendCommandToFigma } = figmaClient;
|
|
268
|
+
const { extend } = config ?? {};
|
|
266
269
|
// join_channel tool
|
|
267
270
|
server.tool("join_channel", "Join a specific channel to communicate with Figma", {
|
|
268
271
|
channel: z.string().describe("The name of the channel to join").default("")
|
|
@@ -331,6 +334,31 @@ function registerTools(server, figmaClient) {
|
|
|
331
334
|
return formatErrorResponse("get_annotations", error);
|
|
332
335
|
}
|
|
333
336
|
});
|
|
337
|
+
// Component Info Tool
|
|
338
|
+
server.tool("get_component_info", "Get detailed information about a specific component node in Figma", {
|
|
339
|
+
nodeId: z.string().describe("The ID of the component node to get information about")
|
|
340
|
+
}, async ({ nodeId })=>{
|
|
341
|
+
try {
|
|
342
|
+
const result = await sendCommandToFigma("get_node_info", {
|
|
343
|
+
nodeId
|
|
344
|
+
});
|
|
345
|
+
const node = result.document;
|
|
346
|
+
if (node.type !== "COMPONENT" && node.type !== "COMPONENT_SET") {
|
|
347
|
+
return formatErrorResponse("get_component_info", new Error(`Node with ID ${nodeId} is not a component node`));
|
|
348
|
+
}
|
|
349
|
+
const key = result.componentSets[nodeId]?.key ?? result.components[nodeId]?.key;
|
|
350
|
+
if (!key) {
|
|
351
|
+
return formatErrorResponse("get_component_info", new Error(`${nodeId} is not present in exported component data`));
|
|
352
|
+
}
|
|
353
|
+
return formatObjectResponse({
|
|
354
|
+
name: node.name,
|
|
355
|
+
key,
|
|
356
|
+
componentPropertyDefinitions: node.componentPropertyDefinitions
|
|
357
|
+
});
|
|
358
|
+
} catch (error) {
|
|
359
|
+
return formatErrorResponse("get_node_info", error);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
334
362
|
// Node Info Tool
|
|
335
363
|
server.tool("get_node_info", "Get detailed information about a specific node in Figma", {
|
|
336
364
|
nodeId: z.string().describe("The ID of the node to get information about")
|
|
@@ -341,15 +369,19 @@ function registerTools(server, figmaClient) {
|
|
|
341
369
|
});
|
|
342
370
|
const normalizer = createRestNormalizer(result);
|
|
343
371
|
const node = normalizer(result.document);
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
shouldInferVariableName: false
|
|
347
|
-
|
|
372
|
+
const noInferPipeline = figma.createPipeline({
|
|
373
|
+
shouldInferAutoLayout: false,
|
|
374
|
+
shouldInferVariableName: false
|
|
375
|
+
});
|
|
376
|
+
const inferPipeline = figma.createPipeline({
|
|
377
|
+
shouldInferAutoLayout: true,
|
|
378
|
+
shouldInferVariableName: true
|
|
379
|
+
});
|
|
380
|
+
const original = noInferPipeline.generateCode(node, {
|
|
381
|
+
shouldPrintSource: true
|
|
348
382
|
}) ?? "Failed to generate summarized node info";
|
|
349
|
-
const inferred =
|
|
350
|
-
shouldPrintSource: true
|
|
351
|
-
shouldInferVariableName: false,
|
|
352
|
-
shouldInferAutoLayout: true
|
|
383
|
+
const inferred = inferPipeline.generateCode(node, {
|
|
384
|
+
shouldPrintSource: true
|
|
353
385
|
}) ?? "Failed to generate summarized node info";
|
|
354
386
|
return formatObjectResponse({
|
|
355
387
|
original: {
|
|
@@ -376,15 +408,19 @@ function registerTools(server, figmaClient) {
|
|
|
376
408
|
});
|
|
377
409
|
const normalizer = createRestNormalizer(result);
|
|
378
410
|
const node = normalizer(result.document);
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
411
|
+
const noInferPipeline = figma.createPipeline({
|
|
412
|
+
shouldInferAutoLayout: false,
|
|
413
|
+
shouldInferVariableName: false
|
|
414
|
+
});
|
|
415
|
+
const inferPipeline = figma.createPipeline({
|
|
416
|
+
shouldInferAutoLayout: true,
|
|
417
|
+
shouldInferVariableName: true
|
|
418
|
+
});
|
|
419
|
+
const original = noInferPipeline.generateCode(node, {
|
|
420
|
+
shouldPrintSource: true
|
|
383
421
|
}) ?? "Failed to generate summarized node info";
|
|
384
|
-
const inferred =
|
|
385
|
-
|
|
386
|
-
shouldPrintSource: true,
|
|
387
|
-
shouldInferAutoLayout: false
|
|
422
|
+
const inferred = inferPipeline.generateCode(node, {
|
|
423
|
+
shouldPrintSource: true
|
|
388
424
|
}) ?? "Failed to generate summarized node info";
|
|
389
425
|
return {
|
|
390
426
|
nodeId,
|
|
@@ -411,10 +447,13 @@ function registerTools(server, figmaClient) {
|
|
|
411
447
|
nodeId
|
|
412
448
|
});
|
|
413
449
|
const normalizer = createRestNormalizer(result);
|
|
414
|
-
const
|
|
450
|
+
const pipeline = react.createPipeline({
|
|
451
|
+
shouldInferAutoLayout: true,
|
|
415
452
|
shouldInferVariableName: true,
|
|
416
|
-
|
|
417
|
-
|
|
453
|
+
extend
|
|
454
|
+
});
|
|
455
|
+
const code = pipeline.generateCode(normalizer(result.document), {
|
|
456
|
+
shouldPrintSource: false
|
|
418
457
|
}) ?? "Failed to generate code";
|
|
419
458
|
return formatTextResponse(code);
|
|
420
459
|
} catch (error) {
|
|
@@ -636,7 +675,34 @@ function registerPrompts(server) {
|
|
|
636
675
|
});
|
|
637
676
|
}
|
|
638
677
|
|
|
639
|
-
var version = "0.0.
|
|
678
|
+
var version = "0.0.23";
|
|
679
|
+
|
|
680
|
+
// Config loader
|
|
681
|
+
async function loadConfig(configPath) {
|
|
682
|
+
try {
|
|
683
|
+
const resolvedPath = path.resolve(process.cwd(), configPath);
|
|
684
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
685
|
+
logger.error(`Config file not found: ${resolvedPath}`);
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
// Handle different file types
|
|
689
|
+
if (resolvedPath.endsWith(".json")) {
|
|
690
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
691
|
+
return JSON.parse(content);
|
|
692
|
+
}
|
|
693
|
+
if (resolvedPath.endsWith(".js") || resolvedPath.endsWith(".mjs") || resolvedPath.endsWith(".ts") || resolvedPath.endsWith(".mts")) {
|
|
694
|
+
// For JS/MJS/TS/MTS files, we can dynamically import with Bun
|
|
695
|
+
// Bun has built-in TypeScript support without requiring transpilation
|
|
696
|
+
const config = await import(resolvedPath);
|
|
697
|
+
return config.default || config;
|
|
698
|
+
}
|
|
699
|
+
logger.error(`Unsupported config file format: ${resolvedPath}`);
|
|
700
|
+
return null;
|
|
701
|
+
} catch (error) {
|
|
702
|
+
logger.error(`Failed to load config file: ${error instanceof Error ? error.message : String(error)}`);
|
|
703
|
+
return null;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
640
706
|
|
|
641
707
|
// Initialize CLI
|
|
642
708
|
const cli = cac("@seed-design/mcp");
|
|
@@ -791,13 +857,28 @@ async function startWebSocketServer(port) {
|
|
|
791
857
|
console.log(`WebSocket server running on port ${server.port}`);
|
|
792
858
|
return server;
|
|
793
859
|
}
|
|
794
|
-
async function startMcpServer(serverUrl, experimental) {
|
|
860
|
+
async function startMcpServer(serverUrl, experimental, configPath) {
|
|
861
|
+
// Load config if provided
|
|
862
|
+
let configData = null;
|
|
863
|
+
if (configPath) {
|
|
864
|
+
configData = await loadConfig(configPath);
|
|
865
|
+
if (configData) {
|
|
866
|
+
logger.info(`Loaded configuration from: ${configPath}`);
|
|
867
|
+
// Log component transformers if present
|
|
868
|
+
if (configData.extend?.componentHandlers) {
|
|
869
|
+
const handlers = configData.extend.componentHandlers;
|
|
870
|
+
if (handlers.length > 0) {
|
|
871
|
+
logger.info(`Found ${handlers.length} custom component handlers`);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
795
876
|
const figmaClient = createFigmaWebSocketClient(serverUrl);
|
|
796
877
|
const server = new McpServer({
|
|
797
878
|
name: "SEED Design MCP",
|
|
798
879
|
version
|
|
799
880
|
});
|
|
800
|
-
registerTools(server, figmaClient);
|
|
881
|
+
registerTools(server, figmaClient, configData);
|
|
801
882
|
if (experimental) {
|
|
802
883
|
registerEditingTools(server, figmaClient);
|
|
803
884
|
}
|
|
@@ -817,8 +898,8 @@ cli.command("", "Start the MCP server").option("--server <server>", "Server URL"
|
|
|
817
898
|
default: "localhost"
|
|
818
899
|
}).option("--experimental", "Enable experimental features", {
|
|
819
900
|
default: false
|
|
820
|
-
}).action(async (options)=>{
|
|
821
|
-
await startMcpServer(options.server, options.experimental);
|
|
901
|
+
}).option("--config <config>", "Path to configuration file (.js, .mjs, .ts, .mts)").action(async (options)=>{
|
|
902
|
+
await startMcpServer(options.server, options.experimental, options.config);
|
|
822
903
|
});
|
|
823
904
|
cli.command("socket", "Start the WebSocket server").option("--port <port>", "Port number", {
|
|
824
905
|
default: 3055
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seed-design/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/daangn/seed-design.git",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
|
26
|
-
"@seed-design/figma": "0.0.
|
|
26
|
+
"@seed-design/figma": "0.0.23",
|
|
27
27
|
"cac": "^6.7.14",
|
|
28
28
|
"uuid": "^11.1.0",
|
|
29
29
|
"ws": "^8.18.1",
|
package/src/bin/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { registerEditingTools, registerTools } from "../tools";
|
|
|
9
9
|
import { registerPrompts } from "../prompts";
|
|
10
10
|
import { version } from "../../package.json" assert { type: "json" };
|
|
11
11
|
import type { Server, ServerWebSocket } from "bun";
|
|
12
|
+
import { loadConfig, type McpConfig } from "../config";
|
|
12
13
|
|
|
13
14
|
// Initialize CLI
|
|
14
15
|
const cli = cac("@seed-design/mcp");
|
|
@@ -188,14 +189,31 @@ async function startWebSocketServer(port: number) {
|
|
|
188
189
|
return server;
|
|
189
190
|
}
|
|
190
191
|
|
|
191
|
-
async function startMcpServer(serverUrl: string, experimental: boolean) {
|
|
192
|
+
async function startMcpServer(serverUrl: string, experimental: boolean, configPath?: string) {
|
|
193
|
+
// Load config if provided
|
|
194
|
+
let configData: McpConfig | null = null;
|
|
195
|
+
if (configPath) {
|
|
196
|
+
configData = await loadConfig(configPath);
|
|
197
|
+
if (configData) {
|
|
198
|
+
logger.info(`Loaded configuration from: ${configPath}`);
|
|
199
|
+
|
|
200
|
+
// Log component transformers if present
|
|
201
|
+
if (configData.extend?.componentHandlers) {
|
|
202
|
+
const handlers = configData.extend.componentHandlers;
|
|
203
|
+
if (handlers.length > 0) {
|
|
204
|
+
logger.info(`Found ${handlers.length} custom component handlers`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
192
210
|
const figmaClient = createFigmaWebSocketClient(serverUrl);
|
|
193
211
|
const server = new McpServer({
|
|
194
212
|
name: "SEED Design MCP",
|
|
195
213
|
version,
|
|
196
214
|
});
|
|
197
215
|
|
|
198
|
-
registerTools(server, figmaClient);
|
|
216
|
+
registerTools(server, figmaClient, configData);
|
|
199
217
|
if (experimental) {
|
|
200
218
|
registerEditingTools(server, figmaClient);
|
|
201
219
|
}
|
|
@@ -220,8 +238,9 @@ cli
|
|
|
220
238
|
.command("", "Start the MCP server")
|
|
221
239
|
.option("--server <server>", "Server URL", { default: "localhost" })
|
|
222
240
|
.option("--experimental", "Enable experimental features", { default: false })
|
|
241
|
+
.option("--config <config>", "Path to configuration file (.js, .mjs, .ts, .mts)")
|
|
223
242
|
.action(async (options) => {
|
|
224
|
-
await startMcpServer(options.server, options.experimental);
|
|
243
|
+
await startMcpServer(options.server, options.experimental, options.config);
|
|
225
244
|
});
|
|
226
245
|
|
|
227
246
|
cli
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { CreatePipelineConfig } from "@seed-design/figma/codegen/targets/react";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { logger } from "./logger";
|
|
5
|
+
|
|
6
|
+
// Define config type
|
|
7
|
+
export interface McpConfig {
|
|
8
|
+
extend?: CreatePipelineConfig["extend"];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Config loader
|
|
12
|
+
export async function loadConfig(configPath: string) {
|
|
13
|
+
try {
|
|
14
|
+
const resolvedPath = path.resolve(process.cwd(), configPath);
|
|
15
|
+
|
|
16
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
17
|
+
logger.error(`Config file not found: ${resolvedPath}`);
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Handle different file types
|
|
22
|
+
if (resolvedPath.endsWith(".json")) {
|
|
23
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
24
|
+
return JSON.parse(content);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (
|
|
28
|
+
resolvedPath.endsWith(".js") ||
|
|
29
|
+
resolvedPath.endsWith(".mjs") ||
|
|
30
|
+
resolvedPath.endsWith(".ts") ||
|
|
31
|
+
resolvedPath.endsWith(".mts")
|
|
32
|
+
) {
|
|
33
|
+
// For JS/MJS/TS/MTS files, we can dynamically import with Bun
|
|
34
|
+
// Bun has built-in TypeScript support without requiring transpilation
|
|
35
|
+
const config = await import(resolvedPath);
|
|
36
|
+
return config.default || config;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
logger.error(`Unsupported config file format: ${resolvedPath}`);
|
|
40
|
+
return null;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
logger.error(
|
|
43
|
+
`Failed to load config file: ${error instanceof Error ? error.message : String(error)}`,
|
|
44
|
+
);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/tools.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
+
import type { GetFileNodesResponse } from "@figma/rest-api-spec";
|
|
1
2
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import {
|
|
3
|
-
createRestNormalizer,
|
|
4
|
-
generateCode,
|
|
5
|
-
generateFigmaSummary,
|
|
6
|
-
getFigmaColorVariableNames,
|
|
7
|
-
} from "@seed-design/figma";
|
|
3
|
+
import { createRestNormalizer, figma, getFigmaColorVariableNames, react } from "@seed-design/figma";
|
|
8
4
|
import { z } from "zod";
|
|
5
|
+
import type { McpConfig } from "./config";
|
|
9
6
|
import {
|
|
10
7
|
formatErrorResponse,
|
|
11
8
|
formatImageResponse,
|
|
@@ -14,8 +11,13 @@ import {
|
|
|
14
11
|
} from "./responses";
|
|
15
12
|
import type { FigmaWebSocketClient } from "./websocket";
|
|
16
13
|
|
|
17
|
-
export function registerTools(
|
|
14
|
+
export function registerTools(
|
|
15
|
+
server: McpServer,
|
|
16
|
+
figmaClient: FigmaWebSocketClient,
|
|
17
|
+
config: McpConfig | null = {},
|
|
18
|
+
): void {
|
|
18
19
|
const { joinChannel, sendCommandToFigma } = figmaClient;
|
|
20
|
+
const { extend } = config ?? {};
|
|
19
21
|
|
|
20
22
|
// join_channel tool
|
|
21
23
|
server.tool(
|
|
@@ -117,6 +119,46 @@ export function registerTools(server: McpServer, figmaClient: FigmaWebSocketClie
|
|
|
117
119
|
},
|
|
118
120
|
);
|
|
119
121
|
|
|
122
|
+
// Component Info Tool
|
|
123
|
+
server.tool(
|
|
124
|
+
"get_component_info",
|
|
125
|
+
"Get detailed information about a specific component node in Figma",
|
|
126
|
+
{
|
|
127
|
+
nodeId: z.string().describe("The ID of the component node to get information about"),
|
|
128
|
+
},
|
|
129
|
+
async ({ nodeId }) => {
|
|
130
|
+
try {
|
|
131
|
+
const result = (await sendCommandToFigma("get_node_info", {
|
|
132
|
+
nodeId,
|
|
133
|
+
})) as GetFileNodesResponse["nodes"][string];
|
|
134
|
+
|
|
135
|
+
const node = result.document;
|
|
136
|
+
if (node.type !== "COMPONENT" && node.type !== "COMPONENT_SET") {
|
|
137
|
+
return formatErrorResponse(
|
|
138
|
+
"get_component_info",
|
|
139
|
+
new Error(`Node with ID ${nodeId} is not a component node`),
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const key = result.componentSets[nodeId]?.key ?? result.components[nodeId]?.key;
|
|
144
|
+
if (!key) {
|
|
145
|
+
return formatErrorResponse(
|
|
146
|
+
"get_component_info",
|
|
147
|
+
new Error(`${nodeId} is not present in exported component data`),
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return formatObjectResponse({
|
|
152
|
+
name: node.name,
|
|
153
|
+
key,
|
|
154
|
+
componentPropertyDefinitions: node.componentPropertyDefinitions,
|
|
155
|
+
});
|
|
156
|
+
} catch (error) {
|
|
157
|
+
return formatErrorResponse("get_node_info", error);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
);
|
|
161
|
+
|
|
120
162
|
// Node Info Tool
|
|
121
163
|
server.tool(
|
|
122
164
|
"get_node_info",
|
|
@@ -130,17 +172,21 @@ export function registerTools(server: McpServer, figmaClient: FigmaWebSocketClie
|
|
|
130
172
|
const normalizer = createRestNormalizer(result);
|
|
131
173
|
const node = normalizer(result.document);
|
|
132
174
|
|
|
175
|
+
const noInferPipeline = figma.createPipeline({
|
|
176
|
+
shouldInferAutoLayout: false,
|
|
177
|
+
shouldInferVariableName: false,
|
|
178
|
+
});
|
|
179
|
+
const inferPipeline = figma.createPipeline({
|
|
180
|
+
shouldInferAutoLayout: true,
|
|
181
|
+
shouldInferVariableName: true,
|
|
182
|
+
});
|
|
133
183
|
const original =
|
|
134
|
-
|
|
184
|
+
noInferPipeline.generateCode(node, {
|
|
135
185
|
shouldPrintSource: true,
|
|
136
|
-
shouldInferVariableName: false,
|
|
137
|
-
shouldInferAutoLayout: false,
|
|
138
186
|
}) ?? "Failed to generate summarized node info";
|
|
139
187
|
const inferred =
|
|
140
|
-
|
|
188
|
+
inferPipeline.generateCode(node, {
|
|
141
189
|
shouldPrintSource: true,
|
|
142
|
-
shouldInferVariableName: false,
|
|
143
|
-
shouldInferAutoLayout: true,
|
|
144
190
|
}) ?? "Failed to generate summarized node info";
|
|
145
191
|
|
|
146
192
|
return formatObjectResponse({
|
|
@@ -174,17 +220,21 @@ export function registerTools(server: McpServer, figmaClient: FigmaWebSocketClie
|
|
|
174
220
|
const normalizer = createRestNormalizer(result);
|
|
175
221
|
const node = normalizer(result.document);
|
|
176
222
|
|
|
223
|
+
const noInferPipeline = figma.createPipeline({
|
|
224
|
+
shouldInferAutoLayout: false,
|
|
225
|
+
shouldInferVariableName: false,
|
|
226
|
+
});
|
|
227
|
+
const inferPipeline = figma.createPipeline({
|
|
228
|
+
shouldInferAutoLayout: true,
|
|
229
|
+
shouldInferVariableName: true,
|
|
230
|
+
});
|
|
177
231
|
const original =
|
|
178
|
-
|
|
179
|
-
shouldInferVariableName: false,
|
|
232
|
+
noInferPipeline.generateCode(node, {
|
|
180
233
|
shouldPrintSource: true,
|
|
181
|
-
shouldInferAutoLayout: false,
|
|
182
234
|
}) ?? "Failed to generate summarized node info";
|
|
183
235
|
const inferred =
|
|
184
|
-
|
|
185
|
-
shouldInferVariableName: true,
|
|
236
|
+
inferPipeline.generateCode(node, {
|
|
186
237
|
shouldPrintSource: true,
|
|
187
|
-
shouldInferAutoLayout: false,
|
|
188
238
|
}) ?? "Failed to generate summarized node info";
|
|
189
239
|
|
|
190
240
|
return {
|
|
@@ -216,11 +266,14 @@ export function registerTools(server: McpServer, figmaClient: FigmaWebSocketClie
|
|
|
216
266
|
const result: any = await sendCommandToFigma("get_node_info", { nodeId });
|
|
217
267
|
const normalizer = createRestNormalizer(result);
|
|
218
268
|
|
|
269
|
+
const pipeline = react.createPipeline({
|
|
270
|
+
shouldInferAutoLayout: true,
|
|
271
|
+
shouldInferVariableName: true,
|
|
272
|
+
extend,
|
|
273
|
+
});
|
|
219
274
|
const code =
|
|
220
|
-
generateCode(normalizer(result.document), {
|
|
221
|
-
shouldInferVariableName: true,
|
|
275
|
+
pipeline.generateCode(normalizer(result.document), {
|
|
222
276
|
shouldPrintSource: false,
|
|
223
|
-
shouldInferAutoLayout: true,
|
|
224
277
|
}) ?? "Failed to generate code";
|
|
225
278
|
|
|
226
279
|
return formatTextResponse(code);
|
package/src/websocket.ts
CHANGED
|
@@ -54,7 +54,7 @@ export function createFigmaWebSocketClient(serverUrl: string) {
|
|
|
54
54
|
ws.on("open", () => {
|
|
55
55
|
logger.info("Connected to Figma socket server");
|
|
56
56
|
// Reset channel on new connection
|
|
57
|
-
|
|
57
|
+
joinChannel("local-default");
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
ws.on("message", (data: any) => {
|