GitHub: stnwlls/Figmex-MCP · Contact: hello@austinwells.dev
Figmex MCP is the Figma-side companion to the Figmex MCP Bridge. Together they let Codex CLI (or any MCP-aware agent) read and manipulate the open Figma document using JSON-RPC commands.
This repository contains the plugin UI and controller code (ui.html + code.ts). The bridge lives in a separate Python package (figmex-mcp-bridge) and launches automatically from Codex CLI.
- Figma Desktop (plugins running in development mode cannot open
localhostsockets from the web app). - Node.js 18+ with npm for building the plugin.
- Python 3.10+ (comes from the bridge, installed via pip).
- Codex CLI installed and configured.
If you need Node quickly:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
nvm install --lts
nvm use --ltsRestart your shell so nvm and node are available.
git clone https://github.com/stnwlls/Figmex-MCP.git
cd Figmex-MCP
npm install
npm run buildThe compiled plugin lives in code.js, generated by npm run build. Re-run this whenever you modify the TypeScript.
In a separate terminal:
git clone https://github.com/stnwlls/Figmex-MCP-Bridge.git
cd Figmex-MCP-Bridge
python3 -m pip install --upgrade pip
python3 -m pip install -e .Later we will install the published bridge from PyPI; the editable install above is helpful during development.
The bridge is also available on PyPI as figmex-mcp-bridge. For a clean setup on a new machine run:
python3 -m pip install --user figmex-mcp-bridgeCodex CLI looks for the executable on your $PATH. If you installed with --user, ensure ~/Library/Python/3.x/bin (macOS) or the appropriate platform-specific scripts directory is on your PATH.
Add the following snippet to ~/.codex/config.toml (adjust the command path if needed):
[mcp_servers.figmex]
command = "/Users/YOU/Library/Python/3.11/bin/figmex-mcp-bridge"
args = ["serve", "--log-level", "DEBUG"]
startup_timeout_sec = 30
tool_timeout_sec = 60Restart Codex CLI and you should see the figmex MCP server start automatically. The bridge spins up a WebSocket listener on ws://127.0.0.1:8787.
- Open Figma Desktop.
- Go to Plugins → Development → Import plugin from manifest….
- Select the
manifest.jsonfile from this repository. - Launch Figmex MCP Bridge from Plugins → Development to open the control panel.
The UI will display connection status, logs, and an auto-generated command reference. You can collapse the console or minimise the panel entirely when Codex is driving the session.
Codex interacts with Figmex through two tools exposed by the bridge:
figmex.list_figma_commands— returns available command names and metadata.figmex.describe_figma_commands— full documentation payload, mirrored from the plugin.figmex.invoke_figma_command— executes a specific command. Pass either:{"command": "create-rectangle", "args": {...}}, or{"command": "create-rectangle", "params": {...}}, or- just the string
"create-rectangle"when no arguments are needed.
When Codex calls get-selection it simply returns whatever is currently selected. If the agent needs to operate on specific nodes it can call set-selection first (or create-* commands and then keep track of the IDs returned). There is no requirement for the human operator to pre-select items, but be aware that get-selection will return an empty array if nothing is highlighted.
| Command | Description | Key Arguments / Notes |
|---|---|---|
ping |
Health check returning { ok: true, timestamp }. |
– |
get-document |
Serialises the entire document graph (all pages and nodes). | – |
get-current-page |
Returns the active page and its immediate children. | – |
get-selection |
Returns the current selection array (empty if nothing selected). | Use set-selection first to guarantee a selection. |
get-node |
Reads a node by ID. | id (string, required) |
get-layout-summary |
Returns geometry metadata for pages/frames and the recommended next placement position. | Use this before laying out new elements to understand spacing/alignment. |
create-rectangle |
Creates a rectangle on the current page. | width, height, x, y, fills, strokes, strokeWeight, parentId, name (omit x/y to auto-place with 32 px spacing) |
create-ellipse |
Creates an ellipse. | Same arguments as create-rectangle; auto-places if x/y omitted. |
create-line |
Creates a line. | width, x, y, strokes, strokeWeight, parentId, name; auto-places if x/y omitted. |
create-frame |
Creates a frame (supports auto-layout settings). | width, height, x, y, layoutMode, primaryAxisSizingMode, counterAxisSizingMode, clipsContent, parentId, name; auto-places if x/y omitted. |
create-text |
Creates a text node. | characters, x, y, fontName, fontSize, fills, textAutoResize, parentId, name; auto-places if x/y omitted. |
duplicate-node |
Duplicates a node. | id (required), parentId |
delete-node |
Deletes a node. | id (required) |
update-node |
Applies partial updates to a node. | id (required), properties (object) |
set-selection |
Sets the current selection to the provided nodes. | ids (string[] required) |
zoom-into-view |
Zooms to specific nodes or the current selection. | ids (optional string[]) |
🧭 Auto-placement: When you omit x and y, Figmex automatically parks the node in the next sensible slot (rows first, then wraps to a new row with 32 px spacing). The get-layout-summary tool reports the recommended next insertion point per container so Codex can plan before creating additional nodes.
The UI shows these definitions and any additional notes. Codex receives the same dataset via figmex.describe_figma_commands, so you can prompt the agent to consult that tool before crafting requests.
- Toggle Console hides/shows the JSON log without disconnecting.
- Minimise collapses the entire panel and resizes the window (click again to restore).
- Command definitions update live once the bridge connects; if the list is empty make sure Codex CLI has launched the bridge and the plugin log shows “Bootstrap information received”.
Spacing accuracy for complex layouts comes from the arguments you supply. For example, when creating an iPhone home screen:
- Create the device frame at the desired origin using
create-frame. - Compute icon positions in your Codex prompt (e.g. start at
(x=40, y=180)and step bygridSpacing = 20 + iconSize). - Pass explicit
x/yvalues tocreate-rectangleorcreate-framefor predictable placement. - Use
update-nodeto tweak properties orzoom-into-viewto focus the result.
| Symptom | Fix |
|---|---|
| Plugin log shows “Attempted to send on closed socket” repeatedly | Codex CLI hasn’t started the bridge yet. Keep Figmex open; it auto-retries. |
invoke_figma_command returns “Input validation error” |
Ensure you pass an object. Strings are accepted, but the bridge now normalises either args or params. |
| Commands time out | The bridge waits for the bootstrap payload. Confirm the plugin log shows “Connected” and “Bootstrap information received”. |
get-selection returns [] |
No nodes are selected. Have Codex call set-selection first, or select nodes manually in Figma. |
| Fonts fail to load | Supply fontName (family + style) when creating/updating text. The plugin will load the font automatically if available. |
Questions, bugs, or feature requests: please open an issue or email hello@austinwells.dev.
- Plugin repository: https://github.com/stnwlls/Figmex-MCP
- Bridge repository: https://github.com/stnwlls/Figmex-MCP-Bridge
Pull requests that improve the command surface or docs are very welcome!