从照片到翻新方案:用 Pascal 3D 编辑器的 MCP Vision 工具链完成实景驱动装修规划

📅 发布时间:2026/9/12 12:33:26
从照片到翻新方案:用 Pascal 3D 编辑器的 MCP Vision 工具链完成实景驱动装修规划
从照片到翻新方案用 Pascal 3D 编辑器的 MCP Vision 工具链完成实景驱动装修规划【免费下载链接】editorOpen-source 3D architectural editor with a local CLI, MCP tools, and practical workflows for humans and AI agents.项目地址: https://gitcode.com/GitHub_Trending/editor93/editor导读本文讲解 Pascal 3D 编辑器开源仓库GitHub_Trending/editor93/editorMCP 服务器中一个完整的 Agent 实战工作流如何将「renovation_from_photos提示词」与analyze_floorplan_image、analyze_room_photo两个视觉分析工具组合起来以真实照片为事实依据生成一套落地的装修翻新方案。读完本文你将掌握从「用户丢进 4 张照片 一句需求」到「场景被墙、分区、开窗、家具全量建模并通过校验」的完整工具调用链路、底层 MCP Sampling 机制、Zod 输出校验原理以及apply_patch原子化批量修改与undo/redo时间旅行的工程实现。该示例文档位于仓库 packages/mcp/examples/renovate-from-photos.md与同目录的 packages/mcp/examples/photo-to-scene.md单张平面图直接建场景互为姊妹篇。背景这条工作流解决什么问题renovation_from_photos的核心目标是让 AI Agent 基于当前状态照片 参考风格照片提出最小改动量的翻新方案而不是凭空生成。它属于 Pascal MCP 服务器提供的三个提示词之一完整清单见 packages/mcp/README.md提示词参数用途from_brief{ brief, constraints? }从一段文字需求如80 m² 两居室开始增量建场景iterate_on_feedback{ feedback }以最小 diff 满足用户反馈renovation_from_photos{ currentPhotos, referencePhotos, goals }串联视觉工具与场景变更工具产出照片驱动的翻新计划关键设计在于视觉工具只返回数据、绝不修改场景任何结构变更都必须由 Agent 通过apply_patch显式提出。这让整条链路可以审计、可回滚。前置条件宿主必须支持 MCP Sampling两个视觉工具内部使用 MCP 的samplingcreateMessage能力把图片交给宿主模型推理Claude Desktop 当前支持该能力可直接运行此工作流不支持 sampling 的宿主会收到结构化的sampling_unavailable错误此时应回退到纯文本的from_brief提示词改由用户以文字描述现状。在源码层面该检查位于 packages/mcp/src/tools/vision/analyze-floorplan-image.ts 与 packages/mcp/src/tools/vision/analyze-room-photo.ts工具先读取客户端能力server.server.getClientCapabilities()若caps?.sampling为空则直接抛出McpError(ErrorCode.InvalidRequest, sampling_unavailable)。对应的测试用例见 packages/mcp/src/tools/vision/analyze-floorplan-image.test.ts。用户需求The Brief用户向聊天窗口投入四张照片平面图——PDF 页面导出为 PNG客厅现状照片厨房现状照片灵感参考图——一本杂志里的极简北欧 Loft 风格。然后输入User:Claude, help me plan a renovation. Heres the current plan and two room photos. I want something like this Scandinavian reference — open-plan, neutral tones, keep the footprint.这句话事实上已经携带了三个关键信息保留 footprint占地轮廓、开放平面、中性色调——这些会成为goals参数的内容。Agent 的执行流程宿主加载renovation_from_photos提示词其参数组装如下currentPhotos: [data:image/png;base64,..., data:image/jpeg;base64,...] referencePhotos: [data:image/jpeg;base64,...] goals: Open-plan living/kitchen, neutral tones, keep the footprint.提示词要求 Agent 按顺序执行五步(1) 分析平面图(2) 分析每张房间照片(3) 依据平面图播种场景(4) 与参考图对比(5) 提出补丁方案。提示词的源码实现与参数解析提示词注册位于 packages/mcp/src/prompts/renovation-from-photos.ts其argsSchema全部声明为字符串类型MCP 提示词参数是 stringly-typed并提供了buildRenovationMessages纯函数来构造完整的消息数组。内部有几层值得注意的健壮性处理PREAMBLE 规则要求对每张当前照片调用analyze_floorplan_image和/或analyze_room_photo对比现状与参考分析找出与 goals 对齐的具体差异最终只发出一次apply_patch且包含收敛到目标所需的最小补丁集。同时硬性规定不得编造尺寸必须取自分析工具结果、不得改动与目标无关的节点、只允许工具调用、不许输出散文。图片输入归一化toImageContentdata:image/...;base64,...前缀会被剥离mime 类型取自 URI其余作为图片块type: imagehttp(s)://URL 回退为文本URL: ...裸 base64 通过保守检测长度 ≥ 32、长度是 4 的倍数、仅含 base64 字符后按image/jpeg当作图片块其余情况一律回退为文本绝不猜测。照片列表解析parsePhotoList支持 JSON 数组字符串与逗号分隔两种形式。最终消息结构为intro含 Goals、图片数量统计→ ## Current photos → 各当前照片 → ## Reference photos → 各参考照片 → ## Task要求只用分析工具得出的尺寸与家具生成apply_patch。这些行为在 packages/mcp/src/prompts/prompts.test.ts 中有完整测试覆盖JSON 数组解析、显式 mimeType 的 data URL、逗号分隔回退、空列表仅剩 intro task 两条消息等。1. 提取平面图Extract the floorplanAgent 调用analyze_floorplan_image把平面图 PNG 与比例提示一起交给视觉模型// tool: analyze_floorplan_image { name: analyze_floorplan_image, arguments: { image: data:image/png;base64,iVBORw0KGgoAAAANS..., scaleHint: 1 m grid, total footprint ~9.5 m × 7 m } }底层原理见 packages/mcp/src/tools/vision/analyze-floorplan-image.tsscaleHint是可选字符串如1 cm 1 m或approximately 80 m²会被拼进采样指令工具通过server.server.createMessage发起采样请求temperature: 0、maxTokens: 2000system prompt 强制模型只输出与 schema 严格一致的裸 JSON禁止 markdown 围栏、禁止解释返回文本先做 JSON 解析再用OutputSchemaZod做safeParse校验解析失败抛sampling_response_unparseable校验失败抛sampling_response_invalid均带原始文本与错误明细校验通过后payload 同时写入contentJSON 字符串与structuredContent结构化对象两个通道。工具的输入/输出 schema 如下源码 analyzeFloorplanImageInput / analyzeFloorplanImageOutput输入imagebase64 或 http(s) URL必填、scaleHint?输出walls[]start/end为[x, z]二元组thickness?、rooms[]name、polygon、approximateAreaSqM?、approximateDimensionswidthM、depthM、confidence0~1。一次典型返回{ walls: [ { start: [0, 0], end: [9.5, 0], thickness: 0.25 }, { start: [9.5, 0], end: [9.5, 7], thickness: 0.25 }, { start: [9.5, 7], end: [0, 7], thickness: 0.25 }, { start: [0, 7], end: [0, 0], thickness: 0.25 }, { start: [4.5, 0], end: [4.5, 7], thickness: 0.15 }, { start: [4.5, 3.5], end: [9.5, 3.5], thickness: 0.15 } ], rooms: [ { label: Living, polygon: [[0, 0], [4.5, 0], [4.5, 7], [0, 7]] }, { label: Kitchen, polygon: [[4.5, 0], [9.5, 0], [9.5, 3.5], [4.5, 3.5]] }, { label: Bedroom, polygon: [[4.5, 3.5], [9.5, 3.5], [9.5, 7], [4.5, 7]] } ], approximateDimensions: { widthMeters: 9.5, depthMeters: 7, areaSqMeters: 66.5 }, confidence: 0.82 }注意label与widthMeters等字段在示例中为文档演示写法源码 schema 中对应字段为name、widthM/depthM坐标一律以米为单位原点取平面图中心或左下角并保持一致见 SYSTEM_PROMPT。图片来源安全当image是http(s)://URL 时工具不会直接fetch而是走 packages/mcp/src/lib/safe-fetch.ts 的SSRF 防护抓取——阻止回环地址、链路本地含云元数据 169.254.169.254、私网段、非 http(s) 协议限制最大 20 MB、10 秒超时、最多 3 次重定向且每次跳转都重新做允许名单校验还支持PASCAL_ALLOWED_ASSET_ORIGINS环境变量追加来源白名单。抓取后按content-type嗅探 mime 类型再内联为 base64。2. 分析房间照片Analyze the room photos对客厅、厨房照片分别调用analyze_room_photo// tool: analyze_room_photo { name: analyze_room_photo, arguments: { image: data:image/jpeg;base64,/9j/4AAQ... } }返回示例{ approximateDimensions: { widthMeters: 4.4, depthMeters: 5.8, heightMeters: 2.5 }, identifiedFixtures: [ { kind: sofa, approximatePosition: [2.2, 3.5] }, { kind: coffee-table, approximatePosition: [2.2, 2.4] }, { kind: tv-unit, approximatePosition: [0.3, 2.0] } ], identifiedWindows: [ { wallHint: south, approximateWidth: 1.4, approximateHeight: 1.5 } ] }源码中的真实 schema 见 analyzeRoomPhotoOutputapproximateDimensionswidthM、lengthM、heightM?、identifiedFixtures[]type、approximatePosition?、identifiedWindows[]wallLabel?、approximateWidthM?、approximateHeightM?。system prompt 明确要求估不准的度量宁可省略可选字段也不要瞎猜fixture 的type是短语如sofa、kitchen island、door。厨房照片按同样的方式分析。两个视觉工具都标记为READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONSreadOnlyHint: true、idempotentHint: true、openWorldHint: true见 packages/mcp/src/tools/annotations.ts即只读、幂等、面向开放世界从注解层面保证它们不会改动场景。3. 播种场景Seed the sceneAgent 先读取get_scene确认默认的空Site → Building → Level骨架存在然后按平面图结果批量创建墙体// tool: apply_patch { name: apply_patch, arguments: { patches: [ { op: create, parentId: level-1, node: { type: wall, start: [0, 0], end: [9.5, 0], thickness: 0.25, height: 2.5 } }, /* ...remaining perimeter partition walls from the vision result... */ ] } }接着调用三次set_zone把平面图识别出的 Living / Kitchen / Bedroom 多边形播种为分区。坐标约定提醒Pascal 是右手坐标系X、Z 构成地平面Y 朝上长度单位为米。wall.start/wall.end、zone.polygon等二维点都是[x, z]形式第二个分量是世界的 Z深度而不是上详见 packages/mcp/README.md 的 Coordinate conventions 一节。因此平面图分析工具返回的[x, z]元组可以直接映射到墙体和分区无需翻轴。4. 开洞Cut the identified openings对视觉工具报告出的每一扇窗Agent 在对应外墙上调cut_opening{ name: cut_opening, arguments: { wallId: wall-south, type: window, position: 0.5, width: 1.4, height: 1.5 } }cut_opening的position是0..1 的沿墙归一化比例内部会换算并以墙局部米存储见 packages/mcp/README.md 的工具表。视觉分析给出的南墙 1.4 m 宽 × 1.5 m 高窗户由此转成精确的开洞参数。5. 提出翻新方案Propose the renovation受参考图分析结果的引导明亮中性色、开放平面、极简陈设Agent 提出单一逻辑补丁拆除 Living 与 Kitchen 之间的隔墙把厨房中岛向西移动删除笨重的电视柜 item保留沙发与茶几将合并后的分区重命名为Open-Plan Living / Kitchen。全部操作放进一次apply_patch{ name: apply_patch, arguments: { patches: [ { op: delete, id: wall-partition-living-kitchen, cascade: false }, { op: update, id: zone-living, data: { label: Open-Plan Living / Kitchen, polygon: [[0, 0], [9.5, 0], [9.5, 3.5], [0, 3.5]] } }, { op: delete, id: zone-kitchen, cascade: false } /* item moves / deletes for the TV unit etc. */ ] } }apply_patch的原子性保证见 packages/mcp/src/tools/apply-patch.ts输入为patches[]每个 patch 支持create/update/delete三种 op均通过PatchSchema校验所有补丁先整体验证再逐个应用——任何一个非法都会让整批失败不会出现半改状态整批操作被 Zundo 时间中间件捕获为一个可撤销的时间步返回值包含appliedOps、deletedIds、createdIds并通过publishLiveSceneSnapshot触发实时同步若编辑器与 MCP 共享PASCAL_DATA_DIR浏览器标签页可通过/api/scenes/:id/events的 SSE 流实时看到 Agent 的每次改动。正因如此用户随时可以用undo回退到翻新前用redo回到翻新方案——整条链路天然支持前后对比。6. 收尾校验Sanity-checkAgent 最后做两层一致性检查// tool: validate_scene { name: validate_scene, arguments: {} } // → { valid: true, errors: [] } // tool: check_collisions { name: check_collisions, arguments: { levelId: level-1 } } // → { collisions: [] }validate_scene用 Zod 逐个校验节点并检查父子完整性{ valid, errors: { nodeId, path, message }[] }check_collisions查找重叠 item 与越界摆放{ collisions: { aId, bId, kind }[] }。随后 Agent 汇报变更摘要 近似可用面积来自pascal://scene/current/summary资源用户即可在pascal-app/viewer中打开场景查看翻新后的 3D 布局。关键经验Takeaways视觉工具只返回数据。analyze_floorplan_image与analyze_room_photo被标记为只读/幂等READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS从不直接改动场景每一次结构变更都由 Agent 通过apply_patch显式声明整个流程可审计、可追溯。照片提供了纯文字简报无法提供的信息——近似尺寸、家具类型、窗户位置等先验数据。当用户同时给出参考图与具体文字目标时把本工作流与from_brief风格的提示词结合使用效果最佳。每个翻新步骤都是单一时间步一次apply_patch 一个可撤销单位配合undo/redo用户可以在任意时刻对比改造前 / 改造后。延伸阅读提示词实现与注册packages/mcp/src/prompts/renovation-from-photos.ts视觉工具实现与测试packages/mcp/src/tools/vision/analyze-floorplan-image.ts、packages/mcp/src/tools/vision/analyze-room-photo.ts、packages/mcp/src/tools/vision/analyze-floorplan-image.test.ts原子化补丁工具packages/mcp/src/tools/apply-patch.tsSSRF 防护抓取packages/mcp/src/lib/safe-fetch.ts提示词测试packages/mcp/src/prompts/prompts.test.ts姊妹示例单图建场景packages/mcp/examples/photo-to-scene.mdMCP 服务器总览与全部工具/资源/提示词清单packages/mcp/README.md【免费下载链接】editorOpen-source 3D architectural editor with a local CLI, MCP tools, and practical workflows for humans and AI agents.项目地址: https://gitcode.com/GitHub_Trending/editor93/editor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考