New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

figma-vector-mcp

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

figma-vector-mcp

MCP server + Figma plugin for AI-driven vector creation on the Figma canvas

latest
Source
npmnpm
Version
0.3.3
Version published
Weekly downloads
2
-33.33%
Maintainers
1
Weekly downloads
 
Created
Source

Figma Vector MCP

A Figma plugin + MCP server that lets Claude (or any MCP client) create and manipulate fully-editable vector nodes on the Figma canvas — paths, shapes, gradients, text, effects, image fills, and more — via a local WebSocket relay.

Developed by Working Model Inc

npm version npm downloads

Version 0.3.3 — 58 tools across creation, styling, layout, components, effects, pages, and export.

Why This Exists

cursor-talk-to-figma-mcp is great for reading Figma state and creating basic primitives, but it has no vector path creation, gradient, effects, or compositing tools. This plugin fills that gap:

Capabilitycursor-talk-to-figma-mcpfigma-vector-mcp
Create rectangle / ellipse / frame / text✅✅
Create from SVG string❌✅
Create from path d string❌✅
Create polyline / polygon❌✅
Gradient fills (linear, radial, angular, diamond)❌✅
Image fills (base64 → canvas)❌✅
Effects (shadow, blur)❌✅
Blend modes❌✅
Boolean operations (union, subtract, etc.)❌✅
Auto-layout❌✅
Components + instances❌✅
Font discovery❌✅
Node search❌✅
Multi-page management❌✅
Named node registry❌✅
Batch commands (single round-trip)❌✅
Auto-reconnect + command queue❌✅
Export SVG + PNG❌✅

Architecture

Claude (MCP client)
  ↕ stdio (MCP protocol)
server.ts (MCP server)
  ↕ WebSocket (ws://localhost:3055)
socket.ts (relay — channel-based routing)
  ↕ WebSocket
Figma plugin (ui.html ↔ code.js)
  ↕ postMessage
Figma Plugin API → canvas

The socket relay runs locally. The Figma plugin connects and joins a named channel. The MCP server joins the same channel and sends commands. Results flow back the same path.

AI Agent Quickstart

For AI agents (Claude Code, Cursor, etc.) — the recommended call sequence to start any session:

1. health_check                    → confirm plugin is connected
2. get_document_info               → get page IDs, current page, top-level nodes
3. get_available_fonts             → discover loadable fonts before create_text
4. get_styles                      → load brand colours/text styles if available

Color convention: All RGB values are 0–1 throughout (matching Figma's internal format). r: 1, g: 0, b: 0 = red. Never use 0–255.

Gradient workflow:

1. create_frame({ width, height })          → get frameId
2. set_gradient_fill({ nodeId: frameId, type: "LINEAR", angle: 135,
     stops: [{ color: { r:0.2, g:0.1, b:0.9 }, position: 0 },
             { color: { r:0.9, g:0.2, b:0.4 }, position: 1 }] })

Image fill workflow (with generative AI):

1. Generate image via Replicate/fal.ai → get base64 PNG
2. create_frame({ width: 512, height: 512 })
3. set_image_fill({ nodeId, base64, scaleMode: "FILL" })

Batch compositions — use $prev.id to chain commands without extra round-trips:

{ "commands": [
    { "command": "create_frame", "params": { "width": 400, "height": 300, "name": "Card" } },
    { "command": "set_gradient_fill", "params": { "nodeId": "$prev.id", "type": "LINEAR",
        "stops": [{"color":{"r":0.1,"g":0.1,"b":0.9},"position":0},
                  {"color":{"r":0.8,"g":0.2,"b":0.5},"position":1}] } },
    { "command": "create_text", "params": { "parentId": "$results.0.id",
        "text": "Hello", "fontSize": 32, "x": 24, "y": 24 } }
]}

Known SVG limits: figma.createNodeFromSvg() strips <defs>, gradients, filters, masks, and animations. Use set_gradient_fill for gradients instead of SVG <linearGradient>.

Reconnection: If the plugin disconnects, it auto-reconnects with exponential backoff (1s→30s max) and replays queued commands (up to 30s old). No manual intervention needed for short interruptions.

Setup

1 — Install the plugin

  • Clone this repo or download the source
  • In Figma desktop: Plugins → Development → Import plugin from manifest
  • Select src/figma-plugin/manifest.json

2 — Install the MCP server

npm install -g figma-vector-mcp
# or use without installing via npx / bunx (see MCP config below)

3 — Start the socket relay

bun run socket

Listens on ws://localhost:3055. Auto-start on login (macOS):

./scripts/setup.sh --launchd

4 — Configure the MCP server

# Auto-detect Claude Code / Cursor and write config:
./scripts/setup.sh

# Local build:
./scripts/setup.sh --local

# Install git pre-commit sandbox lint hook:
./scripts/setup.sh --hooks

Manual config (~/.claude/settings.json or ~/.cursor/mcp.json):

{
  "mcpServers": {
    "FigmaVectorMCP": {
      "command": "bunx",
      "args": ["figma-vector-mcp@latest"],
      "env": { "FVMCP_CHANNEL": "figma-vector-mcp" }
    }
  }
}

5 — Connect the plugin

  • Open your Figma file
  • Plugins → Development → Figma Vector MCP
  • Enter server URL (ws://localhost:3055) → Connect
  • Enter channel name (figma-vector-mcp) → Join

The plugin saves your last URL and channel — pre-filled on next open. Keep the plugin panel open during your session — closing it terminates the WebSocket connection.

6 — Verify

health_check → { "status": "ok", "version": "0.3.3", "currentPage": { ... } }

Environment Variables

VariableDefaultDescription
FVMCP_PORT3055Socket relay port
FVMCP_CHANNELfigma-vector-mcpChannel name — must match the plugin
FVMCP_TIMEOUT_MS10000Default command timeout (ms)

Per-tool timeout overrides: health_check → 3s, export_node_as_png → 30s, export_node_as_svg → 15s, create_batch → 60s.

Tool Reference

Connection & Health

ToolDescriptionKey Params
health_checkPing plugin; confirm connectivity—
join_channelJoin a named channelchannel

Vector Creation

ToolDescriptionKey Params
create_vector_from_svgPlace editable vector from SVG stringsvg, x, y, name, parentId
create_pathVector from SVG d path stringd, x, y, fillColor, strokeColor, strokeWeight
create_polylineVector from [x,y][] point pairspoints, closed, strokeColor, strokeWeight

Primitives

ToolDescriptionKey Params
create_frameContainer framewidth, height, x, y, fillColor
create_rectangleRectanglewidth, height, x, y, fillColor
create_ellipseEllipse / circlewidth, height, x, y, fillColor
create_textText node with optional fixed-width columntext, fontSize, fontFamily, fontStyle, fillColor, width, height, textAutoResize

Fills & Colour

ToolDescriptionKey Params
set_fill_colorSolid RGBA fill (0–1)nodeId, r, g, b, a
set_gradient_fillGradient fill — LINEAR, RADIAL, ANGULAR, DIAMONDnodeId, type, stops, angle, center, gradientTransform
set_image_fillBase64 image as fillnodeId, base64, scaleMode, opacity

Stroke

ToolDescriptionKey Params
set_strokeFull stroke controlnodeId, color, weight, position, dashPattern, lineCap, lineJoin
set_stroke_colorQuick stroke colour + weightnodeId, r, g, b, a, weight

Effects & Compositing

ToolDescriptionKey Params
set_effectDrop shadow, inner shadow, blur, background blurnodeId, effects[] (type, color, offset, blur, spread), mode (REPLACE | APPEND)
set_blend_modeLayer blend modenodeId, mode (NORMAL, MULTIPLY, SCREEN, OVERLAY…)

Node Manipulation

ToolDescriptionKey Params
set_corner_radiusCorner radius — uniform or per-cornernodeId, radius or topLeft, topRight, bottomLeft, bottomRight
set_opacityOpacity 0–1nodeId, opacity
set_text_styleModify text properties + text box sizenodeId, fontSize, fontFamily, fontStyle, letterSpacing, lineHeight, textAlign, fillColor, width, height, textAutoResize
rename_nodeRename a nodenodeId, name
set_visibilityShow or hide a nodenodeId, visible
reorder_nodeChange Z-order within parentnodeId, action (BRING_TO_FRONT / SEND_TO_BACK / BRING_FORWARD / SEND_BACKWARD) or index
move_nodeRepositionnodeId, x, y
resize_nodeResizenodeId, width, height
delete_nodeRemove from canvasnodeId
clone_nodeDuplicate, optionally repositionnodeId, x, y, parentId
group_nodesGroup nodesnodeIds[], name, parentId
ungroup_nodesUngroupnodeId
boolean_operationUnion, subtract, intersect, excludenodeIds[], operation, name
create_maskClip mask — maskNode clips targetNodemaskNodeId, targetNodeId, name

Layout

ToolDescriptionKey Params
set_auto_layoutEnable / configure auto-layoutnodeId, direction, spacing, padding, primaryAxisAlign, counterAxisAlign, primaryAxisSizingMode, counterAxisSizingMode, wrap
set_layout_gridColumn / row / grid guides on a framenodeId, grids[] (pattern, count, gutterSize, sectionSize, alignment, color)
batch_set_propertiesBulk update fill/stroke/opacity/position/sizeoperations[] (nodeId + any subset of properties)

Components

ToolDescriptionKey Params
create_componentConvert frame/group to componentnodeId, name
create_instancePlace component instancecomponentId, x, y, parentId
get_componentsList all local components—
get_library_componentsSearch local components by namequery

Document & Pages

ToolDescriptionKey Params
get_document_infoDocument name, pages, current page children—
get_selectionCurrently selected nodes—
get_node_infoFull node detail: fills, strokes, layout, text, constraintsnodeId
set_focusScroll viewport to node and select itnodeId
find_nodesSearch by name and/or typequery, type, pageId, recursive
get_page_listAll pages—
switch_pageActivate a pagepageId or pageName
create_pageCreate a new pagename
duplicate_frame_to_pageCopy node to another pagenodeId, targetPageId, x, y

Node Registry

ToolDescriptionKey Params
register_nodeSave named alias for a node ID (persists in document)alias, nodeId
resolve_nodeLook up node ID by aliasalias

Color Registry

ToolDescriptionKey Params
register_colorSave a named color to the document palette (0–1)alias, r, g, b, a
resolve_colorLook up a color by aliasalias
list_colorsList all registered colors in the document—

Styles & Fonts

ToolDescriptionKey Params
get_stylesAll local paint and text styles—
apply_styleApply document style to nodenodeId, styleId, styleType
get_available_fontsList loadable fonts; filter by namequery

Export

ToolDescriptionKey Params
export_node_as_svgExport node as SVG stringnodeId
export_node_as_pngExport as base64 PNGnodeId, scale (default 2)
screenshot_current_pageExport full page as base64 PNGscale

Batch

ToolDescriptionKey Params
create_batchRun multiple commands in one round-trip. Supports $prev.id and $results.N.field tokens for chaining.commands[] (command, params)

Sandbox Compatibility

The plugin main thread (code.js) runs in Figma's restricted QuickJS sandbox. The UI (ui.html) is a normal browser context and is not affected.

Run bun run lint:plugin to check code.src.js for violations before building. A pre-commit hook can be installed via ./scripts/install-hooks.sh.

Banned in code.js

API / SyntaxSafe replacement
import / exportInline all deps
x ?? y(x != null) ? x : y
obj?.propobj && obj.prop
{ ...obj } / [ ...arr ]Object.assign({}, obj) / Array.from(arr)
localStoragefigma.clientStorage
TextDecoderChunked String.fromCharCode
fetch()Not available in main thread
figma.getNodeById() (sync)await figma.getNodeByIdAsync()
figma.currentPage = x (sync assign)await figma.setCurrentPageAsync(x)
figma.getLocalPaintStyles() (sync)await figma.getLocalPaintStylesAsync()
figma.getLocalTextStyles() (sync)await figma.getLocalTextStylesAsync()
figma.root.findAllWithCriteria() without page loadawait figma.loadAllPagesAsync() first

SVG compatibility (create_vector_from_svg)

FeatureStatus
<rect>, <polygon>, <polyline>, <path>, <circle>, <ellipse>✅
fill, stroke, stroke-width, stroke-linecap, stroke-linejoin✅
viewBox, width, height✅
<linearGradient> / <radialGradient> in <defs>❌ Stripped — use set_gradient_fill
<filter>, <mask>, <pattern>❌ Stripped
<animate>, <animateTransform>❌ Stripped
<script>, <foreignObject>❌ Stripped
fill="url(#...)" references❌ Replaced with fill="none"

Development

bun install              # install deps
bun run socket           # start relay on :3055
bun run build            # build MCP server → dist/server.js
bun run build:plugin     # build plugin: code.src.js → code.js
bun run lint:plugin      # check code.src.js for sandbox violations
./scripts/install-hooks.sh  # install pre-commit lint hook

Plugin workflow

  • Edit src/figma-plugin/code.src.js
  • bun run lint:plugin — catch sandbox violations before building
  • bun run build:plugin — esbuild outputs code.js (ES2017)
  • Close and reopen the plugin panel in Figma to load the new code.js

Credits

  • Socket relay (src/socket.ts) adapted from cursor-talk-to-figma-mcp — Copyright (c) 2025 sonnylazuardi, MIT License
  • setCharacters helpers in code.src.js adapted from the same project — Copyright (c) 2025 sonnylazuardi, MIT License

License

MIT © Working Model — see LICENSE and THIRD_PARTY_NOTICES.md.

Developed by Working Model Inc

FAQs

Package last updated on 22 Oct 2026

Related posts