Activate this skill when the owner wants to interact with Figma designs: create shapes, modify properties, extract design info, audit components, or automate design tasks.
This skill uses chrome-devtools-mcp to control a browser with Figma open. Instead of the read-only Figma REST API, it executes JavaScript directly against Figma's Plugin API (figma global object) — enabling full read AND write access.
- Server:
chrome-devtools(npx:chrome-devtools-mcp@latest) - Tools used:
navigate_page,evaluate_script - Config:
.mcp.jsonin workspace root
Owner uses Arc (Chromium-based). Remote debugging must be enabled at launch.
Before doing anything, check if port 9222 is listening:
lsof -i :9222 | grep LISTEN- Port open → Arc is running with debugging. Proceed to Figma.
- Port NOT open, but Arc is running (
pgrep -x Arc) → NEVER force-quit Arc. Tell the owner: "Arc is open tapi tanpa remote debugging. Bisa close Arc dulu? Nanti gue launch ulang dengan debugging enabled." Wait for confirmation. - Port NOT open, Arc NOT running → Launch Arc:
open -a "Arc" --args --remote-debugging-port=9222
- Run pre-flight check (above)
- Use
navigate_pageto go tohttps://www.figma.com/ - Ask the owner to log in and open the target design file
- Confirm access to
figmaglobal object viaevaluate_script:typeof figma !== 'undefined'
- Execute design tasks using
evaluate_scriptwith Figma Plugin API JavaScript
- Create and modify shapes, frames, components
- Rename layers, organize structure
- Extract design tokens (colors, typography, spacing)
- Audit components across files
- Compare design vs implementation
- Any operation available via Figma Plugin API
-
Always
await loadFontAsync()BEFORE setting text. Font loading is async — if you setcharactersbefore the font is loaded, text renders as invisible/missing. Pre-load ALL fonts at the start of your script. -
Never use
resize(width, 1)on auto-layout frames.resize()sets a fixed height constraint. Even withcounterAxisSizingMode = "AUTO", the frame stays at 1px height. Combined withclipsContent = true(Figma's default), all content taller than 1px gets clipped — invisible. Instead:- For horizontal auto-layout rows: only set width via
resize(width, height)with a reasonable height, then setcounterAxisSizingMode = "AUTO"AFTER resize. Or avoid resize and uselayoutAlign = "STRETCH"on child frames. - Always set
clipsContent = falseon auto-layout frames unless you intentionally want clipping.
- For horizontal auto-layout rows: only set width via
-
Figma
clipsContentdefaults totrueon new frames. Explicitly setclipsContent = falseon frames where content should overflow (especially auto-layout containers). -
Clean up failed attempts before retrying. When a script errors mid-execution, partially-created nodes (orphan frames, empty containers) get left on the canvas. Always start retry scripts with cleanup:
figma.currentPage.findAll(n => n.name === "Target").forEach(n => n.remove()). Also check for orphan top-level nodes after errors — don't leave junk on the canvas.
If figma is not defined:
- Verify the owner has edit permissions on the file (suggest creating a branch if view-only)
- If still not working, ask the owner to open any Figma plugin and close it — there's a known bug where the
figmaglobal isn't available until a plugin has been opened at least once - Retry the
evaluate_scriptcheck
- chrome-devtools-mcp has full browser access — it can interact with any open tab
- Every tool call goes through our approval flow
- Never execute destructive operations (delete files, account changes) without explicit owner confirmation
- This accesses Figma via browser session — the owner's Figma credentials are never exposed to us