@ufira/vibma 0.3.2 → 1.0.0-rc1

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.
@@ -22,6 +22,7 @@ __export(registry_exports, {
22
22
  registerTools: () => registerTools
23
23
  });
24
24
  module.exports = __toCommonJS(registry_exports);
25
+ var import_zod = require("zod");
25
26
 
26
27
  // src/tools/types.ts
27
28
  var MAX_RESPONSE_CHARS = 5e4;
@@ -46,21 +47,964 @@ function mcpError(prefix, error) {
46
47
  return { content: [{ type: "text", text: `${prefix}: ${msg}` }] };
47
48
  }
48
49
 
50
+ // src/tools/generated/help.ts
51
+ var helpDirectory = `# Available Endpoints
52
+
53
+ [design-system]
54
+ components Create and manage reusable components and variant sets.
55
+ fonts Search available fonts in Figma.
56
+ instances Create and manage component instances.
57
+ styles CRUD for local paint, text, effect, and grid styles.
58
+ variable_collections CRUD for variable collections \u2014 the document-level API for design tokens.
59
+ variables Search and update design variables within a collection.
60
+
61
+ [connection]
62
+ connection Manage the Figma plugin connection.
63
+
64
+ [document]
65
+ document Navigate and manage Figma pages (canvases) in the document.
66
+ version_history Save named versions to the Figma file's version history.
67
+
68
+ [creation]
69
+ frames Create and manage frames, shapes, auto-layout containers, sections, and SVG nodes.
70
+ text Create and manage text nodes.
71
+
72
+ [quality]
73
+ lint Run design quality and accessibility checks.
74
+
75
+ [interaction]
76
+ prototyping Manage prototype interactions, reactions, and navigation flows.
77
+
78
+ [node-inspection]
79
+ selection Read and set the current Figma selection.
80
+
81
+ Topics:
82
+ missing_tools Why create or edit tools are missing and how to fix it
83
+
84
+ Use help(topic: "<endpoint>") for endpoint details.
85
+ Use help(topic: "<endpoint>.<method>") for method details.`;
86
+ var helpEndpoints = {
87
+ "components": {
88
+ "summary": '# components\nCreate and manage reusable components and variant sets.\n\nMethods:\n clone Duplicate nodes [create]\n audit Run lint on a node \u2014 returns severity-ranked findings [read]\n reparent Move nodes into a new parent [edit]\n list List local component names (variant sets as single entries) [read]\n get Get component detail \u2014 property definitions + ID for instances.create [read]\n create Create components [create]\n update Add, edit, or delete component properties [edit]\n delete Delete components or component sets [edit]\n\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).\n// ---\n// visible: false hides the node. Omitted from response when true (the default).\n// locked: true prevents editing in Figma UI. Omitted when false (the default).\n// rotation: degrees (0-360). Omitted when 0.\n// blendMode: layer blend mode. Omitted when PASS_THROUGH (the default).\n// layoutPositioning: ABSOLUTE = floating inside auto-layout parent. Omitted when AUTO (the default).\n// minWidth/maxWidth/minHeight/maxHeight: responsive constraints for auto-layout children.\n// constraints: position behavior in non-auto-layout parents. Ignored inside auto-layout frames.\n// bindings: bind design variables to node properties. field uses slash path: "fills/0/color" (first fill), "strokes/0/color", "opacity", "width", "height", "cornerRadius", "paddingLeft", "itemSpacing".\n// explicitMode: pin a variable mode on this node. Use { collectionName, modeName } (preferred) or { collectionId, modeId }.\n// properties: escape hatch \u2014 set any Figma node property directly. Use only when no dedicated field exists.\ninterface Node {\n id: string; name: string; type: string;\n visible?: boolean; // omitted when true\n locked?: boolean; // omitted when false\n opacity?: number; // omitted when 1\n rotation?: number; // omitted when 0\n blendMode?: string; // omitted when PASS_THROUGH\n layoutPositioning?: "AUTO" | "ABSOLUTE";\n layoutSizingHorizontal?: "FIXED" | "HUG" | "FILL";\n layoutSizingVertical?: "FIXED" | "HUG" | "FILL";\n minWidth?: number; maxWidth?: number; minHeight?: number; maxHeight?: number;\n absoluteBoundingBox: { x: number; y: number; width: number; height: number };\n fills?: Paint[]; // solid: {type: "SOLID", color: {r, g, b, a}}\n strokes?: Paint[];\n effects?: Effect[]; // DROP_SHADOW | INNER_SHADOW | LAYER_BLUR | BACKGROUND_BLUR\n children?: NodeStub[]; // stubs: {id, name, type} \u2014 use depth to expand\n}\n// PatchItem uses flat params matching create shape \u2014 no nested sub-objects.\n// Fill/stroke/corner/layout/text params are identical to frames.create and text.create.\n// Unknown keys produce a warning, preventing silent failures.\n// Components are reusable design elements. Instances stay linked to the component and inherit changes.\n// Workflow: create component (with properties) \u2192 add children \u2192 create instances via instances.create.\n// ---\n// A component set (variant set) groups related components as variants (e.g. Button/Primary, Button/Secondary).\n// Property types: BOOLEAN (toggle visibility), TEXT (editable text), INSTANCE_SWAP (swap child instance), VARIANT (variant picker).\n// exposeText: when creating from_node, text children become editable TEXT properties on the component.\n// Auto-bind: TEXT properties auto-bind to text children with matching names (case-insensitive).\n// Example: properties:[{propertyName:"Label", type:"TEXT", defaultValue:"Click"}] binds to a child text node named "Label".\n// text.create accepts componentPropertyName to bind on creation \u2014 walks up ancestors to find the nearest component.\n// For nested text (text inside frames inside a component), componentPropertyName resolves via ancestor walk. Alternatively, pass componentId explicitly.\n// For existing nodes with many text children, prefer components(method:"create", type:"from_node", exposeText:true) \u2014 it auto-discovers, creates TEXT properties, and binds all text nodes in one operation.\n// Property keys: read returns clean names ("Label"), write requires the #suffix ("Label#1:0"). Call components.get(id) to discover exact keys before edit/delete.\n// ComponentItem accepts the same params as FrameItem (layout, fill, stroke, sizing, min/max).\n// A component IS a frame \u2014 create it directly with all layout properties, then add children.\n// SIZING: Components with text need a width constraint \u2014 set width + layoutSizingHorizontal:"FIXED".\n// Without it, text won\'t wrap and the component grows unboundedly.\n// HUG on both axes is only correct for intrinsically-sized elements (buttons, badges, icons).\n// action: "add" (default) \u2014 requires type + defaultValue. "edit" \u2014 pass defaultValue to change value, name to rename property. "delete" \u2014 just propertyName#suffix.\n// action: "rename_variant" \u2014 renames a variant option VALUE (not the property). Pass defaultValue=current option name, name=new option name.\n// For VARIANT properties: "edit" with defaultValue reorders children to set the default variant.\n\nUse components(method: "help", topic: "<method>") for method details.',
89
+ "methods": {
90
+ "clone": "# components.clone\nDuplicate nodes\n\nParams:\n id (string, required) \u2014 Node ID\n parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
91
+ "audit": '# components.audit\nRun lint on a node \u2014 returns severity-ranked findings\n\nParams:\n id (string, required) \u2014 Node ID to audit\n rules (string[], optional) \u2014 Rules to check. Default: ["all"]. Categories: "component", "composition", "token", "naming", "wcag".\n maxDepth (number, optional) \u2014 Max tree depth (default: 10)\n maxFindings (number, optional) \u2014 Max findings (default: 50)',
92
+ "reparent": "# components.reparent\nMove nodes into a new parent\n\nParams:\n items (array, required) \u2014 Array of {id, parentId, index?}\n id (string, required)\n parentId (string, required)\n index (number, optional)",
93
+ "list": "# components.list\nList local component names (variant sets as single entries)\n\nParams:\n query (string, optional) \u2014 Name search query (case-insensitive substring match)\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)",
94
+ "get": "# components.get\nGet component detail \u2014 property definitions + ID for instances.create\n\nParams:\n id (string, optional) \u2014 Component or component set ID\n names (string[], optional) \u2014 Batch lookup by name (case-insensitive). Either id or names is required.",
95
+ "create": `# components.create
96
+ Create components
97
+
98
+ Example: components(method:"create", type:"component", items:[{name:"Card", layoutMode:"VERTICAL", padding:"16", itemSpacing:"8", fillVariableName:"bg/surface", children:[{type:"text", text:"Title", componentPropertyName:"Title"}, {type:"text", text:"Description", fontSize:14, componentPropertyName:"Description"}], properties:[{propertyName:"Show Icon", type:"BOOLEAN", defaultValue:true}]}])
99
+
100
+ Discriminant: type (component | from_node | variant_set)
101
+
102
+ ## component \u2014 Create component with full frame properties (layout, fill, stroke, sizing). A component IS a frame \u2014 build directly, no need to create a frame first.
103
+ name (string, required) \u2014 Component name
104
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
105
+ x (number, optional) \u2014 X position (default: 0)
106
+ y (number, optional) \u2014 Y position (default: 0)
107
+ width (number, optional) \u2014 Width (default: 100)
108
+ height (number, optional) \u2014 Height (default: 100)
109
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
110
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
111
+ visible (boolean, optional) \u2014 Show/hide (default true)
112
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
113
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
114
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
115
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
116
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
117
+ fillStyleName (string, optional) \u2014 Paint style name for fill
118
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
119
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
120
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
121
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
122
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
123
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
124
+ strokeTopWeight (string, optional)
125
+ strokeBottomWeight (string, optional)
126
+ strokeLeftWeight (string, optional)
127
+ strokeRightWeight (string, optional)
128
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
129
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
130
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
131
+ topLeftRadius (string, optional)
132
+ topRightRadius (string, optional)
133
+ bottomRightRadius (string, optional)
134
+ bottomLeftRadius (string, optional)
135
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
136
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
137
+ layoutWrap (NO_WRAP | WRAP, optional)
138
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
139
+ paddingTop (string, optional)
140
+ paddingRight (string, optional)
141
+ paddingBottom (string, optional)
142
+ paddingLeft (string, optional)
143
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
144
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
145
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
146
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
147
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
148
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
149
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
150
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
151
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
152
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
153
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
154
+ description (string, optional) \u2014 Component description (shown in Figma's component panel)
155
+ children (array, optional) \u2014 Inline child nodes. Text: {type:"text", text, componentPropertyName?, fontFamily?, fontSize?, fontColor?}. Frame: {type:"frame", name?, layoutMode?, fillColor?, children?}. Text with componentPropertyName auto-creates and binds a TEXT property \u2014 no need to add it to properties separately.
156
+ properties (array, optional) \u2014 Component properties to define at creation: [{propertyName, type, defaultValue}]. TEXT properties for inline children with componentPropertyName are created automatically.
157
+ propertyName (string, required) \u2014 Property name
158
+ type (BOOLEAN | TEXT | INSTANCE_SWAP, required) \u2014 Property type
159
+ defaultValue (string_or_boolean, required) \u2014 Default value
160
+ preferredValues (array, optional) \u2014 Preferred values for INSTANCE_SWAP
161
+
162
+ ## from_node \u2014 Convert existing nodes to components. Text children auto-exposed as editable properties (exposeText: true).
163
+ nodeId (string, required) \u2014 Node ID to convert
164
+ exposeText (boolean, optional) \u2014 Auto-expose text as editable properties (default: true)
165
+
166
+ ## variant_set \u2014 Combine components into a variant set. The resulting set is a frame \u2014 accepts all frame properties for layout/styling.
167
+ name (string, optional) \u2014 Node name
168
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
169
+ x (number, optional) \u2014 X position (default: 0)
170
+ y (number, optional) \u2014 Y position (default: 0)
171
+ width (number, optional) \u2014 Width (default: 100)
172
+ height (number, optional) \u2014 Height (default: 100)
173
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
174
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
175
+ visible (boolean, optional) \u2014 Show/hide (default true)
176
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
177
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
178
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
179
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
180
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
181
+ fillStyleName (string, optional) \u2014 Paint style name for fill
182
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
183
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
184
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
185
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
186
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
187
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
188
+ strokeTopWeight (string, optional)
189
+ strokeBottomWeight (string, optional)
190
+ strokeLeftWeight (string, optional)
191
+ strokeRightWeight (string, optional)
192
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
193
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
194
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
195
+ topLeftRadius (string, optional)
196
+ topRightRadius (string, optional)
197
+ bottomRightRadius (string, optional)
198
+ bottomLeftRadius (string, optional)
199
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
200
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
201
+ layoutWrap (NO_WRAP | WRAP, optional)
202
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
203
+ paddingTop (string, optional)
204
+ paddingRight (string, optional)
205
+ paddingBottom (string, optional)
206
+ paddingLeft (string, optional)
207
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
208
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
209
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
210
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
211
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
212
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
213
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
214
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
215
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
216
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
217
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
218
+ componentIds (string[], required) \u2014 Component IDs to combine (min 2)
219
+ variantPropertyName (string, optional) \u2014 Rename the auto-generated variant property (default: 'Property 1')`,
220
+ "update": '# components.update\nAdd, edit, or delete component properties\n\nExample: components(method:"update", items:[{id:"1:23", propertyName:"Label", action:"edit", defaultValue:"Click Me"}])\n\nParams:\n items (UpdatePropertyItem[], required) \u2014 Array of {id, propertyName, action?, type?, defaultValue?, name?, preferredValues?}\n id (string, required) \u2014 Component or component set ID\n propertyName (string, required) \u2014 Property name with #suffix for edit/delete (e.g. "Label#1:0"). Call components.get to find exact keys. For add, plain name works.\n action (add | edit | delete | rename_variant, optional) \u2014 "add" (default): requires type + defaultValue. "edit": pass defaultValue to change default, name to rename property. "delete": just propertyName. "rename_variant": pass defaultValue=current option name, name=new option name.\n type (BOOLEAN | TEXT | INSTANCE_SWAP | VARIANT, optional) \u2014 Property type (required for add)\n defaultValue (string_or_boolean, optional) \u2014 Default value (add/edit). For rename_variant: the CURRENT option name to rename\n name (string, optional) \u2014 New name \u2014 for edit: renames the property itself, for rename_variant: the new option value name\n preferredValues (array, optional) \u2014 Preferred values for INSTANCE_SWAP\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.',
221
+ "delete": "# components.delete\nDelete components or component sets\n\nParams:\n id (string, required) \u2014 Component or component set ID"
222
+ }
223
+ },
224
+ "connection": {
225
+ "summary": '# connection\nManage the Figma plugin connection.\n\nMethods:\n create Join a relay channel (required first step before any other tool) [read]\n get Verify end-to-end connection to Figma [read]\n list Inspect which clients (MCP, plugin) are connected to each channel [read]\n delete Disconnect all clients (MCP server and Figma plugin) from a channel and reset its state [edit]\n\n// Connection manages the WebSocket link between the MCP server and the Figma plugin.\n// Channels are named rooms \u2014 both the MCP server and Figma plugin must join the same channel to communicate.\n// Workflow: connection(method:"create") to join a channel \u2192 connection(method:"get") to verify Figma plugin is connected.\n// If get times out (5s), the Figma plugin is not running or not on the same channel.\n// list shows all active channels and their connected clients. delete factory-resets a channel.\n\nUse connection(method: "help", topic: "<method>") for method details.',
226
+ "methods": {
227
+ "create": "# connection.create\nJoin a relay channel (required first step before any other tool)\n\nParams:\n channel (string, optional) \u2014 The channel name displayed in the Figma plugin panel. Defaults to 'vibma' if omitted.",
228
+ "get": "# connection.get\nVerify end-to-end connection to Figma\n\nNo params.",
229
+ "list": "# connection.list\nInspect which clients (MCP, plugin) are connected to each channel\n\nNo params.",
230
+ "delete": "# connection.delete\nDisconnect all clients (MCP server and Figma plugin) from a channel and reset its state\n\nParams:\n channel (string, optional) \u2014 Channel to reset. Defaults to 'vibma'."
231
+ }
232
+ },
233
+ "document": {
234
+ "summary": '# document\nNavigate and manage Figma pages (canvases) in the document.\n\nMethods:\n get Get current page with top-level children [read]\n list Get document name and list all pages [read]\n set Switch to a page by ID or name. At least one of pageId or pageName must be provided. [read]\n create Create a new page [create]\n update Rename a page [edit]\n\n// A Figma document contains pages \u2014 each page is an independent canvas with its own node tree.\n// The "current page" is where all node operations happen. Use document.set to switch pages before working with nodes.\n// Page IDs look like "0:1", "1:1", etc. The first page is always "0:1".\n// get returns the current page with its top-level children as stubs. list returns all pages in the document.\n\nUse document(method: "help", topic: "<method>") for method details.',
235
+ "methods": {
236
+ "get": "# document.get\nGet current page with top-level children\n\nNo params.",
237
+ "list": "# document.list\nGet document name and list all pages\n\nNo params.",
238
+ "set": "# document.set\nSwitch to a page by ID or name. At least one of pageId or pageName must be provided.\n\nParams:\n pageId (string, optional) \u2014 Page ID\n pageName (string, optional) \u2014 Page name (case-insensitive, substring match)",
239
+ "create": "# document.create\nCreate a new page\n\nParams:\n name (string, optional) \u2014 Page name (default: 'New Page')",
240
+ "update": "# document.update\nRename a page\n\nParams:\n newName (string, required) \u2014 New page name\n pageId (string, optional) \u2014 Page ID (default: current page)"
241
+ }
242
+ },
243
+ "fonts": {
244
+ "summary": '# fonts\nSearch available fonts in Figma.\n\nMethods:\n list List available font families, optionally filtered by name [read]\n\n// Returns font family names installed in the Figma environment. Use to verify a fontFamily before text.create or styles.create.\n// query filters by family name substring (case-insensitive), e.g. query:"inter" matches "Inter", "Inter Tight".\n// ---\n// Default response: just family names. Set includeStyles:true to also get available styles per family (e.g. "Regular", "Bold", "Italic").\n// Use fonts.list with query to narrow results before creating text with specific fontFamily + fontStyle.\n\nUse fonts(method: "help", topic: "<method>") for method details.',
245
+ "methods": {
246
+ "list": '# fonts.list\nList available font families, optionally filtered by name\n\nExample: fonts(method:"list", query:"inter")\n\nParams:\n query (string, optional) \u2014 Filter by family name (case-insensitive substring)\n includeStyles (boolean, optional) \u2014 Include available styles per family (default: false)\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)'
247
+ }
248
+ },
249
+ "frames": {
250
+ "summary": '# frames\nCreate and manage frames, shapes, auto-layout containers, sections, and SVG nodes.\n\nMethods:\n get Get serialized node data [read]\n list Search for nodes (returns stubs only \u2014 use get with depth for full properties) [read]\n update Patch node properties [edit]\n delete Delete nodes [edit]\n clone Duplicate nodes [create]\n audit Run lint on a node \u2014 returns severity-ranked findings [read]\n reparent Move nodes into a new parent [edit]\n create Create frame-like containers [create]\n export Export a node as PNG, JPG, SVG, SVG_STRING, or PDF [read]\n\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).\n// ---\n// visible: false hides the node. Omitted from response when true (the default).\n// locked: true prevents editing in Figma UI. Omitted when false (the default).\n// rotation: degrees (0-360). Omitted when 0.\n// blendMode: layer blend mode. Omitted when PASS_THROUGH (the default).\n// layoutPositioning: ABSOLUTE = floating inside auto-layout parent. Omitted when AUTO (the default).\n// minWidth/maxWidth/minHeight/maxHeight: responsive constraints for auto-layout children.\n// constraints: position behavior in non-auto-layout parents. Ignored inside auto-layout frames.\n// bindings: bind design variables to node properties. field uses slash path: "fills/0/color" (first fill), "strokes/0/color", "opacity", "width", "height", "cornerRadius", "paddingLeft", "itemSpacing".\n// explicitMode: pin a variable mode on this node. Use { collectionName, modeName } (preferred) or { collectionId, modeId }.\n// properties: escape hatch \u2014 set any Figma node property directly. Use only when no dedicated field exists.\ninterface Node {\n id: string; name: string; type: string;\n visible?: boolean; // omitted when true\n locked?: boolean; // omitted when false\n opacity?: number; // omitted when 1\n rotation?: number; // omitted when 0\n blendMode?: string; // omitted when PASS_THROUGH\n layoutPositioning?: "AUTO" | "ABSOLUTE";\n layoutSizingHorizontal?: "FIXED" | "HUG" | "FILL";\n layoutSizingVertical?: "FIXED" | "HUG" | "FILL";\n minWidth?: number; maxWidth?: number; minHeight?: number; maxHeight?: number;\n absoluteBoundingBox: { x: number; y: number; width: number; height: number };\n fills?: Paint[]; // solid: {type: "SOLID", color: {r, g, b, a}}\n strokes?: Paint[];\n effects?: Effect[]; // DROP_SHADOW | INNER_SHADOW | LAYER_BLUR | BACKGROUND_BLUR\n children?: NodeStub[]; // stubs: {id, name, type} \u2014 use depth to expand\n}\n// PatchItem uses flat params matching create shape \u2014 no nested sub-objects.\n// Fill/stroke/corner/layout/text params are identical to frames.create and text.create.\n// Unknown keys produce a warning, preventing silent failures.\n// Frames are the primary container in Figma. Use auto_layout for responsive containers.\n// Sizing: FIXED = explicit size, HUG = shrink to children, FILL = expand to fill parent.\n// Fill: pass fills:[{type:"SOLID", color:"#hex"}] or [] for transparent. Shorthand: fillColor:"#3B82F6" (auto-binds to matching variable/style).\n// Also: fillVariableName:"bg/primary", fillStyleName:"Surface/Primary".\n// Stroke: pass strokes:[{type:"SOLID", color:"#hex"}] or [] to clear. Shorthand: strokeColor:"#000", strokeVariableName:"border/default".\n// Token fields (cornerRadius, opacity, itemSpacing, padding, strokeWeight): pass number for value, string for variable name/ID.\n// ---\n// SIZING: Always think about both axes. Containers with text need a width constraint \u2014 set width + layoutSizingHorizontal:"FIXED".\n// HUG/HUG is only correct for intrinsically-sized elements (buttons, badges, icons).\n// Smart defaults inside auto-layout parent: cross-axis defaults to FILL, primary axis stays HUG.\n// FILL only works inside an auto-layout parent. Use FIXED for top-level frames.\n// minWidth/maxWidth/minHeight/maxHeight: responsive constraints for auto-layout children.\n// clipsContent: true (default) clips children to the frame bounds. Set false for overflow-visible.\n// Sections are top-level organizers (like artboards) \u2014 they cannot be nested inside frames.\n// Shape primitives: rectangle, ellipse, line \u2014 for decorative/visual elements (not containers).\n// group: wraps existing nodes into a Group. boolean_operation: UNION/SUBTRACT/INTERSECT/EXCLUDE combines shapes.\n// SVG create: pass raw SVG markup string (e.g. "<svg>...</svg>") \u2014 Figma converts it to vector nodes.\n\nUse frames(method: "help", topic: "<method>") for method details.',
251
+ "methods": {
252
+ "get": '# frames.get\nGet serialized node data\n\nParams:\n id (string, required) \u2014 Node ID\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.\n verbose (boolean, optional) \u2014 Include all properties (bounding box, constraints, text style details). Default false \u2014 returns slim, actionable output.',
253
+ "list": '# frames.list\nSearch for nodes (returns stubs only \u2014 use get with depth for full properties)\n\nParams:\n query (string, optional) \u2014 Name search query (case-insensitive substring match)\n types (string[], optional) \u2014 Filter by node types (e.g. ["FRAME", "TEXT"])\n parentId (string, optional) \u2014 Search only within this subtree\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)',
254
+ "update": `# frames.update
255
+ Patch node properties
256
+
257
+ Params:
258
+ items (PatchItem[], required) \u2014 Array of {id, ...properties} to patch
259
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
260
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
261
+ fillStyleName (string, optional) \u2014 Paint style name for fill
262
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
263
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
264
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
265
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
266
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
267
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
268
+ strokeTopWeight (string, optional)
269
+ strokeBottomWeight (string, optional)
270
+ strokeLeftWeight (string, optional)
271
+ strokeRightWeight (string, optional)
272
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
273
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
274
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
275
+ topLeftRadius (string, optional)
276
+ topRightRadius (string, optional)
277
+ bottomRightRadius (string, optional)
278
+ bottomLeftRadius (string, optional)
279
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
280
+ visible (boolean, optional) \u2014 Show/hide (default true)
281
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
282
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
283
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
284
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
285
+ layoutWrap (NO_WRAP | WRAP, optional)
286
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
287
+ paddingTop (string, optional)
288
+ paddingRight (string, optional)
289
+ paddingBottom (string, optional)
290
+ paddingLeft (string, optional)
291
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
292
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
293
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
294
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
295
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
296
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
297
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
298
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
299
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
300
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
301
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
302
+ fontSize (number, optional) \u2014 Font size
303
+ fontFamily (string, optional) \u2014 Font family
304
+ fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
305
+ fontWeight (number, optional) \u2014 100-900. Ignored when fontStyle is set.
306
+ fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
307
+ fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
308
+ fontColorStyleName (string, optional) \u2014 Apply paint style \u2014 overrides fontColor
309
+ textStyleId (string, optional) \u2014 Apply text style by ID \u2014 overrides fontSize/fontWeight
310
+ textStyleName (string, optional) \u2014 Text style by name (case-insensitive)
311
+ textAlignHorizontal (LEFT | CENTER | RIGHT | JUSTIFIED, optional)
312
+ textAlignVertical (TOP | CENTER | BOTTOM, optional)
313
+ textAutoResize (NONE | WIDTH_AND_HEIGHT | HEIGHT | TRUNCATE, optional)
314
+ id (string, required)
315
+ name (string, optional) \u2014 Rename node
316
+ rotation (number, optional) \u2014 Degrees (0-360)
317
+ x (number, optional)
318
+ y (number, optional)
319
+ width (number, optional)
320
+ height (number, optional)
321
+ clearFill (boolean, optional) \u2014 Remove all fills
322
+ effects (array, optional) \u2014 Effect array (DROP_SHADOW, INNER_SHADOW, LAYER_BLUR, BACKGROUND_BLUR)
323
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
324
+ constraints (object, optional)
325
+ bindings (array, optional) \u2014 Bind variables to properties. field path examples: 'fills/0/color', 'strokes/0/color', 'opacity', 'width', 'cornerRadius', 'itemSpacing'.
326
+ field (string, required)
327
+ variableName (string, optional)
328
+ variableId (string, optional)
329
+ explicitMode (object, optional) \u2014 Pin variable mode \u2014 use { collectionName, modeName } (preferred) or { collectionId, modeId }
330
+ exportSettings (array, optional) \u2014 Export settings
331
+ properties (object, optional) \u2014 Direct Figma API props (escape hatch)`,
332
+ "delete": "# frames.delete\nDelete nodes\n\nParams:\n id (string, optional) \u2014 Single node ID\n items (array, optional) \u2014 Batch: [{id}, ...]\n id (string, optional)",
333
+ "clone": "# frames.clone\nDuplicate nodes\n\nParams:\n id (string, required) \u2014 Node ID\n parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
334
+ "audit": '# frames.audit\nRun lint on a node \u2014 returns severity-ranked findings\n\nParams:\n id (string, required) \u2014 Node ID to audit\n rules (string[], optional) \u2014 Rules to check. Default: ["all"]. Categories: "component", "composition", "token", "naming", "wcag".\n maxDepth (number, optional) \u2014 Max tree depth (default: 10)\n maxFindings (number, optional) \u2014 Max findings (default: 50)',
335
+ "reparent": "# frames.reparent\nMove nodes into a new parent\n\nParams:\n items (array, required) \u2014 Array of {id, parentId, index?}\n id (string, required)\n parentId (string, required)\n index (number, optional)",
336
+ "create": `# frames.create
337
+ Create frame-like containers
338
+
339
+ Example: frames(method:"create", type:"auto_layout", layoutMode:"VERTICAL", itemSpacing:16, padding:24)
340
+
341
+ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line | group | boolean_operation | svg)
342
+
343
+ ## frame \u2014 Static frame with fixed dimensions
344
+ name (string, optional) \u2014 Node name
345
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
346
+ x (number, optional) \u2014 X position (default: 0)
347
+ y (number, optional) \u2014 Y position (default: 0)
348
+ width (number, optional) \u2014 Width (default: 100)
349
+ height (number, optional) \u2014 Height (default: 100)
350
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
351
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
352
+ visible (boolean, optional) \u2014 Show/hide (default true)
353
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
354
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
355
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
356
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
357
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
358
+ fillStyleName (string, optional) \u2014 Paint style name for fill
359
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
360
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
361
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
362
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
363
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
364
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
365
+ strokeTopWeight (string, optional)
366
+ strokeBottomWeight (string, optional)
367
+ strokeLeftWeight (string, optional)
368
+ strokeRightWeight (string, optional)
369
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
370
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
371
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
372
+ topLeftRadius (string, optional)
373
+ topRightRadius (string, optional)
374
+ bottomRightRadius (string, optional)
375
+ bottomLeftRadius (string, optional)
376
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
377
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
378
+ layoutWrap (NO_WRAP | WRAP, optional)
379
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
380
+ paddingTop (string, optional)
381
+ paddingRight (string, optional)
382
+ paddingBottom (string, optional)
383
+ paddingLeft (string, optional)
384
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
385
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
386
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
387
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
388
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
389
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
390
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
391
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
392
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
393
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
394
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
395
+ clipsContent (boolean, optional)
396
+
397
+ ## auto_layout \u2014 Auto-layout frame that arranges children automatically
398
+ name (string, optional) \u2014 Node name
399
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
400
+ x (number, optional) \u2014 X position (default: 0)
401
+ y (number, optional) \u2014 Y position (default: 0)
402
+ width (number, optional) \u2014 Width (default: 100)
403
+ height (number, optional) \u2014 Height (default: 100)
404
+ rotation (number, optional) \u2014 Rotation in degrees (0-360)
405
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
406
+ visible (boolean, optional) \u2014 Show/hide (default true)
407
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
408
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
409
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
410
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
411
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
412
+ fillStyleName (string, optional) \u2014 Paint style name for fill
413
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
414
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
415
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
416
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
417
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
418
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
419
+ strokeTopWeight (string, optional)
420
+ strokeBottomWeight (string, optional)
421
+ strokeLeftWeight (string, optional)
422
+ strokeRightWeight (string, optional)
423
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
424
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
425
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
426
+ topLeftRadius (string, optional)
427
+ topRightRadius (string, optional)
428
+ bottomRightRadius (string, optional)
429
+ bottomLeftRadius (string, optional)
430
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
431
+ layoutMode (HORIZONTAL | VERTICAL, required) \u2014 Primary axis direction
432
+ layoutWrap (NO_WRAP | WRAP, optional)
433
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
434
+ paddingTop (string, optional)
435
+ paddingRight (string, optional)
436
+ paddingBottom (string, optional)
437
+ paddingLeft (string, optional)
438
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
439
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
440
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
441
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
442
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
443
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
444
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
445
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
446
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
447
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
448
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
449
+ clipsContent (boolean, optional)
450
+ nodeIds (string[], optional) \u2014 Existing node IDs to wrap into auto-layout
451
+
452
+ ## section \u2014 Figma section (top-level organizer)
453
+ name (string, required) \u2014 Section name
454
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
455
+ x (number, optional) \u2014 X position (default: 0)
456
+ y (number, optional) \u2014 Y position (default: 0)
457
+ width (number, optional) \u2014 Width (default: 500)
458
+ height (number, optional) \u2014 Height (default: 500)
459
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent
460
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
461
+ fillStyleName (string, optional) \u2014 Paint style name for fill
462
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
463
+
464
+ ## rectangle \u2014 Rectangle shape node
465
+ name (string, optional) \u2014 Layer name (default: 'Rectangle')
466
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
467
+ x (number, optional) \u2014 X position (default: 0)
468
+ y (number, optional) \u2014 Y position (default: 0)
469
+ width (number, optional) \u2014 Width in px (default: 100)
470
+ height (number, optional) \u2014 Height in px (default: 100)
471
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent
472
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
473
+ fillStyleName (string, optional) \u2014 Paint style name for fill
474
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
475
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear
476
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
477
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
478
+ strokeWeight (string, optional)
479
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
480
+ topLeftRadius (string, optional)
481
+ topRightRadius (string, optional)
482
+ bottomRightRadius (string, optional)
483
+ bottomLeftRadius (string, optional)
484
+ opacity (string, optional)
485
+ layoutSizingHorizontal (FIXED | FILL, optional) \u2014 Horizontal sizing in auto-layout parent
486
+ layoutSizingVertical (FIXED | FILL, optional) \u2014 Vertical sizing in auto-layout parent
487
+
488
+ ## ellipse \u2014 Ellipse/circle shape node
489
+ name (string, optional) \u2014 Layer name (default: 'Ellipse')
490
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
491
+ x (number, optional) \u2014 X position (default: 0)
492
+ y (number, optional) \u2014 Y position (default: 0)
493
+ width (number, optional) \u2014 Width in px (default: 100)
494
+ height (number, optional) \u2014 Height in px (default: 100, same as width for circle)
495
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent
496
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
497
+ fillStyleName (string, optional) \u2014 Paint style name for fill
498
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
499
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear
500
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
501
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
502
+ strokeWeight (string, optional)
503
+ opacity (string, optional)
504
+ layoutSizingHorizontal (FIXED | FILL, optional) \u2014 Horizontal sizing in auto-layout parent
505
+ layoutSizingVertical (FIXED | FILL, optional) \u2014 Vertical sizing in auto-layout parent
506
+
507
+ ## line \u2014 Line shape node
508
+ name (string, optional) \u2014 Layer name (default: 'Line')
509
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
510
+ x (number, optional) \u2014 X position (default: 0)
511
+ y (number, optional) \u2014 Y position (default: 0)
512
+ length (number, optional) \u2014 Line length in px (default: 100)
513
+ rotation (number, optional) \u2014 Rotation in degrees (default: 0 = horizontal)
514
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear
515
+ strokeColor (Color, optional) \u2014 Line color (default: black, auto-binds to matching variable/style)
516
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
517
+ strokeWeight (string, optional) \u2014 Line thickness (default: 1)
518
+ opacity (string, optional)
519
+ layoutSizingHorizontal (FIXED | FILL, optional) \u2014 Horizontal sizing in auto-layout parent (defaults to FILL in vertical auto-layout)
520
+
521
+ ## group \u2014 Group existing nodes together
522
+ nodeIds (string[], required) \u2014 Node IDs to group (min 1)
523
+ name (string, optional) \u2014 Group name
524
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
525
+
526
+ ## boolean_operation \u2014 Combine shapes with boolean operations (union, subtract, intersect, exclude)
527
+ operation (UNION | SUBTRACT | INTERSECT | EXCLUDE, required) \u2014 Boolean operation type
528
+ nodeIds (string[], required) \u2014 Node IDs to combine (min 2, first node is the base for SUBTRACT)
529
+ name (string, optional) \u2014 Result node name
530
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
531
+
532
+ ## svg \u2014 Create node from SVG markup
533
+ svg (string, required) \u2014 SVG markup string
534
+ name (string, optional) \u2014 Layer name (default: 'SVG')
535
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
536
+ x (number, optional) \u2014 X position (default: 0)
537
+ y (number, optional) \u2014 Y position (default: 0)
538
+ fillStyleName (string, optional) \u2014 Paint style to apply to vector fills
539
+ fillVariableName (string, optional) \u2014 Color variable by name for vector fills
540
+ strokeStyleName (string, optional) \u2014 Paint style to apply to vector strokes
541
+ strokeVariableName (string, optional) \u2014 Color variable by name for vector strokes`,
542
+ "export": "# frames.export\nExport a node as PNG, JPG, SVG, SVG_STRING, or PDF\n\nParams:\n id (string, required) \u2014 Node ID to export\n format (PNG | JPG | SVG | SVG_STRING | PDF, optional) \u2014 Export format (default: PNG). SVG_STRING returns raw SVG text.\n scale (number, optional) \u2014 Export scale (default: 1, only for PNG/JPG)"
543
+ }
544
+ },
545
+ "instances": {
546
+ "summary": '# instances\nCreate and manage component instances.\n\nMethods:\n list Search for nodes (returns stubs only \u2014 use get with depth for full properties) [read]\n delete Delete nodes [edit]\n clone Duplicate nodes [create]\n audit Run lint on a node \u2014 returns severity-ranked findings [read]\n reparent Move nodes into a new parent [edit]\n get Get instance detail with component properties and overrides [read]\n create Create component instances [create]\n update Set instance properties [edit]\n swap Swap instance component (preserves overrides) [edit]\n detach Detach instances from their component (converts to frame) [edit]\n reset_overrides Reset all overrides on instances to match their main component [edit]\n\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).\n// ---\n// visible: false hides the node. Omitted from response when true (the default).\n// locked: true prevents editing in Figma UI. Omitted when false (the default).\n// rotation: degrees (0-360). Omitted when 0.\n// blendMode: layer blend mode. Omitted when PASS_THROUGH (the default).\n// layoutPositioning: ABSOLUTE = floating inside auto-layout parent. Omitted when AUTO (the default).\n// minWidth/maxWidth/minHeight/maxHeight: responsive constraints for auto-layout children.\n// constraints: position behavior in non-auto-layout parents. Ignored inside auto-layout frames.\n// bindings: bind design variables to node properties. field uses slash path: "fills/0/color" (first fill), "strokes/0/color", "opacity", "width", "height", "cornerRadius", "paddingLeft", "itemSpacing".\n// explicitMode: pin a variable mode on this node. Use { collectionName, modeName } (preferred) or { collectionId, modeId }.\n// properties: escape hatch \u2014 set any Figma node property directly. Use only when no dedicated field exists.\ninterface Node {\n id: string; name: string; type: string;\n visible?: boolean; // omitted when true\n locked?: boolean; // omitted when false\n opacity?: number; // omitted when 1\n rotation?: number; // omitted when 0\n blendMode?: string; // omitted when PASS_THROUGH\n layoutPositioning?: "AUTO" | "ABSOLUTE";\n layoutSizingHorizontal?: "FIXED" | "HUG" | "FILL";\n layoutSizingVertical?: "FIXED" | "HUG" | "FILL";\n minWidth?: number; maxWidth?: number; minHeight?: number; maxHeight?: number;\n absoluteBoundingBox: { x: number; y: number; width: number; height: number };\n fills?: Paint[]; // solid: {type: "SOLID", color: {r, g, b, a}}\n strokes?: Paint[];\n effects?: Effect[]; // DROP_SHADOW | INNER_SHADOW | LAYER_BLUR | BACKGROUND_BLUR\n children?: NodeStub[]; // stubs: {id, name, type} \u2014 use depth to expand\n}\n// PatchItem uses flat params matching create shape \u2014 no nested sub-objects.\n// Fill/stroke/corner/layout/text params are identical to frames.create and text.create.\n// Unknown keys produce a warning, preventing silent failures.\n// Instances are linked copies of components. Changes to the component propagate to all instances.\n// Overrides: instance-level changes (text, fills, visibility) that differ from the component. Shown in overrides array.\n// variantProperties: when creating from a component set, pick which variant e.g. {"Style":"Secondary","Size":"Large"}.\n// ---\n// Property keys: read returns clean names ("Label"), write requires the #suffix ("Label#1:0"). Call instances.get(id) to discover exact keys before update.\n// swap: change which component an instance points to while preserving compatible overrides.\n// detach: permanently converts an instance to a regular frame, breaking the component link.\n// reset_overrides: reverts all instance overrides to match the main component.\n// Workflow: components.list \u2192 instances.create with componentId + properties (one call). No separate update needed for text/boolean overrides.\n// Instances support frame-level overrides: layoutSizingHorizontal/Vertical (FIXED, FILL, HUG), opacity, width/height, min/max.\n// Use layoutSizingHorizontal: "FILL" to make instances stretch in auto-layout parents.\n\nUse instances(method: "help", topic: "<method>") for method details.',
547
+ "methods": {
548
+ "list": '# instances.list\nSearch for nodes (returns stubs only \u2014 use get with depth for full properties)\n\nParams:\n query (string, optional) \u2014 Name search query (case-insensitive substring match)\n types (string[], optional) \u2014 Filter by node types (e.g. ["FRAME", "TEXT"])\n parentId (string, optional) \u2014 Search only within this subtree\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)',
549
+ "delete": "# instances.delete\nDelete nodes\n\nParams:\n id (string, optional) \u2014 Single node ID\n items (array, optional) \u2014 Batch: [{id}, ...]\n id (string, optional)",
550
+ "clone": "# instances.clone\nDuplicate nodes\n\nParams:\n id (string, required) \u2014 Node ID\n parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
551
+ "audit": '# instances.audit\nRun lint on a node \u2014 returns severity-ranked findings\n\nParams:\n id (string, required) \u2014 Node ID to audit\n rules (string[], optional) \u2014 Rules to check. Default: ["all"]. Categories: "component", "composition", "token", "naming", "wcag".\n maxDepth (number, optional) \u2014 Max tree depth (default: 10)\n maxFindings (number, optional) \u2014 Max findings (default: 50)',
552
+ "reparent": "# instances.reparent\nMove nodes into a new parent\n\nParams:\n items (array, required) \u2014 Array of {id, parentId, index?}\n id (string, required)\n parentId (string, required)\n index (number, optional)",
553
+ "get": '# instances.get\nGet instance detail with component properties and overrides\n\nParams:\n id (string, required) \u2014 Instance node ID\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.\n verbose (boolean, optional) \u2014 Include all properties (bounding box, constraints, text style details). Default false \u2014 returns slim, actionable output.',
554
+ "create": `# instances.create
555
+ Create component instances
556
+
557
+ Example: instances(method:"create", items:[{componentId:"1:23", variantProperties:{"Size":"Large"}, properties:{"Label":"Click me"}, parentId:"2:45", layoutSizingHorizontal:"FILL"}])
558
+
559
+ Params:
560
+ items (InstanceCreateItem[], required) \u2014 Array of {componentId, variantProperties?, x?, y?, parentId?, layoutSizingHorizontal?, ...}
561
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
562
+ visible (boolean, optional) \u2014 Show/hide (default true)
563
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
564
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
565
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
566
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
567
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
568
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
569
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
570
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
571
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
572
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
573
+ componentId (string, required) \u2014 Component or component set ID
574
+ variantProperties (object, optional) \u2014 Pick variant e.g. {"Style":"Secondary"}
575
+ properties (object, optional) \u2014 Set component properties inline e.g. {"Label":"Click me", "ShowIcon":true}. Same as instances.update properties.
576
+ name (string, optional) \u2014 Instance layer name
577
+ x (number, optional)
578
+ y (number, optional)
579
+ width (number, optional) \u2014 Override width (resize)
580
+ height (number, optional) \u2014 Override height (resize)
581
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
582
+ depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.`,
583
+ "update": `# instances.update
584
+ Set instance properties
585
+
586
+ Example: instances(method:"update", items:[{id:"1:23", properties:{"Label#4:0":"Submit"}, fillColor:"#3B82F6", layoutSizingHorizontal:"FILL"}])
587
+
588
+ Params:
589
+ items (InstanceUpdateItem[], required) \u2014 Array of {id, properties: {"Label#1:0":"text"}, fillColor?: ...}
590
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
591
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
592
+ fillStyleName (string, optional) \u2014 Paint style name for fill
593
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
594
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
595
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
596
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
597
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
598
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
599
+ strokeTopWeight (string, optional)
600
+ strokeBottomWeight (string, optional)
601
+ strokeLeftWeight (string, optional)
602
+ strokeRightWeight (string, optional)
603
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
604
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
605
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
606
+ topLeftRadius (string, optional)
607
+ topRightRadius (string, optional)
608
+ bottomRightRadius (string, optional)
609
+ bottomLeftRadius (string, optional)
610
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
611
+ visible (boolean, optional) \u2014 Show/hide (default true)
612
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
613
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
614
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
615
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
616
+ layoutWrap (NO_WRAP | WRAP, optional)
617
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
618
+ paddingTop (string, optional)
619
+ paddingRight (string, optional)
620
+ paddingBottom (string, optional)
621
+ paddingLeft (string, optional)
622
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
623
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
624
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
625
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
626
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
627
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
628
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
629
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
630
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
631
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
632
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
633
+ fontSize (number, optional) \u2014 Font size
634
+ fontFamily (string, optional) \u2014 Font family
635
+ fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
636
+ fontWeight (number, optional) \u2014 100-900. Ignored when fontStyle is set.
637
+ fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
638
+ fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
639
+ fontColorStyleName (string, optional) \u2014 Apply paint style \u2014 overrides fontColor
640
+ textStyleId (string, optional) \u2014 Apply text style by ID \u2014 overrides fontSize/fontWeight
641
+ textStyleName (string, optional) \u2014 Text style by name (case-insensitive)
642
+ textAlignHorizontal (LEFT | CENTER | RIGHT | JUSTIFIED, optional)
643
+ textAlignVertical (TOP | CENTER | BOTTOM, optional)
644
+ textAutoResize (NONE | WIDTH_AND_HEIGHT | HEIGHT | TRUNCATE, optional)
645
+ id (string, required) \u2014 Instance node ID
646
+ properties (object, optional) \u2014 Component property key\u2192value map
647
+ componentProperties (object, optional) \u2014 Alias for properties (matches instances.get response shape)
648
+ name (string, optional) \u2014 Rename node
649
+ rotation (number, optional) \u2014 Degrees (0-360)
650
+ x (number, optional)
651
+ y (number, optional)
652
+ width (number, optional)
653
+ height (number, optional)
654
+ clearFill (boolean, optional) \u2014 Remove all fills
655
+ effects (array, optional) \u2014 Effect array (DROP_SHADOW, INNER_SHADOW, LAYER_BLUR, BACKGROUND_BLUR)
656
+ constraints (object, optional)
657
+ bindings (array, optional) \u2014 Bind variables to properties. field path examples: 'fills/0/color', 'strokes/0/color', 'opacity', 'width', 'cornerRadius', 'itemSpacing'.
658
+ field (string, required)
659
+ variableName (string, optional)
660
+ variableId (string, optional)
661
+ explicitMode (object, optional) \u2014 Pin variable mode \u2014 use { collectionName, modeName } (preferred) or { collectionId, modeId }
662
+ exportSettings (array, optional) \u2014 Export settings`,
663
+ "swap": "# instances.swap\nSwap instance component (preserves overrides)\n\nParams:\n items (array, required) \u2014 Array of {id, componentId}\n id (string, required) \u2014 Instance node ID\n componentId (string, required) \u2014 New component or component set ID",
664
+ "detach": "# instances.detach\nDetach instances from their component (converts to frame)\n\nParams:\n items (array, required) \u2014 Array of {id}\n id (string, required) \u2014 Instance node ID",
665
+ "reset_overrides": "# instances.reset_overrides\nReset all overrides on instances to match their main component\n\nParams:\n items (array, required) \u2014 Array of {id}\n id (string, required) \u2014 Instance node ID"
666
+ }
667
+ },
668
+ "lint": {
669
+ "summary": `# lint
670
+ Run design quality and accessibility checks.
671
+
672
+ Methods:
673
+ check Run design linter on a node tree [read]
674
+ fix Auto-fix frames to auto-layout [edit]
675
+
676
+ // Lint runs automated design quality and accessibility checks on a node tree.
677
+ // ---
678
+ // Rules: "all" (default), or filter by category or specific rule names.
679
+ // Category meta-rules (expand to all rules in that category):
680
+ // "component" \u2014 component property binding checks
681
+ // "composition" \u2014 layout and positioning checks
682
+ // "token" \u2014 design token / style usage checks
683
+ // "naming" \u2014 layer naming checks
684
+ // "wcag" / "accessibility" \u2014 all WCAG accessibility checks
685
+ // ---
686
+ // Severity levels (output is sorted by severity, highest first):
687
+ // "error" \u2014 definite bug, must fix
688
+ // "unsafe" \u2014 likely causes layout/accessibility problems
689
+ // "heuristic" \u2014 probably worth fixing, context-dependent
690
+ // "style" \u2014 opinionated, nice-to-have (leaf nodes, decorative elements often downgraded here)
691
+ // Context-aware: leaf nodes (text, shapes, small frames) are treated differently from containers.
692
+ // Small labels with HUG sizing, leaf nodes on cross-axis \u2014 downgraded to "style" instead of "heuristic".
693
+ // Per-finding severity overrides appear on individual nodes when context changes the default.
694
+ // ---
695
+ // Component rules [component]:
696
+ // "no-text-property" \u2014 component text not exposed as editable property [heuristic]
697
+ // "component-bindings" \u2014 unbound text, orphaned properties, unexposed nested text [heuristic; orphaned\u2192unsafe, nested\u2192style]
698
+ // Composition rules [composition]:
699
+ // "no-autolayout" \u2014 frames with manually positioned children [heuristic; leaf-only containers\u2192style]
700
+ // "overlapping-children" \u2014 children stacked at same position [heuristic]
701
+ // "shape-instead-of-frame" \u2014 shapes used as containers [style]
702
+ // "fixed-in-autolayout" \u2014 FIXED-size children in auto-layout parents [heuristic]
703
+ // "unbounded-hug" \u2014 HUG on both axes [unsafe; short leaf text\u2192style]
704
+ // "hug-cross-axis" \u2014 HUG on cross-axis of constrained parent [heuristic; leaf nodes\u2192style]
705
+ // "empty-container" \u2014 empty frames [style]
706
+ // Token rules [token]:
707
+ // "hardcoded-color" \u2014 colors not using styles or variables [heuristic]
708
+ // "hardcoded-token" \u2014 numeric values not bound to FLOAT variable [heuristic]
709
+ // "no-text-style" \u2014 text without a text style [heuristic]
710
+ // Naming rules [naming]:
711
+ // "default-name" \u2014 default names like "Frame 1" [style]
712
+ // "stale-text-name" \u2014 text node name doesn't match content [style]
713
+ // Accessibility rules [wcag]:
714
+ // "wcag-contrast" \u2014 AA contrast ratio [unsafe]
715
+ // "wcag-contrast-enhanced" \u2014 AAA contrast ratio [style]
716
+ // "wcag-non-text-contrast" \u2014 non-text 3:1 contrast [heuristic]
717
+ // "wcag-target-size" \u2014 targets below 24x24px [unsafe]
718
+ // "wcag-text-size" \u2014 text below 12px [unsafe]
719
+ // "wcag-line-height" \u2014 line height below 1.5x [style]
720
+ // ---
721
+ // maxDepth limits how deep the tree traversal goes (default: 10). maxFindings caps total findings (default: 50).
722
+ // fix: auto-converts frames to auto-layout. Use after lint.check identifies "no-autolayout" issues.
723
+
724
+ Use lint(method: "help", topic: "<method>") for method details.`,
725
+ "methods": {
726
+ "check": '# lint.check\nRun design linter on a node tree\n\nExample: lint(method:"check", nodeId:"0:1", rules:["wcag","hardcoded-color"])\n\nParams:\n nodeId (string, optional) \u2014 Node ID to lint. If omitted: 1 selected node \u2192 lints that node, 2+ selected \u2192 lints entire page (not the selection), 0 selected \u2192 error. Always pass nodeId explicitly for reliable targeting.\n rules (string[], optional) \u2014 Rules to run. Default: ["all"]. Categories: "component", "composition", "token", "naming", "wcag"/"accessibility". Or specific rule names.\n maxDepth (number, optional) \u2014 Max tree depth (default: 10)\n maxFindings (number, optional) \u2014 Max findings (default: 50)',
727
+ "fix": "# lint.fix\nAuto-fix frames to auto-layout\n\nParams:\n items (array, required) \u2014 Array of {nodeId, layoutMode?, itemSpacing?}\n nodeId (string, required) \u2014 Frame node ID\n layoutMode (VERTICAL | HORIZONTAL, optional) \u2014 Direction (default: auto-detected)\n itemSpacing (number, optional) \u2014 Spacing between children\n depth (number, optional) \u2014 Response detail for fixed nodes: omit for stubs, 0=properties, -1=full tree"
728
+ }
729
+ },
730
+ "prototyping": {
731
+ "summary": '# prototyping\nManage prototype interactions, reactions, and navigation flows.\n\nMethods:\n get Get reactions and overflow direction on a node [read]\n add Add a prototype reaction to a node [edit]\n set Replace all reactions on a node (raw reactions array) [edit]\n remove Remove a reaction from a node by index [edit]\n\n// Reactions wire up interactions: trigger (ON_CLICK, ON_HOVER, ...) \u2192 action (navigate, swap, overlay).\n// Common patterns: button ON_CLICK \u2192 NAVIGATE to detail frame; card ON_HOVER \u2192 CHANGE_TO hover variant.\n// Multi-action: pass actions[] array to run multiple actions on one trigger (e.g. navigate + set variable mode).\n// ---\n// TRIGGERS: ON_CLICK | ON_HOVER | ON_PRESS | ON_DRAG | AFTER_TIMEOUT(timeout) | MOUSE_ENTER(delay) | MOUSE_LEAVE(delay) | ON_KEY_DOWN(keyCodes)\n// NAVIGATION: NAVIGATE (go to frame) | SWAP (swap overlay) | OVERLAY (show overlay) | SCROLL_TO | CHANGE_TO (swap component variant)\n// TRANSITIONS: DISSOLVE | SMART_ANIMATE | MOVE_IN | MOVE_OUT | PUSH | SLIDE_IN | SLIDE_OUT (+ direction for directional)\n// EASING: EASE_IN | EASE_OUT | EASE_IN_AND_OUT | LINEAR | GENTLE | QUICK | BOUNCY | SLOW\n// ACTIONS: NODE (navigate/swap) | BACK (go back) | CLOSE (close overlay) | URL (open link) | SET_VARIABLE_MODE (switch theme/mode)\n\nUse prototyping(method: "help", topic: "<method>") for method details.',
732
+ "methods": {
733
+ "get": "# prototyping.get\nGet reactions and overflow direction on a node\n\nParams:\n id (string, required) \u2014 Node ID",
734
+ "add": '# prototyping.add\nAdd a prototype reaction to a node\n\nExample: prototyping(method:"add", id:"btn-1", trigger:"ON_CLICK", destination:"detail-frame-id", navigation:"NAVIGATE")\n\nParams:\n id (string, required) \u2014 Node ID\n trigger (ON_CLICK | ON_HOVER | ON_PRESS | ON_DRAG | AFTER_TIMEOUT | MOUSE_ENTER | MOUSE_LEAVE | ON_KEY_DOWN, required) \u2014 Trigger type\n triggerDelay (number, optional) \u2014 Delay in ms for AFTER_TIMEOUT / MOUSE_ENTER / MOUSE_LEAVE triggers\n triggerKeyCodes (number[], optional) \u2014 Key codes for ON_KEY_DOWN trigger\n triggerDevice (KEYBOARD | XBOX_ONE | PS4 | SWITCH_PRO, optional) \u2014 Device for ON_KEY_DOWN (default: KEYBOARD)\n destination (string, optional) \u2014 Target node ID (required for NODE actions)\n navigation (NAVIGATE | SWAP | OVERLAY | SCROLL_TO | CHANGE_TO, optional) \u2014 Navigation type (default: NAVIGATE)\n transition (DISSOLVE | SMART_ANIMATE | MOVE_IN | MOVE_OUT | PUSH | SLIDE_IN | SLIDE_OUT | INSTANT, optional) \u2014 Transition animation (default: DISSOLVE). INSTANT = no animation.\n transitionDirection (LEFT | RIGHT | TOP | BOTTOM, optional) \u2014 Direction for MOVE_IN, MOVE_OUT, PUSH, SLIDE_IN, SLIDE_OUT\n duration (number, optional) \u2014 Transition duration in seconds (default: 0.3)\n easing (EASE_IN | EASE_OUT | EASE_IN_AND_OUT | LINEAR | GENTLE | QUICK | BOUNCY | SLOW, optional) \u2014 Easing function (default: EASE_OUT)\n actionType (NODE | BACK | CLOSE | URL | SET_VARIABLE_MODE, optional) \u2014 Action type (default: NODE). SET_VARIABLE_MODE switches a variable collection mode.\n url (string, optional) \u2014 URL for URL action type\n collectionName (string, optional) \u2014 Variable collection name (for SET_VARIABLE_MODE)\n modeName (string, optional) \u2014 Mode name to switch to (for SET_VARIABLE_MODE)\n resetScrollPosition (boolean, optional) \u2014 Reset scroll position on navigate (default: true)\n actions (array, optional) \u2014 Multi-action: [{actionType, destination?, navigation?, collectionName?, modeName?, ...}]. Overrides single-action params.',
735
+ "set": "# prototyping.set\nReplace all reactions on a node (raw reactions array)\n\nParams:\n id (string, required) \u2014 Node ID\n reactions (array, required) \u2014 Full reactions array \u2014 [{trigger:{type}, actions:[{type, destinationId, navigation, transition}]}]",
736
+ "remove": "# prototyping.remove\nRemove a reaction from a node by index\n\nParams:\n id (string, required) \u2014 Node ID\n index (number, required) \u2014 Reaction index (0-based)"
737
+ }
738
+ },
739
+ "selection": {
740
+ "summary": '# selection\nRead and set the current Figma selection.\n\nMethods:\n get Get the current selection [read]\n set Set selection to nodes and scroll viewport to show them [read]\n\n// Selection is the set of nodes currently highlighted in the Figma canvas.\n// get returns the current selection. Without depth, returns stubs ({id, name, type}). With depth=0, returns full properties.\n// _truncated: true when the response was cut short due to node budget limits. Use depth=0 or specific fields to reduce payload.\n// set replaces the entire selection AND scrolls the viewport to show the selected nodes.\n\nUse selection(method: "help", topic: "<method>") for method details.',
741
+ "methods": {
742
+ "get": "# selection.get\nGet the current selection\n\nParams:\n depth (number, optional) \u2014 Child recursion depth. Omit for stubs only, 0=selected nodes' properties, -1=unlimited.\n verbose (boolean, optional) \u2014 Include all properties (bounding box, constraints, text style details). Default false \u2014 returns slim, actionable output.",
743
+ "set": '# selection.set\nSet selection to nodes and scroll viewport to show them\n\nParams:\n nodeIds (string[], required) \u2014 Array of node IDs to select. Example: ["1:2","1:3"]'
744
+ }
745
+ },
746
+ "styles": {
747
+ "summary": '# styles\nCRUD for local paint, text, effect, and grid styles.\n\nMethods:\n list List local styles with optional type filter [read]\n get Get full style detail by ID [read]\n create Create local styles [create]\n update Update styles by ID or name [edit]\n delete Delete styles [edit]\n\n// Styles are named, reusable design properties that can be applied to nodes. Four types:\n// paint: a named color (applied to fills/strokes), text: typography settings, effect: shadows/blurs, grid: layout grids.\n// All ID params accept both IDs and display names (case-insensitive). Use whichever you have.\n// ---\n// leadingTrim: "CAP_HEIGHT" trims line-height to cap height (tighter text boxes), "NONE" is default.\n// fontStyle: font variant name like "Bold", "Italic", "Bold Italic". Use fonts.list to find available styles.\n//\n// Effect object shape (for effect styles):\n// { type: "DROP_SHADOW"|"INNER_SHADOW"|"LAYER_BLUR"|"BACKGROUND_BLUR",\n// color?: Color, offset?: {x, y}, radius: number, spread?: number,\n// visible?: boolean, blendMode?: string }\n// DROP_SHADOW/INNER_SHADOW require color, offset, radius. LAYER_BLUR/BACKGROUND_BLUR require radius only.\n// Example: { type: "DROP_SHADOW", color: "#00000040", offset: {x:0,y:4}, radius: 8 }\n//\n// LayoutGrid object shape (for grid styles):\n// Rows/Columns: { pattern: "ROWS"|"COLUMNS", alignment: "MIN"|"MAX"|"STRETCH"|"CENTER",\n// gutterSize: number, count: number, sectionSize?: number, offset?: number, visible?: boolean, color?: Color }\n// Grid: { pattern: "GRID", sectionSize: number, visible?: boolean, color?: Color }\n// Example: { pattern: "COLUMNS", alignment: "STRETCH", gutterSize: 20, count: 12, offset: 40 }\n\nUse styles(method: "help", topic: "<method>") for method details.',
748
+ "methods": {
749
+ "list": '# styles.list\nList local styles with optional type filter\n\nParams:\n type (paint | text | effect | grid, optional) \u2014 Filter by style type\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)',
750
+ "get": '# styles.get\nGet full style detail by ID\n\nParams:\n id (string, required) \u2014 Style ID or name\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.',
751
+ "create": '# styles.create\nCreate local styles\n\nExample: styles(method:"create", type:"effect", name:"Shadow/Medium", effects:[{type:"DROP_SHADOW", color:"#00000040", offset:{x:0,y:4}, radius:8}])\n\nDiscriminant: type (paint | text | effect | grid)\n\n ## paint \u2014 Paint/color style\n name (string, required) \u2014 Style name\n color (Color, required) \u2014 Color value\n colorVariableName (string, optional) \u2014 Bind to a COLOR variable by name (style tracks the variable)\n description (string, optional) \u2014 Style description\n\n ## text \u2014 Text style\n name (string, required) \u2014 Style name\n fontFamily (string, required) \u2014 Font family\n fontStyle (string, optional) \u2014 Font style (default: Regular)\n fontSize (number, required) \u2014 Font size\n lineHeight (line_height, optional)\n letterSpacing (letter_spacing, optional)\n textCase (ORIGINAL | UPPER | LOWER | TITLE | SMALL_CAPS | SMALL_CAPS_FORCED, optional)\n textDecoration (NONE | UNDERLINE | STRIKETHROUGH, optional)\n paragraphIndent (number, optional) \u2014 Paragraph indent (px)\n paragraphSpacing (number, optional) \u2014 Paragraph spacing (px)\n leadingTrim (CAP_HEIGHT | NONE, optional) \u2014 Leading trim mode\n description (string, optional) \u2014 Style description\n\n ## effect \u2014 Effect style\n name (string, required) \u2014 Style name\n effects (array, required) \u2014 Array of Effect objects\n description (string, optional) \u2014 Style description\n\n ## grid \u2014 Grid/layout grid style\n name (string, required) \u2014 Style name\n layoutGrids (array, required) \u2014 Array of LayoutGrid objects\n description (string, optional) \u2014 Style description',
752
+ "update": '# styles.update\nUpdate styles by ID or name\n\nExample: styles(method:"update", items:[{id:"Surface/Primary", color:"#F5F5F5"}])\n\nParams:\n type (paint | text | effect | grid, optional) \u2014 Style type hint for strict validation (optional, auto-detected)\n items (PatchStyleItem[], required) \u2014 Array of {id, ...fields} to update\n id (string, required) \u2014 Style ID or name\n name (string, optional) \u2014 Rename the style\n description (string, optional) \u2014 Style description\n color (Color, optional) \u2014 New color (paint styles)\n colorVariableName (string, optional) \u2014 Bind to a COLOR variable by name (paint styles)\n fontFamily (string, optional)\n fontStyle (string, optional)\n fontSize (number, optional)\n lineHeight (line_height, optional)\n letterSpacing (letter_spacing, optional)\n textCase (ORIGINAL | UPPER | LOWER | TITLE | SMALL_CAPS | SMALL_CAPS_FORCED, optional)\n textDecoration (NONE | UNDERLINE | STRIKETHROUGH, optional)\n paragraphIndent (number, optional) \u2014 Paragraph indent (px)\n paragraphSpacing (number, optional) \u2014 Paragraph spacing (px)\n leadingTrim (CAP_HEIGHT | NONE, optional)\n effects (array, optional) \u2014 Array of Effect objects\n layoutGrids (array, optional) \u2014 Array of LayoutGrid objects (grid styles)',
753
+ "delete": "# styles.delete\nDelete styles\n\nParams:\n id (string, optional) \u2014 Style ID or name\n items (array, optional) \u2014 Batch: [{id}, ...]\n id (string, required) \u2014 Style ID or name"
754
+ }
755
+ },
756
+ "text": {
757
+ "summary": '# text\nCreate and manage text nodes.\n\nMethods:\n get Get serialized node data [read]\n list Search for nodes (returns stubs only \u2014 use get with depth for full properties) [read]\n update Patch node properties [edit]\n delete Delete nodes [edit]\n clone Duplicate nodes [create]\n audit Run lint on a node \u2014 returns severity-ranked findings [read]\n reparent Move nodes into a new parent [edit]\n create Create text nodes [create]\n set_content Replace text content on existing text nodes [edit]\n scan Scan all text nodes within a subtree [read]\n\n// depth: omit \u2192 id+name stubs | 0 \u2192 props + child stubs | N \u2192 recurse N | -1 \u2192 full tree\n// fields: whitelist e.g. ["fills","opacity"] \u2014 id, name, type always included. Pass ["*"] for all.\n// layoutSizingHorizontal/Vertical: FIXED | HUG | FILL \u2014 how the node sizes within auto-layout.\n// Colors: fillVariableName/strokeVariableName bind by name \u2014 preferred over raw color values.\n// Note: node-based endpoints (frames, text, instances, components) use `results` as the list key.\n// Standalone endpoints (styles, variables, variable_collections) use `items`. Components.list uses `items` (catalog view).\n// ---\n// visible: false hides the node. Omitted from response when true (the default).\n// locked: true prevents editing in Figma UI. Omitted when false (the default).\n// rotation: degrees (0-360). Omitted when 0.\n// blendMode: layer blend mode. Omitted when PASS_THROUGH (the default).\n// layoutPositioning: ABSOLUTE = floating inside auto-layout parent. Omitted when AUTO (the default).\n// minWidth/maxWidth/minHeight/maxHeight: responsive constraints for auto-layout children.\n// constraints: position behavior in non-auto-layout parents. Ignored inside auto-layout frames.\n// bindings: bind design variables to node properties. field uses slash path: "fills/0/color" (first fill), "strokes/0/color", "opacity", "width", "height", "cornerRadius", "paddingLeft", "itemSpacing".\n// explicitMode: pin a variable mode on this node. Use { collectionName, modeName } (preferred) or { collectionId, modeId }.\n// properties: escape hatch \u2014 set any Figma node property directly. Use only when no dedicated field exists.\ninterface Node {\n id: string; name: string; type: string;\n visible?: boolean; // omitted when true\n locked?: boolean; // omitted when false\n opacity?: number; // omitted when 1\n rotation?: number; // omitted when 0\n blendMode?: string; // omitted when PASS_THROUGH\n layoutPositioning?: "AUTO" | "ABSOLUTE";\n layoutSizingHorizontal?: "FIXED" | "HUG" | "FILL";\n layoutSizingVertical?: "FIXED" | "HUG" | "FILL";\n minWidth?: number; maxWidth?: number; minHeight?: number; maxHeight?: number;\n absoluteBoundingBox: { x: number; y: number; width: number; height: number };\n fills?: Paint[]; // solid: {type: "SOLID", color: {r, g, b, a}}\n strokes?: Paint[];\n effects?: Effect[]; // DROP_SHADOW | INNER_SHADOW | LAYER_BLUR | BACKGROUND_BLUR\n children?: NodeStub[]; // stubs: {id, name, type} \u2014 use depth to expand\n}\n// PatchItem uses flat params matching create shape \u2014 no nested sub-objects.\n// Fill/stroke/corner/layout/text params are identical to frames.create and text.create.\n// Unknown keys produce a warning, preventing silent failures.\n// Text nodes display text content with typography styling. They inherit node methods (get, list, update, delete, clone, reparent).\n// textAutoResize: NONE (fixed box), WIDTH_AND_HEIGHT (grow both), HEIGHT (fixed width, auto height), TRUNCATE (fixed + ellipsis).\n// Prefer textStyleName for typography, fontColorVariableName/fontColorStyleName for color.\n// Aliases: fillColor \u2192 fontColor, fillVariableName \u2192 fontColorVariableName, fillStyleName \u2192 fontColorStyleName (consistent with frames API).\n// ---\n// Smart defaults inside auto-layout parent: layoutSizingHorizontal defaults to FILL, layoutSizingVertical to HUG, textAutoResize to HEIGHT.\n// Text fills parent width and wraps automatically. Override with explicit values if needed.\n// fontStyle vs fontWeight: fontStyle is a named variant like "Bold", "Italic", "SemiBold". When set, fontWeight is ignored.\n// Use fonts.list to find available fontFamily + fontStyle combinations.\n// scan: finds all text nodes in a subtree. path (when includePath:true) shows the layer hierarchy e.g. "Frame > Card > Label".\n// ScanResult (per-item): { nodeId, count, truncated, textNodes: [{ id, name, characters, fontSize, fontFamily, fontStyle, path?, depth?, absoluteX?, absoluteY?, width?, height? }] }\n\nUse text(method: "help", topic: "<method>") for method details.',
758
+ "methods": {
759
+ "get": '# text.get\nGet serialized node data\n\nParams:\n id (string, required) \u2014 Node ID\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.\n verbose (boolean, optional) \u2014 Include all properties (bounding box, constraints, text style details). Default false \u2014 returns slim, actionable output.',
760
+ "list": '# text.list\nSearch for nodes (returns stubs only \u2014 use get with depth for full properties)\n\nParams:\n query (string, optional) \u2014 Name search query (case-insensitive substring match)\n types (string[], optional) \u2014 Filter by node types (e.g. ["FRAME", "TEXT"])\n parentId (string, optional) \u2014 Search only within this subtree\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)',
761
+ "update": `# text.update
762
+ Patch node properties
763
+
764
+ Params:
765
+ items (PatchItem[], required) \u2014 Array of {id, ...properties} to patch
766
+ fills (array, optional) \u2014 Fill paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] for transparent. Primary way to set fills.
767
+ fillColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid fill (auto-binds to matching variable/style)
768
+ fillStyleName (string, optional) \u2014 Paint style name for fill
769
+ fillVariableName (string, optional) \u2014 Color variable by name e.g. 'bg/primary'
770
+ strokes (array, optional) \u2014 Stroke paints array \u2014 e.g. [{type: 'SOLID', color: '#hex'}] or [] to clear. Primary way to set strokes.
771
+ strokeColor (Color, optional) \u2014 Shorthand \u2014 sets a single solid stroke (auto-binds to matching variable/style)
772
+ strokeStyleName (string, optional) \u2014 Paint style name for stroke
773
+ strokeVariableName (string, optional) \u2014 Color variable by name for stroke
774
+ strokeWeight (string, optional) \u2014 All sides (number) or variable name (string). Per-side: strokeTopWeight, strokeBottomWeight, strokeLeftWeight, strokeRightWeight.
775
+ strokeTopWeight (string, optional)
776
+ strokeBottomWeight (string, optional)
777
+ strokeLeftWeight (string, optional)
778
+ strokeRightWeight (string, optional)
779
+ strokeAlign (INSIDE | OUTSIDE | CENTER, optional) \u2014 Stroke position (default: INSIDE)
780
+ strokesIncludedInLayout (boolean, optional) \u2014 Include stroke width in layout measurements (default: false)
781
+ cornerRadius (string, optional) \u2014 All corners (number) or variable name (string). Per-corner: topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius.
782
+ topLeftRadius (string, optional)
783
+ topRightRadius (string, optional)
784
+ bottomRightRadius (string, optional)
785
+ bottomLeftRadius (string, optional)
786
+ opacity (string, optional) \u2014 Opacity (0-1) or variable name
787
+ visible (boolean, optional) \u2014 Show/hide (default true)
788
+ locked (boolean, optional) \u2014 Lock/unlock (default false)
789
+ blendMode (PASS_THROUGH | NORMAL | DARKEN | MULTIPLY | LINEAR_BURN | COLOR_BURN | LIGHTEN | SCREEN | LINEAR_DODGE | COLOR_DODGE | OVERLAY | SOFT_LIGHT | HARD_LIGHT | DIFFERENCE | EXCLUSION | HUE | SATURATION | COLOR | LUMINOSITY, optional)
790
+ effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
791
+ layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
792
+ layoutWrap (NO_WRAP | WRAP, optional)
793
+ padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
794
+ paddingTop (string, optional)
795
+ paddingRight (string, optional)
796
+ paddingBottom (string, optional)
797
+ paddingLeft (string, optional)
798
+ primaryAxisAlignItems (MIN | MAX | CENTER | SPACE_BETWEEN, optional)
799
+ counterAxisAlignItems (MIN | MAX | CENTER | BASELINE, optional)
800
+ itemSpacing (string, optional) \u2014 Spacing between children (number or variable name string, default: 0)
801
+ counterAxisSpacing (string, optional) \u2014 Gap between wrapped rows (requires layoutWrap: WRAP)
802
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
803
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
804
+ layoutPositioning (AUTO | ABSOLUTE, optional) \u2014 ABSOLUTE = floating inside auto-layout parent
805
+ minWidth (number, optional) \u2014 Min width for responsive auto-layout
806
+ maxWidth (number, optional) \u2014 Max width for responsive auto-layout
807
+ minHeight (number, optional) \u2014 Min height for responsive auto-layout
808
+ maxHeight (number, optional) \u2014 Max height for responsive auto-layout
809
+ fontSize (number, optional) \u2014 Font size
810
+ fontFamily (string, optional) \u2014 Font family
811
+ fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
812
+ fontWeight (number, optional) \u2014 100-900. Ignored when fontStyle is set.
813
+ fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
814
+ fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
815
+ fontColorStyleName (string, optional) \u2014 Apply paint style \u2014 overrides fontColor
816
+ textStyleId (string, optional) \u2014 Apply text style by ID \u2014 overrides fontSize/fontWeight
817
+ textStyleName (string, optional) \u2014 Text style by name (case-insensitive)
818
+ textAlignHorizontal (LEFT | CENTER | RIGHT | JUSTIFIED, optional)
819
+ textAlignVertical (TOP | CENTER | BOTTOM, optional)
820
+ textAutoResize (NONE | WIDTH_AND_HEIGHT | HEIGHT | TRUNCATE, optional)
821
+ id (string, required)
822
+ name (string, optional) \u2014 Rename node
823
+ rotation (number, optional) \u2014 Degrees (0-360)
824
+ x (number, optional)
825
+ y (number, optional)
826
+ width (number, optional)
827
+ height (number, optional)
828
+ clearFill (boolean, optional) \u2014 Remove all fills
829
+ effects (array, optional) \u2014 Effect array (DROP_SHADOW, INNER_SHADOW, LAYER_BLUR, BACKGROUND_BLUR)
830
+ overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
831
+ constraints (object, optional)
832
+ bindings (array, optional) \u2014 Bind variables to properties. field path examples: 'fills/0/color', 'strokes/0/color', 'opacity', 'width', 'cornerRadius', 'itemSpacing'.
833
+ field (string, required)
834
+ variableName (string, optional)
835
+ variableId (string, optional)
836
+ explicitMode (object, optional) \u2014 Pin variable mode \u2014 use { collectionName, modeName } (preferred) or { collectionId, modeId }
837
+ exportSettings (array, optional) \u2014 Export settings
838
+ properties (object, optional) \u2014 Direct Figma API props (escape hatch)`,
839
+ "delete": "# text.delete\nDelete nodes\n\nParams:\n id (string, optional) \u2014 Single node ID\n items (array, optional) \u2014 Batch: [{id}, ...]\n id (string, optional)",
840
+ "clone": "# text.clone\nDuplicate nodes\n\nParams:\n id (string, required) \u2014 Node ID\n parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
841
+ "audit": '# text.audit\nRun lint on a node \u2014 returns severity-ranked findings\n\nParams:\n id (string, required) \u2014 Node ID to audit\n rules (string[], optional) \u2014 Rules to check. Default: ["all"]. Categories: "component", "composition", "token", "naming", "wcag".\n maxDepth (number, optional) \u2014 Max tree depth (default: 10)\n maxFindings (number, optional) \u2014 Max findings (default: 50)',
842
+ "reparent": "# text.reparent\nMove nodes into a new parent\n\nParams:\n items (array, required) \u2014 Array of {id, parentId, index?}\n id (string, required)\n parentId (string, required)\n index (number, optional)",
843
+ "create": `# text.create
844
+ Create text nodes
845
+
846
+ Example: text(method:"create", items:[{text:"Hello", fontFamily:"Inter", fontSize:16, textStyleName:"body/medium"}])
847
+
848
+ Params:
849
+ items (TextItem[], required) \u2014 Array of text items to create
850
+ text (string, optional) \u2014 Text content
851
+ name (string, optional) \u2014 Layer name
852
+ x (number, optional)
853
+ y (number, optional)
854
+ width (number, optional) \u2014 Fixed width in px \u2014 implies layoutSizingHorizontal: FIXED and textAutoResize: HEIGHT
855
+ parentId (string, optional) \u2014 Parent node ID. Omit to place on current page.
856
+ fontFamily (string, optional) \u2014 Font family (default: Inter). Use fonts.list to find installed fonts.
857
+ fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
858
+ fontSize (number, optional) \u2014 Font size (default: 14)
859
+ fontWeight (number, optional) \u2014 100-900 (default: 400). Ignored when fontStyle is set.
860
+ fills (array, optional) \u2014 Text color paints \u2014 e.g. [{type: 'SOLID', color: '#hex'}]. Same as node fills.
861
+ fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
862
+ fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
863
+ fontColorStyleName (string, optional) \u2014 Apply paint style \u2014 overrides fontColor
864
+ textStyleId (string, optional) \u2014 Text style ID or name (case-insensitive) \u2014 overrides fontSize/fontWeight
865
+ textStyleName (string, optional) \u2014 Alias for textStyleId \u2014 accepts name (case-insensitive)
866
+ textAlignHorizontal (LEFT | CENTER | RIGHT | JUSTIFIED, optional)
867
+ textAlignVertical (TOP | CENTER | BOTTOM, optional)
868
+ layoutSizingHorizontal (FIXED | HUG | FILL, optional)
869
+ layoutSizingVertical (FIXED | HUG | FILL, optional)
870
+ textAutoResize (NONE | WIDTH_AND_HEIGHT | HEIGHT | TRUNCATE, optional) \u2014 NONE (fixed box), WIDTH_AND_HEIGHT (grow both), HEIGHT (fixed width, auto height), TRUNCATE (fixed + ellipsis)
871
+ componentPropertyName (string, optional) \u2014 Bind to a component TEXT property by name. Walks up ancestors to find the nearest component, or targets the component specified by componentId. For deeply nested text, consider using components(method:'create', type:'from_node') with exposeText:true instead \u2014 it auto-discovers and binds all text nodes.
872
+ componentId (string, optional) \u2014 Target component ID for componentPropertyName binding. When omitted, walks up ancestors to find the nearest COMPONENT or COMPONENT_SET.
873
+ depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.`,
874
+ "set_content": "# text.set_content\nReplace text content on existing text nodes\n\nParams:\n items (array, required) \u2014 Array of {nodeId, text}\n nodeId (string, required) \u2014 Text node ID\n text (string, required) \u2014 New text content\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
875
+ "scan": "# text.scan\nScan all text nodes within a subtree\n\nParams:\n items ({ nodeId: string; limit?: number; includePath?: boolean; includeGeometry?: boolean }[], required) \u2014 Array of subtrees to scan"
876
+ }
877
+ },
878
+ "variable_collections": {
879
+ "summary": '# variable_collections\nCRUD for variable collections \u2014 the document-level API for design tokens.\n\nMethods:\n list List variable collections [read]\n get Get collection with all variables and values (full document) [read]\n create Create a collection with modes and variables in one call [create]\n update Rename collections [edit]\n delete Delete collections [edit]\n add_mode Add a mode to a collection [create]\n rename_mode Rename a mode [edit]\n remove_mode Remove a mode from a collection [edit]\n\n// Variable collections group design tokens and define their modes (e.g. Light/Dark, Desktop/Mobile).\n// All ID params accept both IDs and display names.\n// ---\n// valuesByMode: values keyed by mode name, e.g. {"Light": "#FFF", "Dark": "#111"}.\n// Aliases: {type: "VARIABLE_ALIAS", name: "other/variable"}.\n// scopes: see variables endpoint for full list.\n// Deleting a collection deletes all variables inside it.\n// The default mode cannot be removed. Use add_mode/remove_mode for additional modes.\n\nUse variable_collections(method: "help", topic: "<method>") for method details.',
880
+ "methods": {
881
+ "list": '# variable_collections.list\nList variable collections\n\nParams:\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)',
882
+ "get": '# variable_collections.get\nGet collection with all variables and values (full document)\n\nParams:\n id (string, required) \u2014 Collection ID or name\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.',
883
+ "create": `# variable_collections.create
884
+ Create a collection with modes and variables in one call
885
+
886
+ Example: variable_collections(method:"create", items:[{name:"Tokens", modes:["Light","Dark"], variables:[{name:"bg/primary", type:"COLOR", valuesByMode:{"Light":"#FFF","Dark":"#111"}, scopes:["ALL_FILLS"]}, {name:"text/primary", type:"COLOR", valuesByMode:{"Light":"#111","Dark":"#F0F0F0"}, scopes:["TEXT_FILL"]}, {name:"space/16", type:"FLOAT", value:16, scopes:["GAP","WIDTH_HEIGHT"]}, {name:"radius/8", type:"FLOAT", value:8, scopes:["CORNER_RADIUS"]}]}])
887
+
888
+ Params:
889
+ items (array, required) \u2014 Array of collection documents
890
+ name (string, required) \u2014 Collection name
891
+ modes (string[], optional) \u2014 Mode names (e.g. ['Light', 'Dark']). Omit for single-mode collection.
892
+ variables (array, optional) \u2014 Variables to create inside this collection
893
+ name (string, required) \u2014 Variable name (unique within collection)
894
+ type (COLOR | FLOAT | STRING | BOOLEAN, required) \u2014 Variable type
895
+ value (variable_value, optional) \u2014 Shorthand \u2014 sets the default mode value. Use valuesByMode for multi-mode.
896
+ valuesByMode (object, optional) \u2014 Values keyed by mode name (e.g. {"Light": "#FFF", "Dark": "#111"})
897
+ description (string, optional)
898
+ scopes (string[], optional) \u2014 Restrict where variable can be applied (default: ALL_SCOPES)`,
899
+ "update": "# variable_collections.update\nRename collections\n\nParams:\n items (array, required) \u2014 Array of {id, name}\n id (string, required) \u2014 Collection ID or name\n name (string, required) \u2014 New name",
900
+ "delete": "# variable_collections.delete\nDelete collections\n\nParams:\n id (string, optional) \u2014 Collection ID or name\n items (array, optional) \u2014 Batch: [{id}, ...]\n id (string, required)",
901
+ "add_mode": "# variable_collections.add_mode\nAdd a mode to a collection\n\nParams:\n items (array, required) \u2014 Array of {collectionId, name}\n collectionId (string, required) \u2014 Collection ID or name\n name (string, required) \u2014 Mode name",
902
+ "rename_mode": '# variable_collections.rename_mode\nRename a mode\n\nParams:\n items (array, required) \u2014 Array of {collectionId, modeId, name}\n collectionId (string, required) \u2014 Collection ID or name\n modeId (string, required) \u2014 Mode ID or name (e.g. "Dark")\n name (string, required) \u2014 New name',
903
+ "remove_mode": '# variable_collections.remove_mode\nRemove a mode from a collection\n\nParams:\n items (array, required) \u2014 Array of {collectionId, modeId}\n collectionId (string, required) \u2014 Collection ID or name\n modeId (string, required) \u2014 Mode ID or name (e.g. "Dark")'
904
+ }
905
+ },
906
+ "variables": {
907
+ "summary": '# variables\nSearch and update design variables within a collection.\n\nMethods:\n list Search variables within a collection [read]\n get Get variable detail by name [read]\n create Create variables in a collection. Use valuesByMode for multi-mode, or value for default mode only. [create]\n update Update variable metadata and/or set values [edit]\n delete Delete variables [edit]\n\n// Search and update variables within a collection. collectionId is required on all methods.\n// Use variable_collections to create full token sets (collection + modes + variables in one call).\n// ---\n// query: prefix match first, then substring. "bg/" matches bg/canvas, bg/surface, etc.\n// valuesByMode: values keyed by mode name. value is shorthand for the default mode.\n// Aliases: {type: "VARIABLE_ALIAS", name: "other/variable"}.\n// scopes: ALL_SCOPES, TEXT_CONTENT, WIDTH_HEIGHT, GAP, CORNER_RADIUS, ALL_FILLS, FRAME_FILL, SHAPE_FILL,\n// TEXT_FILL, STROKE_COLOR, STROKE_FLOAT, EFFECT_FLOAT, EFFECT_COLOR, OPACITY, FONT_FAMILY, FONT_STYLE,\n// FONT_WEIGHT, FONT_SIZE, LINE_HEIGHT, LETTER_SPACING, PARAGRAPH_SPACING, PARAGRAPH_INDENT\n\nUse variables(method: "help", topic: "<method>") for method details.',
908
+ "methods": {
909
+ "list": '# variables.list\nSearch variables within a collection\n\nExample: variables(method:"list", collectionId:"Colors", query:"bg/")\n\nParams:\n collectionId (string, required) \u2014 Collection ID or name\n query (string, optional) \u2014 Search query \u2014 prefix match first, then substring fallback\n type (COLOR | FLOAT | STRING | BOOLEAN, optional) \u2014 Filter by variable type\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.\n offset (number, optional) \u2014 Skip N items for pagination (default 0)\n limit (number, optional) \u2014 Max items per page (default 100)',
910
+ "get": '# variables.get\nGet variable detail by name\n\nParams:\n name (string, required) \u2014 Variable name (unique within collection)\n collectionId (string, required) \u2014 Collection ID or name\n fields (string[], optional) \u2014 Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.',
911
+ "create": '# variables.create\nCreate variables in a collection. Use valuesByMode for multi-mode, or value for default mode only.\n\nExample: variables(method:"create", collectionId:"Colors", items:[{name:"bg/primary", type:"COLOR", valuesByMode:{"Light":"#FFF","Dark":"#111"}, scopes:["ALL_FILLS"]}])\n\nParams:\n collectionId (string, required) \u2014 Collection ID or name\n items (VariableCreateItem[], required) \u2014 Array of variables to create\n name (string, required) \u2014 Variable name (must be unique within collection)\n type (COLOR | FLOAT | STRING | BOOLEAN, required) \u2014 Variable type\n value (variable_value, optional) \u2014 Shorthand \u2014 sets the default mode value. Use valuesByMode for multi-mode.\n valuesByMode (object, optional) \u2014 Values keyed by mode name (e.g. {"Light": "#FFF", "Dark": "#111"}). Takes precedence over value.\n description (string, optional) \u2014 Variable description\n scopes (string[], optional) \u2014 Restrict where variable can be applied (default: ALL_SCOPES)',
912
+ "update": '# variables.update\nUpdate variable metadata and/or set values\n\nExample: variables(method:"update", collectionId:"Colors", items:[{name:"bg/primary", valuesByMode:{"Light":"#FFF","Dark":"#222"}}])\n\nParams:\n collectionId (string, required) \u2014 Collection ID or name\n items (VariableUpdateItem[], required) \u2014 Array of variable updates\n name (string, required) \u2014 Variable name\n rename (string, optional) \u2014 Rename the variable\n description (string, optional) \u2014 Set description\n scopes (string[], optional) \u2014 Update scopes\n value (variable_value, optional) \u2014 Shorthand \u2014 sets the default mode value. Use valuesByMode for multi-mode.\n valuesByMode (object, optional) \u2014 Values keyed by mode name. Takes precedence over value.',
913
+ "delete": "# variables.delete\nDelete variables\n\nParams:\n collectionId (string, required) \u2014 Collection ID or name\n name (string, optional) \u2014 Variable name\n items (array, optional) \u2014 Batch: [{name}, ...]\n name (string, required)"
914
+ }
915
+ },
916
+ "version_history": {
917
+ "summary": `# version_history
918
+ Save named versions to the Figma file's version history.
919
+
920
+ Methods:
921
+ save Save a named version to the file's version history [edit]
922
+
923
+ // Version history lets you create named snapshots of a Figma file.
924
+ // Use this after completing design tasks to create an audit trail of changes.
925
+ // Equivalent to Figma's File \u2192 Save to Version History (Cmd+Opt+S).
926
+
927
+ Use version_history(method: "help", topic: "<method>") for method details.`,
928
+ "methods": {
929
+ "save": `# version_history.save
930
+ Save a named version to the file's version history
931
+
932
+ Params:
933
+ title (string, required) \u2014 Version title (e.g., "Added hero sections with website copy")
934
+ description (string, optional) \u2014 Optional longer description of what changed`
935
+ }
936
+ }
937
+ };
938
+ var helpTopics = {
939
+ "missing_tools": '# Missing Create / Edit Tools\n\nIf the user asks you to create or modify something in Figma but you cannot find create/edit methods on endpoint tools, the MCP server was started without the correct access tier flag.\n\nVibma filters available methods at startup based on CLI flags passed in the MCP config `args` array:\n\n| Flag | Methods available |\n|------|-----------------|\n| _(none)_ | Read-only (get, list, check, scan, export) |\n| `--create` | Read + creation methods (create, clone) |\n| `--edit` | All methods (read + create + update + delete) |\n\nAsk the user to add `--edit` (or `--create`) to their MCP config args:\n\n```json\n{\n "mcpServers": {\n "Vibma": {\n "command": "npx",\n "args": ["-y", "@ufira/vibma", "--edit"]\n }\n }\n}\n```\n\nAfter updating, the user must restart their AI tool or reload MCP servers \u2014 stdio-based servers cannot hot-reload.'
940
+ };
941
+ var allEndpointNames = Object.keys(helpEndpoints);
942
+ var allTopicNames = Object.keys(helpTopics);
943
+ function resolveHelp(topic) {
944
+ if (!topic) return helpDirectory;
945
+ const dot = topic.indexOf(".");
946
+ if (dot === -1) {
947
+ const ep2 = helpEndpoints[topic];
948
+ if (ep2) return ep2.summary;
949
+ const t = helpTopics[topic];
950
+ if (t) return t;
951
+ const all = [...allEndpointNames, ...allTopicNames];
952
+ return "Unknown topic: " + topic + ". Available: " + all.join(", ");
953
+ }
954
+ const epName = topic.slice(0, dot);
955
+ const methodName = topic.slice(dot + 1);
956
+ const ep = helpEndpoints[epName];
957
+ if (!ep) {
958
+ const all = [...allEndpointNames, ...allTopicNames];
959
+ return "Unknown topic: " + epName + ". Available: " + all.join(", ");
960
+ }
961
+ const method = ep.methods[methodName];
962
+ if (method) return method;
963
+ return "Unknown method: " + methodName + " on " + epName + ". Available methods: " + Object.keys(ep.methods).join(", ");
964
+ }
965
+ function resolveEndpointHelp(endpoint, topic) {
966
+ const ep = helpEndpoints[endpoint];
967
+ if (!ep) return null;
968
+ if (!topic) return ep.summary;
969
+ const method = ep.methods[topic];
970
+ if (method) return method;
971
+ return "Unknown method: " + topic + ". Available methods on " + endpoint + ": " + Object.keys(ep.methods).join(", ");
972
+ }
973
+
49
974
  // src/tools/registry.ts
975
+ function resolveCommand(tool, params) {
976
+ if (tool.commandMap && params.method) {
977
+ const cmd = tool.commandMap[params.method];
978
+ if (cmd) return cmd;
979
+ }
980
+ return tool.command ?? tool.name;
981
+ }
50
982
  function registerTools(server, sendCommand, caps, tools) {
51
983
  for (const tool of tools) {
52
984
  if (tool.tier === "create" && !caps.create) continue;
53
985
  if (tool.tier === "edit" && !caps.edit) continue;
54
986
  const schema = typeof tool.schema === "function" ? tool.schema(caps) : tool.schema;
55
- const command = tool.command ?? tool.name;
56
987
  const timeout = tool.timeout;
57
- const format = tool.formatResponse ?? mcpJson;
988
+ const defaultFormat = tool.formatResponse ?? mcpJson;
58
989
  server.registerTool(tool.name, { description: tool.description, inputSchema: schema }, async (params) => {
59
990
  try {
991
+ if (params.method === "help") {
992
+ const text = resolveEndpointHelp(tool.name, params.topic) ?? resolveHelp(tool.name);
993
+ return { content: [{ type: "text", text }] };
994
+ }
60
995
  if (tool.validate) tool.validate(params);
996
+ const command = resolveCommand(tool, params);
61
997
  const result = await sendCommand(command, params, timeout);
998
+ const format = tool.methodFormatters?.[params.method] ?? defaultFormat;
62
999
  return format(result);
63
1000
  } catch (e) {
1001
+ if (e instanceof import_zod.ZodError) {
1002
+ const hints = e.issues.map((i) => {
1003
+ const path = i.path.join(".");
1004
+ return `[${path}] ${i.message}`;
1005
+ });
1006
+ return mcpError(`${tool.name} validation error`, hints.join("; "));
1007
+ }
64
1008
  return mcpError(`${tool.name} error`, e);
65
1009
  }
66
1010
  });