1. 为什么 Figma 转 Flutter 总是差那么一口气
做移动端开发的朋友大概率都有过这种体验:设计稿在 Figma 里漂漂亮亮,标注也齐全,可一旦落到 Flutter 代码里,间距、圆角、字重、颜色就开始各种对不上。一个中等复杂度的页面,手工还原加上反复适配,占掉整个需求 60% 的时间并不夸张。我试过直接截图丢给 AI 让它生成代码,也试过 Figma 插件一键导出,结果要么是宽高全写死、用 Stack + Positioned 堆出来几乎没法维护,要么是还原度差得远、连切图都得自己手动替换。
问题的根子在于信息传递的精度。截图给 AI,它只能靠视觉识别猜间距和颜色,误差天然存在;Figma 插件导出虽然能拿到精确数值,但往往把布局写死,失去了 Flutter 弹性布局的意义。真正理想的方案,是让 AI 直接读取 Figma 的节点数据——层级、尺寸、颜色、字体、圆角这些结构化信息,再结合大模型的代码能力生成可维护的 Widget。
这篇要讲的,就是用 Cursor 的 MCP 能力,把 Figma 设计稿的节点信息喂给模型,走一条「设计稿 → 结构化数据 → Flutter Widget → 真机验证」的落地流程。适合的人群很明确:手里已经有 Figma 设计稿、日常用 Flutter 做移动端、被 UI 还原反复折磨的开发者。整套流程的目标不是生成一次性的代码,而是把重复的 UI 还原工作压缩成一套可复用的配置,下次换个页面直接跑。
需要说明的是,MCP 只是把 Figma 数据接进来的通道,真正决定生成质量的是模型对布局语义的理解。所以配置只是第一步,后面怎么调层级、怎么给提示词、怎么验证,才是能不能真正省时间的关键。下面从环境准备开始,一步步把这条链路搭起来。
2. 前置准备:TaoToken 接入与 Cursor MCP 环境搭建
在动手配 MCP 之前,先把模型调用这条链路理顺。Cursor 本身可以接不同的模型服务,我这里用的是 TaoToken 提供的接口,它的好处是兼容 OpenAI 风格的调用方式,配置起来比较直接,模型对话、Coding Plan、API Keys 这些入口都在控制台里能拿到。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 根地址是 https://taotoken.net/api ,注意 API 地址后面不加 UTM 参数。
第一步是拿到 API Key。进入控制台后创建密钥,这个 Key 后面要填到 Cursor 的模型配置里。控制台入口在 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,API Keys 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。创建时建议给 Key 起个能认出来的名字,比如 cursor-flutter,方便后面区分用途。
拿到 Key 之后,在 Cursor 里配置模型。打开 Settings,找到 Models 相关配置,把 Base URL 填成 https://taotoken.net/api ,API Key 填刚才创建的那串,Model ID 按你实际要用的模型填。这里三件套缺一不可:Base URL、Key、Model ID,任何一个填错都会导致请求失败。如果你用的是 Claude 系列做代码生成,Model ID 要写对应的模型标识,具体可以在模型对话页 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 确认当前可用的模型名。
接下来是 MCP 服务端的配置。Figma 这边需要一个能读取节点数据的 MCP 服务,社区里比较常用的是 Figma-Context-MCP 这类工具。它的作用是提供两个能力:一是获取 Figma 页面的节点信息(返回 JSON),二是下载切图资源。配置方式是在 Cursor 的 MCP 配置文件里加一段服务定义。Cursor 的 MCP 配置一般放在用户目录下的配置文件中,路径类似~/.cursor/mcp.json,Windows 下在%USERPROFILE%\.cursor\mcp.json。
配置内容大致是这样:
{ "mcpServers": { "figma-context": { "command": "npx", "args": ["-y", "figma-context-mcp"], "env": { "FIGMA_API_KEY": "你的Figma个人访问令牌" } } } }这里的 FIGMA_API_KEY 不是 TaoToken 的 Key,而是 Figma 自己的个人访问令牌。在 Figma 账号设置里生成,权限至少要有读取文件内容的权限。生成后填进 env 里。保存配置后重启 Cursor,在 MCP 面板里应该能看到 figma-context 这个服务处于可用状态,并且列出它提供的工具。
有一点要提醒:MCP 服务是通过本地进程启动的,npx 会去拉取对应的包,第一次启动可能稍慢。如果公司网络对 npm 源有限制,可以提前配好镜像源,或者把包全局装好再改 command 指向本地路径。这一步卡住的话,后面所有流程都跑不起来,所以务必先确认 MCP 服务能正常列出工具。
环境搭好之后,整个链路就是:Cursor 通过 MCP 拿到 Figma 节点 JSON,把 JSON 连同提示词一起发给模型,模型生成 Flutter 代码,Cursor 再把切图下载到项目里并引用。下面进入具体的配置和操作。
3. 可复制配置:MCP 服务端、Figma 导出参数与 Cursor 规则
这一节把需要复制的配置集中列出来,照着填就行。先明确一点,配置分三块:MCP 服务端定义、Figma 侧的节点准备、Cursor 的项目规则(rules)。三块配合好,生成质量会稳定很多。
MCP 服务端的配置上面已经给了一版,这里补充一个更完整的版本,把超时和日志也带上,方便排查问题:
{ "mcpServers": { "figma-context": { "command": "npx", "args": ["-y", "figma-context-mcp@latest"], "env": { "FIGMA_API_KEY": "figd_xxxxxxxxxxxxxxxx", "FIGMA_TIMEOUT": "30000" }, "disabled": false, "autoApprove": [] } } }autoApprove 留空是有意的,让每次工具调用都经过确认,避免模型在你不注意的时候拉取大量节点数据。等流程跑顺了,再考虑把只读类的工具加进自动批准。
Figma 侧的节点准备,是决定成败的关键。从实践看,设计稿的层级和命名规范程度,直接决定生成代码的可用性。具体要做几件事:把同一个组件的元素归到同一个 Frame 或 Group 下,比如按钮的文字和背景要在同一个组里,指示器的圆点和容器也要在一起;给每个组起有意义的名字,用英文或拼音,避免「Frame 123」这种默认名;把轮播、列表这类需要交互的区域单独成组,方便模型识别出这是可滑动区域而不是一张静态图。
导出参数方面,MCP 拉取节点时用的是 Figma 的节点 ID。获取方式是在 Figma 里选中目标 Frame,右键复制链接,链接里node-id=后面的部分就是节点 ID,格式类似123-456。把这个 ID 连同文件 Key 一起给 MCP,它就能定位到具体节点。文件 Key 在 Figma 文件链接的/file/和文件名之间那一段。
Cursor 的项目规则建议在项目根目录建一个.cursor/rules目录,放一个flutter-ui.mdc文件,内容约束生成风格:
--- description: Flutter UI 生成规则 globs: lib/**/*.dart alwaysApply: true --- - 使用 Flutter 原生 Widget,优先用 Row/Column/Container 等弹性布局 - 禁止使用 Stack + Positioned 写死绝对位置,除非设计明确要求层叠 - 颜色、字号、圆角从设计稿读取,不要用魔法数字 - 图片资源统一放在 assets/images/ 下,用 Image.asset 引用 - 生成的 Widget 要拆分成独立文件,放在 lib/widgets/ 下 - 状态栏和底部 Home Indicator 不要作为页面内容生成这段规则的作用是给模型一个稳定的输出预期。没有规则约束时,模型容易自由发挥,一会儿用 Stack 一会儿用 Column,代码风格飘忽。加上规则后,生成结果的一致性会明显提升。
还有一点,如果你在项目里用到了 Cline MCP 或者 Codex 的 auth.json 这类配置,记得把 Base URL、Key、Model ID 三件套对齐。比如 Codex 的 auth.json 里,Base URL 指向 https://taotoken.net/api ,Key 填 TaoToken 的密钥,Model ID 填实际模型名。三处不一致是常见的踩坑点,表现为请求发出去了但返回鉴权错误。
配置完成后,建议先用一个简单页面验证链路是否通。选一个结构清晰的 Frame,节点 ID 复制好,在 Cursor 里用 Agent 模式发起请求。下一节讲具体的验证动作和成功结果长什么样。
4. 验证请求:从设计稿到可运行 Widget 的完整动作
配置就绪后,来跑一次完整的生成。我选一个结构不算复杂的页面做演示:顶部一个渐变背景的 Banner,中间一个横向轮播,底部一个带进度的按钮。这个组合能覆盖布局、切图、交互三类典型场景。
第一步,在 Figma 里选中整个页面 Frame,复制节点链接,提取出文件 Key 和节点 ID。然后在 Cursor 里切到 Agent 模式,输入提示词。提示词不要只写「根据设计稿生成 Flutter 代码」,那样模型拿不到足够约束。我用的提示词结构是这样的:
请通过 figma-context MCP 获取节点 <节点ID> 的信息,生成 Flutter Widget 代码。 要求: 1. 使用弹性布局,不要写死绝对位置 2. 轮播区域用 PageView 实现,可左右滑动 3. 切图下载到 assets/images/ 并正确引用 4. 状态栏和底部 Home Indicator 不要生成 5. 按项目规则拆分到 lib/widgets/ 下发出后,Cursor 会先调用 MCP 的获取节点工具,返回一大段 JSON。这段 JSON 里包含层级、每个节点的宽高、颜色、字体、圆角等信息。模型读取后开始生成代码。第一次生成时,Cursor 还会调用下载切图的工具,把图片存到项目里。
生成完成后,检查几个关键点。一是布局方式,看是不是用了 Column、Row、Container 这类弹性布局,而不是一堆 Positioned。二是颜色和字号,对照设计稿看十六进制值和 fontSize 是否一致。三是切图引用路径,确认 assets/images/ 下有对应文件,pubspec.yaml 里也注册了资源目录。
flutter: assets: - assets/images/如果 pubspec 没自动加,手动补上,然后执行flutter pub get。接着跑flutter run到真机或模拟器上。第一次跑大概率会有细节偏差,比如间距不对、字体没生效、渐变丢失。这都属于正常,重点看整体结构对不对、交互有没有实现。
我实测下来,调整过 Figma 层级和命名之后,生成结果的可用度明显提升。轮播能滑动了,字体也对上了,底部按钮只用了高度约束而没有写死宽度。剩下间距的偏差,是因为 Figma 的 JSON 里间距是相对概念,MCP 在简化数据时可能丢掉了部分宽高信息。这个问题可以通过改 MCP 源码保留宽高字段来缓解,但更稳妥的做法是在提示词里明确要求「间距按 8 的倍数取整」,让模型自己补一个合理值。
验证通过的标准很简单:页面能跑起来,主要区块位置正确,交互可用,剩下的微调在可接受范围内。如果生成结果完全跑不起来,先看报错,下一节集中讲常见错误。
5. 常见报错排查:401、local proxy failed 与 reading choices
生成流程跑不通时,报错信息往往指向几个固定位置。这一节把高频错误和对应处理列出来,对照着查能省不少时间。
401 鉴权失败是最常见的。表现是 Cursor 里发起请求后返回 401,或者 MCP 工具调用时报未授权。原因通常是三件套没对齐:Base URL 写成了带路径的完整地址、Key 复制时多了空格、Model ID 用了不存在的名字。排查时先确认 Base URL 是 https://taotoken.net/api ,注意结尾没有多余的斜杠;Key 重新复制一次,确保没有换行符;Model ID 去模型对话页核对当前可用列表。如果用的是 Codex 的 auth.json,检查里面的字段名是否和文档一致,字段值有没有被引号包错。
local proxy failed 一般出现在 MCP 服务启动阶段。表现是 Cursor 的 MCP 面板显示服务不可用,或者日志里提示连接本地端口失败。原因是 MCP 服务进程没起来,可能是 npx 拉包失败、Node 版本不兼容、或者端口被占用。处理方式是先在终端手动执行一遍启动命令,看具体报什么错。如果是拉包慢,换镜像源;如果是 Node 版本低,升级到 18 以上;如果是端口冲突,改配置里的端口或重启 Cursor。
reading choices 这类报错通常出现在模型返回结构不符合预期时。表现是 Cursor 提示解析响应失败,日志里出现 reading 'choices' 字样。这多半是模型返回了非标准格式,或者请求被中间层拦截返回了错误页。排查时先确认请求确实打到了 https://taotoken.net/api ,可以用 curl 手动发一个最小请求验证:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer 你的Key" \ -H "Content-Type: application/json" \ -d '{"model":"你的模型ID","messages":[{"role":"user","content":"hi"}]}'如果这条命令返回正常,说明链路没问题,问题在 Cursor 的配置或 MCP 的调用上。如果返回错误,看错误信息定位是 Key 问题还是模型名问题。
OAuth 相关报错一般和 Figma 令牌有关。表现是 MCP 获取节点时报权限不足或令牌失效。Figma 的个人访问令牌有有效期,过期后需要重新生成并更新到 mcp.json 的 env 里。另外确认令牌的权限范围包含读取文件内容,只勾了读取用户信息是不够的。
还有一类不报错但结果不对的情况:生成代码里图片路径是网络链接而不是本地资源。这是因为 MCP 下载切图失败,模型退而求其次用了 Figma 的图片 URL。处理方式是检查 MCP 的下载工具是否被调用、项目目录是否有写权限、assets 目录是否存在。手动建好 assets/images/ 目录再重试,成功率会高很多。
排障的核心思路是分层定位:先确认模型调用链路通不通,再确认 MCP 服务起没起,最后看 Figma 数据拿没拿到。三层都通了,剩下的就是生成质量的调优。
6. 把流程沉淀成可复用配置,持续迭代生成质量
走到这里,一条从 Figma 设计稿到 Flutter 可运行 Widget 的链路已经跑通了。回头看,真正省时间的不是某一次生成,而是把配置和规则沉淀下来,让下一个页面能直接复用。MCP 服务定义、Cursor 规则文件、Figma 命名规范,这三样固定下来之后,新页面基本就是复制节点 ID、发提示词、微调三步。
模型能力在持续更新,今天生成不理想的渐变背景或字体,换个模型或调下提示词可能就解决了。所以不要把某次结果当成上限,把配置留好,随时可以换模型重跑。需要长期做编码和 Agent 类任务的话,Coding Plan 这类入口 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 可以关注,适合把生成流程固化到日常开发里。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,配置细节以文档为准。
最后留一个实用技巧:每次生成后,把效果好的提示词和对应的 Figma 层级结构记下来,形成自己的模板库。UI 还原这件事,本质是把设计意图翻译成代码约束,模板越细,模型翻车的概率越低。下一篇会讲进一步优化的方案,包括怎么处理间距丢失和渐变还原的问题。