Figma Console MCP
Read and edit Figma designs, variables and components, and sync design tokens with code
Read and edit open Figma and FigJam files through a desktop plugin instead of the Figma REST API
By Hopp - Remote Pair Programming Tool TypeScript Local · stdio Design
60 popularity score ★ 889 ↓ 1.3k/wk
Opens the app, which asks before it adds the server.
claude mcp add figma-bridge -- npx -y @gethopp/figma-mcp-bridge{
"mcpServers": {
"figma-bridge": {
"command": "npx",
"args": [
"-y",
"@gethopp/figma-mcp-bridge"
]
}
}
}{
"mcpServers": {
"figma-bridge": {
"command": "npx",
"args": [
"-y",
"@gethopp/figma-mcp-bridge"
]
}
}
}{
"servers": {
"figma-bridge": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@gethopp/figma-mcp-bridge"
]
}
}
}[mcp_servers.figma-bridge]
command = "npx"
args = ["-y", "@gethopp/figma-mcp-bridge"]gemini mcp add --scope user figma-bridge npx -- -y @gethopp/figma-mcp-bridgeOpens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.
git clone https://github.com/gethopp/figma-mcp-bridge.git
cd figma-mcp-bridge/server && bun install && bun run buildclaude mcp add figma-bridge -- node '<ABSOLUTE_PATH_TO_CLONE>/server/dist/index.js'{
"mcpServers": {
"figma-bridge": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/server/dist/index.js"
]
}
}
}{
"mcpServers": {
"figma-bridge": {
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/server/dist/index.js"
]
}
}
}{
"servers": {
"figma-bridge": {
"type": "stdio",
"command": "node",
"args": [
"<ABSOLUTE_PATH_TO_CLONE>/server/dist/index.js"
]
}
}
}[mcp_servers.figma-bridge]
command = "node"
args = ["<ABSOLUTE_PATH_TO_CLONE>/server/dist/index.js"]gemini mcp add --scope user figma-bridge node -- '<ABSOLUTE_PATH_TO_CLONE>/server/dist/index.js'FIGMA_BRIDGE_ENABLE_RUN_SCRIPT |
Optional: Set to 1 to register run_script. Any other value leaves it off. With several clients running the bridge, set it in each configuration. |
|---|---|
FIGMA_BRIDGE_HOST |
Optional: Address the leader listens on: 127.0.0.1, ::1, 0.0.0.0 or ::. Any other value stops the server at start. Use an all-interfaces address only when the plugin runs on another host such as a VM. |
FIGMA_BRIDGE_PORT |
Optional: Port for the plugin and for other server instances. The server exits on a value outside 1-65535. The stock plugin expects 1994, so another port needs a plugin built to match. |
Figma MCP Bridge, made by the team behind the Hopp pairing app, has two halves: a development plugin you import into the Figma desktop app, and a local Node.js server your AI client starts over stdio. The plugin opens a WebSocket to the server on localhost port 1994 and answers its requests from the open document, so no Figma API token is used and Figma's REST rate limits (which its makers cite as the reason for the project) do not apply.
The server reads the page tree, the selection, single nodes, styles, variables, prototype flows and exports of nodes as images. It can also edit the file: set text, fills, gradients, effects, strokes and auto-layout, create pages, frames, sections, text, shapes, images, SVG layers, FigJam stickies and connectors, move, group, duplicate and delete nodes, and apply animation presets and keyframes (marked beta). Several files can be connected at once. Each tool takes an optional fileKey, and list_files shows which are connected. When several AI clients run the server at once, one becomes the leader that holds the plugin connections and the others forward their calls to it over HTTP.
Since 0.0.25 there is also run_script, which runs whatever Plugin API JavaScript you hand it inside the open file. It stays off by default. In the code the tool is only registered when FIGMA_BRIDGE_ENABLE_RUN_SCRIPT is exactly "1", so with the setting unset the client never sees it (server/src/tools.ts). With it on, v0.0.25 registers 55 tools. That count includes get_layout_tree, which returns absolute positions and layout bounds under a root node.
| Runtime | Node.js |
|---|---|
| Runs on | macOS, Windows |
| Figma | FreeEdit permission on a file is needed for the write tools; no API token is used |
| Also |
|
Import the plugin from the project's GitHub releases in the desktop app via Plugins > Development > Import plugin from manifest. The browser version of Figma cannot import development plugins. Port 1994 must be free on localhost unless FIGMA_BRIDGE_PORT is set, and a different port also needs a plugin built for it.
Works only on files open in the desktop app with the plugin running; nothing is read from Figma's cloud. Write tools fail in Dev Mode; auto-layout and animation tools fail in FigJam, and prototype tools are unavailable there. Its makers list no component or instance editing, no variable or style authoring, no per-segment text styling and no boolean vector operations. Animation tools are beta. create_svg takes up to 2 MiB. In the code, create_image refuses local paths outside the server's working directory, even absolute ones, though the README says absolute paths are read as given; image URLs are fetched with a 32 MiB cap, a 15-second timeout and at most 5 redirects (server/src/tools.ts).
Suits designers and developers on Figma's free plan or anyone hitting REST API limits, who keep the desktop app open while they work and want an assistant to inspect or build layouts in the live file, including FigJam boards. It needs no token but does need the plugin running, so it does not fit headless or CI use, the browser version of Figma, or Linux. It is not published by Figma. For reading files through Figma's REST API without the desktop app, its README names Figma-Context-MCP as the existing alternative, at the cost of API rate limits.
14 only read, 39 change things, 2 can delete or overwrite. A ? marks an optional parameter.
list_filesget_documentfileKey?: stringget_selectionfileKey?: stringget_layout_treerootId: stringmaxNodes?: integerfileKey?: stringget_nodenodeId: stringincludePrototype?: booleanfileKey?: stringget_prototype_connectionsnodeId?: stringmaxNodes?: integerincludeEmpty?: booleanfileKey?: stringtrace_prototype_flownodeId: stringmaxScreens?: integermaxNodesPerScreen?: integerfileKey?: stringget_stylesfileKey?: stringget_metadatafileKey?: stringget_design_contextdepth?: numberfileKey?: stringget_variable_defsfileKey?: stringget_screenshotnodeIds?: arrayformat?: enumscale?: numberclip?: booleanfileKey?: stringset_node_visibility changesitems: arrayfileKey?: stringset_text_content changesnodeId: stringtext?: stringcharacters?: stringfileKey?: stringset_text_properties changesnodeId: stringfontFamily?: stringfontStyle?: stringfontSize?: numbertextAlignHorizontal?: enumtextAlignVertical?: enumtextAutoResize?: enumlineHeightPx?: numberletterSpacingPx?: numberfillHex?: stringfillOpacity?: numberx?: numbery?: numberwidth?: numberheight?: numberfileKey?: stringset_node_properties changesnodeId?: stringnodeIds?: arrayname?: stringx?: numbery?: numberwidth?: numberheight?: numberrotation?: numberopacity?: numbervisible?: booleancornerRadius?: numberfileKey?: stringset_solid_fill changesnodeId: stringhex?: stringfillHex?: stringopacity?: numberfillOpacity?: numbertarget?: enumfileKey?: stringset_gradient_fill changesnodeId: stringgradientType?: enumgradientStops: arraygradientTransform?: arrayopacity?: numbertarget?: enumfileKey?: stringset_effects changesnodeId: stringeffects: arrayfileKey?: stringset_stroke_properties changesnodeId: stringstrokeWeight?: numberstrokeAlign?: enumdashPattern?: arraystrokeCap?: enumstrokeJoin?: enumfileKey?: stringset_auto_layout changesnodeId: stringlayoutMode?: enumitemSpacing?: numbercounterAxisSpacing?: numberpaddingTop?: numberpaddingRight?: numberpaddingBottom?: numberpaddingLeft?: numberprimaryAxisAlignItems?: enumcounterAxisAlignItems?: enumprimaryAxisSizingMode?: enumcounterAxisSizingMode?: enumlayoutWrap?: enumfileKey?: stringcreate_page changesname?: stringsetAsCurrent?: booleanfileKey?: stringcreate_frame changesname?: stringparentId?: stringx?: numbery?: numberwidth?: numberheight?: numberfillHex?: stringfillOpacity?: numberfileKey?: stringcreate_section changesname?: stringparentId?: stringx?: numbery?: numberwidth?: numberheight?: numberfillHex?: stringfillOpacity?: numbersectionContentsHidden?: booleanfileKey?: stringcreate_text changesname?: stringparentId?: stringcharacters?: stringfontFamily?: stringfontStyle?: stringfontSize?: numbertextAlignHorizontal?: enumtextAutoResize?: enumfillHex?: stringfillOpacity?: numberx?: numbery?: numberwidth?: numberheight?: numberfileKey?: stringcreate_shape changesshapeType: enumname?: stringparentId?: stringx?: numbery?: numberwidth?: numberheight?: numberrotation?: numbercornerRadius?: numberfillHex?: stringfillOpacity?: numberstrokeHex?: stringstrokeOpacity?: numberstrokeWeight?: numberfileKey?: stringcreate_shape_with_text changesshapeType?: enumname?: stringparentId?: stringcharacters?: stringfontFamily?: stringfontStyle?: stringfontSize?: numberx?: numbery?: numberwidth?: numberheight?: numberrotation?: numberfillHex?: stringfillOpacity?: numberstrokeHex?: stringstrokeOpacity?: numberstrokeWeight?: numbertextFillHex?: stringtextFillOpacity?: numberfileKey?: stringcreate_image changessource: stringname?: stringparentId?: stringx?: numbery?: numberwidth?: numberheight?: numbercornerRadius?: numberscaleMode?: enumfileKey?: stringcreate_svg changessource: stringname?: stringparentId?: stringx?: numbery?: numberwidth?: numberheight?: numberfileKey?: stringimport_html_layers changessource: stringname?: stringparentId?: stringx?: numbery?: numberfileKey?: stringcreate_sticky changesname?: stringparentId?: stringcharacters?: stringx?: numbery?: numberisWideWidth?: booleanfileKey?: stringcreate_connector changesname?: stringparentId?: stringstartNodeId?: stringendNodeId?: stringstartX?: numberstartY?: numberendX?: numberendY?: numberstartAnchor?: enumendAnchor?: enumstrokeWeight?: numberstrokeHex?: stringfileKey?: stringduplicate_nodes changesnodeIds: arrayfileKey?: stringduplicate_with_offset changesnodeIds: arrayoffsetX: numberoffsetY: numberfileKey?: stringfit_to_content changesnodeId: stringpadding?: numberfileKey?: stringdistribute_horizontally changesnodeIds: arrayfileKey?: stringdistribute_vertically changesnodeIds: arrayfileKey?: stringalign_to_grid changesnodeIds: arraygridSize: numberfileKey?: stringplace_below changesnodeId: stringrelativeToId: stringgap?: numberalign?: enumfileKey?: stringplace_right_of changesnodeId: stringrelativeToId: stringgap?: numberalign?: enumfileKey?: stringreparent_nodes changesnodeIds: arrayparentId: stringfileKey?: stringgroup_nodes changesnodeIds: arrayparentId?: stringname?: stringfileKey?: stringungroup_node changesnodeId: stringfileKey?: stringset_selection changesnodeIds: arrayfileKey?: stringscroll_and_zoom_into_view changesnodeIds: arrayfileKey?: stringdelete_nodes deletesnodeIds: arrayconfirm: booleanfileKey?: stringrun_script deletescode: stringallowRemove?: booleanfileKey?: stringget_motion_stylesfileKey?: stringget_node_motionnodeId: stringfileKey?: stringapply_animation_style changesnodeId: stringstyleId: stringanimationStyleData?: objectfileKey?: stringremove_animation_style changesnodeId: stringanimationStyleId?: stringfileKey?: stringapply_manual_keyframe_track changesnodeId: stringfield: objecttrack: objectfileKey?: stringremove_manual_keyframe_track changesnodeId: stringfield: objectfileKey?: stringset_timeline_duration changesnodeId: stringtimelineId: stringduration: numberfileKey?: stringsave_screenshots changesitems: arrayformat?: enumscale?: numberclip?: booleanfileKey?: string