Skip to main content
Glama
wenym8

figmingo-mcp

by wenym8
README.md
# figmingo-mcp

[![npm version](https://img.shields.io/npm/v/figmingo-mcp.svg)](https://www.npmjs.com/package/figmingo-mcp)
[![node](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
[![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![tests](https://img.shields.io/badge/tests-178%20passed-brightgreen.svg)](#development)
[![MCP](https://img.shields.io/badge/MCP-stdio%20%2B%20streamable%20http-purple.svg)](https://modelcontextprotocol.io)

**Local-first Figma MCP server.** Full read-side parity with the official Figma
MCP on **free** Figma plans (Personal Access Token + public REST API — no seat
quotas, no monthly caps), HTML 1:1 replica tooling with built-in three-gate
acceptance, and write-to-canvas through a companion plugin bridge.

[中文文档 →](#中文文档)

## Architecture

```mermaid
flowchart LR
    subgraph clients["AI clients"]
        A["Cursor · Claude Code · Claude Desktop<br/>VS Code · Kimi CLI · Codex"]
    end
    A -- "stdio / Streamable HTTP" --> B["figmingo-mcp<br/>local server"]
    B -- "REST + Personal Access Token" --> C[("Figma REST API<br/>(free plan OK)")]
    B <-- "WebSocket ws://127.0.0.1:39220" --> D["companion plugin<br/>(Figma desktop)"]
    D -- "Plugin API writes" --> E[("Your canvas")]
    B --- F[("disk cache<br/>docs 15 min · renders 30 days")]

    style B fill:#6e56cf,color:#fff
    style D fill:#0d9e6e,color:#fff
```

Everything runs on **your machine**: no relay servers, no accounts besides your
own Figma PAT, no data leaves localhost except calls to `api.figma.com`.

## Why figmingo?

| Capability | Official Figma MCP | Framelink (figma-developer-mcp) | figmingo-mcp |
|---|---|---|---|
| Free-plan read quota | ~6 calls/month (Dev seat for more) | unlimited (REST + PAT) | **unlimited (REST + PAT)** |
| Simplified design context | ✅ | ✅ | ✅ (+ absolute bounds, auto-layout, effects) |
| Metadata tree (XML/JSON) | ✅ | partial | ✅ |
| Screenshots (node → png/jpg/svg/pdf) | ✅ | ❌ | ✅ |
| Asset download (nodes + raw image fills) | ✅ | partial | ✅ + manifest |
| Variables / design tokens | ✅ (Enterprise API) | ❌ | ✅ with free-plan fallback (styles + inferred, `source` marked) |
| Design-system search | ✅ | ❌ | ✅ local index |
| Code Connect map | ✅ (server-side) | ❌ | ✅ local `figmingo.components.json` |
| whoami / rate-limit / cache status | ❌ | ❌ | ✅ |
| HTML 1:1 replica spec | ❌ | ❌ | ✅ |
| Playwright HTML screenshots | ❌ | ❌ | ✅ |
| Three-gate parity verifier (content/structural/visual) | ❌ | ❌ | ✅ |
| Write to canvas | ❌ | ❌ | ✅ companion plugin bridge |
| Disk cache (TTL) | ❌ | ❌ | ✅ 15 min docs / 30 days renders |

## Install

One command (macOS / Linux):

```bash
curl -fsSL https://raw.githubusercontent.com/wenym8/figmingo-mcp/main/scripts/install.sh | bash
```

Windows (PowerShell):

```powershell
iwr -useb https://raw.githubusercontent.com/wenym8/figmingo-mcp/main/scripts/install.ps1 | iex
```

The installer checks Node ≥ 18, installs the package, installs the Playwright
Chromium browser (~170MB, one-time — required by the HTML render/extract/compare
tools), writes MCP config into
**Cursor** (`~/.cursor/mcp.json`), **Claude Code** (`~/.claude.json`),
**Claude Desktop**, **VS Code**, **Kimi CLI** (`~/.kimi/mcp.json`), and
**Codex CLI** (`~/.codex/config.toml`, TOML — only the
`[mcp_servers.figmingo]` section is touched; the original is backed up to
`config.toml.figmingo-bak`), copies the companion plugin (manifest + code.js +
ui.html) to `~/.figmingo/plugin` **plus a `figmingo-plugin` shortcut on your
Desktop** (so Figma's *Import plugin from manifest…* file picker is one click,
no hidden-folder hunting), and prints next steps. Re-running is
idempotent and never wipes a previously configured Figma token.

After installing, run `figmingo-mcp doctor` to verify the whole environment
(Node, Figma token validity, Chromium, plugin files + version drift, client
config entries, bridge port) — every check prints a ✓/✗ with a fix hint, and
the exit code is 0 only when all checks pass.

Manual setup (any client):

```json
{
  "mcpServers": {
    "figmingo": {
      "command": "npx",
      "args": ["-y", "figmingo-mcp"],
      "env": { "FIGMA_API_KEY": "figd_..." }
    }
  }
}
```

- **Kimi CLI** — same JSON shape in `~/.kimi/mcp.json` (merge into `mcpServers`).
- **Codex CLI** — TOML in `~/.codex/config.toml`:

  ```toml
  [mcp_servers.figmingo]
  command = "figmingo-mcp"
  args = []

  [mcp_servers.figmingo.env]
  FIGMA_API_KEY = "figd_..."
  ```

  (omit the `[mcp_servers.figmingo.env]` table if you configure the token
  another way; use `command = "npx"`, `args = ["-y", "figmingo-mcp"]` for a
  zero-install run)

Get a Personal Access Token: **Figma → Settings → Security → Personal access
tokens → Generate new token** (read scopes are enough for the read tools).

## Usage

```bash
figmingo-mcp                      # stdio transport (default, what AI clients use)
figmingo-mcp --http --port 3845   # Streamable HTTP at http://127.0.0.1:3845/mcp
figmingo-mcp cache-clear          # wipe ~/.figmingo/cache
figmingo-mcp --help
```

Flags: `--token <pat>` · `--http` · `--port <n>` · `--bridge-port <n>` ·
`--no-bridge` · `--cache-ttl <min>` · `--cache-root <path>` · `--no-cache`.

## Tools (15)

### Read tools (REST + PAT, free plan OK)

| Tool | What it does |
|---|---|
| `whoami` | Token sanity check (`GET /v1/me`) + rate-limit observations + cache status. |
| `get_design_context` | Simplified node tree: absolute bounds, auto-layout, fills/strokes/effects, text styles. Params: `fileKey`/`url`, `nodeId`, `depth`, `format: json\|compact`. |
| `get_metadata` | Lightweight tree (id/name/type/bounds) as XML (default) or JSON — orient before deep fetches. |
| `get_screenshot` | Node → image via `GET /v1/images/:fileKey`. `scale 0.01–4`, `format png\|jpg\|svg\|pdf`, inline base64 and/or `savePath`. |
| `download_assets` | Batch-export up to N nodes + raw image fills (`GET /v1/files/:key/images`) into a directory; returns a manifest. |
| `get_variable_defs` | Tries `GET /v1/files/:key/variables/local`; on 403 (non-Enterprise) falls back to `GET /v1/files/:key/styles` + tokens inferred from node styles. Output marks `source`. |
| `search_design_system` | Local index over the file's components / component sets / styles; text query + type filter. |
| `get_code_connect_map` | Reads `figmingo.components.json` (user-maintained component→code mapping) and matches a node subtree. |

Every read tool accepts either `fileKey` or a full `url` (the `node-id` query
param is honored).

### Replica tools (the differentiator)

| Tool | What it does |
|---|---|
| `get_html_replica_spec` | Replica-optimized document: sections/elements with **absolute rects**, computed typography (family/style/size/letter-spacing/line-height/text-case), hex+alpha colors, gradient data, and an asset manifest (icons→SVG, image fills→URLs, logo/icon hints via configurable patterns). Writes `<outPath>` and returns a summary. |
| `render_html_screenshot` | Playwright (chromium) screenshot of a URL / local HTML file / raw HTML string; waits for images, optional `hideFixed`, `selector` element captures, full-page default. |
| `verify_html_parity` | The acceptance gate. Renders the HTML, extracts its layout, then runs three gates against the Figma spec: **content** (copy/font/color), **structural** (±4 px position/size), **visual** (pixelmatch diff ratio ≤ 1 %, 2 px crop tolerance). Emits `report.json` + diff images. |
| `compare_html_to_image` | One-shot visual diff: renders the HTML (same Playwright options as `render_html_screenshot`) and pixel-diffs it against any reference image (e.g. a Figma export). `passed = diffRatio <= maxRatio` (default 0.01 = 1 %; raise `maxRatio` for rework/triage loops). Returns diff ratio, anti-alias accounting (`methodology`), and **per-band diff localization** — equal-height `bands: N` or custom `bandEdges: [y…]` (edges win when both are given) so one band can map to one design element. `outDiffPath` saves the red diff PNG, `outRenderPath` saves the render PNG itself. Eliminates the render → hand-written diff script two-step. |

`compare_html_to_image` methodology (also returned in every response):

- **per-pixel threshold**: pixelmatch `threshold` (default `0.1`) decides whether two pixels count as different.
- **anti-alias accounting**: pixelmatch flags anti-aliased pixels; the primary `diffPixels`/`diffRatio` count **excludes** them (`antiAliasCountedInDiff: false`). `antiAliasPixels` is reported separately (derived from a second `includeAA` run) so you can tell "text-edge jitter" apart from real mismatches.
- **pass line**: `passed = diffRatio <= maxRatio`, default `0.01` (1 %). Sizes must match within a 2 px crop tolerance or the call returns `size_mismatch`.

The output schema of `get_html_replica_spec` **is** the input schema of
`verify_html_parity` (`specPath` or inline `spec`) — the closed loop.

Tolerances (ported from production-proven internal tooling):

```
POS_TOL = 4        FONT_SIZE_TOL = 1      LS_TOL = 0.5
LH_TOL  = 2        COLOR_TOL     = 2/255  VISUAL_MAX_RATIO = 0.01 (crop ≤ 2px)
```

Everything brand-specific is parameterized via options:
`skipSections`, `sectionMap`, `expectedCounts` (`{logos, assets, minIcons}`),
`looseRectHints`, `logoPattern`/`iconPattern`, font aliases/overrides.

### Write tools (companion plugin bridge)

| Tool | What it does |
|---|---|
| `bridge_status` | Plugin connected? queue size, client info, supported commands. |
| `execute_plugin_command` | Generic envelope: `create_frame`, `create_text`, `create_rectangle`, `set_fills`, `set_effects`, `set_auto_layout`, `insert_image`, `move_node`, `resize_node`, `delete_node`, `get_selection`, `get_file_info`, `get_page_children`, `export_node` — plus `commands: [...]` batches (sequential, `$var` node-id refs). Queued (bounded) while disconnected; heartbeat-based timeouts (see below). `create_frame`/`create_rectangle` accept `rotation` (degrees); `export_node` accepts `params.outPath` to save bytes to disk. |
| `import_html_replica` | High-level: rebuild a replica spec as native Figma frames — main frame → section frames → nested containers / text / image nodes. Give it an HTML file (`htmlPath`) or URL (`htmlUrl`) and it extracts layout + computed styles with headless Chromium first (border-radius, borders, shadows, gradients, webfonts, real image bytes), or pass a ready-made spec (`spec`/`specPath`). `x`/`y` set the main frame landing spot; `dryRun` previews the command plan; degradations (missing fonts, SVG assets, failed images) come back in `warnings`. |

The companion plugin (`plugin/`) connects to the MCP server at
`ws://127.0.0.1:39220`. Import once: **Figma desktop → Plugins → Development →
Import plugin from manifest…** → pick **`figmingo-plugin/manifest.json` on your
Desktop** (a shortcut the installer drops there; the canonical copy is
`~/.figmingo/plugin/manifest.json`, or `plugin/manifest.json` in this repo),
then keep it running. Works on free plans — writes never touch the REST quota.

Architecture note: Figma's plugin sandbox (`code.js`) cannot open WebSockets,
so the socket lives in the plugin's **UI iframe** (`ui.html`) and command
envelopes are relayed between the iframe and the sandbox via `postMessage`
(same architecture as proven local plugins like figwright). The UI shows a
small status panel (● connected / ○ connecting / ✕ failed + reason, server
address, executed-command count) so you can tell at a glance the bridge is
alive. In practice the plugin only talks to your local server; image bytes are
pushed over the socket as base64.

**Batch semantics (`commands: [...]`)**: the plugin executes commands
sequentially and sends a `progress` heartbeat over the socket after **every**
command (success or failure). On the server there is no fixed 30 s hard cap:

- **Idle timeout** (`idleTimeoutMs`, default 20 000): max silence between
  heartbeats/result. Every heartbeat resets it, so a healthy 50-command batch
  never trips it no matter how long it runs.
- **Total cap** (`timeoutMs`, default 300 000 = 5 min): the only hard limit,
  and it's yours to set per call.
- **Partial results**: a batch result always carries a per-command `results`
  array (`{index, command, ok, result|error}`) plus `aborted`/`error` when
  `stopOnError` (default true) cut it short — you see exactly what ran.
- **Timeout errors are atomic-friendly**: if a call still times out, the error
  message lists the command indexes **confirmed applied** via heartbeats
  (e.g. `Confirmed completed command indexes: [0, 1, 2] (3/19)`), so you know
  precisely what the canvas contains before retrying; the plugin may continue
  in the background, so inspect the page (`get_page_children`) first.

Single (non-batch) commands use the same idle/total model.

## Replica Playbook

The closed loop, end to end:

```mermaid
flowchart LR
    F["Figma design<br/>(or any reference)"] -- "get_html_replica_spec" --> S["replica spec<br/>(absolute rects, computed<br/>typography, asset manifest)"]
    S --> H["HTML / CSS"]
    H -- "render_html_screenshot" --> R["Chromium render"]
    R -- "verify_html_parity · compare_html_to_image" --> G{"three gates<br/>content · structural ±4px · visual ≤ 1%"}
    G -- "per-band diff localization" --> H
    G -- "passed" --> I["import_html_replica"]
    I -- "plugin bridge · deterministic (MD5-verified)" --> C["native Figma frames"]

    style G fill:#b7791f,color:#fff
    style C fill:#0d9e6e,color:#fff
```

Doing an HTML replica of a Figma design (or any reference screenshot)? Read
[docs/REPLICA-PLAYBOOK.md](docs/REPLICA-PLAYBOOK.md) first — the 6-step battle
flow distilled from six scored replica rounds (measure-before-CSS, font lock-in,
bandEdges-driven iteration, single-variable changes, convergence criteria), diff
image reading, tool cheat sheet, and the copy-proofing checklist. It exists so
your next replica converges in 3–4 rounds instead of 7.

## Free-plan availability

| Surface | Free plan |
|---|---|
| All read tools | ✅ PAT + public REST; per-minute rate limits only (auto-backoff on 429) |
| `get_variable_defs` | ✅ via fallback (`source: styles+inferred`); raw `variables/local` is Enterprise-only and returns 403 |
| Write tools | ✅ plugin API has no plan gating |
| MCP client support | ✅ any MCP-capable client (the official Figma desktop MCP is plan-gated; this server is not) |

## Acceptance (验收)

Battle-tested on six scored replica challenges (independent judge agents,
re-measured from scratch — no self-reported numbers):

| Challenge | Score | Pixel diff | Notes |
|---|---|---|---|
| C1 Korean travel infographic | 91 | 2.46 % | PASS |
| C2 Baidu homepage | 93 | 1.96 % | PASS |
| C3 Kimi settings modal | 93 | 0.51 % | PASS |
| C4 FAQ accordion (3 states) | 93 | 0.46–0.58 % | PASS |
| C5 Music player (image → HTML → Figma) | 92 | 0.87 % | PASS, 30-node MD5-deterministic import |
| C6 SaaS landing page (1440×4148, 7 sections) | 84 | 0.58 % | PASS, 279-node one-shot import, zero manual patches, MD5-verified reproducible |

```bash
npm install
npm run build
npm test            # 178 unit tests (vitest) with recorded fixtures

# live acceptance against the real API:
FIGMA_API_KEY=<pat> TEST_FILE_KEY=<file-key> [TEST_NODE_ID=1:2] npm run accept
```

`npm run accept` walks every tool and prints a ✅ / ⏭️ / ❌ checklist. It exits
gracefully with guidance when the token/file key is missing; write tools report
**SKIP** (not FAIL) when the companion plugin isn't connected.

## Development

```bash
npm run build         # tsup (dist/) + tsc (plugin/code.js)
npm run typecheck     # strict tsc --noEmit
npm test              # vitest
npm run accept        # live acceptance checklist
```

Repo layout: see [ARCHITECTURE.md](ARCHITECTURE.md) — it is the authoritative
spec for the tool list, REST facts, caching, bridge protocol, and the
acceptance plan.

## License

[MIT](LICENSE)

---

## 中文文档

**本地优先的 Figma MCP 服务器**:免费 Figma 套餐也能跑全部读取能力(Personal Access Token + 公开 REST API,无席位配额、无月度上限);HTML 1:1 复刻工具链(内置三关验收);通过伴侣插件桥把内容写回画布。

### 架构

```mermaid
flowchart LR
    subgraph clients["AI 客户端"]
        A["Cursor · Claude Code · Claude Desktop<br/>VS Code · Kimi CLI · Codex"]
    end
    A -- "stdio / Streamable HTTP" --> B["figmingo-mcp<br/>本地服务器"]
    B -- "REST + Personal Access Token" --> C[("Figma REST API<br/>(免费套餐可用)")]
    B <-- "WebSocket ws://127.0.0.1:39220" --> D["伴侣插件<br/>(Figma 桌面端)"]
    D -- "Plugin API 写入" --> E[("你的画布")]
    B --- F[("磁盘缓存<br/>文档 15 分钟 · 渲染图 30 天")]

    style B fill:#6e56cf,color:#fff
    style D fill:#0d9e6e,color:#fff
```

一切都在**你自己的机器**上运行:没有中转服务器,除了调用 `api.figma.com`,数据不出本机。

### 与其他方案对比

| 能力 | 官方 Figma MCP | Framelink (figma-developer-mcp) | figmingo-mcp |
|---|---|---|---|
| 免费套餐读取配额 | 约 6 次/月(更多需 Dev 席位) | 无限(REST + PAT) | **无限(REST + PAT)** |
| 精简设计上下文 | ✅ | ✅ | ✅(+ 绝对坐标、auto-layout、效果) |
| 元数据树(XML/JSON) | ✅ | 部分 | ✅ |
| 截图(节点 → png/jpg/svg/pdf) | ✅ | ❌ | ✅ |
| 资产下载(节点 + 原始图片填充) | ✅ | 部分 | ✅ + 清单 |
| Variables / 设计 tokens | ✅(Enterprise API) | ❌ | ✅ 免费套餐降级方案(styles + 推导,标 `source`) |
| 设计系统搜索 | ✅ | ❌ | ✅ 本地索引 |
| Code Connect 映射 | ✅(服务端) | ❌ | ✅ 本地 `figmingo.components.json` |
| whoami / 限流 / 缓存状态 | ❌ | ❌ | ✅ |
| HTML 1:1 复刻 spec | ❌ | ❌ | ✅ |
| Playwright HTML 截图 | ❌ | ❌ | ✅ |
| 三关验收(内容/结构/视觉) | ❌ | ❌ | ✅ |
| 写回画布 | ❌ | ❌ | ✅ 伴侣插件桥 |
| 磁盘缓存(TTL) | ❌ | ❌ | ✅ 文档 15 分钟 / 渲染图 30 天 |

### 安装

一条命令(macOS / Linux):

```bash
curl -fsSL https://raw.githubusercontent.com/wenym8/figmingo-mcp/main/scripts/install.sh | bash
```

Windows(PowerShell):

```powershell
iwr -useb https://raw.githubusercontent.com/wenym8/figmingo-mcp/main/scripts/install.ps1 | iex
```

安装器会:检测 Node ≥ 18 → 全局安装包 → 安装 Playwright Chromium(约 170MB,一次性,HTML 渲染/提取/对比工具需要)→ 写入 **Cursor**(`~/.cursor/mcp.json`)、**Claude Code**(`~/.claude.json`)、**Claude Desktop**、**VS Code**、**Kimi CLI**(`~/.kimi/mcp.json`)、**Codex CLI**(`~/.codex/config.toml`,TOML,只改 `[mcp_servers.figmingo]` 段,原文件备份为 `config.toml.figmingo-bak`)的 MCP 配置 → 把伴侣插件(manifest + code.js + ui.html)复制到 `~/.figmingo/plugin`,**并在桌面放一个 `figmingo-plugin` 快捷方式**(Figma 导入对话框里一点即中,不用翻隐藏文件夹)→ 打印后续指引。重复运行幂等,不会清掉已配置的 Figma token。

装完运行 `figmingo-mcp doctor` 自检整个环境(Node、token 有效性、Chromium、插件文件与版本漂移、客户端配置项、桥端口)——每项打印 ✓/✗ 并附修复提示,全部通过时退出码才为 0。

手动配置(任意客户端):

```json
{
  "mcpServers": {
    "figmingo": {
      "command": "npx",
      "args": ["-y", "figmingo-mcp"],
      "env": { "FIGMA_API_KEY": "figd_..." }
    }
  }
}
```

获取 PAT:**Figma → 设置 → 安全 → Personal access tokens → 生成新 token**(读工具只需读权限)。

### 用法

```bash
figmingo-mcp                      # stdio 传输(默认,AI 客户端用这个)
figmingo-mcp --http --port 3845   # Streamable HTTP:http://127.0.0.1:3845/mcp
figmingo-mcp cache-clear          # 清空 ~/.figmingo/cache
figmingo-mcp doctor               # 环境自检
figmingo-mcp --help
```

### 15 个工具

**读取工具(REST + PAT,免费套餐可用)**:`whoami`(token 自检 + 限流/缓存状态)· `get_design_context`(精简节点树:绝对坐标、auto-layout、填充/描边/效果、文字样式)· `get_metadata`(轻量树,XML/JSON,深取前先定位)· `get_screenshot`(节点渲染图,scale 0.01–4,png/jpg/svg/pdf)· `download_assets`(批量导出节点 + 原始图片填充,带清单)· `get_variable_defs`(variables 接口 403 时降级 styles + 推导 tokens,标 `source`)· `search_design_system`(本地索引查组件/样式)· `get_code_connect_map`(组件→代码映射)。

所有读取工具都接受 `fileKey` 或完整 `url`(自动解析 `node-id`)。

**复刻工具(差异化能力)**:`get_html_replica_spec`(复刻专用文档:绝对矩形、计算后的字体排版、hex+alpha 颜色、渐变、资产清单)· `render_html_screenshot`(Playwright 截图 URL/本地 HTML/HTML 字符串)· `verify_html_parity`(验收闸门:内容关文案/字体/颜色、结构关 ±4px、视觉关像素 diff ≤ 1%,产出 `report.json` + diff 图)· `compare_html_to_image`(一键视觉 diff,bands 分带定位差异,AA 像素单独记账)。

容差(生产验证过的内部工具移植):

```
POS_TOL = 4        FONT_SIZE_TOL = 1      LS_TOL = 0.5
LH_TOL  = 2        COLOR_TOL     = 2/255  VISUAL_MAX_RATIO = 0.01(裁切 ≤ 2px)
```

**写入工具(伴侣插件桥)**:`bridge_status`(桥连接状态)· `execute_plugin_command`(14 种命令 + `commands: [...]` 批次,顺序执行,`$var` 节点引用,心跳超时机制)· `import_html_replica`(HTML 文件/URL 一键直导为原生 Figma frames,Chromium 提取布局与计算样式,`dryRun` 预览,降级进 `warnings`)。

插件连接 `ws://127.0.0.1:39220`。导入一次:**Figma 桌面端 → 插件 → 开发 → Import plugin from manifest…** → 选**桌面上的 `figmingo-plugin/manifest.json`**(安装器放的快捷方式;本体在 `~/.figmingo/plugin/manifest.json`),保持运行即可。免费套餐可用——写入不占用 REST 配额。

架构说明:Figma 插件沙箱(code.js)无法开 WebSocket,所以连接由插件的 **UI iframe**(ui.html)持有,命令经 `postMessage` 在 iframe 与沙箱间转发。UI 有状态面板(● 已连接 / ○ 连接中 / ✕ 失败原因、服务器地址、已执行命令数)。

**批次语义**:插件顺序执行,每条命令(无论成败)后都发 `progress` 心跳。服务器没有 30s 硬顶:**空闲超时**(`idleTimeoutMs`,默认 20s,心跳即重置)+ **总上限**(`timeoutMs`,默认 5 分钟,可每次调用自设)。批次结果带逐命令 `results` 数组;超时错误会列出**已确认落画布的命令索引**,重试前先用 `get_page_children` 看画布现状。

### 复刻闭环

```mermaid
flowchart LR
    F["Figma 设计稿<br/>(或任意参考图)"] -- "get_html_replica_spec" --> S["复刻 spec<br/>(绝对矩形、计算排版、<br/>资产清单)"]
    S --> H["HTML / CSS"]
    H -- "render_html_screenshot" --> R["Chromium 渲染"]
    R -- "verify_html_parity · compare_html_to_image" --> G{"三关验收<br/>内容 · 结构 ±4px · 视觉 ≤ 1%"}
    G -- "bands 分带定位差异" --> H
    G -- "通过" --> I["import_html_replica"]
    I -- "插件桥 · 确定性(MD5 验证)" --> C["原生 Figma frames"]

    style G fill:#b7791f,color:#fff
    style C fill:#0d9e6e,color:#fff
```

做 HTML 复刻先读 [docs/REPLICA-PLAYBOOK.md](docs/REPLICA-PLAYBOOK.md)——六轮带评分实战沉淀的 6 步流程(先量后写 CSS、字体锁定、bandEdges 驱动迭代、单变量改动、收敛判据)、diff 图读法、工具速查表、防抄漏清单。让你的下一次复刻 3–4 轮收敛,而不是 7 轮。

### 免费套餐可用性

| 能力 | 免费套餐 |
|---|---|
| 全部读取工具 | ✅ PAT + 公开 REST;仅有每分钟限流(429 自动退避) |
| `get_variable_defs` | ✅ 降级方案(`source: styles+inferred`);原始 variables 接口是 Enterprise 限定,返回 403 |
| 写入工具 | ✅ 插件 API 无套餐门槛 |
| MCP 客户端 | ✅ 任意支持 MCP 的客户端(官方 Figma 桌面 MCP 有套餐门槛,本服务器没有) |

### 验收

六轮带评分的复刻挑战实测(独立 judge agent 从零复测,非自报数据):

| 题目 | 分数 | 像素 diff | 备注 |
|---|---|---|---|
| C1 韩国攻略信息图 | 91 | 2.46 % | PASS |
| C2 百度首页 | 93 | 1.96 % | PASS |
| C3 Kimi 设置弹窗 | 93 | 0.51 % | PASS |
| C4 FAQ 手风琴(3 状态) | 93 | 0.46–0.58 % | PASS |
| C5 音乐播放器(图片 → HTML → Figma) | 92 | 0.87 % | PASS,30 节点导入 MD5 确定性 |
| C6 SaaS 落地页(1440×4148,7 个 section) | 84 | 0.58 % | PASS,279 节点一键直导、零手工补丁、MD5 可复现 |

```bash
npm install
npm run build
npm test            # 178 个单元测试(vitest,录制 fixtures)

# 真实 API 验收:
FIGMA_API_KEY=<pat> TEST_FILE_KEY=<file-key> [TEST_NODE_ID=1:2] npm run accept
```

`npm run accept` 逐个工具打 ✅ / ⏭️ / ❌;token/fileKey 缺失时优雅退出并给指引;插件未连接时写工具报 **SKIP**(不是 FAIL)。

### 开发

```bash
npm run build         # tsup(dist/)+ tsc(plugin/code.js)
npm run typecheck     # 严格 tsc --noEmit
npm test              # vitest
npm run accept        # 真实 API 验收清单
```

仓库结构见 [ARCHITECTURE.md](ARCHITECTURE.md)——工具清单、REST 事实、缓存、桥协议、验收方案的权威文档。

### License

[MIT](LICENSE)

TDQS

A4/5.0

Scored across 15 tools

Disambiguation5/5

Each tool targets a distinct aspect of the workflow: fetching Figma data, rendering HTML, performing comparisons, plugin control, and importing. Overlap between compare_html_to_image and verify_html_parity is minimal; the former is a simple pixel-diff while the latter is a comprehensive gate with multiple checks.

Naming Consistency4/5

Most tools follow a verb_noun pattern (e.g., get_design_context, download_assets, execute_plugin_command). However, bridge_status and whoami are noun_first or single-word, breaking the pattern slightly. Overall, names are clear and consistent.

Tool Count5/5

With 15 tools, the set is well-scoped for the domain of Figma-to-HTML comparison and design system interaction. Each tool serves a clear purpose without unnecessary duplication.

Completeness5/5

The tool surface covers the full lifecycle: extracting design data (get_design_context, get_metadata, get_variable_defs), rendering (render_html_screenshot, get_screenshot), comparison (compare_html_to_image, verify_html_parity), importing (import_html_replica, get_html_replica_spec), and plugin control (execute_plugin_command). No obvious gaps for the stated purpose.

Maintenance

ActivitySlowing
ResponsivenessNo issues