create_rectangle
Insert a rectangle shape into a Figma file by specifying its x/y position, width, height, and optional visual properties like fill and stroke. Design UI elements with precise control.
Instructions
Create a new rectangle in Figma
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| x | Yes | X position (local coordinates, relative to parent) | |
| y | Yes | Y position (local coordinates, relative to parent) | |
| width | Yes | Width of the rectangle | |
| height | Yes | Height of the rectangle | |
| name | No | Optional name for the rectangle | |
| parentId | No | Parent node ID. REQUIRED — server enforces this. Use page node ID for top-level elements. Get page IDs via get_pages tool. | |
| fillColor | No | Fill color in RGBA format | |
| strokeColor | No | Stroke color in RGBA format | |
| strokeWeight | No | Stroke weight |
Implementation Reference
- Handler function for the create_rectangle tool. Sends the command to Figma via WebSocket with position, dimensions, optional name, parentId, fill/stroke colors, and stroke weight.
async ({ x, y, width, height, name, parentId, fillColor, strokeColor, strokeWeight }) => { try { const result = await sendCommandToFigma("create_rectangle", { x, y, width, height, name: name || "Rectangle", parentId, fillColor, strokeColor, strokeWeight, }); return { content: [ { type: "text", text: `Created rectangle "${JSON.stringify(result)}"`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error creating rectangle: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } } ); - Input schema for the create_rectangle tool using Zod validation. Defines x, y, width, height (required), plus optional name, parentId, fillColor (RGBA), strokeColor (RGBA), and strokeWeight.
{ x: z.coerce.number().describe("X position (local coordinates, relative to parent)"), y: z.coerce.number().describe("Y position (local coordinates, relative to parent)"), width: z.coerce.number().describe("Width of the rectangle"), height: z.coerce.number().describe("Height of the rectangle"), name: z.string().optional().describe("Optional name for the rectangle"), parentId: z .string() .optional() .describe("Parent node ID. REQUIRED — server enforces this. Use page node ID for top-level elements. Get page IDs via get_pages tool."), fillColor: coerceJson(z.object({ r: z.coerce.number().min(0).max(1).describe("Red component (0-1)"), g: z.coerce.number().min(0).max(1).describe("Green component (0-1)"), b: z.coerce.number().min(0).max(1).describe("Blue component (0-1)"), a: z.coerce.number().min(0).max(1).optional().describe("Alpha component (0-1)"), })) .optional() .describe("Fill color in RGBA format"), strokeColor: coerceJson(z.object({ r: z.coerce.number().min(0).max(1).describe("Red component (0-1)"), g: z.coerce.number().min(0).max(1).describe("Green component (0-1)"), b: z.coerce.number().min(0).max(1).describe("Blue component (0-1)"), a: z.coerce.number().min(0).max(1).optional().describe("Alpha component (0-1)"), })) .optional() .describe("Stroke color in RGBA format"), strokeWeight: z.coerce.number().positive().optional().describe("Stroke weight"), }, - src/talk_to_figma_mcp/tools/creation-tools.ts:13-76 (registration)Registration of the 'create_rectangle' tool via server.tool() in the registerCreationTools function.
server.tool( "create_rectangle", "Create a new rectangle in Figma", { x: z.coerce.number().describe("X position (local coordinates, relative to parent)"), y: z.coerce.number().describe("Y position (local coordinates, relative to parent)"), width: z.coerce.number().describe("Width of the rectangle"), height: z.coerce.number().describe("Height of the rectangle"), name: z.string().optional().describe("Optional name for the rectangle"), parentId: z .string() .optional() .describe("Parent node ID. REQUIRED — server enforces this. Use page node ID for top-level elements. Get page IDs via get_pages tool."), fillColor: coerceJson(z.object({ r: z.coerce.number().min(0).max(1).describe("Red component (0-1)"), g: z.coerce.number().min(0).max(1).describe("Green component (0-1)"), b: z.coerce.number().min(0).max(1).describe("Blue component (0-1)"), a: z.coerce.number().min(0).max(1).optional().describe("Alpha component (0-1)"), })) .optional() .describe("Fill color in RGBA format"), strokeColor: coerceJson(z.object({ r: z.coerce.number().min(0).max(1).describe("Red component (0-1)"), g: z.coerce.number().min(0).max(1).describe("Green component (0-1)"), b: z.coerce.number().min(0).max(1).describe("Blue component (0-1)"), a: z.coerce.number().min(0).max(1).optional().describe("Alpha component (0-1)"), })) .optional() .describe("Stroke color in RGBA format"), strokeWeight: z.coerce.number().positive().optional().describe("Stroke weight"), }, async ({ x, y, width, height, name, parentId, fillColor, strokeColor, strokeWeight }) => { try { const result = await sendCommandToFigma("create_rectangle", { x, y, width, height, name: name || "Rectangle", parentId, fillColor, strokeColor, strokeWeight, }); return { content: [ { type: "text", text: `Created rectangle "${JSON.stringify(result)}"`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error creating rectangle: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } } ); - The sendCommandToFigma function that sends the 'create_rectangle' command over WebSocket to the Figma plugin and returns a promise resolving with the response.
export function sendCommandToFigma( command: FigmaCommand, params: unknown = {}, timeoutMs: number = 300000 ): Promise<unknown> { return new Promise((resolve, reject) => { // If not connected, try to connect first if (!ws || ws.readyState !== WebSocket.OPEN) { connectToFigma(); reject(new Error("Not connected to Figma. Attempting to connect...")); return; } // Check if we need a channel for this command const requiresChannel = command !== "join"; if (requiresChannel && !currentChannel) { reject(new Error("Must join a channel before sending commands")); return; } const id = uuidv4(); const request = { id, type: command === "join" ? "join" : "message", ...(command === "join" ? { channel: (params as any).channel, sessionId: SESSION_ID } : { channel: currentChannel }), message: { id, command, params: { ...(params as any), commandId: id, // Include the command ID in params }, }, }; // Set timeout for request const timeout = setTimeout(() => { if (pendingRequests.has(id)) { pendingRequests.delete(id); logger.error(`Request ${id} to Figma timed out after ${timeoutMs / 1000} seconds`); reject(new Error('Request to Figma timed out')); } }, timeoutMs); // Store the promise callbacks to resolve/reject later pendingRequests.set(id, { resolve, reject, timeout, lastActivity: Date.now() }); // Send the request logger.info(`Sending command to Figma: ${command}`); logger.debug(`Request details: ${JSON.stringify(request)}`); ws.send(JSON.stringify(request)); }); }