1. 设计稿还原这件事到底卡在哪做前端的人对“还原了吗”这四个字应该都不陌生。设计师在蓝湖上标注好了间距、字号、色值切图也上传了然后甩过来一句“这个页面什么时候能还原完”。你打开设计稿对着标注一个一个量margin-left: 24px、font-size: 14px、line-height: 22px、color: #333333写完之后本地跑起来截图对比发现差了 2px回去翻标注发现是padding不是margin。改完再截图颜色又不对因为设计稿用的是#333但项目里 SCSS 变量定义的是$text-primary: #2c2c2c。这种来回拉扯的消耗做过中后台系统或者 C 端页面的人应该都深有体会。一个中等复杂度的页面从拿到设计稿到像素级还原熟练工也得花上大半天中间还要经历“截图-对比-修改-再截图”的循环。设计师那边也难受他们不知道你改到哪一步了只能隔一会儿问一句“还原了吗”问多了你烦不问他们又不放心。我最近把 Cursor 和蓝湖通过 MCP 协议接了起来整个流程变成了在 Cursor 里选中设计稿对应的组件代码AI 直接读取蓝湖上的标注数据自动生成符合项目规范的 Vue 3 组件和 SCSS 样式。设计师在蓝湖上更新了设计稿我这边重新拉一次标注就能同步。这篇文章就把这套方案的完整落地过程拆开讲清楚包括 MCP 服务怎么部署、Cursor 怎么配置、Vue 3 SCSS 的代码怎么生成、遇到问题怎么排查。如果你也在做前端还原或者想了解 MCP 协议在实际项目里怎么用这篇内容应该能帮你省下不少折腾的时间。2. 整体方案设计与技术选型思路2.1 为什么是 MCP 而不是直接调 API蓝湖本身提供了开放平台 API理论上你可以写个脚本去拉标注数据然后手动或者半自动地生成代码。但这样做有几个问题第一你需要自己处理鉴权、分页、数据格式转换写一堆胶水代码第二每次拉数据都要切换上下文从编辑器跳到终端或者浏览器思路容易断第三AI 没法直接感知到这些数据你只能把拉下来的 JSON 复制粘贴给 AI效率很低。MCP 协议解决的就是这个问题。它的全称是 Model Context Protocol你可以把它理解成 AI 和外部工具之间的一个标准接口。Cursor 作为 MCP 客户端可以连接到实现了 MCP 协议的服务端服务端负责去调蓝湖的 API 拿数据然后把数据以 AI 能理解的方式暴露出来。这样你在 Cursor 里跟 AI 对话的时候AI 就能直接读取蓝湖上的设计稿信息不需要你手动搬运数据。提示MCP 是一个软件协议层面的概念跟硬件协议没有关系。它的核心作用是让 AI 模型能够安全、可控地访问外部数据源和工具。2.2 为什么选 Vue 3 SCSS 这套组合这个方案对技术栈其实没有硬性限制React、Vue 2、甚至原生 HTML 都能做。我选 Vue 3 SCSS 是因为当前项目本身就是这套技术栈而且 Vue 3 的script setup语法写起来比较简洁AI 生成代码的准确率也更高。SCSS 的好处是支持变量、嵌套、mixin可以把设计稿里的色值、字号、间距统一管理起来避免硬编码。具体来说我会在项目里维护一个_variables.scss文件把蓝湖上常用的设计 token 定义成 SCSS 变量。AI 生成样式的时候优先引用这些变量而不是直接写死数值。这样做的好处是设计师改了主色调我只需要改一个变量值所有页面自动生效不需要全局搜索替换。2.3 整体数据流是怎样的整个链路是这样的蓝湖设计稿 → 蓝湖开放平台 API → MCP 服务端本地运行→ Cursor MCP 客户端 → AI 模型 → 生成 Vue 3 组件代码 SCSS 样式。MCP 服务端跑在本地通过标准输入输出或者 SSE 跟 Cursor 通信。Cursor 在启动的时候会读取配置文件自动拉起 MCP 服务。你在 Cursor 的 AI 对话框里输入指令比如“帮我还原这个设计稿的卡片组件”AI 就会通过 MCP 协议去调服务端暴露的工具方法拿到标注数据然后结合你项目里的代码规范生成对应的组件代码。这套方案的核心优势在于数据是实时拉取的设计师更新了设计稿你重新拉一次就能拿到最新标注AI 直接读取结构化数据不需要你手动转录生成的代码可以按照你预设的模板和规范来减少后期调整的工作量。3. 核心细节解析与实操要点3.1 蓝湖 MCP 服务怎么部署蓝湖官方目前没有提供现成的 MCP 服务需要自己写一个。我用的方案是基于 Node.js 写一个轻量级的 MCP 服务端核心逻辑就是调蓝湖开放平台的接口拿标注数据然后按照 MCP 协议的格式暴露给 Cursor。先说一下蓝湖开放平台的鉴权方式。你需要在蓝湖的团队设置里生成一个访问令牌然后每次调接口的时候在请求头里带上这个令牌。具体的接口文档蓝湖开放平台上有核心接口就两个一个是获取设计稿列表一个是获取指定设计稿的标注详情。MCP 服务端的代码结构大概是这样// mcp-server.js import { Server } from modelcontextprotocol/sdk/server/index.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; const server new Server({ name: lanhu-mcp, version: 1.0.0, }, { capabilities: { tools: {}, }, }); // 注册工具获取设计稿标注 server.setRequestHandler(tools/list, async () ({ tools: [ { name: get_design_spec, description: 获取蓝湖设计稿的标注数据, inputSchema: { type: object, properties: { designId: { type: string, description: 设计稿 ID }, pageName: { type: string, description: 页面名称 }, }, required: [designId], }, }, ], })); server.setRequestHandler(tools/call, async (request) { if (request.params.name get_design_spec) { const { designId, pageName } request.params.arguments; const spec await fetchLanhuSpec(designId, pageName); return { content: [{ type: text, text: JSON.stringify(spec, null, 2) }], }; } }); const transport new StdioServerTransport(); await server.connect(transport);fetchLanhuSpec这个函数就是去调蓝湖的 API拿到标注数据之后做一层清洗把 AI 不需要的字段去掉只保留图层名称、位置、尺寸、颜色、字体、间距这些关键信息。注意蓝湖 API 返回的数据结构比较深图层是嵌套的。我在清洗数据的时候会把嵌套结构拍平每个图层保留一个path字段记录它的层级关系这样 AI 理解起来更直观。3.2 Cursor 这边怎么配置 MCPCursor 的 MCP 配置入口在设置里找到 Features 下面的 MCP Servers点添加。配置文件的格式是这样的{ mcpServers: { lanhu: { command: node, args: [/path/to/your/mcp-server.js], env: { LANHU_TOKEN: your_token_here } } } }command填nodeargs填你 MCP 服务端脚本的绝对路径env里把蓝湖的访问令牌传进去。保存之后 Cursor 会自动拉起这个服务你可以在 MCP Servers 列表里看到它的状态绿色圆点表示连接正常。这里有个细节要注意Cursor 启动 MCP 服务的时候工作目录可能不是你项目所在的目录。所以脚本里如果用相对路径读文件可能会找不到。我的做法是在脚本里用process.env或者__dirname来定位路径避免踩这个坑。配置好之后你在 Cursor 的 AI 对话框里输入指令AI 就能感知到这个 MCP 服务提供的工具。你可以直接说“帮我拉一下蓝湖上这个设计稿的标注”AI 会问你设计稿 ID 和页面名称然后调工具拿数据。3.3 Vue 3 组件代码的生成规范怎么定AI 生成代码的质量很大程度上取决于你给的约束条件。我在项目根目录放了一个.cursorrules文件里面写清楚了组件命名规范、目录结构、SCSS 变量引用规则、以及一些代码风格要求。比如组件命名我要求所有组件文件用 PascalCase比如UserProfileCard.vue而不是user-profile-card.vue。SCSS 类名用 BEM 风格块名跟组件名保持一致。样式里引用变量而不是硬编码色值比如color: $text-primary而不是color: #333。.cursorrules里还可以写一些示例代码让 AI 参考。比如我给了一个标准的卡片组件模板template div classuser-profile-card div classuser-profile-card__avatar img :srcavatar :altname / /div div classuser-profile-card__info h3 classuser-profile-card__name{{ name }}/h3 p classuser-profile-card__desc{{ description }}/p /div /div /template script setup langts interface Props { avatar: string; name: string; description: string; } definePropsProps(); /script style langscss scoped .user-profile-card { display: flex; align-items: center; padding: $spacing-md; background: $bg-white; border-radius: $radius-md; __avatar { width: 48px; height: 48px; border-radius: 50%; overflow: hidden; } __info { margin-left: $spacing-sm; } __name { font-size: $font-size-lg; color: $text-primary; } __desc { font-size: $font-size-sm; color: $text-secondary; } } /style有了这个模板AI 生成新组件的时候就会参照这个结构来命名风格、变量引用、BEM 写法都能保持一致。3.4 SCSS 变量体系怎么跟设计稿对齐这一步是整个方案里最关键的。如果 SCSS 变量跟设计稿的标注对不上AI 生成的代码还是得手动改。我的做法是先把蓝湖上常用的设计 token 整理出来在项目里建一个styles/_variables.scss文件。具体操作是打开蓝湖的设计稿把常用的色值、字号、间距、圆角、阴影这些属性列出来然后定义成 SCSS 变量。比如// 颜色 $text-primary: #1f1f1f; $text-secondary: #666666; $text-placeholder: #999999; $bg-white: #ffffff; $bg-gray: #f5f5f5; $border-color: #e0e0e0; $primary-color: #1890ff; // 字号 $font-size-xs: 12px; $font-size-sm: 14px; $font-size-md: 16px; $font-size-lg: 18px; $font-size-xl: 24px; // 间距 $spacing-xs: 4px; $spacing-sm: 8px; $spacing-md: 16px; $spacing-lg: 24px; $spacing-xl: 32px; // 圆角 $radius-sm: 4px; $radius-md: 8px; $radius-lg: 12px;定义好之后在.cursorrules里告诉 AI生成样式时优先使用这些变量如果设计稿的标注值跟变量值有偏差以变量值为准并在注释里说明偏差。这样做的好处是整个项目的视觉风格统一不会出现这个页面用#333那个页面用#2c2c2c的情况。提示如果设计稿的标注值跟变量值偏差超过 2px 或者色差肉眼可见建议先跟设计师确认是不是设计稿更新了但变量没同步不要直接硬编码。4. 实操过程与核心环节实现4.1 从蓝湖拉取标注数据的完整流程假设设计师在蓝湖上给了一个新的页面设计稿我需要还原成 Vue 3 组件。第一步是拿到设计稿的 ID。打开蓝湖的设计稿页面URL 里有一串 ID比如https://lanhuapp.com/web/#/item/project/detail?pidxxxxx这个pid就是设计稿 ID。拿到 ID 之后在 Cursor 的 AI 对话框里输入帮我拉取蓝湖设计稿 pidxxxxx 的标注数据页面名称是用户列表AI 会通过 MCP 服务去调蓝湖的 API把标注数据拉下来。返回的数据大概长这样{ pageName: 用户列表, layers: [ { name: 卡片容器, type: frame, x: 0, y: 0, width: 375, height: 200, backgroundColor: #ffffff, borderRadius: 8, padding: { top: 16, right: 16, bottom: 16, left: 16 } }, { name: 头像, type: image, x: 16, y: 16, width: 48, height: 48, borderRadius: 24 }, { name: 用户名, type: text, x: 80, y: 20, width: 100, height: 22, fontSize: 16, fontWeight: 500, color: #1f1f1f, content: 张三 } ] }拿到数据之后我会让 AI 先分析一下图层结构确认它理解得对不对。比如我会问“这个设计稿的布局方式是什么用 flex 还是 grid 更合适”AI 会根据图层的位置和尺寸关系给出建议。这一步很重要因为如果 AI 对布局的理解有偏差后面生成的代码结构就会有问题。4.2 生成 Vue 3 组件代码的实操记录确认布局方式之后我让 AI 生成组件代码。指令大概是这样的根据刚才拉取的标注数据生成一个 Vue 3 组件组件名是 UserListCard使用 script setup 语法样式用 SCSS引用项目里的变量文件。AI 生成的代码template div classuser-list-card div classuser-list-card__avatar img :srcavatar :altname / /div div classuser-list-card__content h3 classuser-list-card__name{{ name }}/h3 p classuser-list-card__desc{{ description }}/p /div /div /template script setup langts interface Props { avatar: string; name: string; description: string; } definePropsProps(); /script style langscss scoped .user-list-card { display: flex; align-items: flex-start; padding: $spacing-md; background: $bg-white; border-radius: $radius-md; __avatar { width: 48px; height: 48px; border-radius: 50%; overflow: hidden; flex-shrink: 0; img { width: 100%; height: 100%; object-fit: cover; } } __content { margin-left: $spacing-md; flex: 1; } __name { font-size: $font-size-md; font-weight: 500; color: $text-primary; line-height: 22px; } __desc { margin-top: $spacing-xs; font-size: $font-size-sm; color: $text-secondary; line-height: 20px; } } /style这段代码基本可以直接用但有几个细节我做了调整。第一设计稿里头像和内容的间距是 16px我用了$spacing-md正好对应。第二用户名的行高设计稿标注是 22px我直接写了line-height: 22px因为 SCSS 变量里没有定义行高变量这种一次性的值可以直接写。第三描述文字的行高是 20px同样直接写。实操心得AI 生成的代码不要直接复制粘贴就用一定要过一遍。重点检查三个方面布局方式是否符合预期、变量引用是否正确、边界情况有没有处理。比如头像加载失败的时候显示什么文字过长的时候怎么截断这些 AI 不一定能考虑到。4.3 样式还原的精度校验方法代码写完之后怎么确认还原精度我的做法是在本地跑起来用浏览器的开发者工具截图然后跟蓝湖的设计稿做对比。具体操作是在 Chrome 里打开页面按 F12 打开开发者工具用设备模拟器切成设计稿的尺寸比如 375px 宽然后截图。把截图和蓝湖的设计稿并排放在一起肉眼对比。如果发现偏差我会用开发者工具的元素检查功能看具体是哪个属性不对。比如间距差了 4px就去看是margin还是padding的问题。颜色不对就用取色器吸一下实际渲染的颜色跟设计稿的色值对比。这里有个小技巧在 Chrome 开发者工具里选中元素之后按CtrlShiftC可以快速定位到对应的 DOM 节点然后在 Styles 面板里直接修改样式值实时看效果。确认没问题之后再把修改同步回代码里。对于精度要求高的项目我会用 Playwright 写一个截图对比脚本自动截取页面截图跟设计稿做像素级对比。不过这个方案搭建成本比较高适合对还原精度要求极高的场景。日常开发用肉眼对比加开发者工具微调就够了。4.4 设计师更新设计稿后的同步流程设计师改了设计稿之后我这边不需要重新生成整个组件只需要让 AI 对比新旧标注数据的差异然后针对性地修改代码。具体操作是重新拉一次标注数据然后跟 AI 说这是更新后的标注数据跟之前的对比一下告诉我哪些地方变了然后修改对应的代码。AI 会对比两份数据找出差异点比如某个间距从 16px 变成了 12px某个色值从#333变成了#666然后定位到代码里对应的位置进行修改。这个流程比重新生成整个组件要高效得多而且不会引入不必要的改动。注意如果设计稿的改动比较大比如布局结构变了那还是重新生成组件比较稳妥。差异对比适合微调场景结构性的改动还是走完整流程。5. 常见问题与排查技巧实录5.1 MCP 服务连接失败的排查思路最常见的问题是 Cursor 启动之后 MCP 服务显示红色连接不上。排查步骤是这样的第一检查 Node.js 版本。MCP SDK 对 Node.js 版本有要求建议用 18 以上的版本。在终端里跑node -v确认一下。第二检查脚本路径。Cursor 配置里的args必须是绝对路径相对路径可能会因为工作目录的问题找不到文件。在终端里手动跑一下node /path/to/mcp-server.js看能不能正常启动。第三检查环境变量。蓝湖的访问令牌如果没传进去服务启动的时候可能不会报错但调接口的时候会返回 401。在脚本里加一行console.error(process.env.LANHU_TOKEN)确认令牌有没有读到。第四看 Cursor 的日志。Cursor 的 MCP 日志在输出面板里可以找到切换到 MCP 相关的频道能看到服务启动的详细日志和报错信息。5.2 标注数据解析出来对不上的情况有时候拉下来的标注数据跟设计稿上看到的不一致比如某个图层的尺寸对不上或者颜色值有偏差。这种情况通常是以下几个原因一是设计稿有多个版本你拉的是旧版本的数据。确认一下设计稿 ID 是不是最新的。二是图层被锁定了或者隐藏了蓝湖 API 默认可能不返回隐藏图层的数据。在设计稿里把图层解锁并显示出来。三是标注数据的单位问题。蓝湖的标注数据默认是 px但如果你在设计稿里用了其他单位API 返回的值可能需要转换。检查一下设计稿的设置。四是颜色值的格式问题。蓝湖返回的颜色可能是 RGB 格式也可能是 HEX 格式需要统一转换。我在 MCP 服务里做了一层处理统一转成 HEX 格式再返回给 AI。5.3 AI 生成的代码不符合项目规范怎么办这个问题通常是因为.cursorrules文件写得不够具体。AI 对规范的理解依赖于你给的示例和约束条件。如果生成的代码命名风格不对就在.cursorrules里明确写清楚命名规则并给出正例和反例。如果变量引用不对就把变量文件的路径和可用变量列表写进去。另外Cursor 的 AI 模型对上下文的理解能力有限如果项目很大它可能记不住所有的规范。我的做法是把最常用的规范放在.cursorrules的前面确保 AI 优先读到。不常用的规范可以放到单独的文档里需要的时候手动提醒 AI。还有一个技巧是在对话里直接给 AI 反馈。比如它生成的代码用了#333而不是$text-primary你就说“样式里不要硬编码色值用 SCSS 变量”AI 会记住这个反馈并在后续生成中调整。5.4 常见问题速查表问题现象可能原因排查方法解决方案MCP 服务显示红色Node 版本过低终端跑node -v升级到 Node 18MCP 服务显示红色脚本路径错误手动跑node 脚本路径改用绝对路径调接口返回 401令牌未传入打印process.env.LANHU_TOKEN检查 Cursor 配置的 env 字段标注数据对不上设计稿版本旧确认设计稿 ID用最新版本的设计稿 ID标注数据对不上图层被隐藏在设计稿里检查图层状态解锁并显示图层颜色值格式不对API 返回 RGB打印原始数据在 MCP 服务里统一转 HEX代码命名不规范.cursorrules不具体检查规则文件补充命名规则和示例变量引用错误变量文件未告知 AI检查.cursorrules写入变量文件路径和变量列表布局方式不对AI 理解偏差先让 AI 分析布局确认后再生成代码样式精度不够未做截图对比开发者工具截图对比用元素检查微调5.5 几个踩过的坑和避坑建议第一个坑是蓝湖 API 的调用频率限制。蓝湖开放平台对接口调用有频率限制短时间内大量请求可能会被限流。我的做法是在 MCP 服务里加一个简单的缓存同一个设计稿 ID 的标注数据缓存 5 分钟避免重复请求。第二个坑是 MCP 服务的日志输出。MCP 协议通过标准输入输出通信如果你在脚本里用console.log打印调试信息可能会干扰协议通信。调试信息应该用console.error输出到标准错误流这样不会影响 MCP 的正常通信。第三个坑是 AI 生成的代码里图片路径问题。设计稿里的图片在蓝湖上是一个 URL但项目里通常会把图片下载到本地。AI 生成代码的时候可能会直接用蓝湖的 URL你需要手动替换成本地路径。我的做法是在.cursorrules里约定图片路径的格式让 AI 生成占位路径然后手动替换。第四个坑是 SCSS 变量的作用域问题。如果变量文件没有在组件里正确引入编译的时候会报变量未定义的错误。Vue 3 项目里通常用use或者import引入变量文件需要在vite.config.js里配置additionalData让每个 SCSS 文件自动引入变量。// vite.config.js export default defineConfig({ css: { preprocessorOptions: { scss: { additionalData: use /styles/variables as *;, }, }, }, });这样配置之后组件里的 SCSS 就可以直接用变量不需要每个文件都手动引入。6. 这套方案的实际效果和后续扩展用这套方案跑了大概两周最直观的感受是还原一个中等复杂度页面的时间从原来的 3-4 小时压缩到了 1 小时左右。省下来的时间主要是在“量标注”和“写样式”这两个环节AI 直接读数据生成代码我只需要做校验和微调。设计师那边也不再频繁追问“还原了吗”因为我在蓝湖上更新设计稿之后重新拉一次数据就能同步他们能看到进度。后续我打算在这几个方向继续优化一是把截图对比做成自动化用 Playwright 定时跑截图任务跟设计稿做像素级 diff有偏差自动告警二是把常用的组件模板沉淀到.cursorrules里让 AI 生成的代码更贴近项目风格三是探索把 MCP 服务部署到团队内部让其他前端同事也能用上这套流程减少重复配置的成本。如果你也在做前端还原建议先从一个小页面开始试把 MCP 服务和 Cursor 配置跑通感受一下整个流程。跑通之后再逐步把 SCSS 变量体系和代码规范补全效果会越来越明显。遇到问题优先看 Cursor 的 MCP 日志和蓝湖 API 的返回数据大部分问题都能从日志里找到线索。