@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,4 +1,4 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import type { SceneOperations } from '../operations/index.js';
4
4
  export declare const measureInput: {
@@ -1 +1 @@
1
- {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../../src/tools/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAExE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAMpD,eAAO,MAAM,YAAY;;;CAGxB,CAAA;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;CAQzB,CAAA;AAeD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA6FhF"}
1
+ {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../../src/tools/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAE7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAMpD,eAAO,MAAM,YAAY;IACvB,MAAM;IACN,IAAI;CACL,CAAA;AAED,eAAO,MAAM,aAAa;IACxB,cAAc;IACd,SAAS;IACT,OAAO;IACP,WAAW;;;;IACX,YAAY;IACZ,KAAK;IACL,SAAS;CACV,CAAA;AAeD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA6FhF"}
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
3
- import { ErrorCode, throwMcpError } from './errors.js';
3
+ import { ProtocolErrorCode, throwMcpError } from './errors.js';
4
4
  import { resolveNodeWorldPoint } from './node-world-point.js';
5
5
  import { NodeIdSchema } from './schemas.js';
6
6
  export const measureInput = {
@@ -33,17 +33,17 @@ export function registerMeasure(server, bridge) {
33
33
  server.registerTool('measure', {
34
34
  title: 'Measure',
35
35
  description: "Measure the distance (in meters) between two nodes, or the net area of a polygon node when fromId === toId. Distance is between world-space reference points, returned as fromPoint/toPoint: a positioned node's origin in its host's frame (an item's base, a door's or window's centre in its wall), a wall's or fence's midpoint at its base, a slab's, ceiling's or zone's polygon centroid on its plane, a block's or imported mesh's vertex-bounds centre, a level's plan centre on its base plane, and another container's descendants' centre. `approximate` lists nodes whose renderer derives the pose from data not modelled here (a downspout at its gutter outlet, a gutter at the eave), with the reason.",
36
- inputSchema: measureInput,
37
- outputSchema: measureOutput,
36
+ inputSchema: z.object(measureInput),
37
+ outputSchema: z.object(measureOutput),
38
38
  annotations: READ_ONLY_TOOL_ANNOTATIONS,
39
39
  }, async ({ fromId, toId }) => {
40
40
  const from = bridge.getNode(fromId);
41
41
  if (!from) {
42
- throwMcpError(ErrorCode.InvalidParams, `Node not found: ${fromId}`);
42
+ throwMcpError(ProtocolErrorCode.InvalidParams, `Node not found: ${fromId}`);
43
43
  }
44
44
  const to = bridge.getNode(toId);
45
45
  if (!to) {
46
- throwMcpError(ErrorCode.InvalidParams, `Node not found: ${toId}`);
46
+ throwMcpError(ProtocolErrorCode.InvalidParams, `Node not found: ${toId}`);
47
47
  }
48
48
  // Self-measurement: compute area for polygon-bearing nodes.
49
49
  if (fromId === toId) {
@@ -81,9 +81,9 @@ export function registerMeasure(server, bridge) {
81
81
  }
82
82
  catch (err) {
83
83
  const reason = err instanceof Error ? err.message : String(err);
84
- throwMcpError(ErrorCode.InvalidRequest, `Cannot derive a world point for ${node.type} ${node.id}: ${reason}`);
84
+ throwMcpError(ProtocolErrorCode.InvalidRequest, `Cannot derive a world point for ${node.type} ${node.id}: ${reason}`);
85
85
  }
86
- throwMcpError(ErrorCode.InvalidRequest, `Cannot derive a world point for ${node.type} ${node.id}`);
86
+ throwMcpError(ProtocolErrorCode.InvalidRequest, `Cannot derive a world point for ${node.type} ${node.id}`);
87
87
  };
88
88
  const fromResolved = pointOf(from);
89
89
  const toResolved = pointOf(to);
@@ -9,7 +9,7 @@ type Nodes = Readonly<Record<string, AnyNode>>;
9
9
  * `@pascal-app/nodes`, so their lift is unresolved and flagged, not guessed. A
10
10
  * test keeps this list in step with the definitions.
11
11
  */
12
- export declare const HEADLESS_UNRESOLVED_FLOOR_LIFT_KINDS: readonly ["block", "cabinet", "cabinet-module", "column", "duct-terminal", "hvac-equipment", "spawn", "stair"];
12
+ export declare const HEADLESS_UNRESOLVED_FLOOR_LIFT_KINDS: readonly ['block', 'cabinet', 'cabinet-module', 'column', 'duct-terminal', 'hvac-equipment', 'spawn', 'stair'];
13
13
  /**
14
14
  * World-space reference point of any node, following the frames the viewer
15
15
  * renders it in (core's `nodeLevelFrame`, the level's stacked base Y and its
@@ -1 +1 @@
1
- {"version":3,"file":"node-world-point.d.ts","sourceRoot":"","sources":["../../src/tools/node-world-point.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mCAAmC,CAAA;AAS7D,OAAO,EACL,OAAO,EAIR,MAAM,yBAAyB,CAAA;AAEhC,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAgN9C;;;;;;;GAOG;AACH,eAAO,MAAM,oCAAoC,gHASvC,CAAA;AA6KV;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,IAAI,CAAA;IACX,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,cAAc,GAAG,IAAI,CAMrF"}
1
+ {"version":3,"file":"node-world-point.d.ts","sourceRoot":"","sources":["../../src/tools/node-world-point.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mCAAmC,CAAA;AAS7D,OAAO,EACL,OAAO,EAIR,MAAM,yBAAyB,CAAA;AAEhC,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAgN9C;;;;;;;GAOG;AACH,eAAO,MAAM,oCAAoC,YAC/C,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,OAAO,EACP,OAAO,CACC,CAAA;AA6KV;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,IAAI,CAAA;IACX,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,cAAc,GAAG,IAAI,CAMrF"}
@@ -1,3 +1,3 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  export declare function normalizeToolSchemaDialect(server: McpServer): void;
3
3
  //# sourceMappingURL=normalize-schema-dialect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"normalize-schema-dialect.d.ts","sourceRoot":"","sources":["../../src/tools/normalize-schema-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AA0CxE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAWlE"}
1
+ {"version":3,"file":"normalize-schema-dialect.d.ts","sourceRoot":"","sources":["../../src/tools/normalize-schema-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAyC9E,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAWlE"}
@@ -1,4 +1,3 @@
1
- import { ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
2
1
  const DIALECT_2020_12 = 'https://json-schema.org/draft/2020-12/schema';
3
2
  /**
4
3
  * A tuple of one item schema, `items: [A, A]` (draft-07), as 2020-12 writes an array of that length:
@@ -40,8 +39,8 @@ export function normalizeToolSchemaDialect(server) {
40
39
  if (!original)
41
40
  return;
42
41
  server.server.removeRequestHandler('tools/list');
43
- server.server.setRequestHandler(ListToolsRequestSchema, async (request, extra) => {
44
- const result = (await original(request, extra));
42
+ server.server.setRequestHandler('tools/list', async (request, ctx) => {
43
+ const result = (await original(request, ctx));
45
44
  retargetDialect(result.tools);
46
45
  return result;
47
46
  });
@@ -1,22 +1,24 @@
1
1
  import { type NodeDeletionPlan, type NodeDeletionScene } from '@pascal-app/core';
2
2
  import { AnyNode, type AnyNodeId } from '@pascal-app/core/schema';
3
3
  import type { Patch } from '../bridge/scene-bridge.js';
4
- export type PatchRefusalCode = 'node_exists' | 'identity_change' | 'immutable_field' | 'invalid_parent' | 'invalid_update' | 'regenerated_default' | 'scripted_field' | 'unknown_field' | 'unknown_material' | 'field_required' | 'shadowed_field';
4
+ export type PatchRefusalCode = 'node_exists' | 'identity_change' | 'immutable_field' | 'invalid_parent' | 'invalid_update' | 'regenerated_default' | 'scripted_field' | 'unknown_field' | 'unknown_material' | 'field_required' | 'shadowed_field' | 'roof_level' | 'roof_level_holds_storey' | 'roof_level_on_top';
5
5
  /**
6
6
  * A check apply_patch runs over the whole patch before applying it, registered by the module that
7
7
  * owns what it protects, so a feature brings its own check (the honest-update check is the
8
8
  * first). It may rewrite an update's data (the cleaned data is what is written) and
9
9
  * refuses by throwing: a PatchRefusedError comes back as `{ code, patchIndex, id, message }`, an
10
- * McpError as it is. Lower `order` runs first.
10
+ * ProtocolError as it is. What it changed in the patch it says in notes, which the answer carries.
11
+ * Lower `order` runs first.
11
12
  */
12
13
  export type PatchGuard = {
13
14
  name: string;
14
15
  order: number;
15
- run(patches: Patch[], nodes: Readonly<Record<string, AnyNode>>): void;
16
+ run(patches: Patch[], nodes: Readonly<Record<string, AnyNode>>): string[] | void;
16
17
  };
17
18
  /** Runs a guard on every apply_patch from now on; registering a guard again replaces it. */
18
19
  export declare function registerPatchGuard(guard: PatchGuard): void;
19
- export declare function runPatchGuards(patches: Patch[], nodes: Readonly<Record<string, AnyNode>>): void;
20
+ /** Runs every guard in order; the notes are what the guards changed in the patch. */
21
+ export declare function runPatchGuards(patches: Patch[], nodes: Readonly<Record<string, AnyNode>>): string[];
20
22
  /**
21
23
  * A patch op refused because it would break node identity, the hierarchy or
22
24
  * the node's schema. apply_patch returns it as a tool error whose text is
@@ -1 +1 @@
1
- {"version":3,"file":"patch-guards.d.ts","sourceRoot":"","sources":["../../src/tools/patch-guards.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAKvB,MAAM,kBAAkB,CAAA;AAKzB,OAAO,EAAE,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,yBAAyB,CAAA;AACxF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAEnD,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,iBAAiB,GACjB,iBAAiB,GACjB,gBAAgB,GAChB,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,GAEhB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,CAAA;AAEpB;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAA;CACtE,CAAA;AAID,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,QAKnD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,QAExF;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAExC,QAAQ,CAAC,IAAI,EAAE,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAFd,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM;CAKjB;AAkDD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,KAAK,EAAE,EACzB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,WAAW,EAAE,SAAS,SAAS,EAAE,EACjC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,gBAAgB,GAC9E,IAAI,CA+KN"}
1
+ {"version":3,"file":"patch-guards.d.ts","sourceRoot":"","sources":["../../src/tools/patch-guards.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAKvB,MAAM,kBAAkB,CAAA;AAKzB,OAAO,EAAE,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,yBAAyB,CAAA;AACxF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAEnD,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,iBAAiB,GACjB,iBAAiB,GACjB,gBAAgB,GAChB,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,GAEhB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAEhB,YAAY,GACZ,yBAAyB,GACzB,mBAAmB,CAAA;AAEvB;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;CACjF,CAAA;AAID,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,QAKnD;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAC5B,OAAO,EAAE,KAAK,EAAE,EAChB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACvC,MAAM,EAAE,CAKV;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAExC,QAAQ,CAAC,IAAI,EAAE,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM;IAHzB,YACW,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EAIf;CACF;AAkDD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,KAAK,EAAE,EACzB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,WAAW,EAAE,SAAS,SAAS,EAAE,EACjC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,gBAAgB,GAC9E,IAAI,CA+KN"}
@@ -11,9 +11,12 @@ export function registerPatchGuard(guard) {
11
11
  guards.push(guard);
12
12
  guards.sort((a, b) => a.order - b.order);
13
13
  }
14
+ /** Runs every guard in order; the notes are what the guards changed in the patch. */
14
15
  export function runPatchGuards(patches, nodes) {
15
- for (const guard of guards)
16
- guard.run(patches, nodes);
16
+ return guards.flatMap((guard) => {
17
+ const notes = guard.run(patches, nodes);
18
+ return Array.isArray(notes) ? notes : [];
19
+ });
17
20
  }
18
21
  /**
19
22
  * A patch op refused because it would break node identity, the hierarchy or
@@ -1,4 +1,4 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  import type { SceneOperations } from '../../operations/index.js';
3
3
  /**
4
4
  * Register the `photo_to_scene` orchestrator tool. Chains the vision
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/photo-to-scene/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGvD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAEzF;AAED,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/photo-to-scene/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGvD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAEzF;AAED,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA"}
@@ -1,4 +1,4 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import type { SceneOperations } from '../../operations/index.js';
4
4
  /**
@@ -10,8 +10,8 @@ export declare const photoToSceneInput: {
10
10
  scaleHint: z.ZodOptional<z.ZodString>;
11
11
  name: z.ZodDefault<z.ZodString>;
12
12
  save: z.ZodDefault<z.ZodBoolean>;
13
- defaultWallThickness: z.ZodDefault<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
14
- defaultWallHeight: z.ZodDefault<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
13
+ defaultWallThickness: z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
14
+ defaultWallHeight: z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
15
15
  };
16
16
  export declare const photoToSceneOutput: {
17
17
  sceneId: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"photo-to-scene.d.ts","sourceRoot":"","sources":["../../../src/tools/photo-to-scene/photo-to-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAMxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;CAa7B,CAAA;AAED,eAAO,MAAM,kBAAkB;;;;;;;;CAQ9B,CAAA;AAmTD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA8ErF"}
1
+ {"version":3,"file":"photo-to-scene.d.ts","sourceRoot":"","sources":["../../../src/tools/photo-to-scene/photo-to-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAM7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD;;;GAGG;AACH,eAAO,MAAM,iBAAiB;IAC5B,KAAK;IACL,SAAS;IACT,IAAI;IACJ,IAAI;IACJ,oBAAoB;IAIpB,iBAAiB;CAIlB,CAAA;AAED,eAAO,MAAM,kBAAkB;IAC7B,OAAO;IACP,GAAG;IACH,KAAK;IACL,KAAK;IACL,UAAU;IACV,KAAK;IACL,KAAK;CACN,CAAA;AAmTD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA8ErF"}
@@ -1,4 +1,4 @@
1
- import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
1
+ import { ProtocolError, ProtocolErrorCode } from '@modelcontextprotocol/server';
2
2
  import { newZone } from '@pascal-app/core';
3
3
  import { AnyNode, BuildingNode, LevelNode, SiteNode, WallNode } from '@pascal-app/core/schema';
4
4
  import { z } from 'zod';
@@ -122,7 +122,7 @@ function extractText(content) {
122
122
  async function callVisionSampling(server, image, scaleHint) {
123
123
  const caps = server.server.getClientCapabilities();
124
124
  if (!caps?.sampling) {
125
- throw new McpError(ErrorCode.InvalidRequest, 'sampling_unavailable');
125
+ throw new ProtocolError(ProtocolErrorCode.InvalidRequest, 'sampling_unavailable');
126
126
  }
127
127
  const imageBlock = await resolveImageBlock(image);
128
128
  const instruction = scaleHint
@@ -141,7 +141,7 @@ async function callVisionSampling(server, image, scaleHint) {
141
141
  });
142
142
  const text = extractText(response.content);
143
143
  if (!text) {
144
- throw new McpError(ErrorCode.InternalError, 'sampling_response_unparseable', {
144
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_unparseable', {
145
145
  reason: 'no text content returned by host',
146
146
  });
147
147
  }
@@ -150,14 +150,14 @@ async function callVisionSampling(server, image, scaleHint) {
150
150
  parsed = JSON.parse(text);
151
151
  }
152
152
  catch (err) {
153
- throw new McpError(ErrorCode.InternalError, 'sampling_response_unparseable', {
153
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_unparseable', {
154
154
  raw: text,
155
155
  reason: err instanceof Error ? err.message : String(err),
156
156
  });
157
157
  }
158
158
  const validation = VisionResponseSchema.safeParse(parsed);
159
159
  if (!validation.success) {
160
- throw new McpError(ErrorCode.InternalError, 'sampling_response_invalid', {
160
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_invalid', {
161
161
  raw: text,
162
162
  errors: validation.error.issues,
163
163
  });
@@ -280,8 +280,8 @@ export function registerPhotoToScene(server, bridge) {
280
280
  server.registerTool('photo_to_scene', {
281
281
  title: 'Photo to Pascal scene',
282
282
  description: 'Orchestrator: analyse a floor-plan photo via MCP sampling, translate the structured vision result into a Pascal SceneGraph (site → building → level with walls and zones), optionally save it, and swap the bridge to the new scene. Requires host support for sampling.',
283
- inputSchema: photoToSceneInput,
284
- outputSchema: photoToSceneOutput,
283
+ inputSchema: z.object(photoToSceneInput),
284
+ outputSchema: z.object(photoToSceneOutput),
285
285
  annotations: DESTRUCTIVE_OPEN_WORLD_TOOL_ANNOTATIONS,
286
286
  }, async ({ image, scaleHint, name, save, defaultWallThickness, defaultWallHeight }) => {
287
287
  // 1. Vision.
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
+ import { type ProjectFileToolExecutor } from '@pascal-app/core/agent-operations';
3
+ export declare function registerProjectFileTools(server: McpServer, execute: ProjectFileToolExecutor): void;
4
+ //# sourceMappingURL=project-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-files.d.ts","sourceRoot":"","sources":["../../src/tools/project-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,mCAAmC,CAAA;AAQ1C,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,uBAAuB,QAmC3F"}
@@ -0,0 +1,30 @@
1
+ import { executeProjectFileTool, } from '@pascal-app/core/agent-operations';
2
+ import { isAgentRefusal, PROJECT_FILE_TOOL_CONTRACTS, refusalPayload, } from '@pascal-app/core/agent-tools';
3
+ import { z } from 'zod';
4
+ export function registerProjectFileTools(server, execute) {
5
+ for (const contract of PROJECT_FILE_TOOL_CONTRACTS) {
6
+ server.registerTool(contract.name, {
7
+ title: contract.title,
8
+ description: contract.description,
9
+ inputSchema: z.object(contract.input).strict(),
10
+ annotations: contract.annotations,
11
+ }, async (input, ctx) => {
12
+ try {
13
+ const result = await executeProjectFileTool(contract.name, input, execute, ctx.mcpReq.signal);
14
+ return { content: [{ type: 'text', text: JSON.stringify(result) }] };
15
+ }
16
+ catch (error) {
17
+ const result = isAgentRefusal(error)
18
+ ? refusalPayload(error)
19
+ : {
20
+ code: 'file_error',
21
+ error: 'Could not complete the file request. List project files before retrying an upload.',
22
+ };
23
+ return {
24
+ isError: true,
25
+ content: [{ type: 'text', text: JSON.stringify(result) }],
26
+ };
27
+ }
28
+ });
29
+ }
30
+ }
@@ -1,4 +1,4 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import type { SceneOperations } from '../operations/index.js';
4
4
  export declare const redoInput: {
@@ -9,8 +9,8 @@ export declare const redoOutput: {
9
9
  unsaved: z.ZodOptional<z.ZodString>;
10
10
  persistence: z.ZodOptional<z.ZodObject<{
11
11
  status: z.ZodEnum<{
12
- unbound: "unbound";
13
12
  events_unsupported: "events_unsupported";
13
+ unbound: "unbound";
14
14
  }>;
15
15
  warning: z.ZodString;
16
16
  }, z.core.$strip>>;
@@ -1 +1 @@
1
- {"version":3,"file":"redo.d.ts","sourceRoot":"","sources":["../../src/tools/redo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AASpD,eAAO,MAAM,SAAS;;CAErB,CAAA;AAED,eAAO,MAAM,UAAU;;;;;;;;;;;CAGtB,CAAA;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAsB7E"}
1
+ {"version":3,"file":"redo.d.ts","sourceRoot":"","sources":["../../src/tools/redo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AASpD,eAAO,MAAM,SAAS;IACpB,KAAK;CACN,CAAA;AAED,eAAO,MAAM,UAAU;;;;;;;;;;;CAGtB,CAAA;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAsB7E"}
@@ -12,8 +12,8 @@ export function registerRedo(server, bridge) {
12
12
  server.registerTool('redo', {
13
13
  title: 'Redo',
14
14
  description: 'Redo the next N previously-undone steps (default 1). Returns the number of steps actually redone.',
15
- inputSchema: redoInput,
16
- outputSchema: redoOutput,
15
+ inputSchema: z.object(redoInput),
16
+ outputSchema: z.object(redoOutput),
17
17
  annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
18
18
  }, async ({ steps }) => {
19
19
  const redone = bridge.redo(steps ?? 1);
@@ -0,0 +1,10 @@
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
+ import { type RetiredTool } from '@pascal-app/core/agent-tools';
3
+ /**
4
+ * A retired tool (`RETIRED_MCP_TOOLS`, or a host's own map) is listed nowhere and still answered: a
5
+ * call to its name gets `tool_retired` with the tool that replaced it and how to use that one,
6
+ * where the SDK would answer an unknown name with a bare error. Install it once the tools are
7
+ * registered.
8
+ */
9
+ export declare function answerRetiredTools(server: McpServer, retired?: Readonly<Record<string, RetiredTool>>): void;
10
+ //# sourceMappingURL=retired-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retired-tools.d.ts","sourceRoot":"","sources":["../../src/tools/retired-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,8BAA8B,CAAA;AAKrC;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAqB,GACjE,IAAI,CAYN"}
@@ -0,0 +1,22 @@
1
+ import { RETIRED_MCP_TOOLS, retiredToolRefusal, } from '@pascal-app/core/agent-tools';
2
+ import { toolError } from './errors.js';
3
+ /**
4
+ * A retired tool (`RETIRED_MCP_TOOLS`, or a host's own map) is listed nowhere and still answered: a
5
+ * call to its name gets `tool_retired` with the tool that replaced it and how to use that one,
6
+ * where the SDK would answer an unknown name with a bare error. Install it once the tools are
7
+ * registered.
8
+ */
9
+ export function answerRetiredTools(server, retired = RETIRED_MCP_TOOLS) {
10
+ const registry = server.server;
11
+ const original = registry._requestHandlers.get('tools/call');
12
+ if (!original)
13
+ return;
14
+ server.server.removeRequestHandler('tools/call');
15
+ server.server.setRequestHandler('tools/call', async (request, ctx) => {
16
+ const { name } = request.params;
17
+ if (!Object.hasOwn(retired, name))
18
+ return (await original(request, ctx));
19
+ const { error, ...answer } = retiredToolRefusal(name, retired[name]);
20
+ return toolError(error, answer);
21
+ });
22
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=roof-level-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roof-level-guard.d.ts","sourceRoot":"","sources":["../../src/tools/roof-level-guard.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { seatWrittenRoofs } from '@pascal-app/core/agent-operations';
2
+ import { isAgentRefusal } from '@pascal-app/core/agent-tools';
3
+ import { PatchRefusedError, registerPatchGuard } from './patch-guards.js';
4
+ /**
5
+ * The roof-level rule: a roof the patch puts on its walls' storey is seated on the level above by
6
+ * ops appended to the patch, said in notes, so every refusal's patchIndex stays on the model's own
7
+ * op; storey content on a roof level, a walled level declared the roof level and a roof level
8
+ * moved under a storey are refused. After the level heights, before the identity check, which
9
+ * checks the appended ops too.
10
+ */
11
+ function roofLevels(patches, scene) {
12
+ try {
13
+ return seatWrittenRoofs(patches, scene);
14
+ }
15
+ catch (error) {
16
+ if (!isAgentRefusal(error))
17
+ throw error;
18
+ const { index, id } = error.details;
19
+ throw new PatchRefusedError(error.code, index, id, error.message);
20
+ }
21
+ }
22
+ registerPatchGuard({ name: 'roof-levels', order: 40, run: roofLevels });
@@ -1,59 +1,60 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
+ import { z } from 'zod';
2
3
  import type { SceneOperations } from '../operations/index.js';
3
4
  import { type GeometryScriptHost } from './add-object.js';
4
5
  /** The contract's one result (core `addWallOpening`), and the live sync's note. */
5
6
  export declare const addDoorOutput: {
6
- project: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
7
- unsaved: import("zod").ZodOptional<import("zod").ZodString>;
8
- persistence: import("zod").ZodOptional<import("zod").ZodObject<{
9
- status: import("zod").ZodEnum<{
10
- unbound: "unbound";
7
+ ok: z.ZodLiteral<true>;
8
+ wallId: z.ZodString;
9
+ localX: z.ZodNumber;
10
+ t: z.ZodNumber;
11
+ wallLength: z.ZodNumber;
12
+ clamped: z.ZodBoolean;
13
+ coordinateSystem: z.ZodLiteral<"wall-local-meters">;
14
+ message: z.ZodString;
15
+ achieved: z.ZodObject<{
16
+ created: z.ZodRecord<z.ZodString, z.ZodNumber>;
17
+ updated: z.ZodNumber;
18
+ deleted: z.ZodRecord<z.ZodString, z.ZodNumber>;
19
+ unchanged: z.ZodOptional<z.ZodLiteral<true>>;
20
+ }, z.core.$strip>;
21
+ doorId: z.ZodString;
22
+ project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
23
+ unsaved: z.ZodOptional<z.ZodString>;
24
+ persistence: z.ZodOptional<z.ZodObject<{
25
+ status: z.ZodEnum<{
11
26
  events_unsupported: "events_unsupported";
27
+ unbound: "unbound";
12
28
  }>;
13
- warning: import("zod").ZodString;
14
- }, import("zod/v4/core").$strip>>;
15
- ok: import("zod").ZodLiteral<true>;
16
- wallId: import("zod").ZodString;
17
- localX: import("zod").ZodNumber;
18
- t: import("zod").ZodNumber;
19
- wallLength: import("zod").ZodNumber;
20
- clamped: import("zod").ZodBoolean;
21
- coordinateSystem: import("zod").ZodLiteral<"wall-local-meters">;
22
- message: import("zod").ZodString;
23
- achieved: import("zod").ZodObject<{
24
- created: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
25
- updated: import("zod").ZodNumber;
26
- deleted: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
27
- unchanged: import("zod").ZodOptional<import("zod").ZodLiteral<true>>;
28
- }, import("zod/v4/core").$strip>;
29
- doorId: import("zod").ZodString;
29
+ warning: z.ZodString;
30
+ }, z.core.$strip>>;
30
31
  };
31
32
  export declare const addWindowOutput: {
32
- project: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
33
- unsaved: import("zod").ZodOptional<import("zod").ZodString>;
34
- persistence: import("zod").ZodOptional<import("zod").ZodObject<{
35
- status: import("zod").ZodEnum<{
36
- unbound: "unbound";
33
+ ok: z.ZodLiteral<true>;
34
+ wallId: z.ZodString;
35
+ localX: z.ZodNumber;
36
+ t: z.ZodNumber;
37
+ wallLength: z.ZodNumber;
38
+ clamped: z.ZodBoolean;
39
+ coordinateSystem: z.ZodLiteral<"wall-local-meters">;
40
+ message: z.ZodString;
41
+ achieved: z.ZodObject<{
42
+ created: z.ZodRecord<z.ZodString, z.ZodNumber>;
43
+ updated: z.ZodNumber;
44
+ deleted: z.ZodRecord<z.ZodString, z.ZodNumber>;
45
+ unchanged: z.ZodOptional<z.ZodLiteral<true>>;
46
+ }, z.core.$strip>;
47
+ windowId: z.ZodString;
48
+ sillHeight: z.ZodOptional<z.ZodNumber>;
49
+ project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
50
+ unsaved: z.ZodOptional<z.ZodString>;
51
+ persistence: z.ZodOptional<z.ZodObject<{
52
+ status: z.ZodEnum<{
37
53
  events_unsupported: "events_unsupported";
54
+ unbound: "unbound";
38
55
  }>;
39
- warning: import("zod").ZodString;
40
- }, import("zod/v4/core").$strip>>;
41
- sillHeight: import("zod").ZodOptional<import("zod").ZodNumber>;
42
- ok: import("zod").ZodLiteral<true>;
43
- wallId: import("zod").ZodString;
44
- localX: import("zod").ZodNumber;
45
- t: import("zod").ZodNumber;
46
- wallLength: import("zod").ZodNumber;
47
- clamped: import("zod").ZodBoolean;
48
- coordinateSystem: import("zod").ZodLiteral<"wall-local-meters">;
49
- message: import("zod").ZodString;
50
- achieved: import("zod").ZodObject<{
51
- created: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
52
- updated: import("zod").ZodNumber;
53
- deleted: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodNumber>;
54
- unchanged: import("zod").ZodOptional<import("zod").ZodLiteral<true>>;
55
- }, import("zod/v4/core").$strip>;
56
- windowId: import("zod").ZodString;
56
+ warning: z.ZodString;
57
+ }, z.core.$strip>>;
57
58
  };
58
59
  export declare function registerAddDoor(server: McpServer, bridge: SceneOperations, geometryScripts?: GeometryScriptHost): void;
59
60
  export declare function registerAddWindow(server: McpServer, bridge: SceneOperations, geometryScripts?: GeometryScriptHost): void;
@@ -1 +1 @@
1
- {"version":3,"file":"room-tools.d.ts","sourceRoot":"","sources":["../../src/tools/room-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAyBxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAmB,KAAK,kBAAkB,EAAc,MAAM,cAAc,CAAA;AAMnF,mFAAmF;AACnF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;CAA0C,CAAA;AACpE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;CAA4C,CAAA;AAoHxE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CA8BN;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CA8BN;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CAGN"}
1
+ {"version":3,"file":"room-tools.d.ts","sourceRoot":"","sources":["../../src/tools/room-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAyB7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAmB,KAAK,kBAAkB,EAAc,MAAM,cAAc,CAAA;AAMnF,mFAAmF;AACnF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;CAA0C,CAAA;AACpE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;CAA4C,CAAA;AAwHxE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CA8BN;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CA8BN;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,eAAe,CAAC,EAAE,kBAAkB,GACnC,IAAI,CAGN"}
@@ -2,6 +2,7 @@ import { isScriptedNode, scriptedObjectMeta } from '@pascal-app/core';
2
2
  import { achievedChanges, addWallOpening, editedScriptLanguage, editedScriptParams, rebuiltOpeningResult, rescriptOpening, } from '@pascal-app/core/agent-operations';
3
3
  import { addDoorOutput as addDoorResult, addDoorTool, addWindowOutput as addWindowResult, addWindowTool, isAgentRefusal, } from '@pascal-app/core/agent-tools';
4
4
  import { GeometryReuseFields } from '@pascal-app/core/schema';
5
+ import { z } from 'zod';
5
6
  import { compileAndStore, readScript } from './add-object.js';
6
7
  import { ADDITIVE_TOOL_ANNOTATIONS } from './annotations.js';
7
8
  import { refusalResult, toolError } from './errors.js';
@@ -42,7 +43,7 @@ async function rebuildOpening(kind, bridge, host, input) {
42
43
  ...GeometryReuseFields.parse(input),
43
44
  },
44
45
  });
45
- outcome = rescriptOpening(nodes, { ...input, compiled }, { activeLevelId: null });
46
+ outcome = rescriptOpening(nodes, { ...input, compiled }, { activeLevelId: bridge.activeLevelId?.() ?? null });
46
47
  }
47
48
  catch (error) {
48
49
  if (isAgentRefusal(error))
@@ -94,8 +95,8 @@ export function registerAddDoor(server, bridge, geometryScripts) {
94
95
  server.registerTool(addDoorTool.name, {
95
96
  title: addDoorTool.title,
96
97
  description: addDoorTool.description,
97
- inputSchema: addDoorTool.input,
98
- outputSchema: addDoorOutput,
98
+ inputSchema: z.object(addDoorTool.input),
99
+ outputSchema: z.object(addDoorOutput),
99
100
  annotations: ADDITIVE_TOOL_ANNOTATIONS,
100
101
  }, async (input) => {
101
102
  if (input.nodeId)
@@ -123,8 +124,8 @@ export function registerAddWindow(server, bridge, geometryScripts) {
123
124
  server.registerTool(addWindowTool.name, {
124
125
  title: addWindowTool.title,
125
126
  description: addWindowTool.description,
126
- inputSchema: addWindowTool.input,
127
- outputSchema: addWindowOutput,
127
+ inputSchema: z.object(addWindowTool.input),
128
+ outputSchema: z.object(addWindowOutput),
128
129
  annotations: ADDITIVE_TOOL_ANNOTATIONS,
129
130
  }, async (input) => {
130
131
  if (input.nodeId)
@@ -1,4 +1,4 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import type { SceneOperations } from '../../operations/index.js';
4
4
  export declare const createProjectInput: {
@@ -1 +1 @@
1
- {"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../../src/tools/scene-lifecycle/create-project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;CAsB/B,CAAA;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CA4E1F"}
1
+ {"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../../src/tools/scene-lifecycle/create-project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD,eAAO,MAAM,kBAAkB;IAC7B,IAAI;IACJ,EAAE;IACF,SAAS;CACV,CAAA;AAED,eAAO,MAAM,mBAAmB;IAC9B,EAAE;IACF,SAAS;IACT,IAAI;IACJ,SAAS;IACT,GAAG;IACH,OAAO;IACP,YAAY;IACZ,gBAAgB;IAChB,aAAa;IACb,YAAY;IACZ,qBAAqB;IACrB,OAAO;IACP,OAAO;IACP,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,QAAQ;IACR,cAAc;IACd,QAAQ;CACT,CAAA;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CA4E1F"}
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { ADDITIVE_TOOL_ANNOTATIONS } from '../annotations.js';
3
- import { ErrorCode, throwMcpError } from '../errors.js';
3
+ import { ProtocolErrorCode, throwMcpError } from '../errors.js';
4
4
  import { currentLevelContext, projectStatusPayload } from './metadata.js';
5
5
  export const createProjectInput = {
6
6
  name: z.string().min(1).max(200),
@@ -34,12 +34,12 @@ export function registerCreateProject(server, operations) {
34
34
  server.registerTool('create_project', {
35
35
  title: 'Create project',
36
36
  description: 'Create a browser-visible Pascal project for the authenticated user. Use this before save_scene when the user asks for a new project.',
37
- inputSchema: createProjectInput,
38
- outputSchema: createProjectOutput,
37
+ inputSchema: z.object(createProjectInput),
38
+ outputSchema: z.object(createProjectOutput),
39
39
  annotations: ADDITIVE_TOOL_ANNOTATIONS,
40
40
  }, async ({ name, id, isPrivate }) => {
41
41
  if (!operations.canCreateProject) {
42
- throwMcpError(ErrorCode.InvalidRequest, 'create_project_unavailable: this MCP store cannot create hosted projects');
42
+ throwMcpError(ProtocolErrorCode.InvalidRequest, 'create_project_unavailable: this MCP store cannot create hosted projects');
43
43
  }
44
44
  try {
45
45
  const bound = operations.getActiveScene();
@@ -91,7 +91,7 @@ export function registerCreateProject(server, operations) {
91
91
  }
92
92
  catch (err) {
93
93
  const msg = err instanceof Error ? err.message : String(err);
94
- throwMcpError(ErrorCode.InvalidRequest, msg);
94
+ throwMcpError(ProtocolErrorCode.InvalidRequest, msg);
95
95
  }
96
96
  });
97
97
  }
@@ -1,4 +1,4 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import type { SceneOperations } from '../../operations/index.js';
4
4
  export declare const deleteSceneInput: {
@@ -1 +1 @@
1
- {"version":3,"file":"delete-scene.d.ts","sourceRoot":"","sources":["../../../src/tools/scene-lifecycle/delete-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD,eAAO,MAAM,gBAAgB;;;CAG5B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;CAI7B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAmCxF"}
1
+ {"version":3,"file":"delete-scene.d.ts","sourceRoot":"","sources":["../../../src/tools/scene-lifecycle/delete-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD,eAAO,MAAM,gBAAgB;IAC3B,EAAE;IACF,eAAe;CAChB,CAAA;AAED,eAAO,MAAM,iBAAiB;IAC5B,OAAO;IACP,MAAM;IACN,OAAO;CACR,CAAA;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAmCxF"}