@iflow-mcp/allan-simon-figma-kiwi-protocol
v0.1.2
Published
Decode Figma's binary Kiwi wire protocol — extract scenegraph, SVG vectors, and CSS from WebSocket frames
Downloads
197
Readme
figma-kiwi-protocol
Decode Figma's binary Kiwi wire protocol. Extract the full scenegraph, SVG vectors, and CSS properties from WebSocket frames — no REST API rate limits, no paid plan required.
Ships as a lib, CLI, MCP server, and Claude Code plugin.
What this does
Figma uses Kiwi (a binary serialization format by Evan Wallace) over WebSocket for real-time sync between the editor and the server. When you open a Figma file in the browser, the entire scenegraph — every node, every vector path, every style — is streamed as Kiwi-encoded binary frames.
This library intercepts those frames via Chrome DevTools Protocol, decodes the binary data, and gives you structured access to everything Figma knows about your design:
- Full scenegraph as JSON (5000+ nodes for a typical file)
- SVG path extraction from Figma's proprietary
commandsBlobandvectorNetworkBlobbinary formats - CSS properties from both the decoded scenegraph and the REST API
- Component variants, prototype interactions, and state machines
- Image hash mapping to Figma's CDN URLs
Why
The Figma REST API has aggressive rate limits. The official MCP server requires a paid Dev Mode subscription. Community MCP servers hit the same REST API limits.
This tool reads the same data Figma's own editor reads — directly from the WebSocket stream. No rate limits. No paid plan. Just the raw protocol.
Architecture
lib/ Pure functions — buffer in, data out. No I/O, no side effects.
├── kiwi.mjs fig-wire frame detection and schema extraction
├── scenegraph.mjs decode, merge, and query scenegraph data
├── svg.mjs commandsBlob / vectorNetworkBlob → SVG paths
├── css.mjs node properties → CSS (Kiwi + REST API formats)
└── index.mjs re-exports everything
bin/ CLI tools — CDP capture, file I/O, orchestration.
├── cli.mjs entry point
├── capture.mjs single page WebSocket capture
├── capture-all-pages.mjs multi-page capture (auto-discovers pages)
├── decode.mjs binary → JSON scenegraph
└── extract-svgs.mjs vector nodes → individual SVG filesThe lib has zero dependencies and zero I/O. It takes Uint8Array buffers and returns objects. You can use it in an MCP server, a Figma plugin, a build tool, or anything else.
The CLI tools handle the messy parts: Chrome DevTools Protocol, file system, zstd decompression, Kiwi decoder generation.
Quick start
npm install figma-kiwi-protocol
# 1. Open your Figma file in Chrome with remote debugging:
# chrome --remote-debugging-port=9222
# 2. Set environment variables:
export CDP_WS_URL="ws://localhost:9222/devtools/browser/<id>"
export FIGMA_TOKEN="figd_..." # for page discovery
export FIGMA_FILE_KEY="abc123def" # from your Figma URL
# 3. Capture all pages:
npx figma-kiwi-protocol capture-all-pages
# 4. Decode into JSON:
npx figma-kiwi-protocol decode
# 5. Extract SVGs:
npx figma-kiwi-protocol extract-svgsLibrary usage
import {
commandsBlobToPath,
vectorNetworkBlobToPath,
extractSvgs,
extractCSSFromKiwi,
isFigWireFrame,
extractCompressedSchema,
mergePages,
buildTree,
} from 'figma-kiwi-protocol';
// Decode a commandsBlob to SVG path
const svgPath = commandsBlobToPath(blobBytes);
// → "M 0.00 0.00 L 24.00 0.00 L 24.00 24.00 Z"
// Extract CSS from a decoded node
const css = extractCSSFromKiwi(nodeChange);
// → { width: "100px", display: "flex", background: "#1a1a1a", ... }
// Check if a binary frame contains the Kiwi schema
if (isFigWireFrame(frameBytes)) {
const compressedSchema = extractCompressedSchema(frameBytes);
// decompress with fzstd, then generate decoder with kiwi CLI
}Binary formats documented
Machine-readable Kaitai Struct specifications (.ksy) are in kaitai/ — you can generate parsers in any language or visualize binary data in the Kaitai Web IDE.
fig-wire frame
Offset Size Description
0 8 Magic: "fig-wire" (ASCII)
8 4 Version (uint32 LE)
12 ... zstd-compressed Kiwi schema (~558 types)commandsBlob (pre-computed SVG paths)
Byte Command Parameters
0x01 MoveTo x(f32) y(f32)
0x02 LineTo x(f32) y(f32)
0x03 ClosePath (none)
0x04 CubicBezier x1(f32) y1(f32) x2(f32) y2(f32) x(f32) y(f32)
0x00 (separator) subpath boundaryvectorNetworkBlob (editable path data)
Header: vertexCount(u32) segmentCount(u32) regionCount(u32)
Per vertex (12 bytes):
flags(u32) x(f32) y(f32)
Per segment (28 bytes):
flags(u32) startVertexIdx(u32) tangentStartX(f32) tangentStartY(f32)
endVertexIdx(u32) tangentEndX(f32) tangentEndY(f32)Legal
This tool exercises the right to reverse-engineer for interoperability, as provided by:
- EU Directive 2009/24/EC, Article 6 — permits decompilation and reverse-engineering of software for interoperability purposes, without authorization from the rightholder
- French Code de la propriété intellectuelle, Article L122-6-1 IV — French transposition of the above
Contractual clauses (such as Terms of Service) that restrict this statutory right are void under EU law.
This project contains no Figma proprietary code. It only decodes the wire format of data transmitted to the user's own browser.
Not affiliated with Figma, Inc.
MCP server
Expose Figma scenegraph tools to any MCP-compatible AI tool (Claude Code, Cursor, Windsurf, VS Code).
Configure
Add to .mcp.json or ~/.claude/settings.json:
{
"mcpServers": {
"figma": {
"command": "node",
"args": ["/path/to/figma-kiwi-protocol/mcp/server.mjs"],
"env": {
"FIGMA_KIWI_DIR": "/tmp/figma_kiwi"
}
}
}
}Tools exposed
| Tool | Description |
|------|-------------|
| figma_pages | List all pages |
| figma_page | Show page tree at configurable depth |
| figma_node | Inspect node with CSS and tree |
| figma_search | Search nodes by name |
| figma_css | Extract CSS properties |
| figma_texts | Extract all text from a page |
| figma_components | List components and variants |
Requires a decoded scenegraph — run figma-kiwi-protocol capture-all-pages then decode first.
Claude Code plugin
This repo ships as an installable Claude Code plugin with a skill that lets Claude explore Figma designs directly.
Install
# Test locally
claude --plugin-dir /path/to/figma-kiwi-protocol
# Or install from GitHub
/plugin marketplace add allan-simon/figma-kiwi-protocol
/plugin install figma-kiwi-protocolUse
The skill is auto-invoked by Claude when you ask about Figma designs. Just give Claude a Figma URL or ask it to explore a design — it will use the skill automatically.
Claude will have access to all capture, decode, and query commands.
Known limitations / TODO
SVG extraction
- Composite icons: Icon SYMBOLs with child VECTOR nodes need transform composition (parent + children → one SVG). Currently each VECTOR is extracted individually.
- Transforms: Rotation/translation matrices on child nodes are not applied to SVG output yet.
- Boolean operations: BOOLEAN_OPERATION nodes (union, subtract, intersect) are not handled — these combine child paths.
- Computed shapes: ROUNDED_RECTANGLE, ELLIPSE, STAR, REGULAR_POLYGON don't have
commandsBlob— their geometry is computed from parameters. Need to generate SVG paths from cornerRadius, point count, etc. - Image fills:
type: IMAGEreferences SHA1 hashes, not vector data. Use the image batch endpoint to resolve URLs.
Scenegraph
- Prototype interactions: Decoded but not yet exposed in the MCP server or lib API.
- Component property overrides: Parsed (symbolOverrides, componentPropAssignments) but not exposed in query tools.
- Gradient fills: Decoded from Kiwi but CSS extraction only outputs solid colors.
Protocol
- Incremental updates: Only the initial full scenegraph load is captured. Real-time edits (subsequent smaller WS frames) are not decoded.
- Write support: Read-only — no ability to push changes back to Figma.
- Schema versioning: The Kiwi schema (~558 types) is extracted per-session. Figma may change it at any time.
Distribution
- npm publish: Not yet published to npm registry.
- Kaitai Web IDE: Sample fixture files exist but aren't hosted for direct web visualization.
License
MIT
