feat(figma): add Figma MCP for design-to-code context
Why
Most Studio tasks link a Figma frame, but the board agents have no access to it. Figma only offers its official MCP to approved clients. So the agents guess, and the result often does not match the design. This MCP reads designs through the public REST API with each user's own Figma account (OAuth). It gives agents a real reference: a screenshot, the layout as CSS, the tokens and the designer's comments.
What
New figma/ MCP. Tool names follow Figma's official MCP server, so prompts and skills written for it carry over.
- Design to code:
get_design_context(start here),get_metadata,get_screenshot,download_assets,get_variable_defs,get_motion_context,get_figjam,get_comments - Design systems:
get_libraries,search_design_system - Code Connect:
get_code_connect_map,add_code_connect_map,get_code_connect_suggestions,get_context_for_code_connect. Mappings are stored as Figma dev resources, because Figma's own Code Connect data is not in the public API. whoami, plus thecreate_design_system_rulesprompt
get_design_context returns the PNG of the node and one line per layer:
FRAME "Card" [1:1] 320×200 styles{fill:"Surface/White"} { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 16px 24px; background: #FFFFFF; border-radius: 8px }
TEXT "Title" [1:2] 272×24 { align-self: stretch; color: #000000; font-family: "Inter"; font-weight: 700; font-size: 20px; line-height: 24px } "Tênis 574"
FRAME "Icon" [1:3] 24×24 asset=svg { width: 24px; height: 24px }
INSTANCE "Buy" [1:6] 272×48 <Button Label="Comprar" Size="Large"> { align-self: stretch }
The output also lists the unresolved comments pinned inside the frame. Briefs often say these are part of the spec.
Not included, by design: use_figma, generate_figma_design, create_new_file, upload_assets and generate_diagram. Creating or editing layers needs the Plugin API inside an open Figma client, and REST does not offer it. generate_image already exists in Studio.
https://github.com/user-attachments/assets/170a6422-fc77-4e3e-9b7a-f6f356685979
Deploy and auth (needs a reviewer)
- Deploy: kubernetes-bun, entry added to
deploy.json, served athttps://sites-figma.deco.site/mcp. - Auth exemption:
figmais added toauth-exemptions.json, which needs reviewer sign-off. TheAuthorizationheader carries the caller's own Figma token, and every tool forwards it toapi.figma.com. There is no shared secret to check and no server-side credential exposed. This is the same situation asdynamic-yield. - OAuth hardening: runtime
^3.0.0withstateSecret. The server refuses to boot withoutOAUTH_STATE_SECRET, so the code that carries the token is never plain base64.allowedRedirectHostsis pinned todecocms.com(plusEXTRA_ALLOWED_REDIRECT_HOSTS). - Personal tokens: a personal access token (
figd_…) in the connection's Token field also works. It is sent asX-Figma-Token.
Before merging
- Create the Figma OAuth app with callback
https://sites-figma.deco.site/oauth/callbackand the scopes listed infigma/README.md. A private app only accepts users from the Figma org that owns it; a public app goes through Figma review. - Provision these site secrets:
FIGMA_CLIENT_ID,FIGMA_CLIENT_SECRET,OAUTH_STATE_SECRET. - Rate limits follow the connected seat. View and Collab seats get only about 20 Tier-1 reads per month. Dev and Full seats get 10 to 20 per minute. See the README.
Verified
bun testinfigma/: 10 tests pass (URL parsing, CSS conversion, truncation, XML output, comment scoping).tsc --noEmitis clean forfigma/server/**. The errors inside@decocms/runtime@3.0.0sources also show up forgithub/and come from how dependencies were installed in this environment.check:auth,build:registryand the pre-commit format and lint checks pass.- Local boot of the built
dist/server/main.js:/.well-known/oauth-authorization-serveris served.tools/listreturns the 15 tools andprompts/listreturns the prompt./authorizeredirects tofigma.com/oauthwith sealed state, and a non-decoredirect_uriis rejected.- A tool call reaches
api.figma.comwith the forwarded token.
- Not yet verified against a real Figma file. That needs the OAuth app, or a personal token from a Dev or Full seat.
🤖 Generated with Claude Code
Summary by cubic
Adds a Figma MCP server so coding agents get real design context — screenshot, layout as flexbox CSS, tokens, comments, library search and Code Connect — read through the public REST API with each user's own Figma account (OAuth). Tool names mirror Figma's official MCP server, so prompts and skills written for it carry over.
The server is read-only: creating or editing layers is not included because the REST API doesn't offer it. Code Connect mappings are stored as Figma dev resources. get_design_context output was refined from a real run: LINE layers render as border-top dividers with the stroke color, text shows its content instead of stale layer names, fonts in use are listed so missing ones get flagged, and layout noise (gaps on single-child frames, missing position: relative) is dropped.
Reviewer notes
figmais added toauth-exemptions.json: every tool forwards the caller's own Figma token in the Authorization header, so there is no shared secret to check and no server-side credential to protect. OAuth state and code are sealed withOAUTH_STATE_SECRET, and redirect hosts are pinned to decocms.com.- Before merging, create the Figma OAuth app with the callback and scopes listed in
figma/README.mdand provisionFIGMA_CLIENT_ID,FIGMA_CLIENT_SECRETandOAUTH_STATE_SECRETas site secrets. Until the app is approved, only its owner can authorize, so users connect with a personal access token (figd_…) through a Custom Connection; aBearerprefix on the token is stripped before detection. Note rate limits: View and Collab seats get about 20 Tier-1 reads per month; Dev and Full seats get 10–20 per minute. - An explicit screenshot scale is honored even when the node size is unknown, and a failed token refresh from bad client credentials no longer evicts the stored token.