figma-preview-mcp 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +217 -99
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,16 +1,58 @@
1
1
  # figma-preview-mcp
2
2
 
3
- 一个 Model Context Protocol (MCP) 服务器,可将 Figma 设计稿渲染为**高保真交互式预览**——带有节点检查器,可直接点击复制节点信息到 AI 对话中。
3
+ 一个 Model Context Protocol (MCP) 服务器,提供从 Figma 设计稿到代码还原的完整工具链——**设计稿预览、Layout AST 生成、切图导出、程序化布局验收**,一站式解决 Figma-to-Code 的全流程。
4
+
5
+ > 💡 核心理念:在 Figma 原始数据和 AI 编码之间,插入一个结构化中间层 —— **Enriched Layout AST**,将 AI "理解设计稿"的过程转变为"翻译结构化数据"的确定性任务。
4
6
 
5
7
  ---
6
8
 
7
9
  ## ✨ 功能特性
8
10
 
11
+ ### 🎨 设计稿预览 & 检查
9
12
  - 📸 **高保真预览** — 在浏览器中预览 Figma 设计稿,100% 还原视觉效果
10
13
  - 🖱️ **节点检查器** — 悬停查看节点名称,点击复制节点信息到剪贴板
11
- - 🔍 **节点详情查询** — 获取完整节点数据,包括被压缩的内联样式
12
- - 📷 **截图验证** — 截取预览页面图片,在 AI 对话中展示
13
- - 🔬 **像素级 Diff 对比** 使用 pixelmatch 进行程序化像素级对比,生成差异高亮图 + 差异百分比统计
14
+ - 🔍 **节点详情查询** — 获取完整节点数据,包括被压缩的内联样式和字符级文字样式
15
+
16
+ ### 🧠 Layout AST 生成 & 布局推断
17
+ - 🌳 **Enriched Layout AST** — 将 Figma 节点树转化为结构化布局 JSON,包含预计算的 flex 属性、样式、flags
18
+ - � **布局推断引擎** — "Figma 优先 + 坐标交叉验证"策略,从精确坐标反推 flex-direction、gap、alignment、padding
19
+ - 📦 **模块化拆分** — 大页面(60+ 节点)自动拆分为多个模块,每个模块独立 AST 文件,避免 LLM 上下文溢出
20
+ - 🏷️ **图形子树识别** — 自动标记 `isGraphicSubtree`,AI 知道哪些节点该用 `<img>` 而非 CSS 还原
21
+
22
+ ### 🖼️ 切图资源导出
23
+ - ✂️ **批量图片下载** — 支持 SVG / PNG 格式,批量导出最多 50 个节点
24
+ - 🔬 **Retina 支持** — PNG 默认 2x 导出,可配置 1-4x 缩放
25
+
26
+ ### ✅ 程序化布局验收
27
+ - 📏 **verify_layout_bounds** — 用 Puppeteer 测量开发页面实际 DOM 边界,与 Figma 精确坐标逐节点对比
28
+ - 🩺 **差异诊断系统** — 5 种诊断模式(SIBLING_SHIFT / WIDTH_OVERFLOW / ALIGNMENT_OFF / CUMULATIVE_DRIFT / MISSING),精准定位布局偏差原因
29
+ - 🔄 **验收-修复闭环** — AI 根据结构化报告自动修复,循环验收直到通过
30
+
31
+ ### 📷 截图工具
32
+ - 🖥️ **Figma API 截图** — 直接从 Figma 导出高清截图
33
+ - 🌐 **URL 截图** — 截取任意网页,支持 CSS 选择器定位特定元素
34
+
35
+ ---
36
+
37
+ ## 🏗️ 整体架构
38
+
39
+ ![整体架构图](./docs/images/article-main-architecture.svg)
40
+
41
+ ```
42
+ Figma API ──► NodeTree + AbsoluteBounds ──► BoundsCache
43
+
44
+ ┌──────────────────┼──────────────────┐
45
+ ▼ ▼ ▼
46
+ render_preview Layout Inference generate_layout_ast
47
+ (交互式预览) Engine (推断引擎) (结构化 AST)
48
+
49
+ ┌──────────────────────────┤
50
+ ▼ ▼
51
+ Module Map (拆分) verify_layout_bounds
52
+ │ (程序化验收)
53
+ ▼ │
54
+ AI 编码 ◄──── 修复循环 ◄────────┘
55
+ ```
14
56
 
15
57
  ---
16
58
 
@@ -33,8 +75,7 @@
33
75
  "command": "npx",
34
76
  "args": ["-y", "figma-preview-mcp"],
35
77
  "env": {
36
- "FIGMA_TOKEN": "figd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
37
- "PIXELMATCH_THRESHOLD": "0.2"
78
+ "FIGMA_TOKEN": "figd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
38
79
  }
39
80
  }
40
81
  }
@@ -45,137 +86,211 @@
45
86
 
46
87
  ---
47
88
 
48
- ## 🎮 使用方法
89
+ ## 🎮 MCP 工具一览
49
90
 
50
- 配置完成后,在 AI 对话中粘贴 Figma 链接:
91
+ ### `render_preview`
92
+ 渲染 Figma 设计稿的交互式预览页面,同时缓存所有节点的精确边界数据。
51
93
 
52
94
  ```
53
- 预览 https://www.figma.com/design/YOUR_FILE_KEY/MyApp?node-id=123-456
95
+ 调用 render_preview:
96
+ fileKey: "E2gHeS2vZt48DYiiQhNzkq"
97
+ nodeId: "985-14549"
54
98
  ```
55
99
 
56
- AI 会自动:
57
- 1. 解析 URL 中的 `fileKey` 和 `nodeId`
58
- 2. 直接从 Figma API 获取完整节点树(包含所有子节点)
59
- 3. 下载目标节点的高清截图
60
- 4. **http://localhost:3456** 打开交互式预览
61
-
62
- ### 节点检查器
63
-
64
- | 操作 | 效果 |
65
- |------|------|
66
- | **悬停** 任意元素 | 蓝色高亮边框 + 节点名称提示 |
67
- | **点击** 任意元素 | 橙色选中边框 + 节点信息复制到剪贴板 |
68
- | **再次点击** | 取消选中 |
100
+ | 参数 | 必需 | 说明 |
101
+ |------|------|------|
102
+ | `fileKey` | ✅ | Figma 文件 Key |
103
+ | `nodeId` | 否 | 目标节点 ID |
104
+ | `yaml` | 否 | 来自其他 MCP 的 YAML 数据(备选输入) |
69
105
 
70
- 复制的文本格式:
106
+ ### `generate_layout_ast`
107
+ 生成 Enriched Layout AST —— 包含预计算布局属性、样式和 flags 的结构化 JSON。
71
108
 
72
109
  ```
73
- 节点路径: MyPage / header / navigation-bar / back-button
74
- 节点ID: 978:14642
75
- 类型: INSTANCE
76
- fileKey: YOUR_FILE_KEY
110
+ 调用 generate_layout_ast:
111
+ fileKey: "E2gHeS2vZt48DYiiQhNzkq"
112
+ nodeId: "985-14549"
113
+ outputDir: "/project/.codemaker/figma-specs/my-page" # 可选,传入则启用模块化
114
+ splitThreshold: 60 # 可选,默认 60
77
115
  ```
78
116
 
79
- 直接粘贴到 AI 对话中即可引用该节点。
117
+ | 参数 | 必需 | 说明 |
118
+ |------|------|------|
119
+ | `fileKey` | ✅ | Figma 文件 Key |
120
+ | `nodeId` | ✅ | 根节点 ID(需先调用 render_preview) |
121
+ | `outputDir` | 否 | 模块化输出目录。传入后大页面自动拆分 |
122
+ | `splitThreshold` | 否 | 每模块最大节点数(默认 60) |
80
123
 
81
- ### 获取完整节点详情
124
+ **输出两种模式:**
125
+ - **普通模式**(≤ 阈值节点):直接返回完整 AST JSON
126
+ - **模块化模式**(> 阈值节点):输出文件到 `outputDir`,返回轻量级 Module Map
82
127
 
83
- 当需要完整节点数据(如修复内联文字样式)时,AI 会调用 `get_node_details`:
128
+ ```
129
+ outputDir/
130
+ ├── module-map.json # 模块索引(文件名、节点数、切图清单)
131
+ ├── skeleton.json # 根容器布局 + 模块占位符
132
+ ├── module-0-header.ast.json # 模块 0 完整 AST
133
+ ├── module-1-hero.ast.json # 模块 1 完整 AST
134
+ └── module-2-footer.ast.json # 模块 2 完整 AST
135
+ ```
136
+
137
+ ### `verify_layout_bounds`
138
+ 程序化布局验收:用 Puppeteer 测量开发页面 DOM 边界,与 Figma 精确坐标逐节点对比。
84
139
 
85
140
  ```
86
- 修复这个节点的样式
87
- 节点路径: MyPage / title
88
- 节点ID: 981:18766
89
- 类型: TEXT
90
- fileKey: YOUR_FILE_KEY
141
+ 调用 verify_layout_bounds:
142
+ fileKey: "E2gHeS2vZt48DYiiQhNzkq"
143
+ nodeId: "985-14549"
144
+ url: "http://localhost:5173"
145
+ threshold: 2 # 可选,像素容差,默认 2
91
146
  ```
92
147
 
93
- AI 会自动获取完整数据,包括:
94
- - `characterStyleOverrides` — 逐字符样式索引
95
- - `styleOverrideTable` 内联样式定义
96
- - `fills`、`strokes`、`effects` 完整视觉属性
97
- - 更多...
148
+ | 参数 | 必需 | 说明 |
149
+ |------|------|------|
150
+ | `fileKey` | ✅ | Figma 文件 Key |
151
+ | `nodeId` | ✅ | 根节点 ID(需先调用 render_preview) |
152
+ | `url` | ✅ | 开发页面 URL |
153
+ | `threshold` | 否 | 像素容差(默认 2px) |
98
154
 
99
- ### 截图与对比工具
155
+ **输出包含:**
156
+ - `matchRate` — 匹配率百分比
157
+ - `matched` — 匹配的节点列表
158
+ - `mismatched` — 不匹配的节点 + 偏差详情 + 诊断模式
159
+ - `missing` — 缺失的节点列表
100
160
 
101
- #### 截取预览页面
161
+ **差异诊断模式:**
102
162
 
103
- ```
104
- 截取当前预览页面的图片
105
- ```
163
+ | 模式 | 含义 |
164
+ |------|------|
165
+ | `SIBLING_SHIFT` | 同父多个兄弟节点偏移相同,前方兄弟尺寸有误 |
166
+ | `WIDTH_OVERFLOW` | 宽度溢出至父元素边界,缺少宽度约束 |
167
+ | `ALIGNMENT_OFF` | 同行/列子节点交叉轴偏移不一致,对齐属性错误 |
168
+ | `CUMULATIVE_DRIFT` | 连续子节点偏移递增,gap 或尺寸有累积偏差 |
169
+ | `MISSING` | AST 中有但 DOM 中无对应节点 |
106
170
 
107
- #### 像素级 Diff 对比
171
+ ### `get_node_details`
172
+ 获取指定节点的完整数据,包括内联样式、字符级文字样式等在预览中可能被压缩的信息。
108
173
 
109
- 使用 **pixelmatch** 进行程序化像素级对比。工作流程:
174
+ ```
175
+ 调用 get_node_details:
176
+ fileKey: "E2gHeS2vZt48DYiiQhNzkq"
177
+ nodeId: "981-18766"
178
+ depth: 1
179
+ ```
110
180
 
111
- 1. **渲染设计稿预览** — 调用 `render_preview` 获取 Figma 设计稿截图(自动返回 Base64 截图)
112
- 2. **截取开发环境截图** 使用 Chrome DevTools MCP 的 `take_screenshot` 保存开发页面为 PNG
113
- 3. **执行像素级对比** — 调用 `compare_design_implementation` 对比两张截图
181
+ ### `download_figma_images`
182
+ 批量下载图片资源(图标、插图、照片),支持 SVG PNG 格式。
114
183
 
115
184
  ```
116
- # Step 1: 渲染设计稿(figma-preview-mcp)
117
- 调用 render_preview:
118
- fileKey: <fileKey>
119
- nodeId: <nodeId>
120
- # 返回结果包含 screenshot (Base64) url,直接使用 screenshot 即可
185
+ 调用 download_figma_images:
186
+ fileKey: "E2gHeS2vZt48DYiiQhNzkq"
187
+ nodes: [
188
+ { "nodeId": "985:14560", "fileName": "icon_arrow.svg" },
189
+ { "nodeId": "985:14570", "fileName": "img_banner.png", "format": "png" }
190
+ ]
191
+ localPath: "/project/src/assets/images"
192
+ pngScale: 2
193
+ ```
121
194
 
122
- # Step 2: 截取开发页面(Chrome DevTools MCP)
123
- 调用 resize_page: { width: 375, height: 812 }
124
- 调用 take_screenshot: { filePath: /tmp/dev.png }
195
+ ### `take_preview_screenshot`
196
+ 截图工具,支持 Figma API 截图和 URL 网页截图两种模式。
125
197
 
126
- # Step 3: 像素级对比(figma-preview-mcp)
127
- 调用 compare_design_implementation:
128
- designImagePath: /tmp/design.png # 从 render_preview 的 screenshot 保存而来
129
- devImagePath: /tmp/dev.png
198
+ ```
199
+ # Figma API 模式
200
+ 调用 take_preview_screenshot:
201
+ fileKey: "E2gHeS2vZt48DYiiQhNzkq"
202
+ nodeId: "985-14549"
203
+
204
+ # URL 模式
205
+ 调用 take_preview_screenshot:
206
+ url: "http://localhost:5173"
207
+ selector: ".main-container" # 可选
130
208
  ```
131
209
 
132
- AI 会返回:
210
+ ---
133
211
 
134
- 1. **差异高亮图** 红色区域表示像素不匹配
135
- 2. **差异统计** — 不匹配像素数、差异百分比
212
+ ## 🔄 推荐工作流:figma-to-code Skill
136
213
 
137
- 示例输出:
138
- ```
139
- ## ❌ 像素级对比结果
214
+ 配合 **`figma-to-code` Skill** 使用,可实现标准化的 5 阶段闭环工作流:
140
215
 
141
- **差异统计:**
142
- - 不匹配像素数:**12,345** / 608,400
143
- - 差异率:**2.03%**
144
- - 对比尺寸:750 × 812px
216
+ ![Skill 标准工作流](./docs/images/article-skill-workflow.svg)
145
217
 
146
- **结论:** 发现明显差异,请查看红色高亮区域。
218
+ ```
219
+ Phase 1: 设计稿解析 + Layout AST 生成
220
+
221
+ Phase 2: 资源切图导出
222
+
223
+ Phase 3: 编码实现(AST → HTML/CSS 的确定性翻译)
224
+
225
+ Phase 4: 自动化布局验收(verify_layout_bounds)
226
+
227
+ Phase 5: 精准修复 → 循环回 Phase 4 直到通过
147
228
  ```
148
229
 
149
- **可选参数:**
150
- - `threshold` — 颜色差异灵敏度(0-1,默认 0.2,越小越敏感)
230
+ ### 验收-修复闭环
151
231
 
152
- **如何解读 Diff 图:**
153
- - 🔴 **红色区域** = 像素颜色不匹配(位置偏移、颜色错误、元素缺失)
154
- - 🟠 **橙色区域** = 抗锯齿差异(通常可忽略)
155
- - **暗色区域** = 完全匹配
232
+ ![验收修复闭环](./docs/images/article-verification-loop.svg)
233
+
234
+ **关键约束:**
235
+ - AST 是编码的唯一参考,不允许 AI 自行猜测样式
236
+ - 每个 HTML 元素必须添加 `data-node-id` 属性用于验收匹配
237
+ - 编码完成后必须执行验收,不能跳过
238
+ - 循环修复直到 `matchRate ≥ 85%`(安全阀:最多 5 轮)
156
239
 
157
240
  ---
158
241
 
159
- ## 🔧 工作原理
242
+ ## 🧩 核心技术要点
243
+
244
+ ### 布局推断引擎
245
+
246
+ 采用三级优先级策略:
247
+
248
+ 1. **Figma Auto Layout 优先** — 有 `layoutMode` 时直接采信,但用精确坐标交叉验证 gap/padding
249
+ 2. **坐标推断** — 无 Auto Layout 时,从子节点坐标反推 direction、gap、alignment
250
+ 3. **保守降级** — 推断不确定时降级为 `position: absolute`,宁可不推断也不推错
160
251
 
161
252
  ```
162
- Figma URL
163
-
164
- └─► figma-preview-mcp
165
-
166
- ├─► Figma REST API 完整节点树(depth=100)
167
- ├─► 计算相对坐标每个节点的 _absX / _absY
168
- ├─► Figma Export API 高清 PNG 截图(2 倍分辨率)
169
-
170
- └─► 本地 HTTP 服务器(端口 3456)
171
- ├── PNG 截图作为背景
172
- └── 透明覆盖层(每个节点一个 div)
173
- └── 悬停 / 点击 → 节点信息
253
+ ε = 3px (容差)
254
+ yGroups = groupByProximity(children.y, ε)
255
+ xGroups = groupByProximity(children.x, ε)
256
+
257
+ yGroups.length === 1row
258
+ xGroups.length === 1 column
259
+ otherwiseabsolute
260
+ ```
261
+
262
+ ### Enriched AST 节点结构
263
+
264
+ ```json
265
+ {
266
+ "nodeId": "985:14549",
267
+ "name": "card-container",
268
+ "type": "FRAME",
269
+ "bounds": { "x": 16, "y": 100, "width": 343, "height": 200 },
270
+ "layout": {
271
+ "display": "flex",
272
+ "flexDirection": "column",
273
+ "gap": 12,
274
+ "alignItems": "flex-start",
275
+ "padding": { "top": 16, "right": 16, "bottom": 16, "left": 16 },
276
+ "source": "figma | inferred | absolute",
277
+ "selfSizing": { "horizontal": "fill", "vertical": "hug" }
278
+ },
279
+ "style": { "backgroundColor": "#ffffff", "borderRadius": "12px" },
280
+ "flags": {
281
+ "isGraphicSubtree": false,
282
+ "isAbsoluteOverlay": false,
283
+ "needsDetailFetch": false
284
+ },
285
+ "children": [...]
286
+ }
174
287
  ```
175
288
 
176
- ### 为什么用截图 + 覆盖层,而不是 CSS 重建?
289
+ ### 验收原理
177
290
 
178
- CSS 像素级还原 Figma 布局极其复杂(渐变、蒙版、混合模式、自动布局变体、组件覆盖...)。我们直接用 Figma 自身的渲染作为真实来源,在上面叠加一个透明交互层——100% 视觉保真度,零布局 bug。
291
+ - **Viewport 精确匹配** `deviceScaleFactor: 1`,CSS 像素与 Figma 像素 1:1 对应
292
+ - **坐标归一化** — 所有浏览器坐标相对于根容器,消除页面 margin/padding 影响
293
+ - **data-node-id 桥接** — 通过 DOM 属性 `data-node-id` 实现 Figma 节点与 HTML 元素的精确映射
179
294
 
180
295
  ---
181
296
 
@@ -185,7 +300,6 @@ Figma URL
185
300
  |---------|------|------|
186
301
  | `FIGMA_TOKEN` | ✅ 是 | Figma 个人访问令牌 |
187
302
  | `PORT` | 否 | HTTP 服务器端口(默认 `3456`) |
188
- | `PIXELMATCH_THRESHOLD` | 否 | 像素对比灵敏度阈值 0-1(默认 `0.2`,越小越敏感) |
189
303
 
190
304
  ---
191
305
 
@@ -193,7 +307,7 @@ Figma URL
193
307
 
194
308
  ```bash
195
309
  # 克隆仓库
196
- cd figma-preview-mcp
310
+ cd figma-preview-mcp/src
197
311
 
198
312
  # 安装依赖
199
313
  npm install
@@ -201,9 +315,12 @@ npm install
201
315
  # 构建
202
316
  npm run build
203
317
 
204
- # 在 MCP 配置中使用本地构建
205
- # mcp.json 中:
206
- # "args": ["/absolute/path/to/figma-preview-mcp/dist/index.js"]
318
+ # 开发模式
319
+ npm run dev
320
+
321
+ # 在 MCP 配置中使用本地构建:
322
+ # "command": "node"
323
+ # "args": ["/absolute/path/to/src/dist/index.js"]
207
324
  ```
208
325
 
209
326
  ---
@@ -212,6 +329,7 @@ npm run build
212
329
 
213
330
  - Node.js ≥ 18.0.0
214
331
  - 有效的 Figma 访问令牌
332
+ - Puppeteer 兼容环境(用于 verify_layout_bounds 和截图功能)
215
333
 
216
334
  ---
217
335
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figma-preview-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "MCP Server for previewing Figma designs in browser with node inspector, layout AST generation, and pixel-level verification",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",