绕过 Claude Desktop!Affinity MCP 直连 WorkBuddy/Cursor 完整配置指南(Windows) 绕过 Claude DesktopAffinity MCP 直连 WorkBuddy/Cursor 完整配置指南Windows适用人群Affinity Designer / Photo / Publisher 用户想用自然语言操控设计软件、批量处理图层、自动化设计工作流的开发者。Windows 本地配置记录把 Affinity by Canva 的 MCP 连接到 Codex楔子Affinity 终于有脚本接口了——只是藏得有点深2026 年 4 月Canva 在 Affinity 的「April 26」版本中悄悄内置了MCPModel Context Protocol服务器。官方文档只说配合 Claude Desktop 使用而且宣称中国区不可用。经过一整天的逆向分析和踩坑我成功绕过了所有限制✅中国区 Windows 版本可用设置里直接有 MCP 开关✅不需要 Claude Desktop直连 SSE 端点即可✅支持 WorkBuddy、Cursor、Codex 等任意 MCP 客户端✅暴露 11 个 MCP 工具 完整 JavaScript SDK文档、文档节点、图层、文字、颜色、填充、导出…全部 API这篇文章记录完整的发现过程和配置方法。一、前置条件条件要求Affinity 版本April 26 或更新我用的 Designer 2.6.xPhoto/Publisher 同理操作系统Windows 10/11macOS 同理端口绑定行为可能不同MCP 客户端WorkBuddy / Cursor / Codex / Claude Desktop任选打开 Affinity MCP打开 AffinityEdit → Settings → Model Context Protocol勾选Enable MCP server把下面这些权限也全部打开后面要用访问桌面上的文件访问网络使用已保存的脚本将脚本保存到脚本面板保存任务提示到设备本地内存重启 Affinity二、架构剖析官方方案的套娃结构先搞清楚官方是怎么连的才能谈怎么绕。官方连接链路Claude DesktopAI 客户端 │ │ stdio标准输入输出 ▼ Affinity ConnectorNode.js 代理npm 包 │ ant.dir.gh.canva.affinity v1.0.8 │ 安装位置%APPDATA%/Claude/Claude Extensions/ant.dir.gh.canva.affinity/ │ 入口server/index.js │ │ SSE Client Transport → http://localhost:6767/sse ▼ Affinity 应用内置 MCP Server │ 进程名Affinity.exe │ 监听[::1]:6767IPv6关键发现Claude Desktop 的 Affinity Connector 本质上就是个stdio ↔ SSE 转发代理。它没有自己的业务逻辑所有工具调用直接透传给 Affinity。代理源码印证server/index.js核心代码简化后const SSE_URL process.env.SSE_URL || http://localhost:6767/sse; // 作为 MCP Server 暴露给 Claude Desktopstdio 传输 const stdioTransport new StdioServerTransport(); await server.connect(stdioTransport); // 同时作为 MCP Client 连接到 AffinitySSE 传输 async function freshConnect() { const transport new SSEClientTransport(new URL(SSE_URL)); const client new Client({ name: Claude Desktop, version: 1.0.8 }); await client.connect(transport); upstream client; } // 工具调用直接转发 server.setRequestHandler(CallToolRequestSchema, async (request) { return await withUpstream(() upstream.callTool(request.params)); });既然代理只是个透明转发层我们当然可以直连 Affinity 的 SSE 端点完全跳过 Claude Desktop。三、配置任意 MCP 客户端Schema11 个可用工具工具描述毁坏性execute_script执行 JavaScript 脚本核心工具万物皆可操作 毁坏性render_spread渲染整个画布/页面 → base64 JPEG 只读render_selection渲染当前选中对象 → base64 JPEG 只读list_sdk_documentation列出 Affinity JavaScript SDK 全部文档主题 只读read_sdk_documentation_topic读取指定 SDK 文档内容 只读search_sdk_hints从百万级全局 hints 中搜索参考方案 只读list_library_scripts列出脚本库中所有已保存脚本 只读read_library_script读取脚本库中指定脚本源码 只读save_script_to_library将脚本保存到脚本库可复用 毁坏性add_sdk_hint贡献 hint 到全局池 毁坏性report_sdk_issue向 Serif 报告 SDK 问题 毁坏性WorkBuddy 配置编辑~/.workbuddy/mcp.json添加{ mcpServers: { affinity: { url: http://[::1]:6767/sse, transport: sse, disabled: false } } }然后去 WorkBuddy 连接器管理页面点「重连」或重启 WorkBuddy。Cursor / Codex / 其他 MCP 客户端同样的配置把url和transport写入对应的mcp.json即可{ mcpServers: { affinity: { url: http://[::1]:6767/sse, transport: sse } } }⚠️ 关键注意事项IPv6 绑定Affinity 的 MCP Server只绑定 IPv6不绑定 IPv4地址结果http://127.0.0.1:6767/sse❌ECONNREFUSEDIPv4 没人在家http://[::1]:6767/sse✅ 正常返回 SSE endpointhttp://localhost:6767/sse⚠️ 取决于系统 IPv4/IPv6 优先级不稳定必须使用[::1]格式可以用 curl 验证# 验证 IPv4应该失败 curl http://127.0.0.1:6767/sse # 验证 IPv6应该返回 SSE endpoint curl http://[::1]:6767/sse # 预期输出 # event: endpoint # data: /message?session_idxxxxxxxxxxxxxxxxxxxxx四、验证连接 初探 SDK连接成功后先让 AI 执行list_sdk_documentation查看全部可用的 SDK 文档。会返回一个庞大的清单包含Affinity JavaScript SDK 全览# 文档核心模块 document.js — 文档对象 API nodes.js — 图层/节点操作 layereffects.js — 图层效果阴影、发光等 curvesinterface.js — 贝塞尔曲线路径 shapeinterface.js — 形状操作 textframeinterface.js — 文字框 story.js — 文字排版引擎段落、字符属性、样式 selections.js — 选区管理 rasterinterface.js — 光栅/位图操作 vectorbrush.js — 矢量画笔 artboardinterface.js — 画板操作 exportconfig.js — 导出配置 colours.js — 颜色管理 fills.js — 填充渐变/图案/位图 blendmodeinterface.js — 混合模式 geometry.js — 几何变换 fonts.js — 字体管理 # 示例脚本 examples/artboardGrid.js — 创建画板网格 examples/addGuides.js — 添加参考线 examples/alignToPage.js — 对齐到页面 examples/tableFromJson.js — 从 JSON 生成表格 examples/flexibleLayout.js — 弹性布局 # 单元测试学习 API 的最佳参考 tests/documentTests.js tests/storyTests.js tests/curveTests.js ...20 个测试文件覆盖所有核心 API五、API 核心模式从猜到对⚠️ 这一节很重要——Affinity SDK 的 API 不是直觉型的踩了很多坑才跑通。5.1 必须显式require()导入Affinity 的 JS 引擎不暴露全局变量。所有模块Document、ShapeNodeDefinition、RGBA8…必须用require()导入才能使用var Document require(/document).Document; var NewDocumentOptions require(/document).NewDocumentOptions; var UnitType require(/units).UnitType; var RasterFormat require(/rasterobject).RasterFormat; var ShapeNodeDefinition require(/nodes).ShapeNodeDefinition; var Shape require(/shapes).Shape; var ShapeType require(/shapes).ShapeType; var FillDescriptor require(/fills).FillDescriptor; var RGBA8 require(/colours).RGBA8; var BlendMode require(affinity:common).BlendMode; var Rectangle require(/geometry).Rectangle;直接写Document.create(...)不导入→ReferenceError: Document is not defined。5.2 创建文档var opts NewDocumentOptions.createDefault(); opts.width 600; opts.height 240; opts.units UnitType.Pixel; opts.rasterFormat RasterFormat.RGBA8; opts.dpi 150; var doc Document.create(opts); var dpi doc.dpi; // 后面文字样式要用 var fmt doc.rasterFormat;5.3 创建形状三个坑坑 1边界框必须用new Rectangle()不能用{x,y,w,h}字面量// ❌ 报错expected RectangleHandle ShapeNodeDefinition.create(shape, {x:0, y:0, w:600, h:240}, fill, null, null, null); // ✅ 正确 ShapeNodeDefinition.create(shape, new Rectangle(0, 0, 600, 240), fill, null, null, null);坑 2create()第一个参数是Shape对象不是ShapeType枚举// ❌ 直接传枚举 ShapeNodeDefinition.create(ShapeType.Rectangle, ...); // ✅ 先用 Shape.create() 包装 var shape Shape.create(ShapeType.Rectangle); ShapeNodeDefinition.create(shape, new Rectangle(0,0,600,240), fill, null, null, null);坑 3形状必须用addShapeNode()文字才用addNode()var def ShapeNodeDefinition.create(shape, rect, fill, null, null, null); var builder AddChildNodesCommandBuilder.create(); // ❌ 形状用 addNode 会静默失败图层不出现 builder.addNode(def); // ✅ 形状用 addShapeNode builder.addShapeNode(def); doc.executeCommand(builder.createCommand(false, NodeChildType.Main));5.4 创建文字最大的坑文字节点用ArtTextNodeDefinitionStoryBuilder创建。直接addText()后文字存在但不可见——因为缺少默认文本样式。关键必须调用setToArtisticTextDefaultStyle(dpi, format)var StoryBuilder require(/storybuilder).StoryBuilder; var GlyphAtts require(/glyphatts).GlyphAtts; var GlyphAttDoubleType require(/glyphatts).GlyphAttDoubleType; var StoryDelta require(/storydelta).StoryDelta; var ArtTextNodeDefinition require(/nodes).ArtTextNodeDefinition; var sb StoryBuilder.create(); // ⚠️ 这一行是文字可见的关键不调文字就隐形 sb.setToArtisticTextDefaultStyle(dpi, fmt); // 设置字号用 applyGlyphDelta不是 ga.height sb.applyGlyphDelta( StoryDelta.createGlyphDouble(GlyphAttDoubleType.Height, 34) ); // 设置文字颜色 var ga GlyphAtts.create(); ga.brushFill FillDescriptor.createSolid(RGBA8(255, 255, 255, 255), BlendMode.Normal); sb.setGlyphAtts(ga); // ⚠️ setGlyphAtts 会重置字号必须重新 apply sb.applyGlyphDelta( StoryDelta.createGlyphDouble(GlyphAttDoubleType.Height, 34) ); // 添加文字内容 sb.addText(Hello World); // 创建节点 var def ArtTextNodeDefinition.createFromStoryBuilder({x: 50, y: 100}, sb); var builder AddChildNodesCommandBuilder.create(); builder.addNode(def); // 文字用 addNode不是 addShapeNode doc.executeCommand(builder.createCommand(false, NodeChildType.Main));5.5 渲染验证// 获取文档 UUID console.log(UUID:, doc.sessionUuid); // 输出类似UUID: 92F6B057-2CDD-4691-8599-222B4C350AF5然后用render_spread工具传入document_session_uuid和spread_index: 0得到 base64 JPEG 预览。注意render_spread的视口约为700×525px固定大小。画布尺寸超过此范围的右侧内容会被裁切。建议设计稿宽度控制在 650px 以内或使用较小画布多次渲染。六、实战程序化生成店招海报把上面的 API 组合起来用一段脚本在 Affinity 中生成完整的店招海报。效果预览深蓝底 金色装饰条 菱形装饰 中英文文字全部通过代码生成元素说明背景深海军蓝RGBA8(15, 23, 42, 255)顶/底装饰条金色矩形RGBA8(212, 175, 55, 255)左右菱形各 3 个递减大小金色菱形主标题AICSF Studio — 白色 34pt副标题AI Commercial Svc Framework — 金色 13pt中文标语让 AI 成为每个人的超级能力 — 白色 12pt角标by AICSF — 金色 9pt完整代码// 导入所有模块必须显式 require var Document require(/document).Document; var NewDocumentOptions require(/document).NewDocumentOptions; var UnitType require(/units).UnitType; var RasterFormat require(/rasterobject).RasterFormat; var ShapeNodeDefinition require(/nodes).ShapeNodeDefinition; var ArtTextNodeDefinition require(/nodes).ArtTextNodeDefinition; var AddChildNodesCommandBuilder require(/commands).AddChildNodesCommandBuilder; var NodeChildType require(/nodes).NodeChildType; var StoryBuilder require(/storybuilder).StoryBuilder; var GlyphAtts require(/glyphatts).GlyphAtts; var GlyphAttDoubleType require(/glyphatts).GlyphAttDoubleType; var FillDescriptor require(/fills).FillDescriptor; var RGBA8 require(/colours).RGBA8; var BlendMode require(affinity:common).BlendMode; var Shape require(/shapes).Shape; var ShapeType require(/shapes).ShapeType; var StoryDelta require(/storydelta).StoryDelta; var Rectangle require(/geometry).Rectangle; // 创建文档 var opts NewDocumentOptions.createDefault(); opts.width 600; opts.height 240; opts.units UnitType.Pixel; opts.rasterFormat RasterFormat.RGBA8; opts.dpi 150; var doc Document.create(opts); var dpi doc.dpi, fmt doc.rasterFormat; // 工具函数 function addShape(shapeType, x, y, w, h, fill) { var s Shape.create(shapeType); var d ShapeNodeDefinition.create(s, new Rectangle(x, y, w, h), fill, null, null, null); var b AddChildNodesCommandBuilder.create(); b.addShapeNode(d); doc.executeCommand(b.createCommand(false, NodeChildType.Main)); } function addText(text, x, y, height, fillColor) { var sb StoryBuilder.create(); sb.setToArtisticTextDefaultStyle(dpi, fmt); // 关键 sb.applyGlyphDelta(StoryDelta.createGlyphDouble(GlyphAttDoubleType.Height, height)); if (fillColor) { var ga GlyphAtts.create(); ga.brushFill fillColor; sb.setGlyphAtts(ga); sb.applyGlyphDelta(StoryDelta.createGlyphDouble(GlyphAttDoubleType.Height, height)); } sb.addText(text); var def ArtTextNodeDefinition.createFromStoryBuilder({x: x, y: y}, sb); var b AddChildNodesCommandBuilder.create(); b.addNode(def); doc.executeCommand(b.createCommand(false, NodeChildType.Main)); } // 颜色定义 var navyFill FillDescriptor.createSolid(RGBA8(15, 23, 42, 255), BlendMode.Normal); var goldFill FillDescriptor.createSolid(RGBA8(212, 175, 55, 255), BlendMode.Normal); var whiteFill FillDescriptor.createSolid(RGBA8(255, 255, 255, 255), BlendMode.Normal); var goldDimFill FillDescriptor.createSolid(RGBA8(160, 135, 30, 255), BlendMode.Normal); // 1. 深蓝背景 addShape(ShapeType.Rectangle, 0, 0, 600, 240, navyFill); // 2. 顶/底金色装饰条 addShape(ShapeType.Rectangle, 0, 0, 600, 3, goldFill); addShape(ShapeType.Rectangle, 0, 237, 600, 3, goldFill); // 3. 左侧菱形装饰3个递减 addShape(ShapeType.Diamond, 12, 88, 14, 14, goldFill); addShape(ShapeType.Diamond, 12, 108, 9, 9, goldFill); addShape(ShapeType.Diamond, 12, 124, 5, 5, goldFill); // 4. 右侧菱形装饰 addShape(ShapeType.Diamond, 574, 88, 14, 14, goldFill); addShape(ShapeType.Diamond, 579, 108, 9, 9, goldFill); addShape(ShapeType.Diamond, 582, 124, 5, 5, goldFill); // 5. 文字 addText(AICSF Studio, 32, 72, 34, whiteFill); addText(AI Commercial Svc Framework, 34, 115, 13, goldFill); addText(让 AI 成为每个人的超级能力, 34, 140, 12, whiteFill); addText(by AICSF, 490, 220, 9, goldDimFill); console.log(UUID:, doc.sessionUuid);执行后用render_spread渲染即可看到完整海报。整个过程零 UI 操作完全代码驱动。踩坑总结表问题原因解决方案Document is not defined未 require 导入每个 API 都要显式require()形状图层不出现用了addNode()形状用addShapeNode()文字用addNode()expected RectangleHandle传了{x,y,w,h}字面量必须用new Rectangle(x, y, w, h)文字创建成功但不可见缺少默认文本样式调用sb.setToArtisticTextDefaultStyle(dpi, fmt)setGlyphAtts后字号消失setGlyphAtts 重置了所有属性之后重新applyGlyphDelta设字号渲染右侧被裁切render_spread 视口 ~700px画布控制在 650px 宽以内七、常见问题Q1中国区能用吗能。官方文档说 “MCP is not available in Affinity China”但我用的就是中国区购买的版本Windows设置里 MCP 开关可用、端口正常监听。这个限制可能只是针对某些特定渠道或者未严格执行。Q2一定要 Claude Desktop 吗不。这篇文章的核心结论就是Affinity MCP Server 是独立的 SSE 服务任何支持 SSE 传输的 MCP 客户端都可以直连。Q3端口会变吗不会。端口固定6767变的是每次连接的session_idSSE 协议标准行为。Q4为什么我的连接失败检查 Affinity 是否正在运行检查Edit → Settings → Model Context Protocol → Enable MCP server是否勾选检查端口netstat -ano | findstr 6767确认使用 IPv6 地址http://[::1]:6767/sseQ5支持哪些 Affinity 产品Designer、Photo、Publisher 均支持。MCP Server 是 Affinity 框架层功能不是某个具体产品的独有功能。Q6文字创建成功但渲染不可见检查是否调用了sb.setToArtisticTextDefaultStyle(dpi, fmt)。不调用这行StoryBuilder不会设置默认填充色文字虽然存在于图层列表中doc.layers可查到plainText但渲染时完全透明。详见第五节 5.4。Q7渲染出来的画面右边被截断render_spread工具的视口约为 700×525px 固定大小超过部分被裁切。如果画布是 1200px 宽只有左侧约 650px 可见。解决方案设计稿控制在 650px 宽以内或分区域多次渲染。八、后续方向打通 MCP 并验证实战之后这些方向已经具备可行性批量设计自动化— “把文件夹里 100 张图全部加上水印导出 PNG”已验证形状文字渲染链路模板引擎— 从数据库/CSV 读取数据自动填充到 Affinity 模板生成海报本文店招海报即为原型验证图层 AI 管理— “按内容自动分组和命名所有图层”doc.layers可迭代isArtTextNode/isShapeNode可判断类型设计审查机器人— 检查颜色一致性、边距违规、字体缺失跨工具联动— ComfyUI 出图 → Affinity 排版 → 一键发布脚本库复用—save_script_to_library保存常用生成脚本后续run_saved_workflow一键调用总结阶段认知事实之前「Affinity 没有脚本接口无法自动化」错的探索「只有 Claude Desktop 能用 MCP」不完全破解后「任何 MCP 客户端都能直连 Affinity 的 SSE 端点」✅从完全没有脚本能力到11 个 MCP 工具 完整 JS SDK 直接可用再到实际跑通程序化海报生成——Affinity 的自动化潜力比想象中大得多。希望这篇文章能帮到同样在 Windows 上用 Affinity 的开发者。作者WorkBuddy × 用户联合探索日期2026-07-08初版/ 2026-07-09更新补充真实 API 模式 店招海报实战案例技术栈Affinity April 26 · MCP · SSE · WorkBuddy · JavaScript更新记录2026-07-09第五节重写为真实验证过的 API 模式替换猜测 API新增第六节店招海报完整实战代码补充踩坑总结表