Skip to main content
Glama

Cursor Talk to Figma MCP

by paragdesai1

create_frame

Generate a new frame in Figma directly from Cursor AI, enabling quick design adjustments within the Figma workspace via MCP integration.

Instructions

Create a new frame in Figma

Input Schema

NameRequiredDescriptionDefault

No arguments

Input Schema (JSON Schema)

{ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": {}, "type": "object" }

Implementation Reference

  • Core handler function that executes the create_frame tool logic in the Figma plugin: creates Frame node, sets position/size/name/layout/fill/stroke properties, handles parent appending.
    async function createFrame(params) { const { x = 0, y = 0, width = 100, height = 100, name = "Frame", parentId, fillColor, strokeColor, strokeWeight, layoutMode = "NONE", layoutWrap = "NO_WRAP", paddingTop = 10, paddingRight = 10, paddingBottom = 10, paddingLeft = 10, primaryAxisAlignItems = "MIN", counterAxisAlignItems = "MIN", layoutSizingHorizontal = "FIXED", layoutSizingVertical = "FIXED", itemSpacing = 0, } = params || {}; const frame = figma.createFrame(); frame.x = x; frame.y = y; frame.resize(width, height); frame.name = name; // Set layout mode if provided if (layoutMode !== "NONE") { frame.layoutMode = layoutMode; frame.layoutWrap = layoutWrap; // Set padding values only when layoutMode is not NONE frame.paddingTop = paddingTop; frame.paddingRight = paddingRight; frame.paddingBottom = paddingBottom; frame.paddingLeft = paddingLeft; // Set axis alignment only when layoutMode is not NONE frame.primaryAxisAlignItems = primaryAxisAlignItems; frame.counterAxisAlignItems = counterAxisAlignItems; // Set layout sizing only when layoutMode is not NONE frame.layoutSizingHorizontal = layoutSizingHorizontal; frame.layoutSizingVertical = layoutSizingVertical; // Set item spacing only when layoutMode is not NONE frame.itemSpacing = itemSpacing; } // Set fill color if provided if (fillColor) { const paintStyle = { type: "SOLID", color: { r: parseFloat(fillColor.r) || 0, g: parseFloat(fillColor.g) || 0, b: parseFloat(fillColor.b) || 0, }, opacity: parseFloat(fillColor.a) || 1, }; frame.fills = [paintStyle]; } // Set stroke color and weight if provided if (strokeColor) { const strokeStyle = { type: "SOLID", color: { r: parseFloat(strokeColor.r) || 0, g: parseFloat(strokeColor.g) || 0, b: parseFloat(strokeColor.b) || 0, }, opacity: parseFloat(strokeColor.a) || 1, }; frame.strokes = [strokeStyle]; } // Set stroke weight if provided if (strokeWeight !== undefined) { frame.strokeWeight = strokeWeight; } // If parentId is provided, append to that node, otherwise append to current page if (parentId) { const parentNode = await figma.getNodeByIdAsync(parentId); if (!parentNode) { throw new Error(`Parent node not found with ID: ${parentId}`); } if (!("appendChild" in parentNode)) { throw new Error(`Parent node does not support children: ${parentId}`); } parentNode.appendChild(frame); } else { figma.currentPage.appendChild(frame); } return { id: frame.id, name: frame.name, x: frame.x, y: frame.y, width: frame.width, height: frame.height, fills: frame.fills, strokes: frame.strokes, strokeWeight: frame.strokeWeight, layoutMode: frame.layoutMode, layoutWrap: frame.layoutWrap, parentId: frame.parent ? frame.parent.id : undefined, }; }
  • MCP tool registration for 'create_frame', including input schema validation (zod) and proxy handler that forwards to Figma plugin via sendCommandToFigma.
    server.tool( "create_frame", "Create a new frame in Figma", { x: z.number().describe("X position"), y: z.number().describe("Y position"), width: z.number().describe("Width of the frame"), height: z.number().describe("Height of the frame"), name: z.string().optional().describe("Optional name for the frame"), parentId: z .string() .optional() .describe("Optional parent node ID to append the frame to"), fillColor: z .object({ r: z.number().min(0).max(1).describe("Red component (0-1)"), g: z.number().min(0).max(1).describe("Green component (0-1)"), b: z.number().min(0).max(1).describe("Blue component (0-1)"), a: z .number() .min(0) .max(1) .optional() .describe("Alpha component (0-1)"), }) .optional() .describe("Fill color in RGBA format"), strokeColor: z .object({ r: z.number().min(0).max(1).describe("Red component (0-1)"), g: z.number().min(0).max(1).describe("Green component (0-1)"), b: z.number().min(0).max(1).describe("Blue component (0-1)"), a: z .number() .min(0) .max(1) .optional() .describe("Alpha component (0-1)"), }) .optional() .describe("Stroke color in RGBA format"), strokeWeight: z.number().positive().optional().describe("Stroke weight"), layoutMode: z.enum(["NONE", "HORIZONTAL", "VERTICAL"]).optional().describe("Auto-layout mode for the frame"), layoutWrap: z.enum(["NO_WRAP", "WRAP"]).optional().describe("Whether the auto-layout frame wraps its children"), paddingTop: z.number().optional().describe("Top padding for auto-layout frame"), paddingRight: z.number().optional().describe("Right padding for auto-layout frame"), paddingBottom: z.number().optional().describe("Bottom padding for auto-layout frame"), paddingLeft: z.number().optional().describe("Left padding for auto-layout frame"), primaryAxisAlignItems: z .enum(["MIN", "MAX", "CENTER", "SPACE_BETWEEN"]) .optional() .describe("Primary axis alignment for auto-layout frame. Note: When set to SPACE_BETWEEN, itemSpacing will be ignored as children will be evenly spaced."), counterAxisAlignItems: z.enum(["MIN", "MAX", "CENTER", "BASELINE"]).optional().describe("Counter axis alignment for auto-layout frame"), layoutSizingHorizontal: z.enum(["FIXED", "HUG", "FILL"]).optional().describe("Horizontal sizing mode for auto-layout frame"), layoutSizingVertical: z.enum(["FIXED", "HUG", "FILL"]).optional().describe("Vertical sizing mode for auto-layout frame"), itemSpacing: z .number() .optional() .describe("Distance between children in auto-layout frame. Note: This value will be ignored if primaryAxisAlignItems is set to SPACE_BETWEEN.") }, async ({ x, y, width, height, name, parentId, fillColor, strokeColor, strokeWeight, layoutMode, layoutWrap, paddingTop, paddingRight, paddingBottom, paddingLeft, primaryAxisAlignItems, counterAxisAlignItems, layoutSizingHorizontal, layoutSizingVertical, itemSpacing }) => { try { const result = await sendCommandToFigma("create_frame", { x, y, width, height, name: name || "Frame", parentId, fillColor: fillColor || { r: 1, g: 1, b: 1, a: 1 }, strokeColor: strokeColor, strokeWeight: strokeWeight, layoutMode, layoutWrap, paddingTop, paddingRight, paddingBottom, paddingLeft, primaryAxisAlignItems, counterAxisAlignItems, layoutSizingHorizontal, layoutSizingVertical, itemSpacing }); const typedResult = result as { name: string; id: string }; return { content: [ { type: "text", text: `Created frame "${typedResult.name}" with ID: ${typedResult.id}. Use the ID as the parentId to appendChild inside this frame.`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error creating frame: ${error instanceof Error ? error.message : String(error) }`, }, ], }; } } );
  • Dispatch handler in Figma plugin code that routes 'create_frame' command to the createFrame implementation function.
    case "create_frame": return await createFrame(params);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/paragdesai1/parag-Figma-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server