@pascal-app/mcp 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +166 -62
  3. package/dist/bin/pascal-mcp.js +1 -1
  4. package/dist/bridge/agent-session.d.ts +18 -0
  5. package/dist/bridge/agent-session.d.ts.map +1 -0
  6. package/dist/bridge/agent-session.js +15 -0
  7. package/dist/bridge/index.d.ts +1 -1
  8. package/dist/bridge/index.d.ts.map +1 -1
  9. package/dist/bridge/scene-bridge.d.ts +3 -0
  10. package/dist/bridge/scene-bridge.d.ts.map +1 -1
  11. package/dist/bridge/scene-bridge.js +7 -0
  12. package/dist/lib/safe-fetch.d.ts +22 -4
  13. package/dist/lib/safe-fetch.d.ts.map +1 -1
  14. package/dist/lib/safe-fetch.js +233 -134
  15. package/dist/operations/scene-operations.d.ts +18 -0
  16. package/dist/operations/scene-operations.d.ts.map +1 -1
  17. package/dist/operations/scene-operations.js +11 -0
  18. package/dist/prompts/from-brief.d.ts +1 -1
  19. package/dist/prompts/from-brief.d.ts.map +1 -1
  20. package/dist/prompts/from-brief.js +3 -3
  21. package/dist/prompts/index.d.ts +1 -1
  22. package/dist/prompts/index.d.ts.map +1 -1
  23. package/dist/prompts/iterate-on-feedback.d.ts +1 -1
  24. package/dist/prompts/iterate-on-feedback.d.ts.map +1 -1
  25. package/dist/prompts/iterate-on-feedback.js +2 -2
  26. package/dist/prompts/renovation-from-photos.d.ts +1 -1
  27. package/dist/prompts/renovation-from-photos.d.ts.map +1 -1
  28. package/dist/prompts/renovation-from-photos.js +2 -2
  29. package/dist/prompts/scene-guidance.d.ts.map +1 -1
  30. package/dist/prompts/scene-guidance.js +10 -3
  31. package/dist/resources/agent-guide.d.ts +1 -1
  32. package/dist/resources/agent-guide.d.ts.map +1 -1
  33. package/dist/resources/agent-guide.js +52 -44
  34. package/dist/resources/catalog-items.d.ts +1 -1
  35. package/dist/resources/catalog-items.d.ts.map +1 -1
  36. package/dist/resources/constraints.d.ts +1 -1
  37. package/dist/resources/constraints.d.ts.map +1 -1
  38. package/dist/resources/constraints.js +1 -1
  39. package/dist/resources/design-schema.d.ts +1 -1
  40. package/dist/resources/design-schema.d.ts.map +1 -1
  41. package/dist/resources/index.d.ts +1 -1
  42. package/dist/resources/index.d.ts.map +1 -1
  43. package/dist/resources/scene-current.d.ts +1 -1
  44. package/dist/resources/scene-current.d.ts.map +1 -1
  45. package/dist/resources/scene-summary.d.ts +1 -1
  46. package/dist/resources/scene-summary.d.ts.map +1 -1
  47. package/dist/server.d.ts +7 -2
  48. package/dist/server.d.ts.map +1 -1
  49. package/dist/server.js +59 -21
  50. package/dist/storage/disk-artifact-store.d.ts.map +1 -1
  51. package/dist/storage/sqlite-scene-store.d.ts +1 -1
  52. package/dist/storage/sqlite-scene-store.d.ts.map +1 -1
  53. package/dist/storage/types.d.ts +4 -4
  54. package/dist/storage/types.d.ts.map +1 -1
  55. package/dist/templates/empty-studio.d.ts +3 -3
  56. package/dist/templates/empty-studio.d.ts.map +1 -1
  57. package/dist/templates/garden-house.d.ts +3 -3
  58. package/dist/templates/garden-house.d.ts.map +1 -1
  59. package/dist/templates/index.d.ts.map +1 -1
  60. package/dist/templates/two-bedroom.d.ts +3 -3
  61. package/dist/templates/two-bedroom.d.ts.map +1 -1
  62. package/dist/tools/add-column.d.ts +1 -1
  63. package/dist/tools/add-column.d.ts.map +1 -1
  64. package/dist/tools/add-column.js +3 -2
  65. package/dist/tools/add-object.d.ts +19 -3
  66. package/dist/tools/add-object.d.ts.map +1 -1
  67. package/dist/tools/add-object.js +66 -35
  68. package/dist/tools/annotations.d.ts.map +1 -1
  69. package/dist/tools/apply-patch.d.ts +6 -2
  70. package/dist/tools/apply-patch.d.ts.map +1 -1
  71. package/dist/tools/apply-patch.js +13 -8
  72. package/dist/tools/asset-catalog.d.ts.map +1 -1
  73. package/dist/tools/asset-catalog.js +23 -0
  74. package/dist/tools/author-scene.d.ts +10 -0
  75. package/dist/tools/author-scene.d.ts.map +1 -0
  76. package/dist/tools/author-scene.js +140 -0
  77. package/dist/tools/check-collisions.d.ts +6 -6
  78. package/dist/tools/check-collisions.d.ts.map +1 -1
  79. package/dist/tools/check-collisions.js +6 -6
  80. package/dist/tools/clear-scene.d.ts +1 -1
  81. package/dist/tools/clear-scene.d.ts.map +1 -1
  82. package/dist/tools/clear-scene.js +3 -3
  83. package/dist/tools/collections.d.ts +1 -1
  84. package/dist/tools/collections.d.ts.map +1 -1
  85. package/dist/tools/collections.js +3 -2
  86. package/dist/tools/construction-tools.d.ts +6 -49
  87. package/dist/tools/construction-tools.d.ts.map +1 -1
  88. package/dist/tools/construction-tools.js +9 -158
  89. package/dist/tools/create-unit.d.ts +3 -3
  90. package/dist/tools/create-unit.d.ts.map +1 -1
  91. package/dist/tools/create-unit.js +2 -2
  92. package/dist/tools/errors.d.ts +5 -5
  93. package/dist/tools/errors.d.ts.map +1 -1
  94. package/dist/tools/errors.js +4 -4
  95. package/dist/tools/export-glb.d.ts +1 -1
  96. package/dist/tools/export-glb.d.ts.map +1 -1
  97. package/dist/tools/export-glb.js +2 -2
  98. package/dist/tools/export-json.d.ts +1 -1
  99. package/dist/tools/export-json.d.ts.map +1 -1
  100. package/dist/tools/export-json.js +2 -2
  101. package/dist/tools/get-scene.d.ts +1 -1
  102. package/dist/tools/get-scene.d.ts.map +1 -1
  103. package/dist/tools/get-scene.js +2 -2
  104. package/dist/tools/hosted-services.d.ts +1 -1
  105. package/dist/tools/hosted-services.d.ts.map +1 -1
  106. package/dist/tools/hosted-services.js +13 -3
  107. package/dist/tools/index.d.ts +4 -3
  108. package/dist/tools/index.d.ts.map +1 -1
  109. package/dist/tools/index.js +8 -13
  110. package/dist/tools/level-height-guard.d.ts +2 -0
  111. package/dist/tools/level-height-guard.d.ts.map +1 -0
  112. package/dist/tools/level-height-guard.js +11 -0
  113. package/dist/tools/list-units.d.ts +2 -2
  114. package/dist/tools/list-units.d.ts.map +1 -1
  115. package/dist/tools/list-units.js +2 -2
  116. package/dist/tools/live-sync.d.ts +1 -1
  117. package/dist/tools/live-sync.d.ts.map +1 -1
  118. package/dist/tools/live-sync.js +4 -4
  119. package/dist/tools/measure.d.ts +1 -1
  120. package/dist/tools/measure.d.ts.map +1 -1
  121. package/dist/tools/measure.js +7 -7
  122. package/dist/tools/node-world-point.d.ts +1 -1
  123. package/dist/tools/node-world-point.d.ts.map +1 -1
  124. package/dist/tools/normalize-schema-dialect.d.ts +1 -1
  125. package/dist/tools/normalize-schema-dialect.d.ts.map +1 -1
  126. package/dist/tools/normalize-schema-dialect.js +2 -3
  127. package/dist/tools/patch-guards.d.ts +6 -4
  128. package/dist/tools/patch-guards.d.ts.map +1 -1
  129. package/dist/tools/patch-guards.js +5 -2
  130. package/dist/tools/photo-to-scene/index.d.ts +1 -1
  131. package/dist/tools/photo-to-scene/index.d.ts.map +1 -1
  132. package/dist/tools/photo-to-scene/photo-to-scene.d.ts +3 -3
  133. package/dist/tools/photo-to-scene/photo-to-scene.d.ts.map +1 -1
  134. package/dist/tools/photo-to-scene/photo-to-scene.js +7 -7
  135. package/dist/tools/project-files.d.ts +4 -0
  136. package/dist/tools/project-files.d.ts.map +1 -0
  137. package/dist/tools/project-files.js +30 -0
  138. package/dist/tools/redo.d.ts +2 -2
  139. package/dist/tools/redo.d.ts.map +1 -1
  140. package/dist/tools/redo.js +2 -2
  141. package/dist/tools/retired-tools.d.ts +10 -0
  142. package/dist/tools/retired-tools.d.ts.map +1 -0
  143. package/dist/tools/retired-tools.js +22 -0
  144. package/dist/tools/roof-level-guard.d.ts +2 -0
  145. package/dist/tools/roof-level-guard.d.ts.map +1 -0
  146. package/dist/tools/roof-level-guard.js +22 -0
  147. package/dist/tools/room-tools.d.ts +47 -46
  148. package/dist/tools/room-tools.d.ts.map +1 -1
  149. package/dist/tools/room-tools.js +6 -5
  150. package/dist/tools/scene-lifecycle/create-project.d.ts +1 -1
  151. package/dist/tools/scene-lifecycle/create-project.d.ts.map +1 -1
  152. package/dist/tools/scene-lifecycle/create-project.js +5 -5
  153. package/dist/tools/scene-lifecycle/delete-scene.d.ts +1 -1
  154. package/dist/tools/scene-lifecycle/delete-scene.d.ts.map +1 -1
  155. package/dist/tools/scene-lifecycle/delete-scene.js +6 -6
  156. package/dist/tools/scene-lifecycle/get-project-status.d.ts +1 -1
  157. package/dist/tools/scene-lifecycle/get-project-status.d.ts.map +1 -1
  158. package/dist/tools/scene-lifecycle/get-project-status.js +6 -6
  159. package/dist/tools/scene-lifecycle/index.d.ts +1 -1
  160. package/dist/tools/scene-lifecycle/index.d.ts.map +1 -1
  161. package/dist/tools/scene-lifecycle/list-scenes.d.ts +1 -1
  162. package/dist/tools/scene-lifecycle/list-scenes.d.ts.map +1 -1
  163. package/dist/tools/scene-lifecycle/list-scenes.js +4 -4
  164. package/dist/tools/scene-lifecycle/load-scene.d.ts +2 -2
  165. package/dist/tools/scene-lifecycle/load-scene.d.ts.map +1 -1
  166. package/dist/tools/scene-lifecycle/load-scene.js +5 -5
  167. package/dist/tools/scene-lifecycle/metadata.d.ts +1 -1
  168. package/dist/tools/scene-lifecycle/rename-scene.d.ts +1 -1
  169. package/dist/tools/scene-lifecycle/rename-scene.d.ts.map +1 -1
  170. package/dist/tools/scene-lifecycle/rename-scene.js +6 -6
  171. package/dist/tools/scene-lifecycle/save-scene.d.ts +5 -3
  172. package/dist/tools/scene-lifecycle/save-scene.d.ts.map +1 -1
  173. package/dist/tools/scene-lifecycle/save-scene.js +80 -12
  174. package/dist/tools/scene-lifecycle/test-utils.d.ts +1 -1
  175. package/dist/tools/scene-lifecycle/test-utils.d.ts.map +1 -1
  176. package/dist/tools/set-unit-members.d.ts +2 -2
  177. package/dist/tools/set-unit-members.d.ts.map +1 -1
  178. package/dist/tools/set-unit-members.js +6 -6
  179. package/dist/tools/set-zone.d.ts +2 -2
  180. package/dist/tools/set-zone.d.ts.map +1 -1
  181. package/dist/tools/set-zone.js +30 -18
  182. package/dist/tools/shared-tools.d.ts +15 -5
  183. package/dist/tools/shared-tools.d.ts.map +1 -1
  184. package/dist/tools/shared-tools.js +242 -29
  185. package/dist/tools/structure-tools.d.ts +3 -3
  186. package/dist/tools/templates/create-from-template.d.ts +2 -2
  187. package/dist/tools/templates/create-from-template.d.ts.map +1 -1
  188. package/dist/tools/templates/create-from-template.js +6 -6
  189. package/dist/tools/templates/create-house-from-brief.d.ts +1 -1
  190. package/dist/tools/templates/create-house-from-brief.d.ts.map +1 -1
  191. package/dist/tools/templates/create-house-from-brief.js +6 -6
  192. package/dist/tools/templates/index.d.ts +1 -1
  193. package/dist/tools/templates/index.d.ts.map +1 -1
  194. package/dist/tools/templates/list-templates.d.ts +1 -1
  195. package/dist/tools/templates/list-templates.d.ts.map +1 -1
  196. package/dist/tools/templates/list-templates.js +2 -2
  197. package/dist/tools/undo.d.ts +2 -2
  198. package/dist/tools/undo.d.ts.map +1 -1
  199. package/dist/tools/undo.js +2 -2
  200. package/dist/tools/unit-members.d.ts.map +1 -1
  201. package/dist/tools/unit-members.js +6 -6
  202. package/dist/tools/variants/generate-variants.d.ts +6 -6
  203. package/dist/tools/variants/generate-variants.d.ts.map +1 -1
  204. package/dist/tools/variants/generate-variants.js +6 -6
  205. package/dist/tools/variants/index.d.ts +1 -1
  206. package/dist/tools/variants/index.d.ts.map +1 -1
  207. package/dist/tools/view-scene.d.ts +8 -2
  208. package/dist/tools/view-scene.d.ts.map +1 -1
  209. package/dist/tools/view-scene.js +17 -5
  210. package/dist/tools/vision/analyze-floorplan-image.d.ts +1 -1
  211. package/dist/tools/vision/analyze-floorplan-image.d.ts.map +1 -1
  212. package/dist/tools/vision/analyze-floorplan-image.js +7 -7
  213. package/dist/tools/vision/analyze-room-photo.d.ts +1 -1
  214. package/dist/tools/vision/analyze-room-photo.d.ts.map +1 -1
  215. package/dist/tools/vision/analyze-room-photo.js +7 -7
  216. package/dist/tools/vision/index.d.ts +1 -1
  217. package/dist/tools/vision/index.d.ts.map +1 -1
  218. package/dist/transports/http.d.ts +8 -2
  219. package/dist/transports/http.d.ts.map +1 -1
  220. package/dist/transports/http.js +9 -3
  221. package/dist/transports/stdio.d.ts +15 -9
  222. package/dist/transports/stdio.d.ts.map +1 -1
  223. package/dist/transports/stdio.js +18 -11
  224. package/examples/coordinate-conventions-demo.md +12 -13
  225. package/examples/embed-in-agent.ts +5 -6
  226. package/examples/generate-apartment.md +4 -4
  227. package/examples/photo-to-scene.md +2 -3
  228. package/examples/renovate-from-photos.md +3 -5
  229. package/package.json +13 -9
  230. package/dist/tools/describe-node.d.ts +0 -17
  231. package/dist/tools/describe-node.d.ts.map +0 -1
  232. package/dist/tools/describe-node.js +0 -99
  233. package/dist/tools/find-nodes.d.ts +0 -16
  234. package/dist/tools/find-nodes.d.ts.map +0 -1
  235. package/dist/tools/find-nodes.js +0 -204
  236. package/dist/tools/place-design.d.ts +0 -34
  237. package/dist/tools/place-design.d.ts.map +0 -1
  238. package/dist/tools/place-design.js +0 -91
  239. package/dist/tools/validate-design.d.ts +0 -136
  240. package/dist/tools/validate-design.d.ts.map +0 -1
  241. package/dist/tools/validate-design.js +0 -28
  242. package/dist/tools/validate-scene.d.ts +0 -19
  243. package/dist/tools/validate-scene.d.ts.map +0 -1
  244. package/dist/tools/validate-scene.js +0 -28
@@ -1,16 +1,23 @@
1
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
1
+ import { serveStdio, } from '@modelcontextprotocol/server/stdio';
2
2
  /**
3
- * Attach an `McpServer` to the stdio transport.
3
+ * Serve Pascal over stdio from a server factory.
4
4
  *
5
- * The server takes ownership of stdin/stdout for JSON-RPC messaging. Callers
6
- * must send any operator logging to stderr (not stdout) to avoid corrupting
7
- * the protocol stream.
5
+ * The SDK negotiates the protocol era per connection: a client that opens with
6
+ * the 2025 `initialize` handshake and one that opens with the 2026-07-28
7
+ * `server/discover` probe are both served. A server handed to
8
+ * `StdioServerTransport` directly would answer only the first. The factory can
9
+ * be called twice on one connection (a discarded probe instance, then the
10
+ * instance that serves it), so it must build a fresh, unconnected server each
11
+ * time.
8
12
  *
9
- * Resolves once the transport is started. The underlying transport keeps the
10
- * process alive as long as stdin is open, so callers typically just `await`
11
- * this and then let the event loop run.
13
+ * The connection owns stdin/stdout for JSON-RPC messaging. Callers must send
14
+ * any operator logging to stderr (not stdout) to avoid corrupting the protocol
15
+ * stream. The process stays alive while stdin is open; the connection tears
16
+ * itself down when stdin reaches end-of-file.
12
17
  */
13
- export async function connectStdio(server) {
14
- const transport = new StdioServerTransport();
15
- await server.connect(transport);
18
+ export function connectStdio(createServer, options = {}) {
19
+ return serveStdio(createServer, {
20
+ onerror: (error) => console.error('[pascal-mcp] stdio transport error', error),
21
+ ...options,
22
+ });
16
23
  }
@@ -19,43 +19,42 @@ A flat ground level with four demos, plus a labelled compass at the
19
19
  origin so the world axes are unambiguous regardless of which viewport
20
20
  you're in.
21
21
 
22
- | Section | What | Why |
23
- |---|---|---|
24
- | Reference compass at the origin | 12 m `+X` and `+Z` axis bars with arrowhead tips, short `-X` / `-Z` stubs, an origin marker, plus zone labels naming each component of `[x, z]`. | Establishes which way `+X` and `+Z` actually point in world space, independent of viewport rotation. |
25
- | **Demo A** at world `(18, 0)` | Axis-aligned 6 m × 4 m rectangle. | Baseline that matches the only example currently in `examples/generate-apartment.md` style (`[0,0] → [10,0]`). |
26
- | **Demo B** at world `(18, 10)` | The proposed README example, **verbatim**: `polygon: [[0,0],[5.196,3.0],[3.196,6.464],[-2.0,3.464]]` at this offset. | Programmatically verified to be a 6 m × 4 m rectangle whose first edge is heading 30° CCW from `+X` (side lengths 6/4/6/4 m to 4 dp, `AB · AD = 0`, heading = 30.0007°). Confirms the README's worked example produces the geometry it claims. |
27
- | **Demo C** at world `(0, 22)` and `(10, 22)` | An **L** authored on a north-up page (page-+x right, page-+y up) drawn at half scale and faded; alongside it, the same L pasted into `[x, z]` **uncorrected**, drawn at full scale and vivid. | Makes the external-coordinate gotcha visual: the author's page-+y direction lands on world +Z, which does not correspond to "screen-up" in any of Pascal's viewports. |
28
- | **Demo D** at world `(22, 22)` and `(32, 22)` | Same pairing for the L with its second coordinate reflected (`z → 5 − z`) before paste. | Makes plain that z-reflection only "corrects" a true mirror; Pascal's viewports apply a *rotation*, so the reflection produces a mirror-image of Demo C rather than a page-correct L. |
29
- | Takeaway band on the south edge | Short labels summarising the convention. | Self-documenting; readable in any viewport without an external README. |
22
+ | Section | What | Why |
23
+ | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | Reference compass at the origin | 12 m `+X` and `+Z` axis bars with arrowhead tips, short `-X` / `-Z` stubs, an origin marker, plus zone labels naming each component of `[x, z]`. | Establishes which way `+X` and `+Z` actually point in world space, independent of viewport rotation. |
25
+ | **Demo A** at world `(18, 0)` | Axis-aligned 6 m × 4 m rectangle. | Baseline that matches the only example currently in `examples/generate-apartment.md` style (`[0,0] → [10,0]`). |
26
+ | **Demo B** at world `(18, 10)` | The proposed README example, **verbatim**: `polygon: [[0,0],[5.196,3.0],[3.196,6.464],[-2.0,3.464]]` at this offset. | Programmatically verified to be a 6 m × 4 m rectangle whose first edge is heading 30° CCW from `+X` (side lengths 6/4/6/4 m to 4 dp, `AB · AD = 0`, heading = 30.0007°). Confirms the README's worked example produces the geometry it claims. |
27
+ | **Demo C** at world `(0, 22)` and `(10, 22)` | An **L** authored on a north-up page (page-+x right, page-+y up) drawn at half scale and faded; alongside it, the same L pasted into `[x, z]` **uncorrected**, drawn at full scale and vivid. | Makes the external-coordinate gotcha visual: the author's page-+y direction lands on world +Z, which does not correspond to "screen-up" in any of Pascal's viewports. |
28
+ | **Demo D** at world `(22, 22)` and `(32, 22)` | Same pairing for the L with its second coordinate reflected (`z → 5 − z`) before paste. | Makes plain that z-reflection only "corrects" a true mirror; Pascal's viewports apply a _rotation_, so the reflection produces a mirror-image of Demo C rather than a page-correct L. |
29
+ | Takeaway band on the south edge | Short labels summarising the convention. | Self-documenting; readable in any viewport without an external README. |
30
30
 
31
31
  ## What it confirms
32
32
 
33
33
  Open the scene in Pascal (or render it from the JSON) and you can read
34
34
  each claim directly off the geometry:
35
-
36
35
  1. **`[x, z] → world (x, 0, z)` is exact, no sign flip.** Demo A and
37
36
  Demo B both sit flat on the floor at Y = 0; their polygon vertices
38
37
  round-trip through `save_scene` / `get_scene` byte-identical to what
39
- was authored (graph hash matches, see `validate_scene` output).
38
+ was authored (graph hash matches, see `save_scene` output).
40
39
 
41
40
  2. **Demo B is the rectangle the README says it is.** A simple analytic
42
41
  check on its 4 vertices yields side lengths 6, 4, 6, 4 m (to 4 dp)
43
42
  with the first edge at 30.0007° from +X and perpendicular adjacent
44
43
  edges. No rendering required.
45
44
 
46
- 3. **External page coordinates *rotate* (not mirror) when pasted as
45
+ 3. **External page coordinates _rotate_ (not mirror) when pasted as
47
46
  `[x, z]` and viewed in Pascal.** Inspecting Demo C in the 2-D plan
48
47
  panel: the page-up L lands rotated 90° clockwise, so the author's
49
48
  "stem-up, foot-bottom-right" reads as "stem-on-right, foot-along-top"
50
49
  on screen. Inspecting Demo D right next to it: the z-reflected
51
- variant lands as the *mirror* of Demo C — neither matches a
50
+ variant lands as the _mirror_ of Demo C — neither matches a
52
51
  page-correct L. That demonstrates why "reflect across the axis" is
53
52
  the wrong corrective for an issue that is, in this viewport, a
54
53
  rotation.
55
54
 
56
55
  4. **The 3-D "top-down" snap is offset 45° from world axes by default.**
57
56
  Viewing the scene in 3-D and snapping to top-down from the default
58
- iso camera shows the rectangular site polygon as a *diamond* (its
57
+ iso camera shows the rectangular site polygon as a _diamond_ (its
59
58
  long edges are diagonals on screen, not axis-aligned). That's the
60
59
  camera's "up" vector being inherited from the iso start; once you
61
60
  orbit to a true axis-aligned top-down it goes away. The label
@@ -10,8 +10,7 @@
10
10
  * bun run packages/mcp/examples/embed-in-agent.ts
11
11
  */
12
12
 
13
- import { Client } from '@modelcontextprotocol/sdk/client/index.js'
14
- import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'
13
+ import { Client, InMemoryTransport } from '@modelcontextprotocol/client'
15
14
  import { createPascalMcpServer, SceneBridge } from '@pascal-app/mcp'
16
15
 
17
16
  async function main(): Promise<void> {
@@ -40,10 +39,10 @@ async function main(): Promise<void> {
40
39
 
41
40
  // 5. Find the default level, create a 5 m wall, and undo it.
42
41
  const levels = await client.callTool({
43
- name: 'find_nodes',
42
+ name: 'find_by_type',
44
43
  arguments: { type: 'level' },
45
44
  })
46
- const levelId = (levels.structuredContent as { nodes: Array<{ id: string }> }).nodes[0]?.id
45
+ const levelId = (levels.structuredContent as { results: Array<{ id: string }> }).results[0]?.id
47
46
 
48
47
  if (levelId) {
49
48
  const created = await client.callTool({
@@ -63,8 +62,8 @@ async function main(): Promise<void> {
63
62
  }
64
63
 
65
64
  // 6. Validate and export.
66
- const validation = await client.callTool({ name: 'validate_scene', arguments: {} })
67
- console.log('validation:', validation.structuredContent)
65
+ const verification = await client.callTool({ name: 'verify_scene', arguments: {} })
66
+ console.log('verification:', verification.structuredContent)
68
67
 
69
68
  const exported = await client.callTool({
70
69
  name: 'export_json',
@@ -193,14 +193,14 @@ more windows on the east façade.
193
193
  ### 6. Validate and report
194
194
 
195
195
  ```jsonc
196
- // tool: validate_scene
197
- { "name": "validate_scene", "arguments": {} }
196
+ // tool: verify_scene
197
+ { "name": "verify_scene", "arguments": {} }
198
198
  ```
199
199
 
200
200
  Response:
201
201
 
202
202
  ```jsonc
203
- { "valid": true, "errors": [] }
203
+ { "valid": true, "issues": [], "hasIssues": false, … }
204
204
  ```
205
205
 
206
206
  The agent then reads the scene summary for its response to the user:
@@ -235,6 +235,6 @@ Zustand store, the user can `undo` the change if they dislike it:
235
235
  - Mutations batch inside a single `apply_patch` so that `undo` rolls back
236
236
  the whole logical change.
237
237
  - Zones are not walls — they're polygon annotations that make later queries
238
- (`find_nodes({ zoneId })`) and planning steps much easier for the agent.
238
+ (`find_by_type({ zoneId })`) and planning steps much easier for the agent.
239
239
  - The agent never needs to speak to `@pascal-app/viewer`: everything the
240
240
  host sees flows through tools + resources + prompts.
@@ -33,7 +33,6 @@ The agent reads the attachment as a data URI and issues a single tool call:
33
33
  ```
34
34
 
35
35
  Optional knobs:
36
-
37
36
  - `save` (default `true`) — if `false`, the response includes `graph`
38
37
  inline instead of persisting to the `SceneStore`.
39
38
  - `defaultWallThickness` (default `0.2` m) — used when the vision model
@@ -56,7 +55,7 @@ Optional knobs:
56
55
  re-parsed with `AnyNode.safeParse`; invalid ones are dropped with a
57
56
  warning appended to `notes`.
58
57
  4. `bridge.setScene(...)` swaps the live scene so any follow-up MCP call
59
- (`find_nodes`, `measure`, `apply_patch`, ...) operates on the new
58
+ (`find_by_type`, `measure`, `apply_patch`, ...) operates on the new
60
59
  geometry.
61
60
  5. If `save: true`, the graph is persisted via `SceneStore.save` and the
62
61
  response carries `sceneId` + `url: /scene/<id>`.
@@ -109,7 +108,7 @@ operate on it without reloading:
109
108
 
110
109
  > **User:** add a door on the south wall between Living and Kitchen.
111
110
 
112
- The agent calls `find_nodes({ type: "wall" })`, picks the appropriate
111
+ The agent calls `find_by_type({ type: "wall" })`, picks the appropriate
113
112
  wall, and issues `add_door` — no extra wiring needed.
114
113
 
115
114
  ## Takeaways
@@ -12,7 +12,6 @@ tools to propose a renovation plan grounded in real photos.
12
12
  ## The brief
13
13
 
14
14
  The user drops four photos into the chat:
15
-
16
15
  1. A floorplan PDF page (exported as PNG).
17
16
  2. A photo of the current living room.
18
17
  3. A photo of the current kitchen.
@@ -148,7 +147,6 @@ against the corresponding perimeter wall:
148
147
 
149
148
  Guided by the reference photo's analysis (bright neutrals, open plan,
150
149
  minimal furnishing), the agent proposes a single logical patch:
151
-
152
150
  - Remove the partition wall between Living and Kitchen.
153
151
  - Relocate the kitchen island further west.
154
152
  - Delete the bulky TV unit item; leave the sofa and coffee table.
@@ -177,9 +175,9 @@ The user can walk back with `undo`; `redo` returns them to the proposal.
177
175
  ### 6. Sanity-check
178
176
 
179
177
  ```jsonc
180
- // tool: validate_scene
181
- { "name": "validate_scene", "arguments": {} }
182
- // → { "valid": true, "errors": [] }
178
+ // tool: verify_scene
179
+ { "name": "verify_scene", "arguments": {} }
180
+ // → { "valid": true, "issues": [], "hasIssues": false, … }
183
181
 
184
182
  // tool: check_collisions
185
183
  { "name": "check_collisions", "arguments": { "levelId": "level-1" } }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@pascal-app/mcp",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Model Context Protocol server for Pascal 3D editor",
5
+ "mcpName": "app.pascal/editor",
5
6
  "type": "module",
6
7
  "main": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
@@ -61,19 +62,22 @@
61
62
  "prepublishOnly": "bun run build && bun test && bun run smoke:node"
62
63
  },
63
64
  "peerDependencies": {
64
- "@pascal-app/core": "^1.0.4"
65
+ "@pascal-app/core": "^1.0.5"
65
66
  },
66
67
  "dependencies": {
67
- "@modelcontextprotocol/sdk": "^1.30.0",
68
- "@pascal-app/geometry-script": "^1.0.4",
69
- "@pascal-app/lingo": "^0.2.0",
70
- "zod": ">=4.5.4 <4.6"
68
+ "@hono/node-server": "^1.19.15",
69
+ "@modelcontextprotocol/node": "^2.1.1",
70
+ "@modelcontextprotocol/server": "^2.3.1",
71
+ "@pascal-app/geometry-script": "^1.0.5",
72
+ "@pascal-app/lingo": "^0.5.0",
73
+ "zod": ">=4.6.7 <4.7"
71
74
  },
72
75
  "devDependencies": {
73
- "@pascal-app/core": "^1.0.4",
76
+ "@modelcontextprotocol/client": "^2.3.1",
77
+ "@pascal-app/core": "^1.0.5",
74
78
  "@pascal/typescript-config": "*",
75
- "@types/node": "^22.19.20",
76
- "typescript": "6.0.3"
79
+ "@types/node": "^26.6.5",
80
+ "typescript": "7.0.2"
77
81
  },
78
82
  "keywords": [
79
83
  "mcp",
@@ -1,17 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { z } from 'zod';
3
- import type { SceneOperations } from '../operations/index.js';
4
- export declare const describeNodeInput: {
5
- id: z.ZodString;
6
- };
7
- export declare const describeNodeOutput: {
8
- id: z.ZodString;
9
- type: z.ZodString;
10
- parentId: z.ZodNullable<z.ZodString>;
11
- ancestryIds: z.ZodArray<z.ZodString>;
12
- childrenIds: z.ZodArray<z.ZodString>;
13
- properties: z.ZodRecord<z.ZodString, z.ZodUnknown>;
14
- description: z.ZodString;
15
- };
16
- export declare function registerDescribeNode(server: McpServer, bridge: SceneOperations): void;
17
- //# sourceMappingURL=describe-node.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"describe-node.d.ts","sourceRoot":"","sources":["../../src/tools/describe-node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAIxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAKpD,eAAO,MAAM,iBAAiB;;CAE7B,CAAA;AAED,eAAO,MAAM,kBAAkB;;;;;;;;CAQ9B,CAAA;AA4CD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAiDrF"}
@@ -1,99 +0,0 @@
1
- import { floorFootprintName, getLevelDisplayName, resolveCeilingHeight } from '@pascal-app/core';
2
- import { wallResolvedHeight } from '@pascal-app/core/agent-operations';
3
- import { z } from 'zod';
4
- import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
5
- import { ErrorCode, throwMcpError } from './errors.js';
6
- import { NodeIdSchema } from './schemas.js';
7
- export const describeNodeInput = {
8
- id: NodeIdSchema,
9
- };
10
- export const describeNodeOutput = {
11
- id: z.string(),
12
- type: z.string(),
13
- parentId: z.string().nullable(),
14
- ancestryIds: z.array(z.string()),
15
- childrenIds: z.array(z.string()),
16
- properties: z.record(z.string(), z.unknown()),
17
- description: z.string(),
18
- };
19
- /**
20
- * Build a short, human-readable one-liner describing the node.
21
- * Covers the common shapes; falls back to a generic sentence otherwise.
22
- */
23
- function describe(node, bridge) {
24
- switch (node.type) {
25
- case 'wall': {
26
- const [x1, z1] = node.start;
27
- const [x2, z2] = node.end;
28
- const t = node.thickness ?? 0.1;
29
- const h = wallResolvedHeight(bridge.getNodes(), node);
30
- return `Wall from (${x1},${z1}) to (${x2},${z2}), thickness ${t.toFixed(2)}m, height ${h.toFixed(2)}m`;
31
- }
32
- case 'level':
33
- return getLevelDisplayName(node);
34
- case 'building': {
35
- const [x, y, z] = node.position;
36
- return `Building at (${x},${y},${z})`;
37
- }
38
- case 'site':
39
- return `Site with ${node.polygon?.points.length ?? 0}-sided property line`;
40
- case 'zone':
41
- return `Zone "${node.name}" with ${node.polygon.length} vertices`;
42
- case 'slab':
43
- return node.plateRole === 'base'
44
- ? `Floor footprint "${floorFootprintName(bridge.getNodes(), node)}" with ${node.polygon.length} vertices`
45
- : `Slab with ${node.polygon.length} vertices`;
46
- case 'ceiling':
47
- return `Ceiling with ${node.polygon.length} vertices, height ${resolveCeilingHeight(node, bridge.getNodes()).toFixed(2)}m`;
48
- case 'door':
49
- return `Door (${node.width.toFixed(2)}m x ${node.height.toFixed(2)}m)`;
50
- case 'window':
51
- return `Window (${node.width.toFixed(2)}m x ${node.height.toFixed(2)}m)`;
52
- case 'item': {
53
- const [x, y, z] = node.position;
54
- return `Item "${node.asset.name}" at (${x},${y},${z})`;
55
- }
56
- default:
57
- return `${node.type} node`;
58
- }
59
- }
60
- export function registerDescribeNode(server, bridge) {
61
- server.registerTool('describe_node', {
62
- title: 'Describe node',
63
- description: 'Return a structured summary of a node including its ancestry, children IDs, key properties, and a short human description.',
64
- inputSchema: describeNodeInput,
65
- outputSchema: describeNodeOutput,
66
- annotations: READ_ONLY_TOOL_ANNOTATIONS,
67
- }, async ({ id }) => {
68
- const node = bridge.getNode(id);
69
- if (!node) {
70
- throwMcpError(ErrorCode.InvalidParams, `Node not found: ${id}`);
71
- }
72
- // Ancestry minus self.
73
- const ancestry = bridge.getAncestry(id);
74
- const ancestryIds = ancestry.slice(1).map((n) => n.id);
75
- const children = bridge.getChildren(id);
76
- const childrenIds = children.map((n) => n.id);
77
- const n = node;
78
- const properties = n.type === 'wall'
79
- ? {
80
- ...n,
81
- resolvedHeight: wallResolvedHeight(bridge.getNodes(), n),
82
- heightIsExplicit: n.height !== undefined,
83
- }
84
- : n;
85
- const payload = {
86
- id: n.id,
87
- type: n.type,
88
- parentId: (n.parentId ?? null),
89
- ancestryIds,
90
- childrenIds,
91
- properties: properties,
92
- description: describe(n, bridge),
93
- };
94
- return {
95
- content: [{ type: 'text', text: JSON.stringify(payload) }],
96
- structuredContent: payload,
97
- };
98
- });
99
- }
@@ -1,16 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { z } from 'zod';
3
- import type { SceneOperations } from '../operations/index.js';
4
- export declare const findNodesInput: {
5
- type: z.ZodOptional<z.ZodString>;
6
- parentId: z.ZodOptional<z.ZodString>;
7
- levelId: z.ZodOptional<z.ZodString>;
8
- zoneId: z.ZodOptional<z.ZodString>;
9
- sourceId: z.ZodOptional<z.ZodString>;
10
- sourceIdPrefix: z.ZodOptional<z.ZodString>;
11
- };
12
- export declare const findNodesOutput: {
13
- nodes: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
14
- };
15
- export declare function registerFindNodes(server: McpServer, bridge: SceneOperations): void;
16
- //# sourceMappingURL=find-nodes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"find-nodes.d.ts","sourceRoot":"","sources":["../../src/tools/find-nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAKxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAOpD,eAAO,MAAM,cAAc;;;;;;;CAyB1B,CAAA;AAED,eAAO,MAAM,eAAe;;CAE3B,CAAA;AAmHD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAuFlF"}
@@ -1,204 +0,0 @@
1
- import { measurementCentroid, nodeRegistry } from '@pascal-app/core';
2
- import { nodeLevelFrame, transformPoint } from '@pascal-app/core/procedural-items';
3
- import { AnyNode, nodeKindOf } from '@pascal-app/core/schema';
4
- import { pointInPolygon } from '@pascal-app/core/spatial-grid';
5
- import { z } from 'zod';
6
- import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
7
- import { ErrorCode, throwMcpError } from './errors.js';
8
- import { NodeIdSchema } from './schemas.js';
9
- const CORE_NODE_KINDS = AnyNode.options.map(nodeKindOf);
10
- export const findNodesInput = {
11
- type: z
12
- .string()
13
- .min(1)
14
- .optional()
15
- .describe(`Node kind: a core kind (${CORE_NODE_KINDS.join(', ')}) or a plugin kind such as "fixture:bench".`),
16
- parentId: NodeIdSchema.optional(),
17
- levelId: NodeIdSchema.optional(),
18
- zoneId: NodeIdSchema.optional(),
19
- sourceId: z
20
- .string()
21
- .min(1)
22
- .optional()
23
- .describe('Exact match on any import source id of the node: provenance.refs[].id or legacy metadata.sourceIds. Characters outside printable ASCII also match their percent-encoded form.'),
24
- sourceIdPrefix: z
25
- .string()
26
- .min(1)
27
- .optional()
28
- .describe('Prefix match on any import source id of the node (provenance.refs[].id or legacy metadata.sourceIds).'),
29
- };
30
- export const findNodesOutput = {
31
- nodes: z.array(z.record(z.string(), z.unknown())),
32
- };
33
- /**
34
- * A source id as importers must write it for typed provenance: printable
35
- * ASCII kept, every other character percent-encoded as UTF-8 bytes.
36
- */
37
- function encodeSourceId(id) {
38
- let out = '';
39
- for (const char of id) {
40
- if (/^[\x20-\x7E]$/.test(char)) {
41
- out += char;
42
- continue;
43
- }
44
- for (const byte of new TextEncoder().encode(char)) {
45
- out += `%${byte.toString(16).toUpperCase().padStart(2, '0')}`;
46
- }
47
- }
48
- return out;
49
- }
50
- /** A node's import source ids: typed `provenance.refs[].id`, then legacy `metadata.sourceIds`. */
51
- function nodeSourceIds(node) {
52
- const typed = (node.provenance?.refs ?? []).map((ref) => ref.id);
53
- const legacy = node.metadata?.sourceIds;
54
- return Array.isArray(legacy)
55
- ? [...typed, ...legacy.filter((id) => typeof id === 'string')]
56
- : typed;
57
- }
58
- function centre(points) {
59
- if (points.length === 0)
60
- return null;
61
- const area = measurementCentroid(points.map(([x, z]) => [x, 0, z]));
62
- if (area)
63
- return [area[0], area[2]];
64
- let cx = 0;
65
- let cz = 0;
66
- for (const [x, z] of points) {
67
- cx += x;
68
- cz += z;
69
- }
70
- return [cx / points.length, cz / points.length];
71
- }
72
- function boundsCentre3(points) {
73
- if (points.length === 0)
74
- return null;
75
- const centre = [0, 0, 0];
76
- for (let axis = 0; axis < 3; axis++) {
77
- const values = points.map((p) => p[axis]);
78
- centre[axis] = (Math.min(...values) + Math.max(...values)) / 2;
79
- }
80
- return centre;
81
- }
82
- /**
83
- * The node's plan point in its level's frame, for zone filtering: a polygon's
84
- * area centroid, a segment's midpoint, a path's centre, or the origin of a
85
- * positioned node resolved through its hosts by core's `nodeLevelFrame` (a
86
- * window in its wall, a module in its cabinet); blocks and imported meshes
87
- * use their vertex-bounds centre, transformed in 3D before projecting.
88
- * Frames are plan-only (no slab support or floor lift, which only move
89
- * heights) and `frames` is shared across one query, so each host resolves once.
90
- */
91
- function levelPlanPoint(node, nodes, frames) {
92
- const n = node;
93
- if (Array.isArray(n.polygon))
94
- return centre(n.polygon);
95
- if (Array.isArray(n.start) && Array.isArray(n.end)) {
96
- const [x1, z1] = n.start;
97
- const [x2, z2] = n.end;
98
- return [(x1 + x2) / 2, (z1 + z2) / 2];
99
- }
100
- if (Array.isArray(n.path)) {
101
- const path = boundsCentre3(n.path);
102
- return path ? [path[0], path[2]] : null;
103
- }
104
- if (!Array.isArray(n.position))
105
- return null;
106
- let frame;
107
- try {
108
- frame = nodeLevelFrame(node.id, nodes, undefined, { cache: frames, planOnly: true });
109
- }
110
- catch {
111
- return null;
112
- }
113
- const local = node.type === 'block'
114
- ? boundsCentre3(node.topology.vertices.map((v) => v.position))
115
- : node.type === 'imported-mesh'
116
- ? boundsCentre3(node.primitives.flatMap((primitive) => {
117
- const out = [];
118
- for (let i = 0; i + 2 < primitive.positions.length; i += 3) {
119
- out.push([
120
- primitive.positions[i],
121
- primitive.positions[i + 1],
122
- primitive.positions[i + 2],
123
- ]);
124
- }
125
- return out;
126
- }))
127
- : null;
128
- const [x, , z] = transformPoint(frame, local ?? [0, 0, 0]);
129
- return [x, z];
130
- }
131
- /** Node kinds `type` accepts: core kinds, registered plugin kinds, and kinds in the scene. */
132
- function knownNodeKinds(nodes) {
133
- const kinds = new Set(CORE_NODE_KINDS);
134
- for (const node of Object.values(nodes))
135
- kinds.add(node.type);
136
- return kinds;
137
- }
138
- export function registerFindNodes(server, bridge) {
139
- server.registerTool('find_nodes', {
140
- title: 'Find nodes',
141
- description: 'Find nodes matching any combination of type, parentId, levelId, zoneId, sourceId or sourceIdPrefix filters. sourceId / sourceIdPrefix match the ids an importer recorded for the source elements: provenance.refs[].id, or legacy metadata.sourceIds.',
142
- inputSchema: findNodesInput,
143
- outputSchema: findNodesOutput,
144
- annotations: READ_ONLY_TOOL_ANNOTATIONS,
145
- }, async (args) => {
146
- const { type, parentId, levelId, zoneId, sourceId, sourceIdPrefix } = args;
147
- // Delegate type/parent/level filtering to the bridge.
148
- const baseFilter = {};
149
- if (type !== undefined) {
150
- if (!(knownNodeKinds(bridge.getNodes()).has(type) || nodeRegistry.get(type))) {
151
- throwMcpError(ErrorCode.InvalidParams, `unknown node type "${type}": not a core kind, a registered plugin kind or a kind in this scene`);
152
- }
153
- baseFilter.type = type;
154
- }
155
- if (parentId !== undefined)
156
- baseFilter.parentId = parentId;
157
- if (levelId !== undefined)
158
- baseFilter.levelId = levelId;
159
- let results = bridge.findNodes(baseFilter);
160
- if (sourceId !== undefined || sourceIdPrefix !== undefined) {
161
- // Legacy ids may be stored raw, typed-provenance ones percent-encoded.
162
- const exact = sourceId === undefined ? [] : [sourceId, encodeSourceId(sourceId)];
163
- const prefixes = sourceIdPrefix === undefined ? [] : [sourceIdPrefix, encodeSourceId(sourceIdPrefix)];
164
- results = results.filter((n) => {
165
- const ids = nodeSourceIds(n);
166
- if (sourceId !== undefined && !ids.some((id) => exact.includes(id)))
167
- return false;
168
- if (sourceIdPrefix !== undefined &&
169
- !ids.some((id) => prefixes.some((prefix) => id.startsWith(prefix)))) {
170
- return false;
171
- }
172
- return true;
173
- });
174
- }
175
- // Zone filter: nodes on the zone's level whose level-frame plan point
176
- // falls inside the zone polygon.
177
- if (zoneId) {
178
- const zone = bridge.getNode(zoneId);
179
- if (zone?.type !== 'zone') {
180
- // Unknown zoneId → return empty list rather than throw; matches
181
- // typical "filter" semantics.
182
- results = [];
183
- }
184
- else {
185
- const nodes = bridge.getNodes();
186
- const frames = new Map();
187
- const zoneLevelId = bridge.resolveLevelId(zone.id);
188
- results = results.filter((n) => {
189
- if (bridge.resolveLevelId(n.id) !== zoneLevelId)
190
- return false;
191
- const pt = levelPlanPoint(n, nodes, frames);
192
- return pt !== null && pointInPolygon(pt[0], pt[1], zone.polygon);
193
- });
194
- }
195
- }
196
- const payload = {
197
- nodes: results,
198
- };
199
- return {
200
- content: [{ type: 'text', text: JSON.stringify(payload) }],
201
- structuredContent: payload,
202
- };
203
- });
204
- }
@@ -1,34 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { z } from 'zod';
3
- import type { SceneOperations } from '../operations/index.js';
4
- export declare const placeDesignInput: {
5
- design: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
6
- hostId: z.ZodString;
7
- position: z.ZodArray<z.ZodNumber>;
8
- rotation: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
9
- side: z.ZodOptional<z.ZodEnum<{
10
- front: "front";
11
- back: "back";
12
- }>>;
13
- surfaceId: z.ZodOptional<z.ZodString>;
14
- parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
15
- slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
16
- name: z.ZodOptional<z.ZodString>;
17
- id: z.ZodOptional<z.ZodString>;
18
- };
19
- export declare const placeDesignOutput: {
20
- project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
21
- unsaved: z.ZodOptional<z.ZodString>;
22
- persistence: z.ZodOptional<z.ZodObject<{
23
- status: z.ZodEnum<{
24
- unbound: "unbound";
25
- events_unsupported: "events_unsupported";
26
- }>;
27
- warning: z.ZodString;
28
- }, z.core.$strip>>;
29
- designId: z.ZodString;
30
- parentId: z.ZodString;
31
- surfaceId: z.ZodNullable<z.ZodString>;
32
- };
33
- export declare function registerPlaceDesign(server: McpServer, bridge: SceneOperations): void;
34
- //# sourceMappingURL=place-design.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"place-design.d.ts","sourceRoot":"","sources":["../../src/tools/place-design.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAOpD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;CA8B5B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;CAK7B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAyDpF"}