figma-code-agent-mcp 1.0.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.
Files changed (67) hide show
  1. package/dist/assetServer.d.ts +34 -0
  2. package/dist/assetServer.js +168 -0
  3. package/dist/codeGenerator/componentDetector.d.ts +57 -0
  4. package/dist/codeGenerator/componentDetector.js +171 -0
  5. package/dist/codeGenerator/index.d.ts +77 -0
  6. package/dist/codeGenerator/index.js +184 -0
  7. package/dist/codeGenerator/jsxGenerator.d.ts +46 -0
  8. package/dist/codeGenerator/jsxGenerator.js +182 -0
  9. package/dist/codeGenerator/styleConverter.d.ts +95 -0
  10. package/dist/codeGenerator/styleConverter.js +306 -0
  11. package/dist/hints.d.ts +14 -0
  12. package/dist/hints.js +105 -0
  13. package/dist/hub.d.ts +9 -0
  14. package/dist/hub.js +252 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +146 -0
  17. package/dist/sandbox.d.ts +18 -0
  18. package/dist/sandbox.js +154 -0
  19. package/dist/toolRegistry.d.ts +19 -0
  20. package/dist/toolRegistry.js +729 -0
  21. package/dist/tools/captureScreenshot.d.ts +28 -0
  22. package/dist/tools/captureScreenshot.js +31 -0
  23. package/dist/tools/cloneNode.d.ts +43 -0
  24. package/dist/tools/cloneNode.js +46 -0
  25. package/dist/tools/createFrame.d.ts +157 -0
  26. package/dist/tools/createFrame.js +114 -0
  27. package/dist/tools/createInstance.d.ts +38 -0
  28. package/dist/tools/createInstance.js +41 -0
  29. package/dist/tools/createRectangle.d.ts +108 -0
  30. package/dist/tools/createRectangle.js +77 -0
  31. package/dist/tools/createText.d.ts +81 -0
  32. package/dist/tools/createText.js +67 -0
  33. package/dist/tools/deleteNode.d.ts +15 -0
  34. package/dist/tools/deleteNode.js +18 -0
  35. package/dist/tools/execute.d.ts +17 -0
  36. package/dist/tools/execute.js +68 -0
  37. package/dist/tools/getCurrentPage.d.ts +16 -0
  38. package/dist/tools/getCurrentPage.js +19 -0
  39. package/dist/tools/getDesignContext.d.ts +42 -0
  40. package/dist/tools/getDesignContext.js +55 -0
  41. package/dist/tools/getLocalComponents.d.ts +20 -0
  42. package/dist/tools/getLocalComponents.js +23 -0
  43. package/dist/tools/getNode.d.ts +30 -0
  44. package/dist/tools/getNode.js +33 -0
  45. package/dist/tools/getSelection.d.ts +10 -0
  46. package/dist/tools/getSelection.js +13 -0
  47. package/dist/tools/getStyles.d.ts +17 -0
  48. package/dist/tools/getStyles.js +20 -0
  49. package/dist/tools/getVariables.d.ts +26 -0
  50. package/dist/tools/getVariables.js +29 -0
  51. package/dist/tools/moveNode.d.ts +28 -0
  52. package/dist/tools/moveNode.js +31 -0
  53. package/dist/tools/openInEditor.d.ts +21 -0
  54. package/dist/tools/openInEditor.js +98 -0
  55. package/dist/tools/searchNodes.d.ts +30 -0
  56. package/dist/tools/searchNodes.js +46 -0
  57. package/dist/tools/searchTools.d.ts +28 -0
  58. package/dist/tools/searchTools.js +28 -0
  59. package/dist/tools/swapComponent.d.ts +23 -0
  60. package/dist/tools/swapComponent.js +26 -0
  61. package/dist/tools/updateNode.d.ts +194 -0
  62. package/dist/tools/updateNode.js +163 -0
  63. package/dist/types.d.ts +101 -0
  64. package/dist/types.js +1 -0
  65. package/dist/websocket.d.ts +30 -0
  66. package/dist/websocket.js +282 -0
  67. package/package.json +29 -0
@@ -0,0 +1,31 @@
1
+ import { figmaWebSocket } from '../websocket.js';
2
+ export const moveNodeSchema = {
3
+ name: 'move_node',
4
+ description: 'Move a node to a new parent or reorder within its current parent. Use index to control position among siblings.',
5
+ inputSchema: {
6
+ type: 'object',
7
+ properties: {
8
+ nodeId: {
9
+ type: 'string',
10
+ description: 'ID of the node to move',
11
+ },
12
+ parentId: {
13
+ type: 'string',
14
+ description: 'ID of the new parent node. If not provided, keeps current parent.',
15
+ },
16
+ index: {
17
+ type: 'number',
18
+ description: 'Position among siblings (0 = first/top in layer order). If not provided, appends to end.',
19
+ },
20
+ returnScreenshot: {
21
+ type: 'boolean',
22
+ description: 'If true, returns a screenshot of the moved node for visual verification',
23
+ default: false,
24
+ },
25
+ },
26
+ required: ['nodeId'],
27
+ },
28
+ };
29
+ export async function moveNode(params) {
30
+ return figmaWebSocket.sendCommand('moveNode', params);
31
+ }
@@ -0,0 +1,21 @@
1
+ export declare const openInEditorSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ path: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ editor: {
12
+ type: string;
13
+ description: string;
14
+ enum: string[];
15
+ default: string;
16
+ };
17
+ };
18
+ required: never[];
19
+ };
20
+ };
21
+ export declare function openInEditor(params: Record<string, unknown>): Promise<string>;
@@ -0,0 +1,98 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { access } from 'node:fs/promises';
3
+ import { resolve } from 'node:path';
4
+ export const openInEditorSchema = {
5
+ name: 'open_in_editor',
6
+ description: 'Open a workspace folder (or file) in VS Code or WebStorm. Defaults to the current working directory.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ path: {
11
+ type: 'string',
12
+ description: 'Absolute or relative path to open. Defaults to the current working directory.',
13
+ },
14
+ editor: {
15
+ type: 'string',
16
+ description: 'Editor to open with',
17
+ enum: ['vscode', 'webstorm'],
18
+ default: 'vscode',
19
+ },
20
+ },
21
+ required: [],
22
+ },
23
+ };
24
+ const EDITORS = {
25
+ vscode: {
26
+ commands: ['code'],
27
+ name: 'VS Code',
28
+ },
29
+ webstorm: {
30
+ commands: ['webstorm', 'wstorm'],
31
+ name: 'WebStorm',
32
+ },
33
+ };
34
+ async function which(command) {
35
+ return new Promise((resolve) => {
36
+ execFile('which', [command], (error, stdout) => {
37
+ resolve(error ? null : stdout.trim());
38
+ });
39
+ });
40
+ }
41
+ async function findEditorBinary(editor) {
42
+ const config = EDITORS[editor];
43
+ if (!config) {
44
+ throw new Error(`Unknown editor: ${editor}. Supported: ${Object.keys(EDITORS).join(', ')}`);
45
+ }
46
+ for (const cmd of config.commands) {
47
+ const bin = await which(cmd);
48
+ if (bin)
49
+ return cmd;
50
+ }
51
+ // macOS fallback: try opening via application name
52
+ if (process.platform === 'darwin') {
53
+ const appNames = {
54
+ vscode: ['Visual Studio Code', 'Visual Studio Code - Insiders'],
55
+ webstorm: ['WebStorm'],
56
+ };
57
+ for (const app of appNames[editor] || []) {
58
+ try {
59
+ await access(`/Applications/${app}.app`);
60
+ return `open -a "${app}"`;
61
+ }
62
+ catch { /* not found */ }
63
+ }
64
+ }
65
+ throw new Error(`${config.name} CLI not found. ` +
66
+ (editor === 'vscode'
67
+ ? 'Install the "code" command: VS Code → Cmd+Shift+P → "Shell Command: Install \'code\' command in PATH"'
68
+ : 'Ensure the "webstorm" CLI launcher is installed: WebStorm → Tools → Create Command-line Launcher'));
69
+ }
70
+ export async function openInEditor(params) {
71
+ const editor = params.editor || 'vscode';
72
+ const targetPath = resolve(params.path || process.cwd());
73
+ // Verify path exists
74
+ await access(targetPath).catch(() => {
75
+ throw new Error(`Path does not exist: ${targetPath}`);
76
+ });
77
+ const bin = await findEditorBinary(editor);
78
+ return new Promise((resolve, reject) => {
79
+ // Handle "open -a ..." macOS fallback
80
+ if (bin.startsWith('open ')) {
81
+ const parts = bin.split(' ');
82
+ execFile(parts[0], [...parts.slice(1), targetPath], (error) => {
83
+ if (error)
84
+ reject(new Error(`Failed to open ${EDITORS[editor].name}: ${error.message}`));
85
+ else
86
+ resolve(`Opened ${targetPath} in ${EDITORS[editor].name}`);
87
+ });
88
+ }
89
+ else {
90
+ execFile(bin, [targetPath], (error) => {
91
+ if (error)
92
+ reject(new Error(`Failed to open ${EDITORS[editor].name}: ${error.message}`));
93
+ else
94
+ resolve(`Opened ${targetPath} in ${EDITORS[editor].name}`);
95
+ });
96
+ }
97
+ });
98
+ }
@@ -0,0 +1,30 @@
1
+ export declare const searchNodesSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ query: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ type: {
12
+ type: string;
13
+ description: string;
14
+ enum: string[];
15
+ };
16
+ caseSensitive: {
17
+ type: string;
18
+ description: string;
19
+ default: boolean;
20
+ };
21
+ limit: {
22
+ type: string;
23
+ description: string;
24
+ default: number;
25
+ };
26
+ };
27
+ required: never[];
28
+ };
29
+ };
30
+ export declare function searchNodes(params: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,46 @@
1
+ import { figmaWebSocket } from '../websocket.js';
2
+ export const searchNodesSchema = {
3
+ name: 'search_nodes',
4
+ description: 'Search for nodes in the current page by name, type, or text content. Returns lightweight results with id, name, type, and path in the tree hierarchy.',
5
+ inputSchema: {
6
+ type: 'object',
7
+ properties: {
8
+ query: {
9
+ type: 'string',
10
+ description: 'Search query - matches against node name or text content (case-insensitive)',
11
+ },
12
+ type: {
13
+ type: 'string',
14
+ description: 'Filter by node type (e.g., FRAME, TEXT, RECTANGLE, INSTANCE, COMPONENT)',
15
+ enum: [
16
+ 'FRAME',
17
+ 'TEXT',
18
+ 'RECTANGLE',
19
+ 'ELLIPSE',
20
+ 'LINE',
21
+ 'VECTOR',
22
+ 'INSTANCE',
23
+ 'COMPONENT',
24
+ 'COMPONENT_SET',
25
+ 'GROUP',
26
+ 'SECTION',
27
+ 'BOOLEAN_OPERATION',
28
+ ],
29
+ },
30
+ caseSensitive: {
31
+ type: 'boolean',
32
+ description: 'Whether search should be case-sensitive (default: false)',
33
+ default: false,
34
+ },
35
+ limit: {
36
+ type: 'number',
37
+ description: 'Maximum number of results to return (default: 50)',
38
+ default: 50,
39
+ },
40
+ },
41
+ required: [],
42
+ },
43
+ };
44
+ export async function searchNodes(params) {
45
+ return figmaWebSocket.sendCommand('searchNodes', params);
46
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Schema for the search_tools tool — progressive discovery of figma.* API methods.
3
+ */
4
+ export declare const searchToolsSchema: {
5
+ name: string;
6
+ description: string;
7
+ inputSchema: {
8
+ type: "object";
9
+ properties: {
10
+ query: {
11
+ type: string;
12
+ description: string;
13
+ };
14
+ category: {
15
+ type: string;
16
+ enum: string[];
17
+ description: string;
18
+ };
19
+ detail_level: {
20
+ type: string;
21
+ enum: string[];
22
+ description: string;
23
+ default: string;
24
+ };
25
+ };
26
+ required: string[];
27
+ };
28
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Schema for the search_tools tool — progressive discovery of figma.* API methods.
3
+ */
4
+ export const searchToolsSchema = {
5
+ name: 'search_tools',
6
+ description: 'Search available figma.* API methods for use with the execute tool. Use this to discover method names, parameters, and usage examples.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ query: {
11
+ type: 'string',
12
+ description: 'Search query — matches against method names and descriptions (e.g., "create", "layout", "text", "component")',
13
+ },
14
+ category: {
15
+ type: 'string',
16
+ enum: ['create', 'read', 'update', 'delete', 'tokens', 'components', 'accessibility', 'figjam'],
17
+ description: 'Filter by operation category. Use "figjam" for FigJam-specific methods (sections, stickies, shapes).',
18
+ },
19
+ detail_level: {
20
+ type: 'string',
21
+ enum: ['name', 'description', 'full'],
22
+ description: 'Amount of detail: "name" = just names, "description" = names + descriptions, "full" = everything including parameters and examples. Default: "description"',
23
+ default: 'description',
24
+ },
25
+ },
26
+ required: ['query'],
27
+ },
28
+ };
@@ -0,0 +1,23 @@
1
+ export declare const swapComponentSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ instanceId: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ newComponentId: {
12
+ type: string;
13
+ description: string;
14
+ };
15
+ newComponentKey: {
16
+ type: string;
17
+ description: string;
18
+ };
19
+ };
20
+ required: string[];
21
+ };
22
+ };
23
+ export declare function swapComponent(params: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,26 @@
1
+ import { figmaWebSocket } from '../websocket.js';
2
+ export const swapComponentSchema = {
3
+ name: 'swap_component',
4
+ description: 'Swap a component instance to a different component or variant. Use this to change variants or swap nested components within instances.',
5
+ inputSchema: {
6
+ type: 'object',
7
+ properties: {
8
+ instanceId: {
9
+ type: 'string',
10
+ description: 'ID of the instance node to swap',
11
+ },
12
+ newComponentId: {
13
+ type: 'string',
14
+ description: 'ID of the new component to swap to (for local components)',
15
+ },
16
+ newComponentKey: {
17
+ type: 'string',
18
+ description: 'Key of the new component to swap to (for library components)',
19
+ },
20
+ },
21
+ required: ['instanceId'],
22
+ },
23
+ };
24
+ export async function swapComponent(params) {
25
+ return figmaWebSocket.sendCommand('swapComponent', params);
26
+ }
@@ -0,0 +1,194 @@
1
+ export declare const updateNodeSchema: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ nodeId: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ properties: {
12
+ type: string;
13
+ description: string;
14
+ properties: {
15
+ name: {
16
+ type: string;
17
+ description: string;
18
+ };
19
+ x: {
20
+ type: string;
21
+ description: string;
22
+ };
23
+ y: {
24
+ type: string;
25
+ description: string;
26
+ };
27
+ width: {
28
+ type: string;
29
+ description: string;
30
+ };
31
+ height: {
32
+ type: string;
33
+ description: string;
34
+ };
35
+ fillColor: {
36
+ type: string;
37
+ description: string;
38
+ properties: {
39
+ r: {
40
+ type: string;
41
+ minimum: number;
42
+ maximum: number;
43
+ };
44
+ g: {
45
+ type: string;
46
+ minimum: number;
47
+ maximum: number;
48
+ };
49
+ b: {
50
+ type: string;
51
+ minimum: number;
52
+ maximum: number;
53
+ };
54
+ a: {
55
+ type: string;
56
+ minimum: number;
57
+ maximum: number;
58
+ default: number;
59
+ };
60
+ };
61
+ required: string[];
62
+ };
63
+ opacity: {
64
+ type: string;
65
+ description: string;
66
+ minimum: number;
67
+ maximum: number;
68
+ };
69
+ visible: {
70
+ type: string;
71
+ description: string;
72
+ };
73
+ locked: {
74
+ type: string;
75
+ description: string;
76
+ };
77
+ text: {
78
+ type: string;
79
+ description: string;
80
+ };
81
+ fontSize: {
82
+ type: string;
83
+ description: string;
84
+ };
85
+ fontWeight: {
86
+ type: string;
87
+ description: string;
88
+ };
89
+ cornerRadius: {
90
+ type: string;
91
+ description: string;
92
+ };
93
+ strokeColor: {
94
+ type: string;
95
+ description: string;
96
+ properties: {
97
+ r: {
98
+ type: string;
99
+ minimum: number;
100
+ maximum: number;
101
+ };
102
+ g: {
103
+ type: string;
104
+ minimum: number;
105
+ maximum: number;
106
+ };
107
+ b: {
108
+ type: string;
109
+ minimum: number;
110
+ maximum: number;
111
+ };
112
+ a: {
113
+ type: string;
114
+ minimum: number;
115
+ maximum: number;
116
+ default: number;
117
+ };
118
+ };
119
+ required: string[];
120
+ };
121
+ strokeWeight: {
122
+ type: string;
123
+ description: string;
124
+ };
125
+ copyFillsFrom: {
126
+ type: string;
127
+ description: string;
128
+ };
129
+ copyStrokesFrom: {
130
+ type: string;
131
+ description: string;
132
+ };
133
+ layoutMode: {
134
+ type: string;
135
+ enum: string[];
136
+ description: string;
137
+ };
138
+ primaryAxisSizingMode: {
139
+ type: string;
140
+ enum: string[];
141
+ description: string;
142
+ };
143
+ counterAxisSizingMode: {
144
+ type: string;
145
+ enum: string[];
146
+ description: string;
147
+ };
148
+ primaryAxisAlignItems: {
149
+ type: string;
150
+ enum: string[];
151
+ description: string;
152
+ };
153
+ counterAxisAlignItems: {
154
+ type: string;
155
+ enum: string[];
156
+ description: string;
157
+ };
158
+ itemSpacing: {
159
+ type: string;
160
+ description: string;
161
+ };
162
+ paddingTop: {
163
+ type: string;
164
+ description: string;
165
+ };
166
+ paddingBottom: {
167
+ type: string;
168
+ description: string;
169
+ };
170
+ paddingLeft: {
171
+ type: string;
172
+ description: string;
173
+ };
174
+ paddingRight: {
175
+ type: string;
176
+ description: string;
177
+ };
178
+ layoutWrap: {
179
+ type: string;
180
+ enum: string[];
181
+ description: string;
182
+ };
183
+ };
184
+ };
185
+ returnScreenshot: {
186
+ type: string;
187
+ description: string;
188
+ default: boolean;
189
+ };
190
+ };
191
+ required: string[];
192
+ };
193
+ };
194
+ export declare function updateNode(params: Record<string, unknown>): Promise<unknown>;