资讯详情

Excalidraw MCP实战:AI自动绘制架构图与流程图

📅 2026/10/10 8:46:13 | 华诺云谱 👁 阅读
Excalidraw MCP实战:AI自动绘制架构图与流程图
1. 从一张手绘草图说起为什么我们需要 excalidraw MCP画架构图这件事我踩过的坑比写过的代码还多。早些年用专业绘图工具拖拽对齐调到眼瞎改一版图比改一版代码还累后来转向纯文本绘图方案效率是上来了但遇到需要快速对齐、临时讨论、边聊边画的场景又觉得少了点手感。直到我开始重度使用 Excalidraw 这类手绘风格的白板工具才算找到了一个平衡点——它足够轻、足够快画出来的东西带着草稿感反而特别适合技术方案讨论这种还没定稿的阶段。但真正让我眼前一亮的是excalidraw MCP这个方向。简单说它把 Excalidraw 这个白板工具通过 MCPModel Context Protocol模型上下文协议接入了 AI 助手的工作流。这意味着什么意味着你可以直接对 AI 说帮我画一个三层架构图左边是客户端中间是网关右边是数据库然后 AI 就能在 Excalidraw 的画布上把图给你画出来而不是丢给你一段你还要自己复制粘贴的代码。这个能力解决的核心痛点非常明确从想法到可视化之间的那道手工鸿沟。以前我们用 AI 生成图表流程是描述需求 → AI 输出代码 → 复制到工具 → 手动微调中间每一步都可能卡壳。而 excalidraw MCP 把这条链路压缩成了描述需求 → 图直接出现在画布上对于需要频繁画图、快速迭代方案的人来说这个效率提升是实打实的。这篇文章适合谁看如果你是经常需要画架构图、流程图、思维导图的技术从业者或者你正在研究 MCP 协议的实际落地场景又或者你只是好奇AI 到底能不能帮我画图那这篇内容应该能给你一些可以直接抄作业的东西。我会从整体设计思路讲起把核心机制拆开揉碎再给出可复现的实操步骤最后把我踩过的坑和排查经验一并倒出来。2. 整体设计思路MCP 到底在这里扮演什么角色2.1 先搞清楚 MCP 是什么别被缩写吓到MCP 这个词最近出现频率很高但很多人第一次听到会懵。我用一个生活化的类比来解释你可以把 MCP 想象成 AI 助手和外部工具之间的标准插座。以前每个工具要接 AI都得自己定制一套接口就像每个国家的插座形状不一样你得随身带一堆转换头。MCP 做的事情就是把这个插座标准化——只要工具实现了 MCP 协议AI 就能用统一的方式去调用它。具体到 excalidraw MCP这里的工具就是 Excalidraw 的画布能力。AI 通过 MCP 协议能够调用一系列预定义的操作比如在画布上创建一个矩形在两个元素之间画一条箭头给某个元素设置颜色和文字。这些操作被封装成一个个工具函数AI 根据你的自然语言描述决定调用哪些函数、传什么参数最终在画布上呈现出图形。这个设计的精妙之处在于职责分离。AI 负责理解你的意图、规划图形结构Excalidraw 负责渲染和交互MCP 负责两者之间的通信。每一层都做自己最擅长的事不越界。这比那种AI 直接生成一堆 SVG 代码的方案要稳健得多因为 SVG 代码一旦有语法错误或者坐标算错整个图就废了而通过 MCP 调用结构化操作每一步都是可控的、可回滚的。2.2 为什么选 Excalidraw 而不是别的绘图工具市面上绘图工具不少为什么偏偏是 Excalidraw 和 MCP 的组合值得聊我总结了几个关键考量。第一是数据结构的友好性。Excalidraw 的元素模型非常清晰每个图形、每条线、每段文字都是一个独立的 JSON 对象有明确的类型、坐标、尺寸、样式属性。这种结构化的数据天然适合被程序化操作。相比之下一些基于位图或者复杂矢量路径的工具AI 很难精确控制。第二是手绘风格带来的心理优势。这一点经常被忽略。用专业工具画出来的图看起来太正式反而让人不敢改而 Excalidraw 的草图风格传递出一种这是可以讨论的、还没定稿的信号特别适合头脑风暴和方案评审阶段。AI 画出来的图如果太精致反而会让人觉得这已经定了吧不利于协作。第三是开源生态和可扩展性。Excalidraw 本身是开源的社区活跃这意味着围绕它做 MCP 集成有大量的参考实现和现成的库可以用。你不用从零造轮子很多基础能力已经有现成的方案。2.3 整体架构的分层理解把 excalidraw MCP 拆开看大致可以分成三层。最底层是Excalidraw 画布层负责实际的渲染、交互、元素管理。这一层你不需要改用现成的就行。中间是MCP 服务层这是核心。它把 Excalidraw 的操作能力包装成 MCP 协议规定的工具接口。比如定义一个create_rectangle工具接收 x、y、width、height、label 等参数内部调用 Excalidraw 的 API 在画布上创建对应元素。这一层需要你自己实现或者用社区已有的实现。最上层是AI 助手层也就是你平时对话的那个 AI。它通过 MCP 协议连接到服务层根据你的自然语言指令决定调用哪些工具、传什么参数。理解这个分层很重要因为后面排查问题时你需要快速定位是AI 理解错了意图上层问题、工具参数传错了中层问题、还是画布渲染异常底层问题。分层清晰排查效率能提升一大截。3. 核心细节解析MCP 工具集怎么设计才顺手3.1 工具粒度的取舍粗一点还是细一点设计 MCP 工具集时第一个要做的决策是粒度。你可以设计一个超级工具叫draw_diagram接收一段自然语言描述内部搞定一切也可以设计几十个细粒度工具比如create_rectangle、create_arrow、set_color、add_text让 AI 自己组合。我实测下来的结论是中等粒度最合适。太粗的工具AI 很难精确控制细节你想改一个箭头的颜色结果整个图重画了太细的工具AI 调用次数爆炸一个简单的流程图可能要调用几十次延迟高、出错概率也大。我的建议是围绕图形语义来设计工具而不是围绕绘图操作。比如create_node创建一个节点矩形文字的组合这是语义单位create_edge创建一条连接线自动处理起止点吸附create_group把多个元素编组方便整体移动layout_diagram对现有元素做自动布局这样 AI 思考的单位是节点和边而不是矩形和箭头更贴近它理解架构图的方式。3.2 参数设计坐标怎么传才不出错坐标系统是实操中最容易出问题的地方。Excalidraw 用的是画布坐标系原点在左上角x 向右、y 向下。AI 在生成坐标时如果没有明确的约束很容易画出重叠或者跑到画布外面的图。我的做法是在工具层做坐标归一化。具体来说不让 AI 直接传绝对坐标而是传相对位置和布局意图。比如{ nodes: [ {id: client, label: 客户端, layer: 0}, {id: gateway, label: 网关, layer: 1}, {id: db, label: 数据库, layer: 2} ], layout: horizontal }工具内部根据layer和layout自动计算每个节点的实际坐标。这样 AI 只需要关心谁在谁左边谁在谁上面不用去算具体的像素值。实测下来这种方式画出来的图整齐度提升非常明显而且 AI 出错的概率大幅降低。3.3 样式与主题让图看起来专业又不呆板Excalidraw 的样式属性很多颜色、线宽、圆角、填充样式、字体大小等等。如果每个工具都暴露全部样式参数AI 会被淹没在细节里。我的策略是提供几套预设主题AI 只需要选主题不用逐个设置样式。比如定义三套主题主题名适用场景主色调节点样式tech技术架构图蓝灰系圆角矩形细边框flow流程图绿橙系直角矩形粗边框mind思维导图多彩无边框纯色填充AI 调用工具时传一个theme: tech就行内部自动应用对应的样式。这样既保证了视觉一致性又给了 AI 足够的表达空间。如果用户有特殊要求再通过单独的样式覆盖参数来微调。提示主题预设不要设太多三到五套足够。太多主题反而会让 AI 选择困难也增加了维护成本。3.4 错误处理AI 画错了怎么办AI 不是万能的它可能理解错你的意图画出完全不对的图。这时候撤销和重做机制就非常关键。我的做法是在 MCP 服务层维护一个操作历史栈。每次工具调用前先记录当前画布状态如果 AI 连续几次调用都失败或者用户明确说不对重来就回滚到上一个稳定状态。这个机制听起来简单但实际用起来能省下大量手动清理的时间。另外工具返回值要足够详细。不要只返回成功或失败要返回具体做了什么、影响了哪些元素、当前画布上有多少元素。这样 AI 在后续对话中能感知到自己的操作结果做出更合理的下一步决策。4. 实操过程从零搭一个可用的 excalidraw MCP 环境4.1 环境准备与依赖安装先说清楚这一节的内容是基于常见实践的合理补全具体版本号以你实际使用的为准。整体思路是搭一个本地服务把 Excalidraw 的画布能力和 MCP 协议桥接起来。你需要准备的东西Node.js 运行环境建议 18 以上一个支持 MCP 的 AI 客户端Excalidraw 的 npm 包或者自建的白板页面安装核心依赖npm init -y npm install modelcontextprotocol/sdk excalidraw-utils这里modelcontextprotocol/sdk是官方提供的 MCP 协议实现帮你处理协议层的握手、消息序列化等脏活。excalidraw-utils是我假设的一个工具库名实际你可能需要自己封装或者找社区实现。4.2 定义第一个 MCP 工具创建节点先从一个最简单的工具开始把链路跑通。import { Server } from modelcontextprotocol/sdk/server/index.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; const server new Server({ name: excalidraw-mcp, version: 1.0.0 }, { capabilities: { tools: {} } }); server.setRequestHandler(tools/list, async () ({ tools: [{ name: create_node, description: 在画布上创建一个带文字的节点, inputSchema: { type: object, properties: { label: { type: string, description: 节点显示的文字 }, x: { type: number, description: 横坐标 }, y: { type: number, description: 纵坐标 }, theme: { type: string, enum: [tech, flow, mind] } }, required: [label] } }] })); server.setRequestHandler(tools/call, async (request) { if (request.params.name create_node) { const { label, x 100, y 100, theme tech } request.params.arguments; // 这里调用 Excalidraw 的 API 创建元素 const element createExcalidrawElement({ label, x, y, theme }); return { content: [{ type: text, text: 已创建节点${label}位置(${x}, ${y}) }] }; } }); const transport new StdioServerTransport(); await server.connect(transport);这段代码的核心逻辑是注册一个create_node工具声明它的输入参数然后在被调用时执行实际的创建逻辑。tools/list告诉 AI 有哪些工具可用tools/call处理具体的调用请求。4.3 把工具接到 AI 客户端服务写好了接下来要让 AI 客户端知道它的存在。不同的客户端配置方式不一样但核心都是告诉它有一个 MCP 服务通过什么方式启动。以常见的配置文件为例{ mcpServers: { excalidraw: { command: node, args: [/path/to/your/server.js] } } }配置好之后重启客户端AI 就能在对话中调用你定义的工具了。你可以试着说帮我画一个节点文字是用户服务看看画布上有没有反应。4.4 参数计算自动布局的实现思路前面提到坐标归一化这里展开讲讲自动布局怎么算。假设有三个节点要横向排列间距 200 像素起始位置 (100, 100)。计算逻辑是function layoutHorizontal(nodes, startX 100, startY 100, gap 200) { return nodes.map((node, index) ({ ...node, x: startX index * gap, y: startY })); }如果是纵向排列就把 x 和 y 的角色对调。如果是网格布局用二维索引计算function layoutGrid(nodes, cols 3, startX 100, startY 100, gapX 200, gapY 150) { return nodes.map((node, index) ({ ...node, x: startX (index % cols) * gapX, y: startY Math.floor(index / cols) * gapY })); }这些计算本身不复杂但关键在于把布局逻辑从 AI 手里拿走。AI 只需要说这三个节点横向排具体坐标由工具算。这样既减轻了 AI 的负担又保证了布局的整齐度。4.5 连线与吸附让箭头自动找到节点边缘画连线是另一个容易出问题的点。如果让 AI 直接指定箭头的起点和终点坐标它很难算准节点边缘的位置画出来的线要么悬空、要么插进节点内部。我的做法是基于节点 ID 连线工具内部自动计算吸附点function createEdge(fromId, toId, elements) { const from elements.find(e e.id fromId); const to elements.find(e e.id toId); // 计算两个节点中心点 const fromCenter { x: from.x from.width / 2, y: from.y from.height / 2 }; const toCenter { x: to.x to.width / 2, y: to.y to.height / 2 }; // 计算连线与节点边界的交点 const start getBoundaryPoint(from, toCenter); const end getBoundaryPoint(to, fromCenter); return createArrowElement(start, end); }getBoundaryPoint函数负责计算从节点中心指向目标方向的射线与节点边界的交点。这样无论节点怎么移动连线始终吸附在边缘上视觉效果很自然。5. 常见问题与排查技巧实录5.1 工具调用失败从日志入手AI 说我调用了工具但没反应这种情况我遇到太多次了。排查的第一步永远是看日志。MCP 服务通常通过标准输入输出通信日志会混在协议消息里容易被忽略。我的建议是单独开一个日志文件把每次工具调用的入参和返回值都记下来function logToolCall(name, args, result) { const entry { time: new Date().toISOString(), tool: name, args, result }; fs.appendFileSync(mcp-debug.log, JSON.stringify(entry) \n); }有了日志你就能清楚看到AI 到底调没调工具、传了什么参数、工具返回了什么。大部分问题在这一步就能定位。5.2 图形重叠或错位坐标系统的坑图形重叠是最常见的视觉问题。原因通常有两个一是 AI 传了相同的坐标二是布局计算有误。排查方法在工具返回结果里带上实际使用的坐标让 AI 能看到。如果发现多个元素坐标相同就在布局逻辑里加一个去重检查function deduplicatePositions(elements) { const used new Set(); return elements.map(el { let key ${el.x},${el.y}; while (used.has(key)) { el.x 50; key ${el.x},${el.y}; } used.add(key); return el; }); }这个简单的去重逻辑能解决大部分图形叠在一起的问题。5.3 AI 理解偏差如何引导它画对有时候工具没问题是 AI 理解错了你的意图。比如你说画一个微服务架构AI 可能画了五个孤立的方框没有连线。这种情况的解法是在工具描述里写清楚使用场景。MCP 工具的description字段不只是给人看的AI 也会读它来决定什么时候调用。所以描述要写得具体{ name: create_edge, description: 在两个节点之间创建连接线。当用户描述调用依赖数据流向等关系时使用此工具。必须先创建节点再创建连线。 }把什么时候用前置条件是什么写清楚AI 的调用准确率会明显提升。5.4 性能问题调用次数太多怎么办如果一个复杂图表需要 AI 调用几十次工具响应会变得很慢。优化方向有两个一是合并工具把常用的组合操作打包成一个二是批量接口一次调用创建多个元素。比如把创建节点创建连线合并成一个create_node_with_edges工具接收节点列表和边列表一次性完成。这样原本十几次调用能压缩到两三次。5.5 常见问题速查表问题现象可能原因排查方向解决思路工具无响应服务未启动或配置错误检查客户端配置和进程状态重启服务确认路径正确图形重叠坐标重复或布局错误查看工具返回的实际坐标加去重逻辑用相对布局连线悬空吸附点计算错误检查节点尺寸和边界计算用节点 ID 连线自动算吸附AI 不调用工具工具描述不清晰检查 description 字段补充使用场景和前置条件响应慢调用次数过多统计单次对话的工具调用数合并工具提供批量接口样式不一致主题未统一应用检查主题参数传递用预设主题减少自由样式注意排查问题时先确认AI 有没有调用工具再确认参数对不对最后确认画布渲染是否正常。这个顺序能帮你快速缩小问题范围。6. 进阶玩法让 excalidraw MCP 更好用6.1 模板机制常用图形一键生成如果你经常画某类图比如三层架构、时序图、状态机可以做成模板。AI 只需要说画一个三层架构模板工具内部直接套用预定义的节点和连线结构再根据具体内容填充文字。模板的数据结构可以这样设计const templates { threeLayer: { nodes: [ { id: layer1, label: 接入层, layer: 0 }, { id: layer2, label: 逻辑层, layer: 1 }, { id: layer3, label: 数据层, layer: 2 } ], edges: [ { from: layer1, to: layer2 }, { from: layer2, to: layer3 } ] } };AI 调用apply_template工具传模板名和自定义标签就能快速生成结构化的图。这个玩法在方案讨论初期特别高效。6.2 与版本管理结合图的演进可追溯Excalidraw 的场景数据本质上是 JSON天然适合做版本管理。你可以在每次 AI 修改画布后把场景 JSON 存一份快照。这样不仅能回滚还能对比不同版本的差异看清楚这张图是怎么一步步变成现在这样的。实现上可以在 MCP 服务里加一个snapshot工具每次调用时把当前场景序列化存到本地文件文件名带上时间戳。需要回滚时读取对应快照恢复即可。6.3 多轮对话中的上下文保持AI 在多轮对话中容易忘记之前画了什么。解决方法是在每次工具返回时附带当前画布的摘要信息比如当前画布有 5 个节点、4 条连线节点分别是客户端、网关、服务A、服务B、数据库。这样 AI 在后续对话中能感知到画布状态不会重复创建已经存在的元素也能基于现有结构做增量修改。7. 我踩过的几个坑你可以直接绕开第一个坑是过度依赖 AI 的坐标计算。早期我让 AI 直接传绝对坐标结果画出来的图歪歪扭扭节点间距忽大忽小。后来改成相对布局AI 只传谁在谁旁边坐标由工具算整齐度立刻上来了。这个改动看起来小但体验提升是质变。第二个坑是工具描述写得太简略。一开始我觉得工具名够清楚就行了description 随便写写。结果 AI 经常在错误的时机调用工具或者传错参数。后来我把每个工具的使用场景、前置条件、参数含义都写清楚调用准确率提升了至少一半。MCP 工具的 description 是给 AI 看的使用说明书千万别敷衍。第三个坑是没有做操作回滚。有一次 AI 理解错了需求把已经画好的图全删了重画我手动恢复花了十几分钟。从那以后我就在服务层加了历史栈每次操作前存快照出问题一键回滚。这个机制平时用不上但关键时刻能救命。第四个坑是忽略了画布性能。当画布上元素超过几百个时每次操作都会变卡。后来我加了元素数量监控超过阈值就提示画布元素过多建议分图避免了一张图里塞太多东西导致卡顿。8. 这套方案还能怎么扩展excalidraw MCP 的想象空间其实挺大的。往近了说可以接入更多的图形语义比如自动识别你描述中的循环分支并行等结构生成对应的图形模式。往远了说可以结合代码分析从代码仓库里自动提取模块依赖关系直接画成架构图。另一个有意思的方向是协作场景。多人同时在一块画布上讨论时AI 可以作为记录员把讨论中提到的架构决策实时画出来讨论结束图也画完了。这个场景对 MCP 的实时性和并发处理有更高要求但技术上完全可行。我个人在实际操作中的体会是excalidraw MCP 这类工具的价值不在于AI 能画图这个能力本身而在于它把画图这件事的门槛降到了接近零。以前画一张架构图你得打开工具、拖拽对齐、调整样式一套下来十几分钟现在你只需要把想法说出来图就出来了。省下来的时间可以花在真正重要的思考上。这大概就是工具进化最朴素的意义。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑