Skip to main content
Glama
paragdesai1

Cursor Talk to Figma MCP

by paragdesai1

create_frame

Add a new frame to Figma designs with customizable position, size, colors, and layout options through Cursor AI integration.

Instructions

Create a new frame in Figma

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
xYesX position
yYesY position
widthYesWidth of the frame
heightYesHeight of the frame
nameNoOptional name for the frame
parentIdNoOptional parent node ID to append the frame to
fillColorNoFill color in RGBA format
strokeColorNoStroke color in RGBA format
strokeWeightNoStroke weight
layoutModeNoAuto-layout mode for the frame
layoutWrapNoWhether the auto-layout frame wraps its children
paddingTopNoTop padding for auto-layout frame
paddingRightNoRight padding for auto-layout frame
paddingBottomNoBottom padding for auto-layout frame
paddingLeftNoLeft padding for auto-layout frame
primaryAxisAlignItemsNoPrimary axis alignment for auto-layout frame. Note: When set to SPACE_BETWEEN, itemSpacing will be ignored as children will be evenly spaced.
counterAxisAlignItemsNoCounter axis alignment for auto-layout frame
layoutSizingHorizontalNoHorizontal sizing mode for auto-layout frame
layoutSizingVerticalNoVertical sizing mode for auto-layout frame
itemSpacingNoDistance between children in auto-layout frame. Note: This value will be ignored if primaryAxisAlignItems is set to SPACE_BETWEEN.

Implementation Reference

  • Registration of the 'create_frame' MCP tool, including schema definition and handler function. The handler forwards parameters to the Figma plugin via sendCommandToFigma('create_frame', params) and handles the response.
    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)
                  }`,
              },
            ],
          };
        }
      }
    );
  • The handler function for the 'create_frame' tool. It collects parameters for creating a Figma frame (position, size, styling, layout options), sends them to the underlying Figma plugin via sendCommandToFigma, and returns a success message with the new frame's ID or an error.
    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)
                }`,
            },
          ],
        };
      }
  • Zod schema defining input parameters for the 'create_frame' tool, including position, dimensions, name, parent, colors, stroke, and extensive auto-layout options (paddings, alignments, sizing modes, spacing).
    {
      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.")
    },

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed22 schema fields changedv1.0.0
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / counterAxisAlignItems
      Added value: +{
      +  "description": "Counter axis alignment for auto-layout frame",
      +  "enum": [
      +    "MIN",
      +    "MAX",
      +    "CENTER",
      +    "BASELINE"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / fillColor
      Added value: +{
      +  "description": "Fill color in RGBA format",
      +  "properties": {
      +    "a": {
      +      "description": "Alpha component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "b": {
      +      "description": "Blue component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "g": {
      +      "description": "Green component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "r": {
      +      "description": "Red component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "r",
      +    "g",
      +    "b"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / height
      Added value: +{
      +  "description": "Height of the frame",
      +  "type": "number"
      +}
    • addedInput schema / properties / itemSpacing
      Added value: +{
      +  "description": "Distance between children in auto-layout frame. Note: This value will be ignored if primaryAxisAlignItems is set to SPACE_BETWEEN.",
      +  "type": "number"
      +}
    • addedInput schema / properties / layoutMode
      Added value: +{
      +  "description": "Auto-layout mode for the frame",
      +  "enum": [
      +    "NONE",
      +    "HORIZONTAL",
      +    "VERTICAL"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / layoutSizingHorizontal
      Added value: +{
      +  "description": "Horizontal sizing mode for auto-layout frame",
      +  "enum": [
      +    "FIXED",
      +    "HUG",
      +    "FILL"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / layoutSizingVertical
      Added value: +{
      +  "description": "Vertical sizing mode for auto-layout frame",
      +  "enum": [
      +    "FIXED",
      +    "HUG",
      +    "FILL"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / layoutWrap
      Added value: +{
      +  "description": "Whether the auto-layout frame wraps its children",
      +  "enum": [
      +    "NO_WRAP",
      +    "WRAP"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / name
      Added value: +{
      +  "description": "Optional name for the frame",
      +  "type": "string"
      +}
    • addedInput schema / properties / paddingBottom
      Added value: +{
      +  "description": "Bottom padding for auto-layout frame",
      +  "type": "number"
      +}
    • addedInput schema / properties / paddingLeft
      Added value: +{
      +  "description": "Left padding for auto-layout frame",
      +  "type": "number"
      +}
    • addedInput schema / properties / paddingRight
      Added value: +{
      +  "description": "Right padding for auto-layout frame",
      +  "type": "number"
      +}
    • addedInput schema / properties / paddingTop
      Added value: +{
      +  "description": "Top padding for auto-layout frame",
      +  "type": "number"
      +}
    • addedInput schema / properties / parentId
      Added value: +{
      +  "description": "Optional parent node ID to append the frame to",
      +  "type": "string"
      +}
    • addedInput schema / properties / primaryAxisAlignItems
      Added value: +{
      +  "description": "Primary axis alignment for auto-layout frame. Note: When set to SPACE_BETWEEN, itemSpacing will be ignored as children will be evenly spaced.",
      +  "enum": [
      +    "MIN",
      +    "MAX",
      +    "CENTER",
      +    "SPACE_BETWEEN"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / strokeColor
      Added value: +{
      +  "description": "Stroke color in RGBA format",
      +  "properties": {
      +    "a": {
      +      "description": "Alpha component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "b": {
      +      "description": "Blue component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "g": {
      +      "description": "Green component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "r": {
      +      "description": "Red component (0-1)",
      +      "maximum": 1,
      +      "minimum": 0,
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "r",
      +    "g",
      +    "b"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / strokeWeight
      Added value: +{
      +  "description": "Stroke weight",
      +  "exclusiveMinimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / width
      Added value: +{
      +  "description": "Width of the frame",
      +  "type": "number"
      +}
    • addedInput schema / properties / x
      Added value: +{
      +  "description": "X position",
      +  "type": "number"
      +}
    • addedInput schema / properties / y
      Added value: +{
      +  "description": "Y position",
      +  "type": "number"
      +}
    • addedInput schema / required
      Added value: +[
      +  "x",
      +  "y",
      +  "width",
      +  "height"
      +]
  2. First observed

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It only says 'Create a new frame' which implies a mutating side effect, but does not mention what the tool returns, whether it requires authentication, whether it appends to a parent, or any other behavioral details. This is minimal disclosure for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, succinct sentence with no wasted words, making it highly concise. However, given the tool's complexity (20 parameters), the extreme brevity could be considered under-specification, but it remains free of fluff and is easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a complex tool with 20 parameters, six enums, nested objects, and no output schema. The description is only one sentence, which does not explain return values, the role of optional parameters like parentId and layoutMode, or any side effects. The schema covers parameter meaning but not overall tool behavior, leaving the description incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% parameter description coverage, so the baseline is 3. The tool description itself adds no parameter information beyond what's in the schema, but the schema already documents all parameters including nested objects and enums.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb+resource ('Create a new frame in Figma') that clearly identifies the tool's function and the object type. It distinguishes itself from sibling creation tools like create_rectangle or create_text by naming the frame resource, though it does not explicitly discuss alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, no prerequisites, and no context about workflow. It simply states the action without explaining scenarios where creating a frame is appropriate or how it relates to other creation/modification tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.