mcpField
F
figsnap-mcp

figsnap-mcp

本地服务
github.com/arimunandar媒体与设计08 周前更新

关于 figsnap-mcp

figsnap-mcp 将当前打开的 Figma 文件通过本地守护进程和插件提供给 MCP 客户端,适合需要读取和修改设计画布的编码 Agent。它包含 41 个工具,并由设计师显式控制写入权限。

主要功能

  1. 01提取节点为 PNG、React、HTML 或 CSS
  2. 02读取选择内容、页面层级和组件库
  3. 03保存并管理组件集合
  4. 04获准后编辑 Figma 画布
  5. 05通过本地守护进程连接插件

适用场景

  1. 01检查当前选中的设计节点
  2. 02将设计内容导出为实现代码
  3. 03保存常用组件供后续查询
  4. 04授权 Agent 修改画布

MCP 相关

向 MCP 客户端提供 41 个 Figma 读取和写入工具,以及可寻址的文件资源。客户端通过 stdio 服务器连接本地守护进程;写入操作需先启用 Allow edits。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"arimunandar-figsnap": {
"command": "npx",
"args": [
"-y",
"figsnap-mcp"
],
"env": {
"FIGSNAP_MCP_URL": "<FIGSNAP_MCP_URL>",
"FIGSNAP_MCP_TOKEN": "<FIGSNAP_MCP_TOKEN>"
}
}
}
}
启动命令npx -y figsnap-mcp
需要配置的环境变量
FIGSNAP_MCP_URLWhere the figsnap-mcp daemon is listening. Default http://127.0.0.1:3058; only needed if you moved it.
FIGSNAP_MCP_TOKEN密钥The daemon's token. Not normally set: the server reads ~/.figsnap-mcp/agent-token, which the daemon writes itself.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmfigsnap-mcp0.2.0

工具

41

收录的工具列表 · 更新于 2 周前

此工具无需参数。

详细介绍

Figsnap MCP

CI npm node licence

将你当前打开的 Figma 文件作为 MCP 工具使用,仅此而已。

在 VS Code 中安装 在 Cursor 中安装

claude mcp add figsnap-mcp -s user -- npx -y figsnap-mcp

这些操作会安装 MCP 服务。守护进程运行且 Figma 插件打开之前,它不会响应任何内容——请参阅启动运行,共五个步骤,大约需要两分钟。

一个 Figma 插件、一个本地守护进程和一个 MCP 服务。你的编码 Agent 可以读取设计,将节点提取为 PNG、React、HTML 或 CSS,在你允许时编辑画布,并与你分享一组已保存的组件。没有中继、没有账户,也不会通过回环地址之外的网络通信。

  MCP client              figsnap-mcp              daemon                 the plugin
  (Claude Code)   stdio    (stateless      HTTP :3058       ws         (open in Figma)
       ─────────────────►   proxy)          ──────────►   /panel   ──────────►   figma.*
                                            127.0.0.1 only

三个进程和一条规则:figma.* 仅在插件打开时存在,因此插件负责维持连接,其他所有内容都通过它提出请求。

这不是什么

这个仓库是 Figsnap 的衍生版本,精简到只做一件事。Figsnap 从一个 package.json 中提供四种产品——插件、带账户的 Cloudflare Worker 中继、ACP 聊天客户端,以及这个 MCP 服务。如果你只想要 MCP 工具和一组已保存的组件,就得克隆整个项目、构建一个你永远不会打开的 4,200 行面板,还要加载一个清单将你永远不会登录的 Worker 列入白名单的插件。

所以:**没有 ACP 客户端、没有运行环境发现、没有会话存储、没有中继、没有账户、没有聊天、没有 API 浏览器、没有代码导出界面。**剩下的是提取引擎、41 个工具,以及一个有三个窗格的面板。

这些改动不会修改 Figsnap,两者可以并行运行——此守护进程使用端口 3058,令牌存放在 ~/.figsnap-mcp/agent-token;Figsnap 则使用端口 3056,令牌存放在 ~/.figsnap/agent-token。

关于清单有一点需要注意:Figma 会验证 allowedDomains,并拒绝 IP 字面值——Invalid value for allowedDomains. 'ws://127.0.0.1:3058' must be a valid URL——而被拒绝的清单不会加载,因此插件会悄悄继续运行上一个有效版本。请使用名称 localhost,并在此处进行任何更改后检查控制台,因为没有其他地方会报告此问题。

在 Figma 中,这两个插件也彼此隔离。clientStorage 以插件 ID 为键,因此清单使用自己的 ID,而不是 Figsnap 的 REPLACE_ON_PUBLISH;此外,此插件写入的每个键都会加上 figsnap-mcp: 前缀。共享其中任意一个插件,就意味着共享所存储的守护进程地址;继承了 ws://localhost:3056 的面板会被自身清单的 CSP 拦截——设计师看不到这条控制台错误。面板还会拒绝任何不在清单允许端口范围内的已存储或手动输入的地址,并丢弃随地址传入的令牌。

安装

npm install -g figsnap-mcp

它附带两个命令:

figsnap-mcp-daemon桥接程序;工作时让它保持运行
figsnap-mcpMCP 服务,由客户端启动,不要手动运行

你也可以跳过安装,让 npx 获取它,这通常就是 MCP 客户端配置的做法。Figma 插件也包含在软件包中:全局安装后,其清单位于

npm root -g   # …/lib/node_modules — the manifest is figsnap-mcp/manifest.json

或者克隆仓库并运行 npm install && npm run build,效果相同,只是源码也在旁边。

启动运行

只需设置一次,分五步完成。

1. 构建。

npm install -g figsnap-mcp

如果是从克隆的仓库开始:npm install && npm run build。

2. 启动守护进程。 让它保持运行;只有它会与 Figma 通信。

figsnap-mcp-daemon                # --allow-edits opens the writing tools at boot

如果是从克隆的仓库开始:npm run daemon。figsnap-mcp-daemon --help 会列出其余信息。

它会打印地址和令牌:

figsnap-mcp-daemon 0.1.0
  panel socket   ws://127.0.0.1:3058/panel
  http           http://127.0.0.1:3058
  token          8fT2qN4vRk1pXwLzYc7BhJ0mAeUdSg9T
  edits          off — turn them on in the plugin, or start with --allow-edits

3. 加载插件。 在 Figma 桌面应用中:插件 → 开发 → 从清单导入插件,选择软件包中的 manifest.json(运行 npm root -g 可找到它,也可以在仓库根目录中找到),然后运行 Figsnap MCP。

4. 配对面板。 将第 2 步中的 token 行复制到面板的 Connect 窗格,然后点击 Connect。圆点会变绿,Address 显示为 ws://localhost:3058/panel。

这是唯一需要输入令牌的地方。令牌会存储在 Figma 自己的用户存储中,因此从现在起,面板每次都会自动重新连接。

5. 注册 MCP 服务。

claude mcp add figsnap-mcp -s user -- npx -y figsnap-mcp

重启客户端,然后运行 claude mcp list,应显示 figsnap-mcp · ✔ Connected。如果是从克隆的仓库开始,请改为指定文件名:-- node /path/to/FigsnapMCP/agent/mcp-stdio.mjs。

检查整条链路:

curl -s http://127.0.0.1:3058/health
# { "ok": true, "panelConnected": true, "editsAllowed": false, ... }

关键是 panelConnected: true 这一行——它表示另一端连接着 Figma。

令牌

MCP 客户端永远不需要令牌。 这一点常常让人意外:claude mcp add 不需要令牌、环境变量或配置。MCP 服务会在运行过程中读取守护进程自己的文件。

只有两处会用到令牌,而且其中只有一处需要你操作:

对象获取方式
Figma 面板你只需在 Connect 中粘贴一次
agent/mcp-stdio.mjs自动读取 ~/.figsnap-mcp/agent-token

令牌的来源。 守护进程首次启动时会生成一个令牌——24 个随机字节,以 base64url 编码——并以 600 模式写入 ~/.figsnap-mcp/agent-token。之后每次启动都会读取同一个文件,因此令牌保持不变,面板每天早上都无需重新配对。

无需重启任何东西即可再次查看:

cat ~/.figsnap-mcp/agent-token

为什么需要令牌。 守护进程监听一个 loopback 端口,而你访问的任何网页都可以打开一个到 localhost 的套接字。有两项措施可以阻止它:升级时检查的 Origin 标头(浏览器无法伪造),以及这个令牌(浏览器 WebSocket 无法设置标头)。只有 GET /health 无需令牌即可访问,因此面板可以在配对前告知你守护进程正在运行。

如果令牌泄露,请轮换它:

npm run daemon -- --new-token

这会生成一个新令牌并使旧令牌失效。在 Connect 中重新粘贴新令牌;MCP 客户端会自行获取新令牌,因为它们会读取该文件。

要使用自己的令牌——例如在脚本中使用固定令牌——请设置 FIGSNAP_MCP_TOKEN,守护进程就会使用它,而不是文件中的令牌。如果 MCP 客户端无法读取你的主目录,也请为它设置相同的变量。FIGSNAP_MCP_URL 用于更改客户端连接的地址。

配置 MCP 客户端

claude mcp add figsnap-mcp -s user -- npx -y figsnap-mcp

对于使用 JSON 配置的客户端:

{ "mcpServers": { "figsnap-mcp": { "command": "npx", "args": ["-y", "figsnap-mcp"] } } }

figsnap-mcp-daemon --mcp 会打印这两种配置,并自动填入路径。

随后,claude mcp list 应显示 figsnap-mcp · ✔ Connected;在会话中,figma_get_selection 会返回画布上当前选中内容的信息。

无响应时

可能有三种问题,每种问题都会以不同方式提示:

工具提示处理方法
No figsnap-mcp daemon at http://127.0.0.1:3058npm run daemon
The Figsnap MCP plugin is not open in Figma打开文件并运行插件
The figsnap-mcp daemon rejected the tokencat ~/.figsnap-mcp/agent-token,或设置 FIGSNAP_MCP_TOKEN
Editing the file is switched off在插件的 Tools 窗格中启用 Allow edits
资源

关于 Figma 文件的问题几乎总会用到以下三项内容。它们可以通过地址访问,而不是通过调用获取,因此客户端可以用 @ 提及它们:

URI内容
figma://selection提取所有选中内容
figma://page三层深度的图层树
figma://library带 ID 的组件、样式和变量
figma://node/{nodeId}单个图层,例如 figma://node/21:10314

面板

面板有四个窗格,打开时默认显示 Selection。

Selection 会预览你在画布上选中的内容,显示图片、名称、类型、尺寸、子项数量和节点 ID,旁边还有文件夹选择器和 Save 按钮。在这里保存是最省事的方式:无需切换窗格,也无需在列表中再次查找图层。

预览会消耗一次 PNG 导出。过去,每次选中内容发生变化,面板都会执行完整提取,生成 HTML、TSX、两个样式表和一张 2× 图片,即使没人查看这张图片;MCP 所需的代码输出会按需生成,而不会因一次点击而生成。小图层最多放大 4×,这样图标和屏幕就不会都占满预览区域。

Minimise(右上角的 ▼)会将窗口收缩为 44px 高的条带,并将预览缩到条带下方,让画布保持清晰,同时插件继续运行。守护进程需要面板保持打开,但你不必一直看着它。条带仍会显示当前选中的内容,并保留 Save,因为工作时这两项最有用。点击 ▲ 可恢复到你拖动设置的大小。

Connect 和 Tools 分别用于配对和查看工具列表;Saved 是文件夹管理器。下文将分别介绍。

工具

共有 41 个:14 个用于读取 Figma,26 个用于写入 Figma,还有一个由守护进程响应。 Tools 窗格会列出所有工具,并标记写入类工具;GET /tools 返回相同的 JSON 列表。

读取始终允许。写入则不行,除非你明确允许——每个修改类工具都会被拒绝,直到开启 Allow edits。这是由设计师掌控的开关,而不是 Agent 能够绕过的提示。即使运行的测试框架禁用了权限提示,也无法绕过它。在终端中进行工作时,可以使用 --allow-edits 打开同一道关卡。

两个工具将 13 个插件命令折叠到各自的一个参数中,因为每次请求都要为 41 个工具描述付出实际的上下文开销:

  • figma_extract 接受 nodeId,也可以批量接受 nodeIds、urls、selection: true、saved: true。
  • figma_saved 接受 action:list、folders、save、unsave、clear、move、newFolder、renameFolder、deleteFolder。

图片会以真正的图像块形式返回,绝不会作为文本字段中的 base64 返回——figma_export_png 就是为此而设的,一次处理一个节点。

figma_ios_spec 会以 Figma 实际保存的属性作答,而不是 CSS,单位为点:各轴的尺寸、自动布局及其内边距、描边粗细和对齐方式、圆角平滑度、效果、文本块,以及每个填充和描边是否标记为 painted。需要着手编写代码时就用它。figmaCss 描述节点在网页上的外观,但它会舍弃实现所需的信息,还会报告实际上并未绘制的内容:即使关闭了描边,仍会返回 border: 1px solid。这里的描边同时包含 layoutFrame 和 visualFrame,因为 CENTER 描边会有一半粗细超出边界,而 UIKit 会在边界内绘制边框;效果则包含 uikitShadowRadius,其值为模糊半径的一半。

有一个限制:渐变填充会报告其类型、不透明度和 painted 标记,但不会报告色标,因此你能知道有渐变,却无法复现它。目前可以从 figma_export_png 中读取这些颜色。

figsnap_skill 是个例外:它不涉及插件,因此即使 Figma 已关闭也能作答。check 会说明此项目是否具备此软件包附带的技能,结果为 missing、current,如果你编辑过自己的副本则为 modified。副本归你所有,因此系统会报告它,而不会替换它。install 会返回文件及其放置位置,而不是直接写入,因为无论调用方是什么,它都会在写入你的代码仓库前征求你的许可。目标项目取自 MCP 客户端自己的目录,mcp-stdio.mjs 会在每次调用时指出该目录——守护进程使用的是你启动它时所在的目录,通常不是你正在工作的目录。

已保存集合

Saved 窗格用于收纳你经常访问的组件:文件夹、Save selection、跳转到节点、移动、移除。它可以通过 MCP 使用 figma_list_saved 和 figma_saved 访问,因此你和 Agent 看到的是同一份列表。

数据保存在 figma.clientStorage 中,以文档 ID 为键。这意味着:**按用户、文件和机器分别保存。**最多可有 100 个条目和 30 个文件夹,且文件夹只有一层。

**一个有意为之的取舍。**Figsnap 也会将此集合镜像到其中继服务,因此你可以在第二台机器上使用它。没有 Worker 时,这些集合仅保存在本地。对这个代码仓库来说,这是合适的取舍——无需账户和网络连接,即使在只能查看的文件中也始终可以写入——但这确实有所不同。如果之后需要跨设备同步,只需增量改动:让插件新增一个同步目标,而不是新增一个数据所有者。

布局

index.mjs              the library entry point; importing it starts nothing
index.d.mts            hand-written types for it
manifest.json          the Figma plugin manifest; localhost:3058 only
build.mjs              esbuild → dist/code.js + a self-contained dist/ui.html
shared/                nodes.mjs (findable types), shape.mjs (what a body means)
agent/
  index.mjs            the daemon: WS server, HTTP server, the Edits gate
  mcp-stdio.mjs        the MCP server; a stateless proxy to the daemon
  lib/tools.mjs        the 41 tools — one command each, no logic in between
  lib/skill.mjs        the skill on disk: the one tool answered without Figma
  lib/plugin-socket.mjs  the panel socket: origin check, token, request/response
  lib/http.mjs         /health, /tools, /tool
  lib/gate.mjs         the Edits switch
  lib/paths.mjs        the port, the host and the token file, defined once
src/
  code.ts              the main thread: 51 commands, extraction and codegen
  figma-css.ts         Figma's own CSS, rendered
  daemon.ts            the one address the plugin dials
  ui/                  the panel: bridge.ts, main.ts, index.html, style.css
test/                  run.mjs and five suites; see Tests below
.github/workflows/     CI on Node 20, 22 and 24; publish on a version tag

将其用作库

大多数人只需要这两个命令。如果你正在构建自己的桥接程序,软件包会导出目录以及组装守护进程所需的组件:

import { toolManifest, createGate, createPluginSocket, createHttpHandler } from 'figsnap-mcp'

console.log(toolManifest().length)  // 39

导入它不会启动服务,也不会打开套接字——agent/mcp-stdio.mjs 在加载时会立即将 MCP 服务连接到标准输入输出,因此它有意不被重新导出;以前定义在其中的常量现在位于 agent/lib/paths.mjs。index.d.mts 是手工编写的,测试套件会从两个方向检查它与运行时是否一致。

从 1.0.0 开始遵循 Semver。在 0.x 阶段,工厂函数最可能发生变动;目录和常量则是稳定的部分。

安全性

守护进程仅绑定到 127.0.0.1,并通过两项检查保护套接字,因为任何你访问的网页都可能连接本地端口:

  • Origin,在升级连接时检查。插件 iframe 是沙盒文档,会发送 null;编辑器会发送 figma.com。其他任何值都会导致连接以 4001 关闭。浏览器无法伪造此标头,而且 CORS 不适用于升级连接,因此这才是关键检查。
  • 令牌,放在查询字符串中,因为浏览器 WebSocket 无法设置标头。它与 HTTP 调用方发送的 x-figsnap-token 相同;只有 /health 无需令牌即可访问,因此面板可以在配对前进行探测。

如果令牌泄露,可以用 --new-token 轮换。

测试

npm test          # four suites: no wrangler, no network, no Figma
npm run typecheck
  • e2e-plugin.mjs 使用模拟的 figma,将发布的 dist/code.js 接入真实守护进程,并通过 POST /tool 驱动它:提取保真度、figma_find_nodes、包括重新加载在内的已保存集合,以及在写入闸门关闭和开启时分别进行写入。
  • e2e-mcp.mjs 会启动守护进程,将面板模拟为 WebSocket 客户端,并通过标准输入输出驱动真实 MCP 客户端:各项保护机制、工具列表、批处理和图像规则、全部 10 条已保存集合命令、资源,以及调用在到达 Figma 前可能失败的 3 种方式。
  • e2e-panel.mjs 会将发布的 dist/ui.html 加载到 jsdom 中,并替换主线程和守护进程,然后驱动设计师一侧:窗格会渲染收到的内容,点击操作符合其描述,破坏性文件夹操作会先启用,之后才执行。
  • contract.mjs 是防止偏离的检查。shared/、agent/lib/tools.mjs 和 src/code.ts 在本仓库和 Figsnap 中都存在,它们之间的协议没有共享类型。因此,它会断言单边修改可能破坏的内容:工具可指定的每条命令都是 src/code.ts 中的一个分支,并且每个分支都可通过工具访问;MAX_BATCH 保持一致;面板显示的上限就是插件执行的上限;find_nodes 架构恰好提供 FINDABLE_TYPES;这 3 个文件都同意使用 3058;并且没有文件悄悄重新导入 relay、accounts 或 ACP 客户端。

向你的组织发布插件

插件可以一直作为开发安装使用——导入清单即可——但将其发布到你的 Figma 组织,就能让它出现在每个人的插件列表中,并自动更新,且不会出现在 Community 中。

此选项需要 Figma Organization 或 Enterprise 方案。使用 Professional 方案时,唯一可发布的选项是 Community,这是公开的;在这种情况下,开发安装是私有方式。

  1. 先构建:npm run build。Figma 发布的是 dist/ 中的内容,而不是 src/ 中的内容。
  2. Figma 桌面版 → Plugins → Development → Figsnap MCP → Publish。
  3. 选择 Only ,而不是 Community。
  4. 填写列表信息:一张 128×128 图标、一段描述和一张封面图片。仅限组织的发布无需经过 Community 审核,提交后即会生效。

首次发布时,Figma 会将插件 id 写入 manifest.json,并替换 REPLACE_ON_PUBLISH_FIGSNAP_MCP。请提交此更改——它用于标识后续版本是更新,而不是新插件,也能让此插件的 clientStorage 与 Figsnap 的存储区分开来。要发布更新,请重新构建,然后从同一菜单再次发布。

需要明确一点:此代码仓库和 npm 包都是公开的,且都包含构建后的插件。仅限组织发布控制的是 Figma 内的列表展示和分发,而不是谁能获取代码——无论哪种方式,代码都采用 MIT 许可。

发布

CI 会在每次推送时使用 Node 20、22 和 24 运行测试套件。

首次发布需要手动进行,因为 npm 需要在软件包自己的设置页面上配置可信发布者,而软件包创建之前不会有该页面:

npm login
npm publish --access public

然后启用可信发布,此操作只需进行一次,前往 npmjs.com/package/figsnap-mcp/access → Trusted Publisher → GitHub Actions:

字段值
组织或用户arimunandar
仓库figsnap-mcp
工作流文件名publish.yml
环境名称留空

此后的每次发布都通过标签进行:

npm version patch          # writes package.json and the v0.1.1 tag
git push --follow-tags

npm version 还会运行 scripts/sync-server-json.mjs,将新版本复制到 server.json 的两个版本字段并暂存,因此三处版本信息最终会位于同一次提交中。如果版本信息不一致,工作流会拒绝发布——这就是 0.2.0 在进入注册表之前被拦下的原因。

.github/workflows/publish.yml 会检测到该标签;如果它与 package.json 中的版本不一致,就会拒绝发布,并通过 OIDC 使用来源证明进行发布——不会产生可泄露的令牌。这一点很重要,因为 npm 正在限制可绕过 2FA 的令牌(账户变更将于 2026 年 8 月实施,直接发布限制将于 2027 年 1 月实施)。

prepublishOnly 会先进行类型检查、构建并运行所有测试套件,因此无法正常运行的发布内容不会进入注册表。npm pack --dry-run 会准确显示将要发送的内容;test/e2e-package.mjs 会断言这些内容。

许可证

MIT。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。