@ufira/vibma 1.0.0-rc5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp.cjs +148 -72
- package/dist/mcp.js +148 -72
- package/dist/tools/generated/guards.cjs +40 -1
- package/dist/tools/generated/guards.d.cts +3 -1
- package/dist/tools/generated/guards.d.ts +3 -1
- package/dist/tools/generated/guards.js +39 -1
- package/dist/tools/registry.cjs +60 -33
- package/dist/tools/registry.js +60 -33
- package/package.json +2 -2
package/dist/mcp.js
CHANGED
|
@@ -76,9 +76,9 @@ Use help(topic: "<endpoint>") for endpoint details.
|
|
|
76
76
|
Use help(topic: "<endpoint>.<method>") for method details.`;
|
|
77
77
|
var helpEndpoints = {
|
|
78
78
|
"components": {
|
|
79
|
-
"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 + optional node tree for structural inspection [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// Adding variants: clone an existing variant into the set with a new name. See guidelines(topic:"component-structure") for workflow.\n\nUse components(method: "help", topic: "<method>") for method details.',
|
|
79
|
+
"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 + optional node tree for structural inspection [read]\n create Create components [create]\n commit Commit a staged component \u2014 unwraps from [STAGED] container into the original target location. [edit]\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// Adding variants: clone an existing variant into the set with a new name. See guidelines(topic:"component-structure") for workflow.\n\nUse components(method: "help", topic: "<method>") for method details.',
|
|
80
80
|
"methods": {
|
|
81
|
-
"clone": "# components.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
81
|
+
"clone": "# components.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n items (array, optional) \u2014 Batch: [{id, name?, parentId?, x?, y?}, ...]. Alternative to single-item params.\n id (string, required) \u2014 Node ID to clone\n name (string, optional) \u2014 Rename the clone\n parentId (string, optional) \u2014 Target parent\n x (number, optional)\n y (number, optional)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
|
|
82
82
|
"audit": `# components.audit
|
|
83
83
|
Run lint on a node \u2014 returns severity-ranked findings
|
|
84
84
|
|
|
@@ -101,7 +101,7 @@ Discriminant: type (component | from_node | variant_set)
|
|
|
101
101
|
|
|
102
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
103
|
name (string, required) \u2014 Component name
|
|
104
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
104
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
105
105
|
x (number, optional) \u2014 X position (default: 0)
|
|
106
106
|
y (number, optional) \u2014 Y position (default: 0)
|
|
107
107
|
width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
|
|
@@ -134,7 +134,7 @@ Discriminant: type (component | from_node | variant_set)
|
|
|
134
134
|
bottomLeftRadius (string, optional)
|
|
135
135
|
effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
|
|
136
136
|
layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)
|
|
137
|
-
layoutWrap (NO_WRAP | WRAP, optional)
|
|
137
|
+
layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
|
|
138
138
|
padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
|
|
139
139
|
paddingTop (string, optional)
|
|
140
140
|
paddingRight (string, optional)
|
|
@@ -152,6 +152,8 @@ Discriminant: type (component | from_node | variant_set)
|
|
|
152
152
|
maxHeight (number, optional) \u2014 Max height for responsive auto-layout
|
|
153
153
|
overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
|
|
154
154
|
description (string, optional) \u2014 Component description (shown in Figma's component panel)
|
|
155
|
+
children (array, optional) \u2014 Inline child nodes \u2014 build nested trees in one call. Types: text: {type:"text", text, componentPropertyName?, fontFamily?, fontSize?, fontWeight?, fontStyle?, fontColor?, layoutSizingHorizontal?}. frame: {type:"frame", name?, layoutMode?, fillColor?, width?, layoutSizingHorizontal?, children?}. instance: {type:"instance", componentId, componentPropertyName?, variantProperties?, properties?}. component: {type:"component", name, children?}. All params from text/frame endpoints are supported on their respective types. componentPropertyName auto-creates and binds a TEXT (text) or INSTANCE_SWAP (instance) property. Always set layoutSizingHorizontal + layoutSizingVertical on children inside auto-layout parents (FILL, HUG, or FIXED). Example: children:[{type:"text", text:"Label", componentPropertyName:"Label", fontSize:14, fontColorVariableName:"text/primary", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}, {type:"frame", name:"Actions", layoutMode:"HORIZONTAL", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG", itemSpacing:8, children:[{type:"instance", componentId:"1:2", componentPropertyName:"Action", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}]}]
|
|
156
|
+
|
|
155
157
|
properties (array, optional) \u2014 Component properties to define at creation: [{propertyName, type, defaultValue}]. TEXT properties for inline children with componentPropertyName are created automatically.
|
|
156
158
|
propertyName (string, required) \u2014 Property name
|
|
157
159
|
type (BOOLEAN | TEXT | INSTANCE_SWAP, required) \u2014 Property type
|
|
@@ -160,11 +162,12 @@ Discriminant: type (component | from_node | variant_set)
|
|
|
160
162
|
|
|
161
163
|
## from_node \u2014 Convert existing nodes to components. Text children auto-exposed as editable properties (exposeText: true).
|
|
162
164
|
nodeId (string, required) \u2014 Node ID to convert
|
|
165
|
+
name (string, optional) \u2014 Rename the component (default: keeps the node's current name)
|
|
163
166
|
exposeText (boolean, optional) \u2014 Auto-expose text as editable properties (default: true)
|
|
164
167
|
|
|
165
168
|
## variant_set \u2014 Combine components into a variant set. The resulting set is a frame \u2014 accepts all frame properties for layout/styling.
|
|
166
169
|
name (string, optional) \u2014 Node name
|
|
167
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
170
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
168
171
|
x (number, optional) \u2014 X position (default: 0)
|
|
169
172
|
y (number, optional) \u2014 Y position (default: 0)
|
|
170
173
|
width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
|
|
@@ -197,7 +200,7 @@ Discriminant: type (component | from_node | variant_set)
|
|
|
197
200
|
bottomLeftRadius (string, optional)
|
|
198
201
|
effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
|
|
199
202
|
layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)
|
|
200
|
-
layoutWrap (NO_WRAP | WRAP, optional)
|
|
203
|
+
layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
|
|
201
204
|
padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
|
|
202
205
|
paddingTop (string, optional)
|
|
203
206
|
paddingRight (string, optional)
|
|
@@ -215,7 +218,9 @@ Discriminant: type (component | from_node | variant_set)
|
|
|
215
218
|
maxHeight (number, optional) \u2014 Max height for responsive auto-layout
|
|
216
219
|
overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
|
|
217
220
|
componentIds (string[], optional) \u2014 Existing component IDs to combine (min 2). Alternative to children.
|
|
218
|
-
variantPropertyName (string, optional) \u2014 Rename the auto-generated variant property (default: 'Property 1')
|
|
221
|
+
variantPropertyName (string, optional) \u2014 Rename the auto-generated variant property (default: 'Property 1')
|
|
222
|
+
children (array, optional) \u2014 Inline variant components. Each must be {type:"component", name, children?, ...frame_params}. All variants must share the same child structure. Alternative to componentIds \u2014 do not combine both.`,
|
|
223
|
+
"commit": '# components.commit\nCommit a staged component \u2014 unwraps from [STAGED] container into the original target location.\n\nExample: components(method:"commit", id:"1:234")\n\nParams:\n id (string, required) \u2014 Staged node ID to commit',
|
|
219
224
|
"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.',
|
|
220
225
|
"delete": "# components.delete\nDelete components or component sets\n\nParams:\n id (string, required) \u2014 Component or component set ID"
|
|
221
226
|
}
|
|
@@ -246,7 +251,7 @@ Discriminant: type (component | from_node | variant_set)
|
|
|
246
251
|
}
|
|
247
252
|
},
|
|
248
253
|
"frames": {
|
|
249
|
-
"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.',
|
|
254
|
+
"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 commit Commit a staged node \u2014 unwraps from [STAGED] container into the original target location. [edit]\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.',
|
|
250
255
|
"methods": {
|
|
251
256
|
"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.',
|
|
252
257
|
"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)',
|
|
@@ -281,7 +286,7 @@ Params:
|
|
|
281
286
|
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)
|
|
282
287
|
effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
|
|
283
288
|
layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
|
|
284
|
-
layoutWrap (NO_WRAP | WRAP, optional)
|
|
289
|
+
layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
|
|
285
290
|
padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
|
|
286
291
|
paddingTop (string, optional)
|
|
287
292
|
paddingRight (string, optional)
|
|
@@ -302,6 +307,10 @@ Params:
|
|
|
302
307
|
fontFamily (string, optional) \u2014 Font family
|
|
303
308
|
fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
|
|
304
309
|
fontWeight (number, optional) \u2014 100-900. Ignored when fontStyle is set.
|
|
310
|
+
lineHeight (number | {value, unit: "PIXELS"|"PERCENT"|"AUTO"}, optional)
|
|
311
|
+
letterSpacing (number | {value, unit: "PIXELS"|"PERCENT"}, optional)
|
|
312
|
+
textCase (ORIGINAL | UPPER | LOWER | TITLE | SMALL_CAPS | SMALL_CAPS_FORCED, optional)
|
|
313
|
+
textDecoration (NONE | UNDERLINE | STRIKETHROUGH, optional)
|
|
305
314
|
fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
|
|
306
315
|
fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
|
|
307
316
|
fontColorStyleName (string, optional) \u2014 Apply paint style \u2014 overrides fontColor
|
|
@@ -329,7 +338,7 @@ Params:
|
|
|
329
338
|
exportSettings (array, optional) \u2014 Export settings
|
|
330
339
|
properties (object, optional) \u2014 Direct Figma API props (escape hatch)`,
|
|
331
340
|
"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)",
|
|
332
|
-
"clone": "# frames.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
341
|
+
"clone": "# frames.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n items (array, optional) \u2014 Batch: [{id, name?, parentId?, x?, y?}, ...]. Alternative to single-item params.\n id (string, required) \u2014 Node ID to clone\n name (string, optional) \u2014 Rename the clone\n parentId (string, optional) \u2014 Target parent\n x (number, optional)\n y (number, optional)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
|
|
333
342
|
"audit": `# frames.audit
|
|
334
343
|
Run lint on a node \u2014 returns severity-ranked findings
|
|
335
344
|
|
|
@@ -350,7 +359,7 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
350
359
|
|
|
351
360
|
## frame \u2014 General-purpose frame \u2014 shrinks to content by default, static when width+height given
|
|
352
361
|
name (string, optional) \u2014 Node name
|
|
353
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
362
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
354
363
|
x (number, optional) \u2014 X position (default: 0)
|
|
355
364
|
y (number, optional) \u2014 Y position (default: 0)
|
|
356
365
|
width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
|
|
@@ -383,7 +392,7 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
383
392
|
bottomLeftRadius (string, optional)
|
|
384
393
|
effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
|
|
385
394
|
layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)
|
|
386
|
-
layoutWrap (NO_WRAP | WRAP, optional)
|
|
395
|
+
layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
|
|
387
396
|
padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
|
|
388
397
|
paddingTop (string, optional)
|
|
389
398
|
paddingRight (string, optional)
|
|
@@ -401,10 +410,12 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
401
410
|
maxHeight (number, optional) \u2014 Max height for responsive auto-layout
|
|
402
411
|
overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
|
|
403
412
|
clipsContent (boolean, optional)
|
|
413
|
+
children (array, optional) \u2014 Inline child nodes \u2014 build nested trees in one call. Types: text: {type:"text", text, fontFamily?, fontSize?, fontWeight?, fontStyle?, fontColor?, layoutSizingHorizontal?}. frame: {type:"frame", name?, layoutMode?, fillColor?, width?, layoutSizingHorizontal?, children?}. instance: {type:"instance", componentId, variantProperties?, properties?}. component: {type:"component", name, children?}. All params from text/frame endpoints are supported on their respective types. Always set layoutSizingHorizontal + layoutSizingVertical on children inside auto-layout parents (FILL, HUG, or FIXED). Example: children:[{type:"text", text:"Title", fontSize:20, layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}, {type:"frame", name:"Row", layoutMode:"HORIZONTAL", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG", itemSpacing:8, children:[{type:"instance", componentId:"1:2", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}]}] Inside components: add componentPropertyName to auto-bind TEXT or INSTANCE_SWAP properties.
|
|
414
|
+
|
|
404
415
|
|
|
405
416
|
## auto_layout \u2014 Auto-layout frame that arranges children automatically
|
|
406
417
|
name (string, optional) \u2014 Node name
|
|
407
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
418
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
408
419
|
x (number, optional) \u2014 X position (default: 0)
|
|
409
420
|
y (number, optional) \u2014 Y position (default: 0)
|
|
410
421
|
width (number, optional) \u2014 Width in px (omit to shrink-to-content via HUG)
|
|
@@ -437,7 +448,7 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
437
448
|
bottomLeftRadius (string, optional)
|
|
438
449
|
effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
|
|
439
450
|
layoutMode (HORIZONTAL | VERTICAL, required) \u2014 Primary axis direction
|
|
440
|
-
layoutWrap (NO_WRAP | WRAP, optional)
|
|
451
|
+
layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
|
|
441
452
|
padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
|
|
442
453
|
paddingTop (string, optional)
|
|
443
454
|
paddingRight (string, optional)
|
|
@@ -456,10 +467,12 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
456
467
|
overflowDirection (NONE | HORIZONTAL | VERTICAL | BOTH, optional) \u2014 Scroll overflow in prototype (default: NONE)
|
|
457
468
|
clipsContent (boolean, optional)
|
|
458
469
|
nodeIds (string[], optional) \u2014 Existing node IDs to wrap into auto-layout
|
|
470
|
+
children (array, optional) \u2014 Inline child nodes \u2014 build nested trees in one call. Types: text: {type:"text", text, fontFamily?, fontSize?, fontWeight?, fontStyle?, fontColor?, layoutSizingHorizontal?}. frame: {type:"frame", name?, layoutMode?, fillColor?, width?, layoutSizingHorizontal?, children?}. instance: {type:"instance", componentId, variantProperties?, properties?}. component: {type:"component", name, children?}. All params from text/frame endpoints are supported on their respective types. Always set layoutSizingHorizontal + layoutSizingVertical on children inside auto-layout parents (FILL, HUG, or FIXED). Example: children:[{type:"text", text:"Title", fontSize:20, layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}, {type:"frame", name:"Row", layoutMode:"HORIZONTAL", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG", itemSpacing:8, children:[{type:"instance", componentId:"1:2", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}]}] Inside components: add componentPropertyName to auto-bind TEXT or INSTANCE_SWAP properties.
|
|
471
|
+
|
|
459
472
|
|
|
460
473
|
## section \u2014 Figma section (top-level organizer)
|
|
461
474
|
name (string, required) \u2014 Section name
|
|
462
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
475
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
463
476
|
x (number, optional) \u2014 X position (default: 0)
|
|
464
477
|
y (number, optional) \u2014 Y position (default: 0)
|
|
465
478
|
width (number, optional) \u2014 Width (default: 500)
|
|
@@ -471,7 +484,7 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
471
484
|
|
|
472
485
|
## rectangle \u2014 Rectangle shape node
|
|
473
486
|
name (string, optional) \u2014 Layer name (default: 'Rectangle')
|
|
474
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
487
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
475
488
|
x (number, optional) \u2014 X position (default: 0)
|
|
476
489
|
y (number, optional) \u2014 Y position (default: 0)
|
|
477
490
|
width (number, optional) \u2014 Width in px (default: 100)
|
|
@@ -495,7 +508,7 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
495
508
|
|
|
496
509
|
## ellipse \u2014 Ellipse/circle shape node
|
|
497
510
|
name (string, optional) \u2014 Layer name (default: 'Ellipse')
|
|
498
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
511
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
499
512
|
x (number, optional) \u2014 X position (default: 0)
|
|
500
513
|
y (number, optional) \u2014 Y position (default: 0)
|
|
501
514
|
width (number, optional) \u2014 Width in px (default: 100)
|
|
@@ -514,7 +527,7 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
514
527
|
|
|
515
528
|
## line \u2014 Line shape node
|
|
516
529
|
name (string, optional) \u2014 Layer name (default: 'Line')
|
|
517
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
530
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
518
531
|
x (number, optional) \u2014 X position (default: 0)
|
|
519
532
|
y (number, optional) \u2014 Y position (default: 0)
|
|
520
533
|
length (number, optional) \u2014 Line length in px (default: 100)
|
|
@@ -529,24 +542,25 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
529
542
|
## group \u2014 Group existing nodes together
|
|
530
543
|
nodeIds (string[], required) \u2014 Node IDs to group (min 1)
|
|
531
544
|
name (string, optional) \u2014 Group name
|
|
532
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
545
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
533
546
|
|
|
534
547
|
## boolean_operation \u2014 Combine shapes with boolean operations (union, subtract, intersect, exclude)
|
|
535
548
|
operation (UNION | SUBTRACT | INTERSECT | EXCLUDE, required) \u2014 Boolean operation type
|
|
536
549
|
nodeIds (string[], required) \u2014 Node IDs to combine (min 2, first node is the base for SUBTRACT)
|
|
537
550
|
name (string, optional) \u2014 Result node name
|
|
538
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
551
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
539
552
|
|
|
540
553
|
## svg \u2014 Create node from SVG markup
|
|
541
554
|
svg (string, required) \u2014 SVG markup string
|
|
542
555
|
name (string, optional) \u2014 Layer name (default: 'SVG')
|
|
543
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
556
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
544
557
|
x (number, optional) \u2014 X position (default: 0)
|
|
545
558
|
y (number, optional) \u2014 Y position (default: 0)
|
|
546
559
|
fillStyleName (string, optional) \u2014 Paint style to apply to vector fills
|
|
547
560
|
fillVariableName (string, optional) \u2014 Color variable by name for vector fills
|
|
548
561
|
strokeStyleName (string, optional) \u2014 Paint style to apply to vector strokes
|
|
549
562
|
strokeVariableName (string, optional) \u2014 Color variable by name for vector strokes`,
|
|
563
|
+
"commit": '# frames.commit\nCommit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n\nExample: frames(method:"commit", id:"1:234")\n\nParams:\n id (string, required) \u2014 Staged node ID to commit',
|
|
550
564
|
"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)"
|
|
551
565
|
}
|
|
552
566
|
},
|
|
@@ -555,7 +569,7 @@ Discriminant: type (frame | auto_layout | section | rectangle | ellipse | line |
|
|
|
555
569
|
"methods": {
|
|
556
570
|
"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)',
|
|
557
571
|
"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)",
|
|
558
|
-
"clone": "# instances.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
572
|
+
"clone": "# instances.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n items (array, optional) \u2014 Batch: [{id, name?, parentId?, x?, y?}, ...]. Alternative to single-item params.\n id (string, required) \u2014 Node ID to clone\n name (string, optional) \u2014 Rename the clone\n parentId (string, optional) \u2014 Target parent\n x (number, optional)\n y (number, optional)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
|
|
559
573
|
"audit": `# instances.audit
|
|
560
574
|
Run lint on a node \u2014 returns severity-ranked findings
|
|
561
575
|
|
|
@@ -596,7 +610,7 @@ Params:
|
|
|
596
610
|
y (number, optional)
|
|
597
611
|
width (number, optional) \u2014 Override width (resize)
|
|
598
612
|
height (number, optional) \u2014 Override height (resize)
|
|
599
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
613
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
600
614
|
depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.`,
|
|
601
615
|
"update": `# instances.update
|
|
602
616
|
Set instance properties
|
|
@@ -631,7 +645,7 @@ Params:
|
|
|
631
645
|
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)
|
|
632
646
|
effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
|
|
633
647
|
layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
|
|
634
|
-
layoutWrap (NO_WRAP | WRAP, optional)
|
|
648
|
+
layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
|
|
635
649
|
padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
|
|
636
650
|
paddingTop (string, optional)
|
|
637
651
|
paddingRight (string, optional)
|
|
@@ -652,6 +666,10 @@ Params:
|
|
|
652
666
|
fontFamily (string, optional) \u2014 Font family
|
|
653
667
|
fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
|
|
654
668
|
fontWeight (number, optional) \u2014 100-900. Ignored when fontStyle is set.
|
|
669
|
+
lineHeight (number | {value, unit: "PIXELS"|"PERCENT"|"AUTO"}, optional)
|
|
670
|
+
letterSpacing (number | {value, unit: "PIXELS"|"PERCENT"}, optional)
|
|
671
|
+
textCase (ORIGINAL | UPPER | LOWER | TITLE | SMALL_CAPS | SMALL_CAPS_FORCED, optional)
|
|
672
|
+
textDecoration (NONE | UNDERLINE | STRIKETHROUGH, optional)
|
|
655
673
|
fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
|
|
656
674
|
fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
|
|
657
675
|
fontColorStyleName (string, optional) \u2014 Apply paint style \u2014 overrides fontColor
|
|
@@ -749,7 +767,7 @@ Use lint(method: "help", topic: "<method>") for method details.`,
|
|
|
749
767
|
"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// IMPORTANT: destination rules depend on navigation type:\n// NAVIGATE/SWAP/OVERLAY/SCROLL_TO \u2192 destination must be a top-level frame (direct child of a page). Nested frames are rejected.\n// CHANGE_TO \u2192 destination must be a variant (COMPONENT inside a COMPONENT_SET). Used for hover/state swaps within the same component.\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.',
|
|
750
768
|
"methods": {
|
|
751
769
|
"get": "# prototyping.get\nGet reactions and overflow direction on a node\n\nParams:\n id (string, required) \u2014 Node ID",
|
|
752
|
-
"add": '# prototyping.add\nAdd a prototype reaction to a node\n\nExample: prototyping(method:"add", id:"btn-1", trigger:"ON_CLICK", destination:"
|
|
770
|
+
"add": '# prototyping.add\nAdd a prototype reaction to a node\n\nExample: prototyping(method:"add", items:[{id:"btn-1", trigger:"ON_CLICK", destination:"frame-2", navigation:"NAVIGATE", transition:"SMART_ANIMATE"}, {id:"btn-2", trigger:"ON_CLICK", destination:"frame-3"}])\n\nParams:\n id (string, optional) \u2014 Node ID\n trigger (ON_CLICK | ON_HOVER | ON_PRESS | ON_DRAG | AFTER_TIMEOUT | MOUSE_ENTER | MOUSE_LEAVE | ON_KEY_DOWN, optional) \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). NAVIGATE/SWAP/OVERLAY: must be a top-level frame. CHANGE_TO: must be a variant (component inside a component set).\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.\n items (array, optional) \u2014 Batch: array of {id, trigger, destination?, ...} reaction items\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 destination (string, optional) \u2014 Target node ID\n navigation (NAVIGATE | SWAP | OVERLAY | SCROLL_TO | CHANGE_TO, optional)\n transition (DISSOLVE | SMART_ANIMATE | MOVE_IN | MOVE_OUT | PUSH | SLIDE_IN | SLIDE_OUT | INSTANT, optional)\n transitionDirection (LEFT | RIGHT | TOP | BOTTOM, optional)\n duration (number, optional)\n easing (EASE_IN | EASE_OUT | EASE_IN_AND_OUT | LINEAR | GENTLE | QUICK | BOUNCY | SLOW, optional)\n actionType (NODE | BACK | CLOSE | URL | SET_VARIABLE_MODE, optional)\n triggerDelay (number, optional)\n url (string, optional)\n collectionName (string, optional)\n modeName (string, optional)\n resetScrollPosition (boolean, optional)\n actions (array, optional)',
|
|
753
771
|
"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}]}]",
|
|
754
772
|
"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)"
|
|
755
773
|
}
|
|
@@ -766,8 +784,8 @@ Use lint(method: "help", topic: "<method>") for method details.`,
|
|
|
766
784
|
"methods": {
|
|
767
785
|
"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)',
|
|
768
786
|
"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.',
|
|
769
|
-
"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, optional) \u2014 Color value. Optional when colorVariableName is provided.\n colorVariableName (string, optional) \u2014 Bind to a COLOR variable by name (style tracks the variable). Can be used alone \u2014 color is resolved from 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 (
|
|
770
|
-
"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 (
|
|
787
|
+
"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, optional) \u2014 Color value. Optional when colorVariableName is provided.\n colorVariableName (string, optional) \u2014 Bind to a COLOR variable by name (style tracks the variable). Can be used alone \u2014 color is resolved from 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 (number | {value, unit: "PIXELS"|"PERCENT"|"AUTO"}, optional)\n letterSpacing (number | {value, unit: "PIXELS"|"PERCENT"}, 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',
|
|
788
|
+
"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 (number | {value, unit: "PIXELS"|"PERCENT"|"AUTO"}, optional)\n letterSpacing (number | {value, unit: "PIXELS"|"PERCENT"}, 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)',
|
|
771
789
|
"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"
|
|
772
790
|
}
|
|
773
791
|
},
|
|
@@ -807,7 +825,7 @@ Params:
|
|
|
807
825
|
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)
|
|
808
826
|
effectStyleName (string, optional) \u2014 Effect style name (e.g. 'Shadow/Card') for shadows, blurs
|
|
809
827
|
layoutMode (NONE | HORIZONTAL | VERTICAL, optional) \u2014 Layout direction (default: NONE)
|
|
810
|
-
layoutWrap (NO_WRAP | WRAP, optional)
|
|
828
|
+
layoutWrap (NO_WRAP | WRAP, optional) \u2014 Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns.
|
|
811
829
|
padding (string, optional) \u2014 All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft.
|
|
812
830
|
paddingTop (string, optional)
|
|
813
831
|
paddingRight (string, optional)
|
|
@@ -828,6 +846,10 @@ Params:
|
|
|
828
846
|
fontFamily (string, optional) \u2014 Font family
|
|
829
847
|
fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
|
|
830
848
|
fontWeight (number, optional) \u2014 100-900. Ignored when fontStyle is set.
|
|
849
|
+
lineHeight (number | {value, unit: "PIXELS"|"PERCENT"|"AUTO"}, optional)
|
|
850
|
+
letterSpacing (number | {value, unit: "PIXELS"|"PERCENT"}, optional)
|
|
851
|
+
textCase (ORIGINAL | UPPER | LOWER | TITLE | SMALL_CAPS | SMALL_CAPS_FORCED, optional)
|
|
852
|
+
textDecoration (NONE | UNDERLINE | STRIKETHROUGH, optional)
|
|
831
853
|
fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
|
|
832
854
|
fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
|
|
833
855
|
fontColorStyleName (string, optional) \u2014 Apply paint style \u2014 overrides fontColor
|
|
@@ -855,7 +877,7 @@ Params:
|
|
|
855
877
|
exportSettings (array, optional) \u2014 Export settings
|
|
856
878
|
properties (object, optional) \u2014 Direct Figma API props (escape hatch)`,
|
|
857
879
|
"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)",
|
|
858
|
-
"clone": "# text.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
880
|
+
"clone": "# text.clone\nDuplicate nodes\n\nParams:\n id (string, optional) \u2014 Node ID\n name (string, optional) \u2014 Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)\n parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.\n x (number, optional) \u2014 X position (default: 0)\n y (number, optional) \u2014 Y position (default: 0)\n items (array, optional) \u2014 Batch: [{id, name?, parentId?, x?, y?}, ...]. Alternative to single-item params.\n id (string, required) \u2014 Node ID to clone\n name (string, optional) \u2014 Rename the clone\n parentId (string, optional) \u2014 Target parent\n x (number, optional)\n y (number, optional)\n depth (number, optional) \u2014 Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited.",
|
|
859
881
|
"audit": `# text.audit
|
|
860
882
|
Run lint on a node \u2014 returns severity-ranked findings
|
|
861
883
|
|
|
@@ -879,11 +901,15 @@ Params:
|
|
|
879
901
|
x (number, optional)
|
|
880
902
|
y (number, optional)
|
|
881
903
|
width (number, optional) \u2014 Fixed width in px \u2014 implies layoutSizingHorizontal: FIXED and textAutoResize: HEIGHT
|
|
882
|
-
parentId (string, optional) \u2014 Parent node ID. Omit to place
|
|
904
|
+
parentId (string, optional) \u2014 Parent node ID. Omit to place at current page root.
|
|
883
905
|
fontFamily (string, optional) \u2014 Font family (default: Inter). Use fonts.list to find installed fonts.
|
|
884
906
|
fontStyle (string, optional) \u2014 Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight
|
|
885
907
|
fontSize (number, optional) \u2014 Font size (default: 14)
|
|
886
908
|
fontWeight (number, optional) \u2014 100-900 (default: 400). Ignored when fontStyle is set.
|
|
909
|
+
lineHeight (number | {value, unit: "PIXELS"|"PERCENT"|"AUTO"}, optional)
|
|
910
|
+
letterSpacing (number | {value, unit: "PIXELS"|"PERCENT"}, optional)
|
|
911
|
+
textCase (ORIGINAL | UPPER | LOWER | TITLE | SMALL_CAPS | SMALL_CAPS_FORCED, optional)
|
|
912
|
+
textDecoration (NONE | UNDERLINE | STRIKETHROUGH, optional)
|
|
887
913
|
fills (array, optional) \u2014 Text color paints \u2014 e.g. [{type: 'SOLID', color: '#hex'}]. Same as node fills.
|
|
888
914
|
fontColor (Color, optional) \u2014 Shorthand \u2014 sets text color (auto-binds to matching variable/style)
|
|
889
915
|
fontColorVariableName (string, optional) \u2014 Bind color variable by name e.g. 'text/primary'
|
|
@@ -919,7 +945,7 @@ Params:
|
|
|
919
945
|
variables (array, optional) \u2014 Variables to create inside this collection
|
|
920
946
|
name (string, required) \u2014 Variable name (unique within collection)
|
|
921
947
|
type (COLOR | FLOAT | STRING | BOOLEAN, required) \u2014 Variable type
|
|
922
|
-
value (variable_value, optional) \u2014
|
|
948
|
+
value (variable_value, optional) \u2014 Sets all modes to this value. Use valuesByMode for per-mode control.
|
|
923
949
|
valuesByMode (object, optional) \u2014 Values keyed by mode name (e.g. {"Light": "#FFF", "Dark": "#111"})
|
|
924
950
|
description (string, optional)
|
|
925
951
|
scopes (string[], optional) \u2014 Restrict where variable can be applied (default: ALL_SCOPES)`,
|
|
@@ -931,11 +957,11 @@ Params:
|
|
|
931
957
|
}
|
|
932
958
|
},
|
|
933
959
|
"variables": {
|
|
934
|
-
"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
|
|
960
|
+
"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 per-mode control, or value to set all modes at once. [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. On create, value sets all modes; on update, value sets the default mode only.\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.',
|
|
935
961
|
"methods": {
|
|
936
962
|
"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)',
|
|
937
963
|
"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.',
|
|
938
|
-
"create": '# variables.create\nCreate variables in a collection. Use valuesByMode for
|
|
964
|
+
"create": '# variables.create\nCreate variables in a collection. Use valuesByMode for per-mode control, or value to set all modes at once.\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 Sets all modes to this value. Use valuesByMode for per-mode control.\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)',
|
|
939
965
|
"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.',
|
|
940
966
|
"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)"
|
|
941
967
|
}
|
|
@@ -1021,6 +1047,7 @@ function registerTools(server2, sendCommand, caps2, tools2) {
|
|
|
1021
1047
|
}
|
|
1022
1048
|
if (tool.validate) tool.validate(params);
|
|
1023
1049
|
const command = resolveCommand(tool, params);
|
|
1050
|
+
params._caps = caps2;
|
|
1024
1051
|
const result = await sendCommand(command, params, timeout);
|
|
1025
1052
|
const format = tool.methodFormatters?.[params.method] ?? defaultFormat;
|
|
1026
1053
|
return format(result);
|
|
@@ -1140,12 +1167,12 @@ function filterMethodsByTier(schema, caps2, methodTiers) {
|
|
|
1140
1167
|
var tools = [
|
|
1141
1168
|
{
|
|
1142
1169
|
name: "components",
|
|
1143
|
-
description: '/** Create and manage reusable components and variant sets. Use method "help" for detailed parameter docs. */\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n list (query?, offset?, limit?) \u2192 { totalCount, items } // List local component names (variant sets as single entries)\n get (id?, names?, depth?, verbose?) \u2192 { results, _truncated? } // Get component detail \u2014 property definitions + optional node tree for structural inspection\n create (type: component|from_node|variant_set, items: (ComponentItem | FromNodeItem | VariantSetItem)[]) \u2192 { results: {id}[] } // Create components\n update (items: UpdatePropertyItem[], depth?) \u2192 { results: ("ok" | {error})[] } // Add, edit, or delete component properties\n delete (id) \u2192 { results: "ok"[] } // Delete components or component sets\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).',
|
|
1170
|
+
description: '/** Create and manage reusable components and variant sets. Use method "help" for detailed parameter docs. */\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n list (query?, offset?, limit?) \u2192 { totalCount, items } // List local component names (variant sets as single entries)\n get (id?, names?, depth?, verbose?) \u2192 { results, _truncated? } // Get component detail \u2014 property definitions + optional node tree for structural inspection\n create (type: component|from_node|variant_set, items: (ComponentItem | FromNodeItem | VariantSetItem)[]) \u2192 { results: {id}[] } // Create components\n commit (id) \u2192 { results: {id}[] } // Commit a staged component \u2014 unwraps from [STAGED] container into the original target location.\n update (items: UpdatePropertyItem[], depth?) \u2192 { results: ("ok" | {error})[] } // Add, edit, or delete component properties\n delete (id) \u2192 { results: "ok"[] } // Delete components or component sets\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).',
|
|
1144
1171
|
schema: (caps2) => filterMethodsByTier({
|
|
1145
|
-
method: z3.enum(["clone", "audit", "reparent", "list", "get", "create", "update", "delete", "help"]),
|
|
1172
|
+
method: z3.enum(["clone", "audit", "reparent", "list", "get", "create", "commit", "update", "delete", "help"]),
|
|
1146
1173
|
id: z3.string().optional().describe("Node ID"),
|
|
1147
1174
|
name: z3.string().optional().describe("Rename the clone (set before appending to parent \u2014 required when cloning a variant into its component set to avoid duplicate names)"),
|
|
1148
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1175
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1149
1176
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1150
1177
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1151
1178
|
items: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe("Array of {id, ...properties} to clone/reparent/update"),
|
|
@@ -1162,10 +1189,13 @@ var tools = [
|
|
|
1162
1189
|
verbose: z3.boolean().optional().describe("Include all properties (bounding box, constraints, text style details). Default false \u2014 returns slim, actionable output."),
|
|
1163
1190
|
type: z3.enum(["component", "from_node", "variant_set"]).optional().describe("Discriminant for create method"),
|
|
1164
1191
|
topic: z3.string().optional().describe('Help topic \u2014 method name for endpoint help, e.g. "create"')
|
|
1165
|
-
}, caps2, { "clone": "create", "audit": "read", "reparent": "edit", "list": "read", "get": "read", "create": "create", "update": "edit", "delete": "edit", "help": "read" }),
|
|
1192
|
+
}, caps2, { "clone": "create", "audit": "read", "reparent": "edit", "list": "read", "get": "read", "create": "create", "commit": "edit", "update": "edit", "delete": "edit", "help": "read" }),
|
|
1166
1193
|
tier: "read",
|
|
1167
1194
|
validate: (params) => {
|
|
1168
1195
|
const m = params.method;
|
|
1196
|
+
if (m === "commit") {
|
|
1197
|
+
if (params.id === void 0) throw new Error('commit requires "id"');
|
|
1198
|
+
}
|
|
1169
1199
|
if (m === "delete") {
|
|
1170
1200
|
if (params.id === void 0) throw new Error('delete requires "id"');
|
|
1171
1201
|
}
|
|
@@ -1182,7 +1212,7 @@ var tools = [
|
|
|
1182
1212
|
const schemas = {
|
|
1183
1213
|
"component": z3.object({
|
|
1184
1214
|
name: z3.string().describe("Component name"),
|
|
1185
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1215
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1186
1216
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1187
1217
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1188
1218
|
width: z3.coerce.number().optional().describe("Width in px (omit to shrink-to-content via HUG)"),
|
|
@@ -1215,7 +1245,7 @@ var tools = [
|
|
|
1215
1245
|
bottomLeftRadius: token.optional(),
|
|
1216
1246
|
effectStyleName: z3.string().optional().describe("Effect style name (e.g. 'Shadow/Card') for shadows, blurs"),
|
|
1217
1247
|
layoutMode: z3.enum(["NONE", "HORIZONTAL", "VERTICAL"]).optional().describe("Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)"),
|
|
1218
|
-
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional(),
|
|
1248
|
+
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional().describe("Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns."),
|
|
1219
1249
|
padding: token.optional().describe("All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft."),
|
|
1220
1250
|
paddingTop: token.optional(),
|
|
1221
1251
|
paddingRight: token.optional(),
|
|
@@ -1233,15 +1263,17 @@ var tools = [
|
|
|
1233
1263
|
maxHeight: z3.coerce.number().optional().describe("Max height for responsive auto-layout"),
|
|
1234
1264
|
overflowDirection: z3.enum(["NONE", "HORIZONTAL", "VERTICAL", "BOTH"]).optional().describe("Scroll overflow in prototype (default: NONE)"),
|
|
1235
1265
|
description: z3.string().optional().describe("Component description (shown in Figma's component panel)"),
|
|
1266
|
+
children: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe('Inline child nodes \u2014 build nested trees in one call. Types: text: {type:"text", text, componentPropertyName?, fontFamily?, fontSize?, fontWeight?, fontStyle?, fontColor?, layoutSizingHorizontal?}. frame: {type:"frame", name?, layoutMode?, fillColor?, width?, layoutSizingHorizontal?, children?}. instance: {type:"instance", componentId, componentPropertyName?, variantProperties?, properties?}. component: {type:"component", name, children?}. All params from text/frame endpoints are supported on their respective types. componentPropertyName auto-creates and binds a TEXT (text) or INSTANCE_SWAP (instance) property. Always set layoutSizingHorizontal + layoutSizingVertical on children inside auto-layout parents (FILL, HUG, or FIXED). Example: children:[{type:"text", text:"Label", componentPropertyName:"Label", fontSize:14, fontColorVariableName:"text/primary", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}, {type:"frame", name:"Actions", layoutMode:"HORIZONTAL", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG", itemSpacing:8, children:[{type:"instance", componentId:"1:2", componentPropertyName:"Action", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}]}]\n'),
|
|
1236
1267
|
properties: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe("Component properties to define at creation: [{propertyName, type, defaultValue}]. TEXT properties for inline children with componentPropertyName are created automatically.")
|
|
1237
1268
|
}).passthrough(),
|
|
1238
1269
|
"from_node": z3.object({
|
|
1239
1270
|
nodeId: z3.string().describe("Node ID to convert"),
|
|
1271
|
+
name: z3.string().optional().describe("Rename the component (default: keeps the node's current name)"),
|
|
1240
1272
|
exposeText: flexBool(z3.boolean()).optional().describe("Auto-expose text as editable properties (default: true)")
|
|
1241
1273
|
}).passthrough(),
|
|
1242
1274
|
"variant_set": z3.object({
|
|
1243
1275
|
name: z3.string().optional().describe("Node name"),
|
|
1244
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1276
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1245
1277
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1246
1278
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1247
1279
|
width: z3.coerce.number().optional().describe("Width in px (omit to shrink-to-content via HUG)"),
|
|
@@ -1274,7 +1306,7 @@ var tools = [
|
|
|
1274
1306
|
bottomLeftRadius: token.optional(),
|
|
1275
1307
|
effectStyleName: z3.string().optional().describe("Effect style name (e.g. 'Shadow/Card') for shadows, blurs"),
|
|
1276
1308
|
layoutMode: z3.enum(["NONE", "HORIZONTAL", "VERTICAL"]).optional().describe("Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)"),
|
|
1277
|
-
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional(),
|
|
1309
|
+
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional().describe("Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns."),
|
|
1278
1310
|
padding: token.optional().describe("All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft."),
|
|
1279
1311
|
paddingTop: token.optional(),
|
|
1280
1312
|
paddingRight: token.optional(),
|
|
@@ -1292,7 +1324,8 @@ var tools = [
|
|
|
1292
1324
|
maxHeight: z3.coerce.number().optional().describe("Max height for responsive auto-layout"),
|
|
1293
1325
|
overflowDirection: z3.enum(["NONE", "HORIZONTAL", "VERTICAL", "BOTH"]).optional().describe("Scroll overflow in prototype (default: NONE)"),
|
|
1294
1326
|
componentIds: flexJson(z3.array(z3.string())).optional().describe("Existing component IDs to combine (min 2). Alternative to children."),
|
|
1295
|
-
variantPropertyName: z3.string().optional().describe("Rename the auto-generated variant property (default: 'Property 1')")
|
|
1327
|
+
variantPropertyName: z3.string().optional().describe("Rename the auto-generated variant property (default: 'Property 1')"),
|
|
1328
|
+
children: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe('Inline variant components. Each must be {type:"component", name, children?, ...frame_params}. All variants must share the same child structure. Alternative to componentIds \u2014 do not combine both.')
|
|
1296
1329
|
}).passthrough()
|
|
1297
1330
|
};
|
|
1298
1331
|
const s = params.type && schemas[params.type];
|
|
@@ -1337,7 +1370,7 @@ var tools = [
|
|
|
1337
1370
|
}
|
|
1338
1371
|
}
|
|
1339
1372
|
},
|
|
1340
|
-
commandMap: { "clone": "components.clone", "audit": "components.audit", "reparent": "components.reparent", "list": "components.list", "get": "components.get", "create": "components.create", "update": "components.update", "delete": "components.delete" }
|
|
1373
|
+
commandMap: { "clone": "components.clone", "audit": "components.audit", "reparent": "components.reparent", "list": "components.list", "get": "components.get", "create": "components.create", "commit": "components.commit", "update": "components.update", "delete": "components.delete" }
|
|
1341
1374
|
},
|
|
1342
1375
|
{
|
|
1343
1376
|
name: "connection",
|
|
@@ -1387,9 +1420,9 @@ var tools = [
|
|
|
1387
1420
|
},
|
|
1388
1421
|
{
|
|
1389
1422
|
name: "frames",
|
|
1390
|
-
description: '/** Create and manage frames, shapes, auto-layout containers, sections, and SVG nodes. Use method "help" for detailed parameter docs. */\n get (id, fields?, depth?, verbose?) \u2192 { results: Node[], _truncated?, _notice? } // Get serialized node data\n list (query?, types?, parentId?, fields?, offset?, limit?) \u2192 { totalCount, returned?, offset?, limit?, results } // Search for nodes (returns stubs only \u2014 use get with depth for full properties)\n update (items: PatchItem[]) \u2192 { results: ("ok" | {error})[] } // Patch node properties\n delete (id?, items?: { id?: string }[]) \u2192 { results: "ok"[] } // Delete nodes\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n create (type: frame|auto_layout|section|rectangle|ellipse|line|group|boolean_operation|svg, items: (FrameItem | AutoLayoutItem | SectionItem | RectangleItem | EllipseItem | LineItem | GroupItem | BooleanOperationItem | SvgItem)[]) \u2192 { results: {id}[] } // Create frame-like containers\n export (id, format?: PNG|JPG|SVG|SVG_STRING|PDF, scale?) \u2192 { imageData?, mimeType? } // Export a node as PNG, JPG, SVG, SVG_STRING, or PDF\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).',
|
|
1423
|
+
description: '/** Create and manage frames, shapes, auto-layout containers, sections, and SVG nodes. Use method "help" for detailed parameter docs. */\n get (id, fields?, depth?, verbose?) \u2192 { results: Node[], _truncated?, _notice? } // Get serialized node data\n list (query?, types?, parentId?, fields?, offset?, limit?) \u2192 { totalCount, returned?, offset?, limit?, results } // Search for nodes (returns stubs only \u2014 use get with depth for full properties)\n update (items: PatchItem[]) \u2192 { results: ("ok" | {error})[] } // Patch node properties\n delete (id?, items?: { id?: string }[]) \u2192 { results: "ok"[] } // Delete nodes\n clone (id?, name?, parentId?, x?, y?, items?: { id: string; name?: string; parentId?: string; x?: number; y?: number }[], depth?) \u2192 { results: {id}[] } // Duplicate nodes\n audit (id, rules?, maxDepth?, maxFindings?, minSeverity?: error|unsafe|heuristic|style|verbose, skipInstances?) \u2192 { nodeId?, nodeName?, categories? } // Run lint on a node \u2014 returns severity-ranked findings\n reparent (items: { id: string; parentId: string; index?: number }[]) \u2192 { results: "ok"[] } // Move nodes into a new parent\n create (type: frame|auto_layout|section|rectangle|ellipse|line|group|boolean_operation|svg, items: (FrameItem | AutoLayoutItem | SectionItem | RectangleItem | EllipseItem | LineItem | GroupItem | BooleanOperationItem | SvgItem)[]) \u2192 { results: {id}[] } // Create frame-like containers\n commit (id) \u2192 { results: {id}[] } // Commit a staged node \u2014 unwraps from [STAGED] container into the original target location.\n export (id, format?: PNG|JPG|SVG|SVG_STRING|PDF, scale?) \u2192 { imageData?, mimeType? } // Export a node as PNG, JPG, SVG, SVG_STRING, or PDF\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).',
|
|
1391
1424
|
schema: (caps2) => filterMethodsByTier({
|
|
1392
|
-
method: z3.enum(["get", "list", "update", "delete", "clone", "audit", "reparent", "create", "export", "help"]),
|
|
1425
|
+
method: z3.enum(["get", "list", "update", "delete", "clone", "audit", "reparent", "create", "commit", "export", "help"]),
|
|
1393
1426
|
id: z3.string().optional().describe("Node ID"),
|
|
1394
1427
|
fields: flexJson(z3.array(z3.string())).optional().describe('Property whitelist. Identity fields (id, name, type) always included. Omit for stubs on list, full on get. Pass ["*"] for all.'),
|
|
1395
1428
|
depth: z3.coerce.number().optional().describe("Response detail: omit for id+name only. 0=properties + child stubs. N=recurse N levels. -1=unlimited."),
|
|
@@ -1412,10 +1445,13 @@ var tools = [
|
|
|
1412
1445
|
format: z3.enum(["PNG", "JPG", "SVG", "SVG_STRING", "PDF"]).optional().describe("Export format (default: PNG). SVG_STRING returns raw SVG text."),
|
|
1413
1446
|
scale: z3.coerce.number().optional().describe("Export scale (default: 1, only for PNG/JPG)"),
|
|
1414
1447
|
topic: z3.string().optional().describe('Help topic \u2014 method name for endpoint help, e.g. "create"')
|
|
1415
|
-
}, caps2, { "get": "read", "list": "read", "update": "edit", "delete": "edit", "clone": "create", "audit": "read", "reparent": "edit", "create": "create", "export": "read", "help": "read" }),
|
|
1448
|
+
}, caps2, { "get": "read", "list": "read", "update": "edit", "delete": "edit", "clone": "create", "audit": "read", "reparent": "edit", "create": "create", "commit": "edit", "export": "read", "help": "read" }),
|
|
1416
1449
|
tier: "read",
|
|
1417
1450
|
validate: (params) => {
|
|
1418
1451
|
const m = params.method;
|
|
1452
|
+
if (m === "commit") {
|
|
1453
|
+
if (params.id === void 0) throw new Error('commit requires "id"');
|
|
1454
|
+
}
|
|
1419
1455
|
if (m === "export") {
|
|
1420
1456
|
if (params.id === void 0) throw new Error('export requires "id"');
|
|
1421
1457
|
}
|
|
@@ -1424,7 +1460,7 @@ var tools = [
|
|
|
1424
1460
|
const schemas = {
|
|
1425
1461
|
"frame": z3.object({
|
|
1426
1462
|
name: z3.string().optional().describe("Node name"),
|
|
1427
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1463
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1428
1464
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1429
1465
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1430
1466
|
width: z3.coerce.number().optional().describe("Width in px (omit to shrink-to-content via HUG)"),
|
|
@@ -1457,7 +1493,7 @@ var tools = [
|
|
|
1457
1493
|
bottomLeftRadius: token.optional(),
|
|
1458
1494
|
effectStyleName: z3.string().optional().describe("Effect style name (e.g. 'Shadow/Card') for shadows, blurs"),
|
|
1459
1495
|
layoutMode: z3.enum(["NONE", "HORIZONTAL", "VERTICAL"]).optional().describe("Layout direction (default: auto \u2014 NONE when width+height set, otherwise inferred from layout props)"),
|
|
1460
|
-
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional(),
|
|
1496
|
+
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional().describe("Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns."),
|
|
1461
1497
|
padding: token.optional().describe("All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft."),
|
|
1462
1498
|
paddingTop: token.optional(),
|
|
1463
1499
|
paddingRight: token.optional(),
|
|
@@ -1474,11 +1510,12 @@ var tools = [
|
|
|
1474
1510
|
minHeight: z3.coerce.number().optional().describe("Min height for responsive auto-layout"),
|
|
1475
1511
|
maxHeight: z3.coerce.number().optional().describe("Max height for responsive auto-layout"),
|
|
1476
1512
|
overflowDirection: z3.enum(["NONE", "HORIZONTAL", "VERTICAL", "BOTH"]).optional().describe("Scroll overflow in prototype (default: NONE)"),
|
|
1477
|
-
clipsContent: flexBool(z3.boolean()).optional()
|
|
1513
|
+
clipsContent: flexBool(z3.boolean()).optional(),
|
|
1514
|
+
children: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe('Inline child nodes \u2014 build nested trees in one call. Types: text: {type:"text", text, fontFamily?, fontSize?, fontWeight?, fontStyle?, fontColor?, layoutSizingHorizontal?}. frame: {type:"frame", name?, layoutMode?, fillColor?, width?, layoutSizingHorizontal?, children?}. instance: {type:"instance", componentId, variantProperties?, properties?}. component: {type:"component", name, children?}. All params from text/frame endpoints are supported on their respective types. Always set layoutSizingHorizontal + layoutSizingVertical on children inside auto-layout parents (FILL, HUG, or FIXED). Example: children:[{type:"text", text:"Title", fontSize:20, layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}, {type:"frame", name:"Row", layoutMode:"HORIZONTAL", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG", itemSpacing:8, children:[{type:"instance", componentId:"1:2", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}]}] Inside components: add componentPropertyName to auto-bind TEXT or INSTANCE_SWAP properties.\n')
|
|
1478
1515
|
}).passthrough(),
|
|
1479
1516
|
"auto_layout": z3.object({
|
|
1480
1517
|
name: z3.string().optional().describe("Node name"),
|
|
1481
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1518
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1482
1519
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1483
1520
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1484
1521
|
width: z3.coerce.number().optional().describe("Width in px (omit to shrink-to-content via HUG)"),
|
|
@@ -1511,7 +1548,7 @@ var tools = [
|
|
|
1511
1548
|
bottomLeftRadius: token.optional(),
|
|
1512
1549
|
effectStyleName: z3.string().optional().describe("Effect style name (e.g. 'Shadow/Card') for shadows, blurs"),
|
|
1513
1550
|
layoutMode: z3.enum(["HORIZONTAL", "VERTICAL"]).describe("Primary axis direction"),
|
|
1514
|
-
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional(),
|
|
1551
|
+
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional().describe("Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns."),
|
|
1515
1552
|
padding: token.optional().describe("All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft."),
|
|
1516
1553
|
paddingTop: token.optional(),
|
|
1517
1554
|
paddingRight: token.optional(),
|
|
@@ -1529,11 +1566,12 @@ var tools = [
|
|
|
1529
1566
|
maxHeight: z3.coerce.number().optional().describe("Max height for responsive auto-layout"),
|
|
1530
1567
|
overflowDirection: z3.enum(["NONE", "HORIZONTAL", "VERTICAL", "BOTH"]).optional().describe("Scroll overflow in prototype (default: NONE)"),
|
|
1531
1568
|
clipsContent: flexBool(z3.boolean()).optional(),
|
|
1532
|
-
nodeIds: flexJson(z3.array(z3.string())).optional().describe("Existing node IDs to wrap into auto-layout")
|
|
1569
|
+
nodeIds: flexJson(z3.array(z3.string())).optional().describe("Existing node IDs to wrap into auto-layout"),
|
|
1570
|
+
children: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe('Inline child nodes \u2014 build nested trees in one call. Types: text: {type:"text", text, fontFamily?, fontSize?, fontWeight?, fontStyle?, fontColor?, layoutSizingHorizontal?}. frame: {type:"frame", name?, layoutMode?, fillColor?, width?, layoutSizingHorizontal?, children?}. instance: {type:"instance", componentId, variantProperties?, properties?}. component: {type:"component", name, children?}. All params from text/frame endpoints are supported on their respective types. Always set layoutSizingHorizontal + layoutSizingVertical on children inside auto-layout parents (FILL, HUG, or FIXED). Example: children:[{type:"text", text:"Title", fontSize:20, layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}, {type:"frame", name:"Row", layoutMode:"HORIZONTAL", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG", itemSpacing:8, children:[{type:"instance", componentId:"1:2", layoutSizingHorizontal:"FILL", layoutSizingVertical:"HUG"}]}] Inside components: add componentPropertyName to auto-bind TEXT or INSTANCE_SWAP properties.\n')
|
|
1533
1571
|
}).passthrough(),
|
|
1534
1572
|
"section": z3.object({
|
|
1535
1573
|
name: z3.string().describe("Section name"),
|
|
1536
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1574
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1537
1575
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1538
1576
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1539
1577
|
width: z3.coerce.number().optional().describe("Width (default: 500)"),
|
|
@@ -1545,7 +1583,7 @@ var tools = [
|
|
|
1545
1583
|
}).passthrough(),
|
|
1546
1584
|
"rectangle": z3.object({
|
|
1547
1585
|
name: z3.string().optional().describe("Layer name (default: 'Rectangle')"),
|
|
1548
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1586
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1549
1587
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1550
1588
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1551
1589
|
width: z3.coerce.number().optional().describe("Width in px (default: 100)"),
|
|
@@ -1569,7 +1607,7 @@ var tools = [
|
|
|
1569
1607
|
}).passthrough(),
|
|
1570
1608
|
"ellipse": z3.object({
|
|
1571
1609
|
name: z3.string().optional().describe("Layer name (default: 'Ellipse')"),
|
|
1572
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1610
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1573
1611
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1574
1612
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1575
1613
|
width: z3.coerce.number().optional().describe("Width in px (default: 100)"),
|
|
@@ -1588,7 +1626,7 @@ var tools = [
|
|
|
1588
1626
|
}).passthrough(),
|
|
1589
1627
|
"line": z3.object({
|
|
1590
1628
|
name: z3.string().optional().describe("Layer name (default: 'Line')"),
|
|
1591
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1629
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1592
1630
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1593
1631
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1594
1632
|
length: z3.coerce.number().optional().describe("Line length in px (default: 100)"),
|
|
@@ -1603,18 +1641,18 @@ var tools = [
|
|
|
1603
1641
|
"group": z3.object({
|
|
1604
1642
|
nodeIds: z3.array(z3.string()).describe("Node IDs to group (min 1)"),
|
|
1605
1643
|
name: z3.string().optional().describe("Group name"),
|
|
1606
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1644
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root.")
|
|
1607
1645
|
}).passthrough(),
|
|
1608
1646
|
"boolean_operation": z3.object({
|
|
1609
1647
|
operation: z3.enum(["UNION", "SUBTRACT", "INTERSECT", "EXCLUDE"]).describe("Boolean operation type"),
|
|
1610
1648
|
nodeIds: z3.array(z3.string()).describe("Node IDs to combine (min 2, first node is the base for SUBTRACT)"),
|
|
1611
1649
|
name: z3.string().optional().describe("Result node name"),
|
|
1612
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1650
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root.")
|
|
1613
1651
|
}).passthrough(),
|
|
1614
1652
|
"svg": z3.object({
|
|
1615
1653
|
svg: z3.string().describe("SVG markup string"),
|
|
1616
1654
|
name: z3.string().optional().describe("Layer name (default: 'SVG')"),
|
|
1617
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1655
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
1618
1656
|
x: z3.coerce.number().optional().describe("X position (default: 0)"),
|
|
1619
1657
|
y: z3.coerce.number().optional().describe("Y position (default: 0)"),
|
|
1620
1658
|
fillStyleName: z3.string().optional().describe("Paint style to apply to vector fills"),
|
|
@@ -1641,7 +1679,7 @@ var tools = [
|
|
|
1641
1679
|
}
|
|
1642
1680
|
}
|
|
1643
1681
|
},
|
|
1644
|
-
commandMap: { "get": "frames.get", "list": "frames.list", "update": "frames.update", "delete": "frames.delete", "clone": "frames.clone", "audit": "frames.audit", "reparent": "frames.reparent", "create": "frames.create", "export": "frames.export" }
|
|
1682
|
+
commandMap: { "get": "frames.get", "list": "frames.list", "update": "frames.update", "delete": "frames.delete", "clone": "frames.clone", "audit": "frames.audit", "reparent": "frames.reparent", "create": "frames.create", "commit": "frames.commit", "export": "frames.export" }
|
|
1645
1683
|
},
|
|
1646
1684
|
{
|
|
1647
1685
|
name: "instances",
|
|
@@ -1704,7 +1742,7 @@ var tools = [
|
|
|
1704
1742
|
y: z3.coerce.number().optional(),
|
|
1705
1743
|
width: z3.coerce.number().optional().describe("Override width (resize)"),
|
|
1706
1744
|
height: z3.coerce.number().optional().describe("Override height (resize)"),
|
|
1707
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
1745
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root.")
|
|
1708
1746
|
}).passthrough();
|
|
1709
1747
|
try {
|
|
1710
1748
|
params.items = z3.array(itemSchema).parse(params.items);
|
|
@@ -1748,7 +1786,7 @@ var tools = [
|
|
|
1748
1786
|
blendMode: z3.enum(["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(),
|
|
1749
1787
|
effectStyleName: z3.string().optional().describe("Effect style name (e.g. 'Shadow/Card') for shadows, blurs"),
|
|
1750
1788
|
layoutMode: z3.enum(["NONE", "HORIZONTAL", "VERTICAL"]).optional().describe("Layout direction (default: NONE)"),
|
|
1751
|
-
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional(),
|
|
1789
|
+
layoutWrap: z3.enum(["NO_WRAP", "WRAP"]).optional().describe("Wrap children to new rows (HORIZONTAL layout only \u2014 Figma does not support WRAP on VERTICAL layouts). Use column frames inside a HORIZONTAL parent for vertical grid patterns."),
|
|
1752
1790
|
padding: token.optional().describe("All edges (number) or variable name (string). Per-edge: paddingTop, paddingRight, paddingBottom, paddingLeft."),
|
|
1753
1791
|
paddingTop: token.optional(),
|
|
1754
1792
|
paddingRight: token.optional(),
|
|
@@ -1769,6 +1807,10 @@ var tools = [
|
|
|
1769
1807
|
fontFamily: z3.string().optional().describe("Font family"),
|
|
1770
1808
|
fontStyle: z3.string().optional().describe('Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight'),
|
|
1771
1809
|
fontWeight: z3.number().optional().describe("100-900. Ignored when fontStyle is set."),
|
|
1810
|
+
lineHeight: lineHeight.optional(),
|
|
1811
|
+
letterSpacing: letterSpacing.optional(),
|
|
1812
|
+
textCase: z3.enum(["ORIGINAL", "UPPER", "LOWER", "TITLE", "SMALL_CAPS", "SMALL_CAPS_FORCED"]).optional(),
|
|
1813
|
+
textDecoration: z3.enum(["NONE", "UNDERLINE", "STRIKETHROUGH"]).optional(),
|
|
1772
1814
|
fontColor: colorRgba.optional().describe("Shorthand \u2014 sets text color (auto-binds to matching variable/style)"),
|
|
1773
1815
|
fontColorVariableName: z3.string().optional().describe("Bind color variable by name e.g. 'text/primary'"),
|
|
1774
1816
|
fontColorStyleName: z3.string().optional().describe("Apply paint style \u2014 overrides fontColor"),
|
|
@@ -1916,7 +1958,7 @@ var tools = [
|
|
|
1916
1958
|
},
|
|
1917
1959
|
{
|
|
1918
1960
|
name: "prototyping",
|
|
1919
|
-
description: '/** Manage prototype interactions, reactions, and navigation flows. Use method "help" for detailed parameter docs. */\n get (id) \u2192 { reactions?, overflowDirection? } // Get reactions and overflow direction on a node\n add (id
|
|
1961
|
+
description: '/** Manage prototype interactions, reactions, and navigation flows. Use method "help" for detailed parameter docs. */\n get (id) \u2192 { reactions?, overflowDirection? } // Get reactions and overflow direction on a node\n add (id?, trigger?: ON_CLICK|ON_HOVER|ON_PRESS|ON_DRAG|AFTER_TIMEOUT|MOUSE_ENTER|MOUSE_LEAVE|ON_KEY_DOWN, triggerDelay?, triggerKeyCodes?, triggerDevice?: KEYBOARD|XBOX_ONE|PS4|SWITCH_PRO, destination?, navigation?: NAVIGATE|SWAP|OVERLAY|SCROLL_TO|CHANGE_TO, transition?: DISSOLVE|SMART_ANIMATE|MOVE_IN|MOVE_OUT|PUSH|SLIDE_IN|SLIDE_OUT|INSTANT, transitionDirection?: LEFT|RIGHT|TOP|BOTTOM, duration?, easing?: EASE_IN|EASE_OUT|EASE_IN_AND_OUT|LINEAR|GENTLE|QUICK|BOUNCY|SLOW, actionType?: NODE|BACK|CLOSE|URL|SET_VARIABLE_MODE, url?, collectionName?, modeName?, resetScrollPosition?, actions?, items?: { id: string; trigger: "ON_CLICK" | "ON_HOVER" | "ON_PRESS" | "ON_DRAG" | "AFTER_TIMEOUT" | "MOUSE_ENTER" | "MOUSE_LEAVE" | "ON_KEY_DOWN"; destination?: string; navigation?: "NAVIGATE" | "SWAP" | "OVERLAY" | "SCROLL_TO" | "CHANGE_TO"; transition?: "DISSOLVE" | "SMART_ANIMATE" | "MOVE_IN" | "MOVE_OUT" | "PUSH" | "SLIDE_IN" | "SLIDE_OUT" | "INSTANT"; transitionDirection?: "LEFT" | "RIGHT" | "TOP" | "BOTTOM"; duration?: number; easing?: "EASE_IN" | "EASE_OUT" | "EASE_IN_AND_OUT" | "LINEAR" | "GENTLE" | "QUICK" | "BOUNCY" | "SLOW"; actionType?: "NODE" | "BACK" | "CLOSE" | "URL" | "SET_VARIABLE_MODE"; triggerDelay?: number; url?: string; collectionName?: string; modeName?: string; resetScrollPosition?: boolean; actions?: unknown[] }[]) \u2192 { results: "ok"[] } // Add a prototype reaction to a node\n set (id, reactions) \u2192 { results: "ok"[] } // Replace all reactions on a node (raw reactions array)\n remove (id, index) \u2192 { results: "ok"[] } // Remove a reaction from a node by index\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).',
|
|
1920
1962
|
schema: (caps2) => filterMethodsByTier({
|
|
1921
1963
|
method: z3.enum(["get", "add", "set", "remove", "help"]),
|
|
1922
1964
|
id: z3.string().optional().describe("Node ID"),
|
|
@@ -1936,6 +1978,7 @@ var tools = [
|
|
|
1936
1978
|
modeName: z3.string().optional().describe("Mode name to switch to (for SET_VARIABLE_MODE)"),
|
|
1937
1979
|
resetScrollPosition: flexBool(z3.boolean()).optional().describe("Reset scroll position on navigate (default: true)"),
|
|
1938
1980
|
actions: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe("Multi-action: [{actionType, destination?, navigation?, collectionName?, modeName?, ...}]. Overrides single-action params."),
|
|
1981
|
+
items: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe("Batch: array of {id, trigger, destination?, ...} reaction items"),
|
|
1939
1982
|
reactions: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional().describe("Full reactions array \u2014 [{trigger:{type}, actions:[{type, destinationId, navigation, transition}]}]"),
|
|
1940
1983
|
index: z3.coerce.number().optional().describe("Reaction index (0-based)"),
|
|
1941
1984
|
topic: z3.string().optional().describe('Help topic \u2014 method name for endpoint help, e.g. "create"')
|
|
@@ -1946,10 +1989,6 @@ var tools = [
|
|
|
1946
1989
|
if (m === "get") {
|
|
1947
1990
|
if (params.id === void 0) throw new Error('get requires "id"');
|
|
1948
1991
|
}
|
|
1949
|
-
if (m === "add") {
|
|
1950
|
-
if (params.id === void 0) throw new Error('add requires "id"');
|
|
1951
|
-
if (params.trigger === void 0) throw new Error('add requires "trigger"');
|
|
1952
|
-
}
|
|
1953
1992
|
if (m === "set") {
|
|
1954
1993
|
if (params.id === void 0) throw new Error('set requires "id"');
|
|
1955
1994
|
if (params.reactions === void 0) throw new Error('set requires "reactions"');
|
|
@@ -1958,6 +1997,39 @@ var tools = [
|
|
|
1958
1997
|
if (params.id === void 0) throw new Error('remove requires "id"');
|
|
1959
1998
|
if (params.index === void 0) throw new Error('remove requires "index"');
|
|
1960
1999
|
}
|
|
2000
|
+
if (!params.items) return;
|
|
2001
|
+
if (m === "add") {
|
|
2002
|
+
const itemSchema = z3.object({
|
|
2003
|
+
id: z3.string().describe("Node ID"),
|
|
2004
|
+
trigger: z3.enum(["ON_CLICK", "ON_HOVER", "ON_PRESS", "ON_DRAG", "AFTER_TIMEOUT", "MOUSE_ENTER", "MOUSE_LEAVE", "ON_KEY_DOWN"]).describe("Trigger type"),
|
|
2005
|
+
destination: z3.string().optional().describe("Target node ID"),
|
|
2006
|
+
navigation: z3.enum(["NAVIGATE", "SWAP", "OVERLAY", "SCROLL_TO", "CHANGE_TO"]).optional(),
|
|
2007
|
+
transition: z3.enum(["DISSOLVE", "SMART_ANIMATE", "MOVE_IN", "MOVE_OUT", "PUSH", "SLIDE_IN", "SLIDE_OUT", "INSTANT"]).optional(),
|
|
2008
|
+
transitionDirection: z3.enum(["LEFT", "RIGHT", "TOP", "BOTTOM"]).optional(),
|
|
2009
|
+
duration: z3.coerce.number().optional(),
|
|
2010
|
+
easing: z3.enum(["EASE_IN", "EASE_OUT", "EASE_IN_AND_OUT", "LINEAR", "GENTLE", "QUICK", "BOUNCY", "SLOW"]).optional(),
|
|
2011
|
+
actionType: z3.enum(["NODE", "BACK", "CLOSE", "URL", "SET_VARIABLE_MODE"]).optional(),
|
|
2012
|
+
triggerDelay: z3.coerce.number().optional(),
|
|
2013
|
+
url: z3.string().optional(),
|
|
2014
|
+
collectionName: z3.string().optional(),
|
|
2015
|
+
modeName: z3.string().optional(),
|
|
2016
|
+
resetScrollPosition: flexBool(z3.boolean()).optional(),
|
|
2017
|
+
actions: flexJson(z3.array(z3.record(z3.string(), z3.unknown()))).optional()
|
|
2018
|
+
}).passthrough();
|
|
2019
|
+
try {
|
|
2020
|
+
params.items = z3.array(itemSchema).parse(params.items);
|
|
2021
|
+
} catch (e) {
|
|
2022
|
+
if (e instanceof z3.ZodError) {
|
|
2023
|
+
throw new Error(e.issues.map((i) => {
|
|
2024
|
+
const path = i.path.join(".");
|
|
2025
|
+
const shape = itemSchema instanceof z3.ZodObject ? itemSchema.shape : null;
|
|
2026
|
+
const desc = shape?.[i.path[1]]?.description;
|
|
2027
|
+
return path + ": " + i.message + (desc ? " (expected: " + desc + ")" : "");
|
|
2028
|
+
}).join("; "));
|
|
2029
|
+
}
|
|
2030
|
+
throw e;
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
1961
2033
|
},
|
|
1962
2034
|
commandMap: { "get": "prototyping.get", "add": "prototyping.add", "set": "prototyping.set", "remove": "prototyping.remove" }
|
|
1963
2035
|
},
|
|
@@ -2147,11 +2219,15 @@ var tools = [
|
|
|
2147
2219
|
x: z3.number().optional(),
|
|
2148
2220
|
y: z3.number().optional(),
|
|
2149
2221
|
width: z3.number().optional().describe("Fixed width in px \u2014 implies layoutSizingHorizontal: FIXED and textAutoResize: HEIGHT"),
|
|
2150
|
-
parentId: z3.string().optional().describe("Parent node ID. Omit to place
|
|
2222
|
+
parentId: z3.string().optional().describe("Parent node ID. Omit to place at current page root."),
|
|
2151
2223
|
fontFamily: z3.string().optional().describe("Font family (default: Inter). Use fonts.list to find installed fonts."),
|
|
2152
2224
|
fontStyle: z3.string().optional().describe('Font variant e.g. "Bold", "Italic" \u2014 overrides fontWeight'),
|
|
2153
2225
|
fontSize: z3.number().optional().describe("Font size (default: 14)"),
|
|
2154
2226
|
fontWeight: z3.number().optional().describe("100-900 (default: 400). Ignored when fontStyle is set."),
|
|
2227
|
+
lineHeight: lineHeight.optional(),
|
|
2228
|
+
letterSpacing: letterSpacing.optional(),
|
|
2229
|
+
textCase: z3.enum(["ORIGINAL", "UPPER", "LOWER", "TITLE", "SMALL_CAPS", "SMALL_CAPS_FORCED"]).optional(),
|
|
2230
|
+
textDecoration: z3.enum(["NONE", "UNDERLINE", "STRIKETHROUGH"]).optional(),
|
|
2155
2231
|
fills: z3.array(z3.record(z3.string(), z3.unknown())).optional().describe("Text color paints \u2014 e.g. [{type: 'SOLID', color: '#hex'}]. Same as node fills."),
|
|
2156
2232
|
fontColor: colorRgba.optional().describe("Shorthand \u2014 sets text color (auto-binds to matching variable/style)"),
|
|
2157
2233
|
fontColorVariableName: z3.string().optional().describe("Bind color variable by name e.g. 'text/primary'"),
|
|
@@ -2351,7 +2427,7 @@ var tools = [
|
|
|
2351
2427
|
},
|
|
2352
2428
|
{
|
|
2353
2429
|
name: "variables",
|
|
2354
|
-
description: '/** Search and update design variables within a collection. Use method "help" for detailed parameter docs. */\n list (collectionId, query?, type?: COLOR|FLOAT|STRING|BOOLEAN, fields?, offset?, limit?) \u2192 { totalCount, items } // Search variables within a collection\n get (name, collectionId, fields?) \u2192 { name, type, collectionId, valuesByMode: Record<string, number | boolean | string | Color | {type: "VARIABLE_ALIAS", name: string}>, description?, scopes? } // Get variable detail by name\n create (collectionId, items: VariableCreateItem[]) \u2192 { results: {name}[] } // Create variables in a collection. Use valuesByMode for
|
|
2430
|
+
description: '/** Search and update design variables within a collection. Use method "help" for detailed parameter docs. */\n list (collectionId, query?, type?: COLOR|FLOAT|STRING|BOOLEAN, fields?, offset?, limit?) \u2192 { totalCount, items } // Search variables within a collection\n get (name, collectionId, fields?) \u2192 { name, type, collectionId, valuesByMode: Record<string, number | boolean | string | Color | {type: "VARIABLE_ALIAS", name: string}>, description?, scopes? } // Get variable detail by name\n create (collectionId, items: VariableCreateItem[]) \u2192 { results: {name}[] } // Create variables in a collection. Use valuesByMode for per-mode control, or value to set all modes at once.\n update (collectionId, items: VariableUpdateItem[]) \u2192 { results: ("ok" | {error})[] } // Update variable metadata and/or set values\n delete (collectionId, name?, items?: { name: string }[]) \u2192 { results: "ok"[] } // Delete variables\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// Shared types:\n// Color: hex "#FF0000" or {r: 0-1, g: 0-1, b: 0-1, a?: 0-1}',
|
|
2355
2431
|
schema: (caps2) => filterMethodsByTier({
|
|
2356
2432
|
method: z3.enum(["list", "get", "create", "update", "delete", "help"]),
|
|
2357
2433
|
collectionId: z3.string().optional().describe("Collection ID or name"),
|
|
@@ -2388,7 +2464,7 @@ var tools = [
|
|
|
2388
2464
|
const itemSchema = z3.object({
|
|
2389
2465
|
name: z3.string().describe("Variable name (must be unique within collection)"),
|
|
2390
2466
|
type: z3.enum(["COLOR", "FLOAT", "STRING", "BOOLEAN"]).describe("Variable type"),
|
|
2391
|
-
value: variableValue.optional().describe("
|
|
2467
|
+
value: variableValue.optional().describe("Sets all modes to this value. Use valuesByMode for per-mode control."),
|
|
2392
2468
|
valuesByMode: z3.record(z3.string(), z3.unknown()).optional().describe('Values keyed by mode name (e.g. {"Light": "#FFF", "Dark": "#111"}). Takes precedence over value.'),
|
|
2393
2469
|
description: z3.string().optional().describe("Variable description"),
|
|
2394
2470
|
scopes: flexJson(z3.array(z3.string())).optional().describe("Restrict where variable can be applied (default: ALL_SCOPES)")
|
|
@@ -2499,9 +2575,9 @@ var guidelinesList = [
|
|
|
2499
2575
|
}
|
|
2500
2576
|
];
|
|
2501
2577
|
var guidelinesContent = {
|
|
2502
|
-
"component-structure": '# Component Structure\n\nComponents need correct sizing, property bindings, and token usage to work well as instances.\n\n## Width Constraints\n\nComponents with text content need a width \u2014 otherwise text never wraps.\n\n- Set `width` and `layoutSizingHorizontal:"FIXED"` on cards, panels, list items\n- HUG on both axes is only correct for buttons, badges, icons \u2014 intrinsically-sized elements\n\n## Property Bindings\n\nEvery text node inside a component should be bound to a TEXT property so instances can edit the content.\n\n- After creation: `frames(method:"update", items:[{id:"<textNodeId>", componentPropertyName:"<propName>"}])`\n- For existing nodes with many text children: `components(method:"create", type:"from_node", exposeText:true)`\n\nOrphaned properties (defined but not bound to any node) should be deleted:\n```\ncomponents(method:"update", items:[{id, propertyName:"<key>", action:"delete"}])\n```\n\n## Variant Sets\n\nGroup related components as variants \u2014 don\'t leave them as separate components.\n\n- Name variants with the property format: `Style=Primary`, `Style=Secondary`\n- Combine: `components(method:"create", type:"variant_set", items:[{componentIds:[...], name:"Button"}])`\n- Instances pick variants via `variantProperties:{"Style":"Primary"}`\n\n### Adding Variants to an Existing Set\n\nClone an existing variant into the same set with a new name. The `name` param is required \u2014 without it, the duplicate name corrupts the set.\n\n**Add a new value to an existing dimension** (e.g. State=Hover):\n```\ncomponents(method:"clone", id:"<variant_id>", name:"Style=Primary, State=Hover", parentId:"<set_id>")\n```\nClone one variant per combination. For a Style\xD7State set, adding State=Hover requires two clones (one per Style). Use batch `items` for efficiency:\n```\ncomponents(method:"clone", items:[\n {id:"<Primary/Default>", name:"Style=Primary, State=Hover", parentId:"<set_id>"},\n {id:"<Secondary/Default>", name:"Style=Secondary, State=Hover", parentId:"<set_id>"}\n])\n```\nThen patch the new variants: `frames(method:"update", items:[{id:"<new>", fillVariableName:"color/hover"}])`\n\n**Add a new dimension** (e.g. Size=sm to a Style\xD7State set):\n1. Batch rename existing variants to include the new dimension: `frames(method:"update", items:[{id:"<each>", name:"..., Size=md"}])`\n2. Batch clone all variants with the new value: `components(method:"clone", items:[{id:"<each>", name:"..., Size=sm", parentId:"<set_id>"}])`\n3. Batch patch the new variants: `frames(method:"update", items:[{id:"<each>", padding:8, minHeight:32}])`\n\nProperty bindings (TEXT, INSTANCE_SWAP) are preserved on cloned variants.\n\n## Checking\n\nRun `components(method:"audit", id)` \u2014 checks both lint rules and property bindings in one call.',
|
|
2578
|
+
"component-structure": '# Component Structure\n\nComponents need correct sizing, property bindings, and token usage to work well as instances.\n\n## Width Constraints\n\nComponents with text content need a width \u2014 otherwise text never wraps.\n\n- Set `width` and `layoutSizingHorizontal:"FIXED"` on cards, panels, list items\n- HUG on both axes is only correct for buttons, badges, icons \u2014 intrinsically-sized elements\n\n## Property Bindings\n\nEvery text node inside a component should be bound to a TEXT property so instances can edit the content.\n\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- On creation: `children:[{type:"text", text:"Title", componentPropertyName:"Title"}]` auto-creates and binds\n- After creation: `frames(method:"update", items:[{id:"<textNodeId>", componentPropertyName:"<propName>"}])`\n- For existing nodes with many text children: `components(method:"create", type:"from_node", exposeText:true)`\n\nOrphaned properties (defined but not bound to any node) should be deleted:\n```\ncomponents(method:"update", items:[{id, propertyName:"<key>", action:"delete"}])\n```\n\n## Variant Sets\n\nGroup related components as variants \u2014 don\'t leave them as separate components.\n\n- Name variants with the property format: `Style=Primary`, `Style=Secondary`\n- Combine: `components(method:"create", type:"variant_set", items:[{componentIds:[...], name:"Button"}])`\n- Instances pick variants via `variantProperties:{"Style":"Primary"}`\n\n### Adding Variants to an Existing Set\n\nClone an existing variant into the same set with a new name. The `name` param is required \u2014 without it, the duplicate name corrupts the set.\n\n**Add a new value to an existing dimension** (e.g. State=Hover):\n```\ncomponents(method:"clone", id:"<variant_id>", name:"Style=Primary, State=Hover", parentId:"<set_id>")\n```\nClone one variant per combination. For a Style\xD7State set, adding State=Hover requires two clones (one per Style). Use batch `items` for efficiency:\n```\ncomponents(method:"clone", items:[\n {id:"<Primary/Default>", name:"Style=Primary, State=Hover", parentId:"<set_id>"},\n {id:"<Secondary/Default>", name:"Style=Secondary, State=Hover", parentId:"<set_id>"}\n])\n```\nThen patch the new variants: `frames(method:"update", items:[{id:"<new>", fillVariableName:"color/hover"}])`\n\n**Add a new dimension** (e.g. Size=sm to a Style\xD7State set):\n1. Batch rename existing variants to include the new dimension: `frames(method:"update", items:[{id:"<each>", name:"..., Size=md"}])`\n2. Batch clone all variants with the new value: `components(method:"clone", items:[{id:"<each>", name:"..., Size=sm", parentId:"<set_id>"}])`\n3. Batch patch the new variants: `frames(method:"update", items:[{id:"<each>", padding:8, minHeight:32}])`\n\nProperty bindings (TEXT, INSTANCE_SWAP) are preserved on cloned variants.\n\n## Checking\n\nRun `components(method:"audit", id)` \u2014 checks both lint rules and property bindings in one call.',
|
|
2503
2579
|
"library-components": '# Working with Library Components\n\nLibrary components are read-only \u2014 they come from external team libraries and cannot be edited in the current file.\n\n## Reading\n\nWhen reading nodes, library instances appear as stubs with their overridable properties:\n```\n{name: "Header", type: "INSTANCE", componentProperties: {"Platform": "Desktop"}}\n```\n\nLibrary internals are hidden: no `componentId`, no variable names, no style names. You see resolved values (hex colors, numbers) instead.\n\n## Using\n\nPlace library instances via `instances(method:"create", items:[{componentId:"<id>"}])` when you have a local component ID. For library components, instances are already placed by the designer \u2014 interact via `instances(method:"update")` to set properties.\n\n## Customizing\n\nTo edit a library component, clone it into the local file first:\n\n```\ncomponents(method:"clone", id:"<instanceId>")\n```\n\nThis resolves the instance to its source component (or full component set) and creates a local copy with a new ID. Edit the local copy freely \u2014 it is independent of the library.\n\nDo not attempt to `components(method:"get")` or `components(method:"update")` a library component directly \u2014 these will error.\n\n## Overriding Instance Properties\n\nUse `instances(method:"update")` to change overridable properties on library instances:\n```\ninstances(method:"update", items:[{id:"<instanceId>", properties:{"Label":"New Text", "State":"Hover"}}])\n```\n\nProperty names are clean (no hash suffixes needed for update \u2014 the system resolves partial keys).',
|
|
2504
|
-
"responsive-designs": '# Responsive Sizing\n\n## Workflow: Top-Down Sizing\n\nBuild layouts from the outside in:\n\n1. **Set the container first.** Every container needs an explicit width \u2014 either `width` + `layoutSizingHorizontal:"FIXED"` for shells and bounded panels, or `layoutSizingHorizontal:"FILL"` inside an auto-layout parent. Set `layoutMode` (VERTICAL or HORIZONTAL) and spacing/padding.\n2. **Children fill the container.** Use `layoutSizingHorizontal:"FILL"` on children so they stretch to the available space. Use `layoutSizingVertical:"HUG"` so height follows content.\n3. **Only leaves use HUG on both axes.** Buttons, badges, icons \u2014 elements with short, predictable content that should shrink-wrap.\n\nThis ensures every level of the tree has a clear width constraint. Text wraps, FILL children stretch, and the layout adapts when the container resizes.\n\nAlways set BOTH axes explicitly on every node. Omitting sizing leads to unintended defaults.\n\n## FIXED / FILL / HUG\n\n- **FIXED** \u2014 explicit bounded widths: page shell, sidebar, modal max-width, specimen frames\n- **FILL** \u2014 children that adapt to parent: cards, rows, panels, nav stacks, text that should wrap. Use `minWidth`/`maxWidth` for responsive constraints.\n- **HUG** \u2014 content-sized leaves only: icons, badges, pills, button labels\n\n## Anti-patterns: HUG/HUG\n\nHUG on both axes is the most common cause of broken layouts. It means "shrink to fit my content on both axes" \u2014 the container has no opinion about its own size and collapses to whatever its children measure.\n\n**Why HUG/HUG breaks designs:**\n\n1. **Text never wraps.** A HUG-width container grows to fit the longest text line. Body text becomes a single very long line instead of wrapping at a readable width. The design looks correct with short placeholder text but breaks with real content.\n\n2. **Layouts don\'t adapt.** HUG/HUG containers ignore their parent\'s width. A card inside a responsive column won\'t stretch to fill available space \u2014 it stays at its content width, leaving gaps or overflowing.\n\n3. **FILL children become under-constrained.** A child with `layoutSizingHorizontal:"FILL"` inside a HUG-width parent has no space to fill \u2014 the parent defers its width to its children, but the FILL child defers its width to the parent. The result is under-constrained sizing that produces unpredictable or collapsed layouts.\n\n4. **Cascading failures.** One HUG/HUG container at the top of a tree forces every child to resolve its own width. The entire layout becomes rigid and content-dependent instead of responsive.\n\n**HUG/HUG is only correct for:**\n- Buttons, pills, badges, chips \u2014 intrinsically-sized leaf elements with short, predictable content\n- Icon containers with fixed-size children\n- Inline tags and status indicators\n\n**For everything else, set at least one axis to FIXED or FILL:**\n- Cards, panels, list rows \u2192 `layoutSizingHorizontal:"FILL"`, vertical `HUG`. Add `minWidth`/`maxWidth` for responsive bounds.\n- Shells, sidebars, modals \u2192 `width` + `layoutSizingHorizontal:"FIXED"`, vertical `FILL` or `HUG`\n- Full-width sections \u2192 `layoutSizingHorizontal:"FILL"`, `layoutSizingVertical:"HUG"`\n\n## Component Sizing\n\nComponent roots use `FILL` when placed in a parent \u2014 they adapt to context, not a fixed specimen width. Use `FIXED` only for the specimen (the component definition itself when it needs a specific preview width).\n\nExample sidebar item:\n- Instance: `FILL` in parent nav stack\n- Icon child: fixed 18x18\n- Label child: `FILL`\n- Badge child: `HUG`\n\n## Text Sizing\n\n- Body text inside containers: prefer `FILL` width, `HUG` height (auto-wraps)\n- Single-line labels: prefer `FILL` horizontal (truncates if needed)\n- Standalone headings: `HUG` is fine\n\nInside auto-layout parents, target `layoutSizingHorizontal:"FILL"` + `layoutSizingVertical:"HUG"` + `textAutoResize:"HEIGHT"` for text that should wrap. These are not auto-applied \u2014 set them explicitly on text.create or text.update.\n\n## Checklist\n\nBefore finalizing a layout, verify:\n1. No container with text has HUG on the horizontal axis (unless it\'s a button/badge)\n2. Children use FILL on the axis that should absorb available space \u2014 not blindly on both axes. Compact controls in horizontal rows often stay HUG vertically.\n3. Top-level containers have an explicit width (FIXED) or stretch to their parent (FILL)\n4. Run `lint(method:"check", nodeId:"<rootId>", rules:["composition"])` to catch overflow-parent, unbounded-hug, and fixed-in-autolayout issues',
|
|
2580
|
+
"responsive-designs": '# Responsive Sizing\n\n## Workflow: Top-Down Sizing\n\nBuild layouts from the outside in:\n\n1. **Set the container first.** Every container needs an explicit width \u2014 either `width` + `layoutSizingHorizontal:"FIXED"` for shells and bounded panels, or `layoutSizingHorizontal:"FILL"` inside an auto-layout parent. Set `layoutMode` (VERTICAL or HORIZONTAL) and spacing/padding.\n2. **Children fill the container.** Use `layoutSizingHorizontal:"FILL"` on children so they stretch to the available space. Use `layoutSizingVertical:"HUG"` so height follows content.\n3. **Only leaves use HUG on both axes.** Buttons, badges, icons \u2014 elements with short, predictable content that should shrink-wrap.\n\nThis ensures every level of the tree has a clear width constraint. Text wraps, FILL children stretch, and the layout adapts when the container resizes.\n\nAlways set BOTH axes explicitly on every node. Omitting sizing leads to unintended defaults.\n\n## FIXED / FILL / HUG\n\n- **FIXED** \u2014 explicit bounded widths: page shell, sidebar, modal max-width, specimen frames\n- **FILL** \u2014 children that adapt to parent: cards, rows, panels, nav stacks, text that should wrap. Use `minWidth`/`maxWidth` for responsive constraints.\n- **HUG** \u2014 content-sized leaves only: icons, badges, pills, button labels\n\n## Anti-patterns: HUG/HUG\n\nHUG on both axes is the most common cause of broken layouts. It means "shrink to fit my content on both axes" \u2014 the container has no opinion about its own size and collapses to whatever its children measure.\n\n**Why HUG/HUG breaks designs:**\n\n1. **Text never wraps.** A HUG-width container grows to fit the longest text line. Body text becomes a single very long line instead of wrapping at a readable width. The design looks correct with short placeholder text but breaks with real content.\n\n2. **Layouts don\'t adapt.** HUG/HUG containers ignore their parent\'s width. A card inside a responsive column won\'t stretch to fill available space \u2014 it stays at its content width, leaving gaps or overflowing.\n\n3. **FILL children become under-constrained.** A child with `layoutSizingHorizontal:"FILL"` inside a HUG-width parent has no space to fill \u2014 the parent defers its width to its children, but the FILL child defers its width to the parent. The result is under-constrained sizing that produces unpredictable or collapsed layouts.\n\n4. **Cascading failures.** One HUG/HUG container at the top of a tree forces every child to resolve its own width. The entire layout becomes rigid and content-dependent instead of responsive.\n\n**HUG/HUG is only correct for:**\n- Buttons, pills, badges, chips \u2014 intrinsically-sized leaf elements with short, predictable content\n- Icon containers with fixed-size children\n- Inline tags and status indicators\n\n**For everything else, set at least one axis to FIXED or FILL:**\n- Cards, panels, list rows \u2192 `layoutSizingHorizontal:"FILL"`, vertical `HUG`. Add `minWidth`/`maxWidth` for responsive bounds.\n- Shells, sidebars, modals \u2192 `width` + `layoutSizingHorizontal:"FIXED"`, vertical `FILL` or `HUG`\n- Full-width sections \u2192 `layoutSizingHorizontal:"FILL"`, `layoutSizingVertical:"HUG"`\n\n## Wrapping Layouts (layoutWrap)\n\n`layoutWrap: WRAP` enables children to flow into new rows when they exceed the container width \u2014 like CSS `flex-wrap`. This only works with **HORIZONTAL** auto-layout. Figma does not support wrap on VERTICAL layouts.\n\n**When to use wrap:**\n- Card grids with a fixed number of columns at a known width\n- Tag/chip collections where items flow into multiple rows\n- Any layout where items should reflow based on available width\n\n**Horizontal wrap pattern:**\n```\nframes.create(type: "auto_layout", layoutMode: "HORIZONTAL", layoutWrap: "WRAP",\n itemSpacing: "space/16", counterAxisSpacing: "space/16")\n```\nChildren use FIXED width to control column count. `counterAxisSpacing` sets the gap between wrapped rows.\n\n**Vertical grid alternative:**\nSince VERTICAL layouts cannot wrap, build column-based grids by nesting VERTICAL columns inside a HORIZONTAL parent:\n```\nouter (HORIZONTAL, itemSpacing: 20, FILL width)\n col-1 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n col-2 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n col-3 (VERTICAL, FILL width, HUG height, itemSpacing: 20)\n```\nEach column gets equal width via FILL. Reparent items into columns for column-first ordering. This handles variable card heights per column independently.\n\n## Component Sizing\n\nComponent roots use `FILL` when placed in a parent \u2014 they adapt to context, not a fixed specimen width. Use `FIXED` only for the specimen (the component definition itself when it needs a specific preview width).\n\nExample sidebar item:\n- Instance: `FILL` in parent nav stack\n- Icon child: fixed 18x18\n- Label child: `FILL`\n- Badge child: `HUG`\n\n## Text Sizing\n\n- Body text inside containers: prefer `FILL` width, `HUG` height (auto-wraps)\n- Single-line labels: prefer `FILL` horizontal (truncates if needed)\n- Standalone headings: `HUG` is fine\n\nInside auto-layout parents, target `layoutSizingHorizontal:"FILL"` + `layoutSizingVertical:"HUG"` + `textAutoResize:"HEIGHT"` for text that should wrap. These are not auto-applied \u2014 set them explicitly on text.create or text.update.\n\n## Checklist\n\nBefore finalizing a layout, verify:\n1. No container with text has HUG on the horizontal axis (unless it\'s a button/badge)\n2. Children use FILL on the axis that should absorb available space \u2014 not blindly on both axes. Compact controls in horizontal rows often stay HUG vertically.\n3. Top-level containers have an explicit width (FIXED) or stretch to their parent (FILL)\n4. Run `lint(method:"check", nodeId:"<rootId>", rules:["composition"])` to catch overflow-parent, unbounded-hug, and fixed-in-autolayout issues',
|
|
2505
2581
|
"token-discipline": '# Token Discipline\n\nEvery color, spacing value, and text style should come from a design token \u2014 not hardcoded values.\n\n## Colors\n\nBind fills and strokes to color variables instead of hex values.\n\n- Fill: `fillVariableName:"bg/primary"` or `fillStyleName:"Surface/Primary"`\n- Stroke: `strokeVariableName:"border/default"`\n- Text color: `fontColorVariableName:"text/primary"`\n\nIf no matching variable exists, create one first:\n```\nvariables(method:"create", collectionId:"Colors", items:[{name:"bg/accent", type:"COLOR", valuesByMode:{"Light":"#E8F0FE","Dark":"#1A3A5C"}, scopes:["ALL_FILLS"]}])\n```\n\n## Spacing and Radius\n\nPass a variable name string instead of a number for cornerRadius, padding, itemSpacing, strokeWeight, opacity.\n\n- `cornerRadius:"radius/8"` not `cornerRadius:8`\n- `paddingTop:"space/16"` not `paddingTop:16`\n- `itemSpacing:"space/8"` not `itemSpacing:8`\n\nCreate FLOAT variables with appropriate scopes:\n```\nvariables(method:"create", collectionId:"Metrics", items:[{name:"space/12", type:"FLOAT", value:12, scopes:["GAP","WIDTH_HEIGHT"]}])\n```\n\n## Text Styles\n\nApply text styles by name \u2014 don\'t set fontSize/fontFamily/fontWeight manually.\n\n- `textStyleName:"Body/M"` on text.create or frames.update\n- Create styles with `styles(method:"create", type:"text", items:[{name:"Body/M", fontFamily:"Inter", fontSize:14, lineHeight:{value:20, unit:"PIXELS"}}])`\n\n## Common Scopes\n\nCOLOR variables:\n- `ALL_FILLS` \u2014 background fills\n- `TEXT_FILL` \u2014 text color\n- `STROKE_COLOR` \u2014 borders and outlines\n\nFLOAT variables:\n- `GAP`, `WIDTH_HEIGHT` \u2014 spacing and padding\n- `CORNER_RADIUS` \u2014 border radius\n- `STROKE_FLOAT` \u2014 stroke weight\n- `OPACITY` \u2014 transparency\n\n## Checking\n\nLint rules `hardcoded-color`, `hardcoded-token`, `no-text-style` catch unbound values. Run `audit` on any node to check.',
|
|
2506
2582
|
"vibma-workflow": '# Vibma Workflow\n\nWork with the tool in a predictable sequence: read before writing, create parents before children, verify after mutations.\n\n## Build Order\n\n1. `connection.create` \u2192 `connection.get` to verify\n2. Inspect existing structure: `document.get`, `variables.list`, `styles.list`, `components.list`\n3. Create design tokens: variable collections \u2192 variables \u2192 text styles \u2192 effect styles\n4. Create components from tokens\n5. Assemble screens from component instances\n6. Verify with `lint.check` and `frames.export`\n\n## Parent-First Rule\n\nCreate parent containers before children. Dependent creates must be sequential \u2014 never parallelize when the child needs the parent ID.\n\n## Component Creation\n\nBuild components early \u2014 they are the building blocks for screens. A component IS a frame: create it directly with layout properties, then add children.\n\n- Use `components.create(type: "component")` with properties for TEXT, BOOLEAN, INSTANCE_SWAP\n- TEXT properties auto-bind to child text nodes with matching names\n- Group related components into variant sets with `components.create(type: "variant_set")` for state dimensions (Style, Size, State)\n- Use flat components (not variant sets) for INSTANCE_SWAP slots like icons or avatars\n- Assemble screens from `instances.create`, not by cloning frames\n\n## Placement Rule\n\nAlways pass `x` and `y` for top-level nodes and clones. Do not stack everything at `0,0`.\n\n## Instance Rule\n\nCall `components.get` or `instances.get` to discover property keys (including `#suffix`) before setting overrides. Do not guess property names.\n\n## Verify After Mutations\n\n`"ok"` means the write succeeded, not that the result is correct. Read back the node after clone, swap, mode pinning, or large batch updates.'
|
|
2507
2583
|
};
|