手把手搭建Figma MCP服务器:让AI看懂设计稿的完整指南
2026/9/9 12:54:49 网站建设 项目流程

如果你和我一样,日常工作里既要对接设计稿,又要写业务代码,还要调 AI 应用,那你大概率遇到过这样的尴尬:AI 助手能写代码、能读文档,但就是“看不懂” Figma 里的设计稿。想让它根据 UI 标注生成前端代码,得先把设计稿手动转成 JSON、截图、甚至复制粘贴节点坐标。这个过程又慢又容易出错,尤其是在设计稿频繁改动的时候。

这篇文章记录的是我自己从零搭建一个 Figma MCP 服务器的完整复盘。所谓“边飞边造引擎”,就是一边在真实项目中用这个工具解决设计稿数据读取问题,一边把它的能力边界、架构设计和踩坑经验沉淀下来。我会从 MCP 的基础概念讲起,逐步拆解 Figma 的开放 API 能力,然后完整给出一个可运行的 MCP Server 代码,最后整理高频报错和工程化建议。

对 AI Engineer、前端开发者和对 MCP 协议感兴趣的同学来说,这篇内容可以作为一套可直接落地的参考方案。读完你不仅能理解 MCP 服务器的工作方式,还能自己动手实现一个连接 Figma 的 AI 工具链。

1. MCP 与 Figma:为什么需要一座桥

1.1 MCP 到底是什么

MCP(Model Context Protocol)是 Anthropic 在 2024 年底提出的一种开放协议,全称是 Model Context Protocol。它解决的核心问题是:让 AI 模型能够以标准化的方式访问外部数据源和工具。

你可以把 MCP 理解成 AI 领域的 USB 接口。USB 定义了设备之间通用的连接标准,鼠标、键盘、U 盘只要符合这个标准,插上就能用。MCP 也一样,它定义了 AI 应用(比如 Claude Desktop、Cline、Cursor)与外部工具(比如数据库、文件系统、设计软件)之间的通信协议。作为开发者,你只需要实现一个 MCP Server,所有支持 MCP 的客户端就能直接复用你的工具能力。

一个 MCP 架构通常包含三层:

  • MCP Host:运行 AI 模型的应用程序,比如 Claude Desktop、VS Code 插件等。
  • MCP Server:轻量级服务,对外暴露 tools、resources、prompts 三种能力。
  • 数据源:MCP Server 背后连接的具体系统,比如 Figma、GitHub、PostgreSQL。

AI 工程师关注 MCP 的主要原因很简单:大模型本身不掌握实时数据,也不具备操作外部系统的能力。通过 MCP,AI 可以调用工具读取 Figma 设计稿的节点信息、颜色变量、文本内容,然后基于这些真实数据生成代码、整理标注、执行设计走查。

1.2 Figma 为什么需要 MCP

Figma 本身已经提供了非常完整的 REST API 和插件机制,那为什么还需要 MCP?

关键在于“谁来调用”这个问题。

  • Figma REST API 是给工程师写的代码调用的。
  • Figma 插件是给设计师在画布上手动操作的。
  • 而 MCP Server 是给 AI 模型调用的。

当 AI 需要“理解”一份设计稿时,它不能自己带着 token 去请求 Figma API,也不方便让设计师手动点插件。MCP Server 作为中间层,把“获取文件结构”“读取选中节点”“提取样式变量”这些动作封装成 AI 可以理解的工具,再通过自然语言触发。

再结合团队协作流程来看:设计师在 Figma 里完成设计后,开发拿到的往往只是静态图片或链接。开发需要自己估算间距、确认字号、核对颜色,这个过程叫“设计标注还原”。而如果 AI 能通过 MCP 直接读取设计稿的真实数据,很多机械劳动就能自动化。

1.3 典型应用场景

根据我自己的实践,Figma MCP Server 在下面几个场景中价值最明显:

  • 设计稿转代码:AI 直接读取节点层级、布局属性、文本内容和样式值,生成更精准的 Tailwind CSS 或小程序代码。
  • UI 走查与标注核对:自动对比设计稿与线上页面的尺寸、颜色、字体是否一致。
  • 批量提取设计资产:从多页面文件中提取图标、颜色变量、字体样式,生成设计令牌(Design Token)。
  • 设计稿变更感知:文件更新后,AI 可以读取 diff 信息,辅助团队快速评估影响范围。

如果你平时使用 Trae、CodeBuddy 或 Codex 这类 AI 编程工具,并且团队设计稿存放在 Figma,那么一个标准的 Figma MCP 服务器能把设计数据直接接入 AI 工作流,减少大量“人肉搬运”环节。

2. 环境准备与版本说明

在动手写代码之前,先把环境准备好。这里的版本信息基于我搭建时的环境,建议你根据自身的系统环境做匹配调整。

2.1 基础运行环境

  • 操作系统:Windows 11 / macOS 均可,本文示例以 macOS 为主。
  • Node.js:建议使用 18 或 20 的 LTS 版本,MCP SDK 依赖较新的 JavaScript 特性。
  • 包管理器:npm 或 pnpm 均可。
  • TypeScript:MCP SDK 官方示例以 TypeScript 为主,建议全局安装 TypeScript。
  • Figma 账号:需要可以创建 Personal Access Token 的 Figma 账号,免费版也可以使用。

如果你使用的是 Windows,注意在代码块中把路径分隔符换成反斜杠,并且确保 Node.js 已经加入系统 PATH。

2.2 Figma API 前置条件

Figma 的 REST API 分为两个层次:

  • 文件 API:读取 .fig 文件数据,比如文件结构、节点属性、样式信息。
  • 实时协作 API:读取设计稿的实时协作状态。

我们这里的 Figma MCP 服务器主要使用文件 API。你需要先获取一个 Personal Access Token,获取路径为:Figma 首页头像菜单 → Settings → Security → Personal access tokens。

创建 token 时,注意选择权限范围。读取设计稿只需要files:read权限,不需要file_comments:writefile_dev_resources:write。实践上建议遵循最小权限原则,只勾选当前 Server 真正会用到的权限。

2.3 MCP SDK 版本选择

目前 MCP 官方 SDK 还在快速迭代中。原生 TypeScript SDK 包名为@modelcontextprotocol/sdk,安装时以官方 npm 最新版本为准。

需要特别提醒的是,MCP SDK 的 API 形态在不同 minor 版本之间可能发生变化,尤其是McpServer类的注册方式和 transport 的初始化方式。本文给出的代码是基于当前主流版本的写法,如果你的版本有差异,参考官方示例调整即可。

2.4 项目结构规划

一个规范的项目结构能省掉后面很多麻烦。我的推荐结构如下:

figma-mcp-server/ ├── src/ │ ├── index.ts # 入口文件 │ ├── figma-client.ts # Figma API 封装 │ ├── tools/ │ │ ├── get-file-info.ts # 获取文件信息工具 │ │ ├── get-node-detail.ts # 获取节点详情工具 │ │ └── search-nodes.ts # 搜索节点工具 │ └── types.ts # 类型定义 ├── package.json ├── tsconfig.json └── .env.example

这个结构的核心思想是:入口文件只负责 MCP 服务的装配,具体的 Figma API 请求逻辑全部封装在figma-client.ts中,每个工具一个文件,便于扩展和维护。

3. 核心原理解析:MCP Server 如何工作

3.1 MCP Server 的三类能力

MCP Server 对外暴露三种能力,理解这三种能力是设计工具集的前提。

  • Tools:可被 AI 调用的函数,适合执行具体操作,比如“获取文件节点树”。
  • Resources:可被 AI 读取的数据资源,适合暴露只读信息,比如“当前文件的样式变量”。
  • Prompts:预设的提示模板,可以引导 AI 以特定方式完成任务,比如“根据设计稿生成 Vue 代码”。

在开发 Figma MCP Server 时,Tools 是最常用的类型。每个 Tool 需要明确声明三件事:

  1. 工具名称(name):唯一标识,AI 根据名称决定何时调用。
  2. 参数结构(inputSchema):描述工具需要哪些参数,使用 JSON Schema 格式。
  3. 处理函数(handler):真正执行任务并返回结果。

3.2 Figma REST API 的关键接口

Figma 的 REST API 中,有两个接口是开发 MCP 服务器时最常用的。

第一个是获取文件数据:

GET https://api.figma.com/v1/files/{fileKey}

返回整个文件的所有节点信息,包括每个 node 的 id、name、type、boundingBox、styles、characters 等。注意:如果文件较大,这个接口的响应体可能非常巨大,甚至达到几十 MB。

第二个是获取节点数据:

GET https://api.figma.com/v1/files/{fileKey}/nodes?ids={nodeId}

返回指定节点的详细信息,适合按需读取场景。请求时可以在ids参数中传入多个节点 ID,用逗号分隔。

这两个接口都需要在请求头中带上:

X-Figma-Token: YOUR_PERSONAL_ACCESS_TOKEN

3.3 AI 调用 MCP 的流程

当你在支持 MCP 的客户端中发送一段自然语言指令,比如“读取 23:88 节点的样式”,完整的链路是这样的:

用户输入 ↓ AI 模型(Host)识别意图 ↓ 根据工具描述选择一个 MCP Tool ↓ 将参数序列化为 JSON,发送给 MCP Server ↓ MCP Server 调用 Figma API ↓ 返回结构化数据给 AI ↓ AI 根据数据生成回复或代码

这个流程里最容易出问题的三个环节是:AI 错误地选择了工具、参数传递不匹配、Figma API 返回的数据结构不符合预期。因此,在设计 MCP Server 的工具时,描述信息要写得足够清晰,参数校验要严格,返回结果最好做一层简化处理,避免把整个原始 JSON 抛给模型。

3.4 为什么不直接让 AI 调 Figma API

有人可能会问:既然 Figma 有 REST API,为什么不直接把 API 文档喂给模型,让 AI 自己构造 HTTP 请求?

这涉及几个现实问题:

  • 认证安全:Personal Access Token 放进提示词容易被泄漏到日志或对话历史。
  • 请求可靠性:AI 自己构造请求容易漏 header、拼错 URL、对错误处理不完善。
  • 响应处理:Figma API 原始响应包含大量与任务无关的字段,直接返回会给模型造成噪音。
  • 工具语义化:MCP Server 可以把底层 API 封装成业务动作,比如“提取页面所有文本内容”,AI 不需要关心具体调用链。

所以,MCP Server 的价值不只是转发请求,更是把复杂的外部系统简化成一组语义清晰的工具。

4. 实战:从零实现一个 Figma MCP Server

下面我们开始完整搭建。这个项目我建议你跟着敲一遍,不要直接复制整个仓库,因为过程中你会理解每一行代码的作用。

4.1 初始化项目

首先创建项目目录并初始化:

mkdir figma-mcp-server && cd figma-mcp-server npm init -y

然后安装必要依赖:

npm install @modelcontextprotocol/sdk zod dotenv npm install -D typescript @types/node tsx
  • @modelcontextprotocol/sdk:MCP 官方 TypeScript SDK。
  • zod:参数校验库,MCP SDK 推荐使用。
  • dotenv:读取.env环境变量文件。
  • tsx:简化 TypeScript 运行流程。

接着创建tsconfig.json

{ "compilerOptions": { "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }

这里的关键配置是modulemoduleResolution都要使用NodeNext,否则在 Node 环境运行 ES Module 时会报错。

4.2 环境变量配置

创建.env.example文件:

FIGMA_API_TOKEN=你的Figma个人访问令牌

创建.env文件并填入真实 token:

FIGMA_API_TOKEN=figd_xxxxxxxxxxxxxxxxxxxxx

package.json的 scripts 中增加启动命令:

{ "scripts": { "dev": "tsx src/index.ts", "build": "tsc", "start": "node dist/index.js" } }

开发阶段直接使用npm run dev即可,tsx 会帮我们处理 TypeScript 编译。

4.3 封装 Figma API Client

创建src/figma-client.ts,用于统一处理对 Figma REST API 的请求。

// src/figma-client.ts import dotenv from 'dotenv'; dotenv.config(); const FIGMA_API_BASE = 'https://api.figma.com/v1'; const FIGMA_TOKEN = process.env.FIGMA_API_TOKEN || ''; export class FigmaClient { private token: string; constructor(token?: string) { this.token = token || FIGMA_TOKEN; if (!this.token) { throw new Error('未找到 FIGMA_API_TOKEN,请检查 .env 文件'); } } private async request<T>(path: string): Promise<T> { const response = await fetch(`${FIGMA_API_BASE}${path}`, { headers: { 'X-Figma-Token': this.token, }, }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Figma API 请求失败 (${response.status}): ${errorText}`); } return response.json() as Promise<T>; } getFile(fileKey: string) { return this.request<FigmaFileResponse>(`/files/${fileKey}`); } getNodes(fileKey: string, nodeIds: string[]) { const params = new URLSearchParams(); params.set('ids', nodeIds.join(',')); return this.request<FigmaNodesResponse>( `/files/${fileKey}/nodes?${params.toString()}` ); } } // 最小类型定义 interface FigmaFileResponse { name: string; document: { id: string; name: string; type: string; children?: any[]; }; } interface FigmaNodesResponse { nodes: Record<string, any>; }

这段代码做了三件事:

  • 定义了一个FigmaClient类,封装request方法统一处理请求头和错误。
  • getFile获取整个文件结构。
  • getNodes按 ID 获取具体节点。

这里没有把 Figma API 的完整类型定义全部写出来,因为完整类型有几百行。实际开发中,你可以根据自己用到的字段逐步补充。

4.4 创建 MCP Server 入口

创建src/index.ts,注册两个核心工具:一个是获取文件基本信息,另一个是读取指定节点的样式和位置信息。

// src/index.ts import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from 'zod'; import { FigmaClient } from './figma-client.js'; const figmaClient = new FigmaClient(); const server = new McpServer({ name: 'figma-mcp-server', version: '1.0.0', }); // 工具1:获取 Figma 文件基本信息 server.tool( 'get_figma_file_info', '获取 Figma 文件的基本信息,包括文件名、页面列表和顶层节点结构', { fileKey: z.string().describe('Figma 文件的 fileKey,可以从分享链接中获取'), }, async ({ fileKey }) => { try { const file = await figmaClient.getFile(fileKey); const pages = file.document.children?.map((child: any) => ({ id: child.id, name: child.name, type: child.type, })) ?? []; return { content: [ { type: 'text' as const, text: JSON.stringify( { name: file.name, pages: pages, }, null, 2 ), }, ], }; } catch (error: any) { return { content: [ { type: 'text' as const, text: `获取文件信息失败: ${error.message}`, }, ], }; } } ); // 工具2:获取指定节点的样式和布局信息 server.tool( 'get_figma_node_styles', '获取 Figma 中指定节点的布局位置、尺寸、填充颜色、字体等样式信息,适用于 UI 还原和代码生成', { fileKey: z.string().describe('Figma 文件的 fileKey'), nodeId: z.string().describe('节点 ID,例如 23:88'), }, async ({ fileKey, nodeId }) => { try { const response = await figmaClient.getNodes(fileKey, [nodeId]); const nodeData = response.nodes[nodeId]; if (!nodeData) { return { content: [ { type: 'text' as const, text: `未找到节点 ${nodeId},请确认 IDs 中的 ID 是否正确`, }, ], }; } const node = nodeData.document; const result = extractNodeStyle(node); return { content: [ { type: 'text' as const, text: JSON.stringify(result, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: 'text' as const, text: `获取节点信息失败: ${error.message}`, }, ], }; } } ); function extractNodeStyle(node: any) { const base = { id: node.id, name: node.name, type: node.type, visible: node.visible !== false, }; const result: any = { ...base }; if (node.absoluteBoundingBox) { const box = node.absoluteBoundingBox; result.position = { x: box.x, y: box.y, width: box.width, height: box.height, }; } if (node.fillStyleId || node.strokeStyleId || node.effectStyleId) { result.styleIds = { fill: node.fillStyleId ?? null, stroke: node.strokeStyleId ?? null, effect: node.effectStyleId ?? null, }; } if (node.fills && node.fills.length > 0) { const solidFills = node.fills.filter( (fill: any) => fill.type === 'SOLID' && fill.visible !== false ); if (solidFills.length > 0) { const fill = solidFills[0]; result.fills = { color: fill.color ? `rgba(${Math.round(fill.color.r * 255)}, ${Math.round( fill.color.g * 255 )}, ${Math.round(fill.color.b * 255)}, ${fill.color.a})` : null, }; } } if (node.characters) { result.text = { content: node.characters, fontSize: node.style?.fontSize ?? null, fontName: node.style?.fontName ?? null, textAlignHorizontal: node.style?.textAlignHorizontal ?? null, textAlignVertical: node.style?.textAlignVertical ?? null, lineHeightPx: node.style?.lineHeightPx ?? null, }; } return result; } // 启动服务 const transport = new StdioServerTransport(); await server.connect(transport); console.error('Figma MCP Server 已启动');

这段代码是核心,解释几个重点。

McpServer是 SDK 提供的高层封装,server.tool方法用于注册工具。第一个参数是工具名,第二个是对工具的描述,第三个是参数 schema,第四个是实际处理函数。

extractNodeStyle函数过滤掉了原始响应里大量无关字段,把 AI 真正关心的位置、颜色、字体信息整理成结构化 JSON。AI 拿到这种格式的数据后,生成代码的准确率会明显高于给它原始 Figma API 响应。

注意,await server.connect(transport)这一行的await要放在顶层。需要确认你的 tsconfig 是否支持顶级 await,如果编译报错,可以改成:

async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('Figma MCP Server 已启动'); } main().catch((error) => { console.error('启动失败:', error); process.exit(1); });

4.5 用 MCP Inspector 验证服务

MCP 官方提供了一个调试工具叫 MCP Inspector,可以模拟 AI 客户端向我们的 Server 发送请求,是排查问题的利器。

安装并运行:

npx @modelcontextprotocol/inspector node dist/index.js

打开浏览器进入 Inspector 页面后,在 Tools 列表里应该能看到刚注册的两个工具。点击get_figma_file_info,在参数输入框中填入一个真实的 fileKey,点击运行,就能看到返回的页面列表。

这里需要解释一个关键概念:MCP 默认使用 stdio 传输层,也就是说 MCP Server 通过标准输入输出和宿主进程通信。所以你在终端启动 Server 后,它会一直等待输入,不会打印普通日志。如果要在调试时观察内部状态,请使用console.error而不是console.log,因为stdout是协议通道,不能混入业务输出。

4.6 集成到 AI 客户端

调试通过后,就可以把服务器接入支持 MCP 的客户端。以 Claude Desktop 为例,配置文件为claude_desktop_config.json

{ "mcpServers": { "figma": { "command": "node", "args": ["/absolute/path/to/figma-mcp-server/dist/index.js"], "env": { "FIGMA_API_TOKEN": "你的Figma个人访问令牌" } } } }

如果你使用 Cursor 或 Trae,通常在设置页面找到 MCP 配置入口,填入启动命令和环境变量即可。注意启动命令要使用绝对路径,path 环境变量不一定包含你的 Node.js 安装位置。

5. 常见问题与排查思路

在实际搭建和使用的过程中,我遇到了不少问题。这里整理成表格,方便快速对照排查。

问题现象常见原因解决思路
启动时报 “Cannot find module”编译产物目录不对或未安装依赖确认执行npm run build,并检查 dist 目录是否存在
Server 启动后没有任何输出stdio 模式下 stdout 被协议占用使用console.error输出日志,而不是console.log
调用工具返回 401 UnauthorizedFigma Token 无效或已过期重新生成 token,检查是否在环境变量中正确注入
调用工具返回 403 ForbiddenToken 权限不足确认 token 包含files:read权限
调用工具返回 404 Not FoundfileKey 或 nodeId 错误复制设计稿 URL 中/file/后面的字段作为 fileKey
AI 选择了错误的工具工具描述不清晰完善 tool 的 description 字段,说明推荐使用场景
返回数据太大导致 AI 误解原始节点包含多层子节点在 handler 中做数据裁剪,只返回必要字段
Figma 文件包含中文字体,AI 识别为空白系统未安装对应字体在系统中安装字体,或在返回数据中同时返回characters文本内容

这里单独说明一下 fileKey 的获取方法。Figma 分享链接通常长这样:

https://www.figma.com/file/AbCdEfGhIjKlMnOpQrStUv/项目名称?node-id=0%3A1

其中AbCdEfGhIjKlMnOpQrStUv就是 fileKey,node-id参数中的数字就是节点 ID。注意 URL 里的%3A是冒号的编码,实际使用时应转换为0:1这种格式。

另外,网络上不少人提到 Figma 汉化、安装字体、客户端设置的问题。如果你在读取设计稿时发现字体信息异常,优先检查 Figma 客户端所在系统是否已经安装对应字体,以及是否在 Figma 账号中正确同步了字体库。这类问题多属于环境问题,不是 MCP 配置问题。

6. 工程实战注意事项与性能优化

6.1 工具设计要符合 AI 的使用习惯

MCP 工具不是给人类用的,而是给 AI 模型用的。所以工具的设计思路和普通 API 设计差别很大。

一个常见误区是:把 Figma 的原始 API 直接映射成 MCP 工具,一个接口对应一个工具。这样做的结果往往是 AI 面对大量底层函数不知所措,不知道该调用哪个。

更推荐的做法是面向场景设计工具。比如,与其暴露“获取节点数据”和“获取文件数据”两个底层工具,不如设计成:

  • get_page_list:获取页面列表。
  • get_node_style:获取节点样式。
  • get_text_content:提取文本内容。
  • extract_design_tokens:提取颜色和字体变量。

这样可以显著降低 AI 的决策成本。

6.2 Token 安全与配置管理

Figma Token 属于敏感凭证,需要注意以下几点:

  • Token 不要硬编码在代码仓库中,建议通过.env文件或宿主环境的环境变量注入。
  • 如果项目使用 Git,.env必须加入.gitignore
  • 使用环境变量时,在启动 MCP Server 的配置文件中直接配置env字段,避免写入 shell 历史。
  • 遵循最小权限原则,创建 Token 时只授予当前场景必需的权限。

6.3 数据裁剪与响应控制

Figma 文件 API 返回的原始数据结构非常深,一个节点下面可能嵌套几十层子节点。如果原样返回给 AI,既浪费 token,又干扰模型判断。

我的经验是:在 handler 里做好两件事。

  • 垂直裁剪:只返回当前节点自己的一组关键属性,不递归展开所有子节点。
  • 水平裁剪:只保留前端代码生成真正需要的字段,比如nametypeabsoluteBoundingBoxfillsstylecharacters

如果需要获取子节点信息,可以单独设计一个“获取子节点列表”的工具,让 AI 根据自己的判断决定是否深入。

6.4 错误处理与日志记录

MCP Server 运行在用户本地或 CI 环境中,不像 Web 服务那样容易监控。所以建议:

  • 所有工具 handler 内部捕获异常,并把错误信息作为文本内容返回,避免服务崩溃。
  • 使用console.error打印关键路径日志,方便排查问题。
  • 记录每次 Figma API 请求的 fileKey 和 nodeId,出现问题时可以快速定位是哪个文件、哪个节点导致的错误。

一个简单的日志工具示例:

function log(level: 'info' | 'error', message: string, meta?: any) { console.error(`[${level}] ${new Date().toISOString()} ${message}`, meta ?? ''); }

6.5 支持多文件与多项目

如果你的团队有多个 Figma 项目,建议把 fileKey 设计成工具参数之一,而不是写死在配置里。这样 AI 可以根据对话上下文,动态决定读取哪个文件。

更进一步,可以在 MCP Server 中维护一个项目映射表,把项目代号映射到 fileKey。例如:

const PROJECT_MAP: Record<string, string> = { web: 'AbCdEfGhIjKl', admin: 'MnOpQrStUvWx', mobile: 'YzAbCdEfGhI', };

这样用户可以直接说“读取 web 项目的首页设计稿”,AI 先查询映射表,再调用对应的工具。

6.6 性能优化与缓存

Figma API 有访问频率限制,如果 AI 在短时间内多次请求大型文件,可能触发限流。建议在 MCP Server 层加一层简单缓存:

const cache = new Map<string, { data: any; expireAt: number }>(); async function getFileWithCache(fileKey: string, ttlMs = 60000) { const cacheKey = `file:${fileKey}`; const cached = cache.get(cacheKey); if (cached && cached.expireAt > Date.now()) { return cached.data; } const data = await figmaClient.getFile(fileKey); cache.set(cacheKey, { data, expireAt: Date.now() + ttlMs }); return data; }

设置 60 秒的 TTL,既能避免短时间内重复拉取,又能保证设计稿更新后能在合理时间内同步。

7. 从 MVP 到生产级:边飞边造的迭代路线

最后梳理一下这个项目从想法到落地的迭代思路,这部分也算是我自己的复盘记录。

7.1 第一版:只做最核心一件事

第一版我只做了一个工具:get_node_styles。目标很简单:输入 fileKey 和 nodeId,返回位置、尺寸、颜色、字体。这个版本解决了“AI 能否拿到设计稿关键数据”的问题,是整条链路的验证模型。

这一步最重要的是快速跑通,不要过度设计。MCP 协议的通信链路、Figma API 的认证流程、数据裁剪的逻辑,都需要在这一步验证清楚。

7.2 第二版:补全语义能力

验证跑通后,再按需增加工具。我在第二版加入了:

  • get_page_list:帮助 AI 定位内容所在的页面。
  • get_children_nodes:让 AI 可以逐层浏览节点树。
  • search_nodes_by_name:根据名称快速检索节点。

这些工具看起来简单,但极大地提升了 AI 在真实文件中的导航能力。AI 不再需要用户精确提供 nodeId,而可以通过名称和页面逐步找到目标。

7.3 第三版:异常场景覆盖

到第三版,主要精力花在异常处理上。核心要覆盖这些场景:

  • 文件不存在或没有访问权限时,返回友好提示。
  • 节点被删除或移动到其他位置时,返回可理解的错误。
  • Figma API 限流时,给出重试建议。
  • 字体缺失导致样式读取不完整时,至少返回源文本内容。

这一步是“边飞”时最真实的体验:项目已经有人在用了,你不能因为一个极端输入把服务搞挂。

7.4 第四版:面向多客户端兼容

MCP 生态还在快速演进,不同的 Host 对工具参数类型、资源协议的支持程度并不一致。如果希望 Server 能被 Claude Desktop、Cursor、Trae 等客户端同时使用,应该在代码中减少对特定客户端特性的依赖,多使用基础协议能力。

例如,在工具返回内容时,尽量只用type: 'text'的 content,不要依赖图片或其他扩展类型,因为并不是所有客户端都支持。

8. 总结与下一步学习方向

写到这里,整套 Figma MCP 服务器的核心内容基本都覆盖了。从 MCP 协议的基本概念,到 Figma REST API 的调用方式,再到完整的 TypeScript 实现,以及最后的工程化注意事项,这是一条可以直接复用的技术链路。

对想继续深入的朋友,我建议按下面几个方向推进:

  1. 阅读 MCP 官方 SDK 的完整文档,了解ResourcesPrompts的更多用法。
  2. 研究 Figma Plugin API 和 REST API 的差异,判断哪些场景适合用插件实现,哪些适合用 MCP。
  3. 结合实际项目,把设计稿转代码的流程做成一个完整的 AI 工程,而不仅仅是读取数据的工具。
  4. 多关注 AI 编程工具的 MCP 配置机制,不同工具之间协议兼容性差异很大,需要实际测试。

Figma MCP 服务器的开发过程,本质上是在给 AI 装上一双“能看懂设计稿的眼睛”。这个方向目前还有很大的探索空间,希望这篇文章能帮你少走一些弯路。如果你在实际部署中遇到其他问题,欢迎在评论区交流。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询