@seed-design/mcp 1.2.0 → 1.3.0

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.
@@ -0,0 +1,113 @@
1
+ import type { GetFileNodesResponse } from "@figma/rest-api-spec";
2
+ import type { FigmaRestClient } from "./figma-rest-client";
3
+ import { createFigmaRestClient } from "./figma-rest-client";
4
+ import type { FigmaWebSocketClient } from "./websocket";
5
+ import type { McpConfig } from "./config";
6
+
7
+ export type ToolMode = "rest" | "websocket" | "all";
8
+
9
+ export interface ToolContext {
10
+ sendCommandToFigma: FigmaWebSocketClient["sendCommandToFigma"] | null;
11
+ restClient: FigmaRestClient | null;
12
+ mode: ToolMode;
13
+ extend?: McpConfig["extend"];
14
+ }
15
+
16
+ export function createToolContext(
17
+ figmaClient: FigmaWebSocketClient | null,
18
+ restClient: FigmaRestClient | null,
19
+ config: McpConfig | null,
20
+ mode: ToolMode,
21
+ ): ToolContext {
22
+ return {
23
+ sendCommandToFigma: figmaClient?.sendCommandToFigma ?? null,
24
+ restClient,
25
+ mode,
26
+ extend: config?.extend,
27
+ };
28
+ }
29
+
30
+ function resolveRestClient(
31
+ personalAccessToken: string | undefined,
32
+ context: ToolContext,
33
+ ): FigmaRestClient | null {
34
+ if (context.mode === "websocket") {
35
+ return null;
36
+ }
37
+
38
+ if (personalAccessToken) {
39
+ return createFigmaRestClient(personalAccessToken);
40
+ }
41
+
42
+ return context.restClient;
43
+ }
44
+
45
+ export async function fetchNodeData(
46
+ params: { fileKey?: string; nodeId: string; personalAccessToken?: string },
47
+ context: ToolContext,
48
+ ): Promise<GetFileNodesResponse["nodes"][string]> {
49
+ const { fileKey, nodeId, personalAccessToken } = params;
50
+ const restClient = resolveRestClient(personalAccessToken, context);
51
+ const { sendCommandToFigma } = context;
52
+
53
+ if (restClient && fileKey) {
54
+ const response = await restClient.getFileNodes(fileKey, [nodeId]);
55
+ const nodeData = response.nodes[nodeId];
56
+
57
+ if (!nodeData) throw new Error(`Node ${nodeId} not found in file ${fileKey}`);
58
+
59
+ return nodeData;
60
+ }
61
+
62
+ if (sendCommandToFigma) {
63
+ return (await sendCommandToFigma("get_node_info", {
64
+ nodeId,
65
+ })) as GetFileNodesResponse["nodes"][string];
66
+ }
67
+
68
+ throw new Error(
69
+ "No connection available. Provide figmaUrl/fileKey with personalAccessToken or FIGMA_PERSONAL_ACCESS_TOKEN, or use WebSocket mode with Figma Plugin.",
70
+ );
71
+ }
72
+
73
+ export async function fetchMultipleNodesData(
74
+ params: { fileKey?: string; nodeIds: string[]; personalAccessToken?: string },
75
+ context: ToolContext,
76
+ ): Promise<GetFileNodesResponse["nodes"]> {
77
+ const { fileKey, nodeIds, personalAccessToken } = params;
78
+ const restClient = resolveRestClient(personalAccessToken, context);
79
+ const { sendCommandToFigma } = context;
80
+
81
+ if (restClient && fileKey) {
82
+ const response = await restClient.getFileNodes(fileKey, nodeIds);
83
+
84
+ return response.nodes;
85
+ }
86
+
87
+ if (sendCommandToFigma) {
88
+ const results: GetFileNodesResponse["nodes"] = {};
89
+
90
+ await Promise.all(
91
+ nodeIds.map(async (nodeId) => {
92
+ const data = (await sendCommandToFigma("get_node_info", {
93
+ nodeId,
94
+ })) as GetFileNodesResponse["nodes"][string];
95
+
96
+ results[nodeId] = data;
97
+ }),
98
+ );
99
+
100
+ return results;
101
+ }
102
+
103
+ throw new Error(
104
+ "No connection available. Provide figmaUrl/fileKey with personalAccessToken or FIGMA_PERSONAL_ACCESS_TOKEN, or use WebSocket mode with Figma Plugin.",
105
+ );
106
+ }
107
+
108
+ export function requireWebSocket(context: ToolContext): asserts context is ToolContext & {
109
+ sendCommandToFigma: NonNullable<ToolContext["sendCommandToFigma"]>;
110
+ } {
111
+ if (!context.sendCommandToFigma)
112
+ throw new Error("WebSocket not available. This tool requires Figma Plugin connection.");
113
+ }