@pascal-app/mcp 1.0.3 → 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 (305) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +181 -56
  3. package/dist/bin/pascal-mcp.js +9 -3
  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 +42 -6
  10. package/dist/bridge/scene-bridge.d.ts.map +1 -1
  11. package/dist/bridge/scene-bridge.js +232 -45
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -0
  15. package/dist/lib/safe-fetch.d.ts +22 -4
  16. package/dist/lib/safe-fetch.d.ts.map +1 -1
  17. package/dist/lib/safe-fetch.js +233 -134
  18. package/dist/operations/scene-operations.d.ts +41 -3
  19. package/dist/operations/scene-operations.d.ts.map +1 -1
  20. package/dist/operations/scene-operations.js +42 -1
  21. package/dist/prompts/from-brief.d.ts +1 -1
  22. package/dist/prompts/from-brief.d.ts.map +1 -1
  23. package/dist/prompts/from-brief.js +3 -3
  24. package/dist/prompts/index.d.ts +1 -1
  25. package/dist/prompts/index.d.ts.map +1 -1
  26. package/dist/prompts/iterate-on-feedback.d.ts +1 -1
  27. package/dist/prompts/iterate-on-feedback.d.ts.map +1 -1
  28. package/dist/prompts/iterate-on-feedback.js +3 -3
  29. package/dist/prompts/renovation-from-photos.d.ts +1 -1
  30. package/dist/prompts/renovation-from-photos.d.ts.map +1 -1
  31. package/dist/prompts/renovation-from-photos.js +2 -2
  32. package/dist/prompts/scene-guidance.d.ts.map +1 -1
  33. package/dist/prompts/scene-guidance.js +13 -6
  34. package/dist/resources/agent-guide.d.ts +1 -1
  35. package/dist/resources/agent-guide.d.ts.map +1 -1
  36. package/dist/resources/agent-guide.js +62 -33
  37. package/dist/resources/catalog-items.d.ts +5 -6
  38. package/dist/resources/catalog-items.d.ts.map +1 -1
  39. package/dist/resources/catalog-items.js +7 -9
  40. package/dist/resources/constraints.d.ts +1 -1
  41. package/dist/resources/constraints.d.ts.map +1 -1
  42. package/dist/resources/constraints.js +1 -1
  43. package/dist/resources/design-schema.d.ts +9 -0
  44. package/dist/resources/design-schema.d.ts.map +1 -0
  45. package/dist/resources/design-schema.js +21 -0
  46. package/dist/resources/index.d.ts +4 -2
  47. package/dist/resources/index.d.ts.map +1 -1
  48. package/dist/resources/index.js +5 -2
  49. package/dist/resources/scene-current.d.ts +1 -1
  50. package/dist/resources/scene-current.d.ts.map +1 -1
  51. package/dist/resources/scene-summary.d.ts +1 -1
  52. package/dist/resources/scene-summary.d.ts.map +1 -1
  53. package/dist/server.d.ts +25 -1
  54. package/dist/server.d.ts.map +1 -1
  55. package/dist/server.js +71 -25
  56. package/dist/storage/disk-artifact-store.d.ts +9 -0
  57. package/dist/storage/disk-artifact-store.d.ts.map +1 -0
  58. package/dist/storage/disk-artifact-store.js +46 -0
  59. package/dist/storage/index.d.ts +1 -0
  60. package/dist/storage/index.d.ts.map +1 -1
  61. package/dist/storage/index.js +1 -0
  62. package/dist/storage/sqlite-scene-store.d.ts +3 -3
  63. package/dist/storage/sqlite-scene-store.d.ts.map +1 -1
  64. package/dist/storage/sqlite-scene-store.js +4 -3
  65. package/dist/storage/types.d.ts +36 -7
  66. package/dist/storage/types.d.ts.map +1 -1
  67. package/dist/storage/types.js +12 -0
  68. package/dist/templates/empty-studio.d.ts +3 -3
  69. package/dist/templates/empty-studio.d.ts.map +1 -1
  70. package/dist/templates/garden-house.d.ts +3 -3
  71. package/dist/templates/garden-house.d.ts.map +1 -1
  72. package/dist/templates/index.d.ts.map +1 -1
  73. package/dist/templates/two-bedroom.d.ts +3 -3
  74. package/dist/templates/two-bedroom.d.ts.map +1 -1
  75. package/dist/tools/add-column.d.ts +5 -0
  76. package/dist/tools/add-column.d.ts.map +1 -0
  77. package/dist/tools/add-column.js +59 -0
  78. package/dist/tools/add-object.d.ts +76 -0
  79. package/dist/tools/add-object.d.ts.map +1 -0
  80. package/dist/tools/add-object.js +187 -0
  81. package/dist/tools/annotations.d.ts.map +1 -1
  82. package/dist/tools/apply-patch.d.ts +9 -2
  83. package/dist/tools/apply-patch.d.ts.map +1 -1
  84. package/dist/tools/apply-patch.js +36 -5
  85. package/dist/tools/asset-catalog.d.ts +9 -5
  86. package/dist/tools/asset-catalog.d.ts.map +1 -1
  87. package/dist/tools/asset-catalog.js +33 -12
  88. package/dist/tools/author-scene.d.ts +10 -0
  89. package/dist/tools/author-scene.d.ts.map +1 -0
  90. package/dist/tools/author-scene.js +140 -0
  91. package/dist/tools/check-collisions.d.ts +7 -7
  92. package/dist/tools/check-collisions.d.ts.map +1 -1
  93. package/dist/tools/check-collisions.js +7 -8
  94. package/dist/tools/clear-scene.d.ts +9 -0
  95. package/dist/tools/clear-scene.d.ts.map +1 -0
  96. package/dist/tools/clear-scene.js +59 -0
  97. package/dist/tools/collections.d.ts +4 -0
  98. package/dist/tools/collections.d.ts.map +1 -0
  99. package/dist/tools/collections.js +53 -0
  100. package/dist/tools/construction-tools.d.ts +12 -88
  101. package/dist/tools/construction-tools.d.ts.map +1 -1
  102. package/dist/tools/construction-tools.js +122 -381
  103. package/dist/tools/create-unit.d.ts +5 -3
  104. package/dist/tools/create-unit.d.ts.map +1 -1
  105. package/dist/tools/create-unit.js +2 -2
  106. package/dist/tools/errors.d.ts +15 -4
  107. package/dist/tools/errors.d.ts.map +1 -1
  108. package/dist/tools/errors.js +14 -4
  109. package/dist/tools/export-glb.d.ts +1 -1
  110. package/dist/tools/export-glb.d.ts.map +1 -1
  111. package/dist/tools/export-glb.js +2 -2
  112. package/dist/tools/export-json.d.ts +1 -1
  113. package/dist/tools/export-json.d.ts.map +1 -1
  114. package/dist/tools/export-json.js +2 -2
  115. package/dist/tools/geometry-script-worker.d.ts +2 -0
  116. package/dist/tools/geometry-script-worker.d.ts.map +1 -0
  117. package/dist/tools/geometry-script-worker.js +21 -0
  118. package/dist/tools/get-scene.d.ts +2 -1
  119. package/dist/tools/get-scene.d.ts.map +1 -1
  120. package/dist/tools/get-scene.js +5 -3
  121. package/dist/tools/honest-patch-guard.d.ts +2 -0
  122. package/dist/tools/honest-patch-guard.d.ts.map +1 -0
  123. package/dist/tools/honest-patch-guard.js +32 -0
  124. package/dist/tools/hosted-services.d.ts +4 -0
  125. package/dist/tools/hosted-services.d.ts.map +1 -0
  126. package/dist/tools/hosted-services.js +40 -0
  127. package/dist/tools/index.d.ts +12 -2
  128. package/dist/tools/index.d.ts.map +1 -1
  129. package/dist/tools/index.js +18 -32
  130. package/dist/tools/level-height-guard.d.ts +2 -0
  131. package/dist/tools/level-height-guard.d.ts.map +1 -0
  132. package/dist/tools/level-height-guard.js +11 -0
  133. package/dist/tools/list-units.d.ts +2 -2
  134. package/dist/tools/list-units.d.ts.map +1 -1
  135. package/dist/tools/list-units.js +2 -2
  136. package/dist/tools/live-sync.d.ts +25 -6
  137. package/dist/tools/live-sync.d.ts.map +1 -1
  138. package/dist/tools/live-sync.js +48 -27
  139. package/dist/tools/local-geometry-scripts.d.ts +8 -0
  140. package/dist/tools/local-geometry-scripts.d.ts.map +1 -0
  141. package/dist/tools/local-geometry-scripts.js +67 -0
  142. package/dist/tools/measure.d.ts +7 -1
  143. package/dist/tools/measure.d.ts.map +1 -1
  144. package/dist/tools/measure.js +38 -70
  145. package/dist/tools/measurement.d.ts +1 -36
  146. package/dist/tools/measurement.d.ts.map +1 -1
  147. package/dist/tools/measurement.js +2 -94
  148. package/dist/tools/node-world-point.d.ts +37 -0
  149. package/dist/tools/node-world-point.d.ts.map +1 -0
  150. package/dist/tools/node-world-point.js +457 -0
  151. package/dist/tools/normalize-schema-dialect.d.ts +1 -1
  152. package/dist/tools/normalize-schema-dialect.d.ts.map +1 -1
  153. package/dist/tools/normalize-schema-dialect.js +22 -3
  154. package/dist/tools/patch-guards.d.ts +60 -0
  155. package/dist/tools/patch-guards.d.ts.map +1 -0
  156. package/dist/tools/patch-guards.js +256 -0
  157. package/dist/tools/photo-to-scene/index.d.ts +1 -1
  158. package/dist/tools/photo-to-scene/index.d.ts.map +1 -1
  159. package/dist/tools/photo-to-scene/photo-to-scene.d.ts +3 -3
  160. package/dist/tools/photo-to-scene/photo-to-scene.d.ts.map +1 -1
  161. package/dist/tools/photo-to-scene/photo-to-scene.js +10 -9
  162. package/dist/tools/project-files.d.ts +4 -0
  163. package/dist/tools/project-files.d.ts.map +1 -0
  164. package/dist/tools/project-files.js +30 -0
  165. package/dist/tools/redo.d.ts +4 -2
  166. package/dist/tools/redo.d.ts.map +1 -1
  167. package/dist/tools/redo.js +4 -4
  168. package/dist/tools/retired-tools.d.ts +10 -0
  169. package/dist/tools/retired-tools.d.ts.map +1 -0
  170. package/dist/tools/retired-tools.js +22 -0
  171. package/dist/tools/roof-level-guard.d.ts +2 -0
  172. package/dist/tools/roof-level-guard.d.ts.map +1 -0
  173. package/dist/tools/roof-level-guard.js +22 -0
  174. package/dist/tools/room-tools.d.ts +36 -98
  175. package/dist/tools/room-tools.d.ts.map +1 -1
  176. package/dist/tools/room-tools.js +130 -565
  177. package/dist/tools/scene-lifecycle/create-project.d.ts +1 -1
  178. package/dist/tools/scene-lifecycle/create-project.d.ts.map +1 -1
  179. package/dist/tools/scene-lifecycle/create-project.js +31 -6
  180. package/dist/tools/scene-lifecycle/delete-scene.d.ts +3 -1
  181. package/dist/tools/scene-lifecycle/delete-scene.d.ts.map +1 -1
  182. package/dist/tools/scene-lifecycle/delete-scene.js +10 -9
  183. package/dist/tools/scene-lifecycle/get-project-status.d.ts +1 -1
  184. package/dist/tools/scene-lifecycle/get-project-status.d.ts.map +1 -1
  185. package/dist/tools/scene-lifecycle/get-project-status.js +6 -6
  186. package/dist/tools/scene-lifecycle/index.d.ts +1 -1
  187. package/dist/tools/scene-lifecycle/index.d.ts.map +1 -1
  188. package/dist/tools/scene-lifecycle/list-scenes.d.ts +1 -1
  189. package/dist/tools/scene-lifecycle/list-scenes.d.ts.map +1 -1
  190. package/dist/tools/scene-lifecycle/list-scenes.js +4 -4
  191. package/dist/tools/scene-lifecycle/load-scene.d.ts +2 -2
  192. package/dist/tools/scene-lifecycle/load-scene.d.ts.map +1 -1
  193. package/dist/tools/scene-lifecycle/load-scene.js +5 -5
  194. package/dist/tools/scene-lifecycle/metadata.d.ts +1 -1
  195. package/dist/tools/scene-lifecycle/rename-scene.d.ts +1 -1
  196. package/dist/tools/scene-lifecycle/rename-scene.d.ts.map +1 -1
  197. package/dist/tools/scene-lifecycle/rename-scene.js +6 -6
  198. package/dist/tools/scene-lifecycle/save-scene.d.ts +6 -3
  199. package/dist/tools/scene-lifecycle/save-scene.d.ts.map +1 -1
  200. package/dist/tools/scene-lifecycle/save-scene.js +124 -16
  201. package/dist/tools/scene-lifecycle/test-utils.d.ts +3 -3
  202. package/dist/tools/scene-lifecycle/test-utils.d.ts.map +1 -1
  203. package/dist/tools/scene-lifecycle/test-utils.js +2 -1
  204. package/dist/tools/set-unit-members.d.ts +4 -2
  205. package/dist/tools/set-unit-members.d.ts.map +1 -1
  206. package/dist/tools/set-unit-members.js +6 -6
  207. package/dist/tools/set-zone.d.ts +4 -2
  208. package/dist/tools/set-zone.d.ts.map +1 -1
  209. package/dist/tools/set-zone.js +30 -18
  210. package/dist/tools/shared-tools.d.ts +40 -0
  211. package/dist/tools/shared-tools.d.ts.map +1 -0
  212. package/dist/tools/shared-tools.js +574 -0
  213. package/dist/tools/structure-tools.d.ts +57 -0
  214. package/dist/tools/structure-tools.d.ts.map +1 -0
  215. package/dist/tools/structure-tools.js +57 -0
  216. package/dist/tools/templates/create-from-template.d.ts +2 -2
  217. package/dist/tools/templates/create-from-template.d.ts.map +1 -1
  218. package/dist/tools/templates/create-from-template.js +6 -6
  219. package/dist/tools/templates/create-house-from-brief.d.ts +1 -1
  220. package/dist/tools/templates/create-house-from-brief.d.ts.map +1 -1
  221. package/dist/tools/templates/create-house-from-brief.js +6 -6
  222. package/dist/tools/templates/index.d.ts +1 -1
  223. package/dist/tools/templates/index.d.ts.map +1 -1
  224. package/dist/tools/templates/list-templates.d.ts +1 -1
  225. package/dist/tools/templates/list-templates.d.ts.map +1 -1
  226. package/dist/tools/templates/list-templates.js +2 -2
  227. package/dist/tools/undo.d.ts +4 -2
  228. package/dist/tools/undo.d.ts.map +1 -1
  229. package/dist/tools/undo.js +4 -4
  230. package/dist/tools/unit-members.d.ts.map +1 -1
  231. package/dist/tools/unit-members.js +6 -6
  232. package/dist/tools/variants/generate-variants.d.ts +6 -6
  233. package/dist/tools/variants/generate-variants.d.ts.map +1 -1
  234. package/dist/tools/variants/generate-variants.js +6 -6
  235. package/dist/tools/variants/index.d.ts +1 -1
  236. package/dist/tools/variants/index.d.ts.map +1 -1
  237. package/dist/tools/variants/mutations.js +1 -1
  238. package/dist/tools/view-scene.d.ts +44 -0
  239. package/dist/tools/view-scene.d.ts.map +1 -0
  240. package/dist/tools/view-scene.js +75 -0
  241. package/dist/tools/vision/analyze-floorplan-image.d.ts +1 -1
  242. package/dist/tools/vision/analyze-floorplan-image.d.ts.map +1 -1
  243. package/dist/tools/vision/analyze-floorplan-image.js +7 -7
  244. package/dist/tools/vision/analyze-room-photo.d.ts +1 -1
  245. package/dist/tools/vision/analyze-room-photo.d.ts.map +1 -1
  246. package/dist/tools/vision/analyze-room-photo.js +7 -7
  247. package/dist/tools/vision/index.d.ts +1 -1
  248. package/dist/tools/vision/index.d.ts.map +1 -1
  249. package/dist/transports/http.d.ts +8 -2
  250. package/dist/transports/http.d.ts.map +1 -1
  251. package/dist/transports/http.js +9 -3
  252. package/dist/transports/stdio.d.ts +15 -9
  253. package/dist/transports/stdio.d.ts.map +1 -1
  254. package/dist/transports/stdio.js +18 -11
  255. package/dist/version.d.ts +5 -0
  256. package/dist/version.d.ts.map +1 -1
  257. package/dist/version.js +17 -3
  258. package/examples/coordinate-conventions-demo.md +12 -13
  259. package/examples/embed-in-agent.ts +6 -7
  260. package/examples/generate-apartment.md +13 -15
  261. package/examples/photo-to-scene.md +3 -4
  262. package/examples/renovate-from-photos.md +6 -9
  263. package/package.json +19 -9
  264. package/dist/tools/create-level.d.ts +0 -21
  265. package/dist/tools/create-level.d.ts.map +0 -1
  266. package/dist/tools/create-level.js +0 -63
  267. package/dist/tools/create-wall.d.ts +0 -22
  268. package/dist/tools/create-wall.d.ts.map +0 -1
  269. package/dist/tools/create-wall.js +0 -57
  270. package/dist/tools/cut-opening.d.ts +0 -25
  271. package/dist/tools/cut-opening.d.ts.map +0 -1
  272. package/dist/tools/cut-opening.js +0 -61
  273. package/dist/tools/delete-node.d.ts +0 -19
  274. package/dist/tools/delete-node.d.ts.map +0 -1
  275. package/dist/tools/delete-node.js +0 -40
  276. package/dist/tools/describe-node.d.ts +0 -17
  277. package/dist/tools/describe-node.d.ts.map +0 -1
  278. package/dist/tools/describe-node.js +0 -97
  279. package/dist/tools/door-clearance.d.ts +0 -135
  280. package/dist/tools/door-clearance.d.ts.map +0 -1
  281. package/dist/tools/door-clearance.js +0 -334
  282. package/dist/tools/duplicate-level.d.ts +0 -19
  283. package/dist/tools/duplicate-level.d.ts.map +0 -1
  284. package/dist/tools/duplicate-level.js +0 -60
  285. package/dist/tools/find-nodes.d.ts +0 -32
  286. package/dist/tools/find-nodes.d.ts.map +0 -1
  287. package/dist/tools/find-nodes.js +0 -107
  288. package/dist/tools/geometry.d.ts +0 -24
  289. package/dist/tools/geometry.d.ts.map +0 -1
  290. package/dist/tools/geometry.js +0 -94
  291. package/dist/tools/get-node.d.ts +0 -11
  292. package/dist/tools/get-node.d.ts.map +0 -1
  293. package/dist/tools/get-node.js +0 -29
  294. package/dist/tools/layout-clearance.d.ts +0 -105
  295. package/dist/tools/layout-clearance.d.ts.map +0 -1
  296. package/dist/tools/layout-clearance.js +0 -190
  297. package/dist/tools/place-item.d.ts +0 -22
  298. package/dist/tools/place-item.d.ts.map +0 -1
  299. package/dist/tools/place-item.js +0 -89
  300. package/dist/tools/scene-query.d.ts +0 -62
  301. package/dist/tools/scene-query.d.ts.map +0 -1
  302. package/dist/tools/scene-query.js +0 -670
  303. package/dist/tools/validate-scene.d.ts +0 -19
  304. package/dist/tools/validate-scene.d.ts.map +0 -1
  305. package/dist/tools/validate-scene.js +0 -28
@@ -1,21 +1,11 @@
1
- import { resolveStairTotalRise } from '@pascal-app/core';
2
- import { CeilingNode, getActiveRoofHeight, LevelNode, RoofNode, RoofSegmentNode, SlabNode, StairNode, StairSegmentNode, WallNode, } from '@pascal-app/core/schema';
1
+ import { createZone, generateId } from '@pascal-app/core';
2
+ import { roofLevelRefusal, unknownMaterialPresetRefusal } from '@pascal-app/core/agent-operations';
3
3
  import { z } from 'zod';
4
- import { ADDITIVE_TOOL_ANNOTATIONS, DESTRUCTIVE_TOOL_ANNOTATIONS } from './annotations.js';
4
+ import { ADDITIVE_TOOL_ANNOTATIONS } from './annotations.js';
5
+ import { refusalResult } from './errors.js';
5
6
  import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
6
7
  import { measurement } from './measurement.js';
7
- import { NodeIdSchema, Vec2Schema, Vec3Schema } from './schemas.js';
8
- const ROOF_TYPES = [
9
- 'hip',
10
- 'gable',
11
- 'shed',
12
- 'gambrel',
13
- 'dutch',
14
- 'mansard',
15
- 'flat',
16
- 'conical',
17
- ];
18
- const RAILING_MODES = ['none', 'left', 'right', 'both'];
8
+ import { NodeIdSchema, Vec2Schema } from './schemas.js';
19
9
  export const createStoryShellInput = {
20
10
  levelId: NodeIdSchema,
21
11
  footprint: z.array(Vec2Schema).min(3),
@@ -27,9 +17,17 @@ export const createStoryShellInput = {
27
17
  positive: true,
28
18
  description: 'Wall thickness.',
29
19
  }).default(0.16),
30
- createSlab: z.boolean().default(true),
31
- createCeiling: z.boolean().default(true),
32
- slabElevation: measurement('length', 'm', { description: 'Slab elevation.' }).default(0.1),
20
+ createSlab: z
21
+ .boolean()
22
+ .default(true)
23
+ .describe('Floor intent for the rooms inside the shell. False records hasFloor: false.'),
24
+ createCeiling: z
25
+ .boolean()
26
+ .default(true)
27
+ .describe('Ceiling intent for the rooms inside the shell. False records hasCeiling: false.'),
28
+ slabElevation: measurement('length', 'm', {
29
+ description: "Walking surface of the derived plate, stored as the room's floor elevation.",
30
+ }).default(0.1),
33
31
  ceilingHeight: measurement('length', 'm', {
34
32
  positive: true,
35
33
  description: 'Ceiling height.',
@@ -42,86 +40,15 @@ export const createStoryShellInput = {
42
40
  export const createStoryShellOutput = {
43
41
  levelId: z.string(),
44
42
  wallIds: z.array(z.string()),
43
+ /** Zones the reconciler derived for the enclosed faces. */
44
+ zoneIds: z.array(z.string()),
45
+ /** Derived floor plate. `null` when floors were declined or nothing reconciled. */
45
46
  slabId: z.string().nullable(),
47
+ /** Derived ceiling. `null` when ceilings were declined or nothing reconciled. */
46
48
  ceilingId: z.string().nullable(),
47
49
  createdIds: z.array(z.string()),
48
50
  ...liveSyncOutput,
49
51
  };
50
- export const createRoofInput = {
51
- levelId: NodeIdSchema,
52
- roofLevelId: NodeIdSchema.optional(),
53
- useDedicatedRoofLevel: z.boolean().default(true),
54
- roofLevelLabel: z.string().default('Roof'),
55
- // A level ordinal (story index), not a length — kept numeric.
56
- roofLevelElevation: z.number().optional(),
57
- roofLevelHeight: measurement('length', 'm', {
58
- positive: true,
59
- description: 'Roof level height.',
60
- }).optional(),
61
- center: Vec3Schema.optional(),
62
- width: measurement('length', 'm', { positive: true, description: 'Roof width.' }),
63
- depth: measurement('length', 'm', { positive: true, description: 'Roof depth.' }),
64
- roofType: z.enum(ROOF_TYPES).default('hip'),
65
- pitch: measurement('angle', 'deg', { min: 0, max: 85, description: 'Roof pitch.' }).default(35),
66
- wallHeight: measurement('length', 'm', { min: 0, description: 'Knee-wall height.' }).default(0.35),
67
- wallThickness: measurement('length', 'm', {
68
- positive: true,
69
- description: 'Wall thickness.',
70
- }).default(0.16),
71
- overhang: measurement('length', 'm', { min: 0, description: 'Eave overhang.' }).default(0.45),
72
- materialPreset: z.string().optional(),
73
- name: z.string().optional(),
74
- };
75
- export const createRoofOutput = {
76
- referenceLevelId: z.string(),
77
- roofLevelId: z.string(),
78
- createdRoofLevelId: z.string().nullable(),
79
- roofId: z.string(),
80
- roofSegmentId: z.string(),
81
- ...liveSyncOutput,
82
- };
83
- export const createStairBetweenLevelsInput = {
84
- fromLevelId: NodeIdSchema,
85
- toLevelId: NodeIdSchema,
86
- position: Vec3Schema,
87
- rotation: measurement('angle', 'rad', { description: 'Y-axis rotation.' }).default(0),
88
- width: measurement('length', 'm', { positive: true, description: 'Stair width.' }).default(1),
89
- runLength: measurement('length', 'm', {
90
- positive: true,
91
- description: 'Horizontal run length.',
92
- }).default(3),
93
- totalRise: measurement('length', 'm', {
94
- positive: true,
95
- description: 'Total vertical rise.',
96
- }).optional(),
97
- stepCount: z.number().int().positive().default(14),
98
- railingMode: z.enum(RAILING_MODES).default('both'),
99
- destinationSlabId: NodeIdSchema.optional(),
100
- sourceCeilingId: NodeIdSchema.optional(),
101
- createDestinationSlabOpening: z.boolean().default(true),
102
- createSourceCeilingOpening: z.boolean().default(true),
103
- openingWidth: measurement('length', 'm', {
104
- positive: true,
105
- description: 'Floor opening width.',
106
- }).optional(),
107
- openingLength: measurement('length', 'm', {
108
- positive: true,
109
- description: 'Floor opening length.',
110
- }).optional(),
111
- openingOffset: measurement('length', 'm', { min: 0, description: 'Opening offset.' }).default(0),
112
- openingCenter: Vec2Schema.optional(),
113
- openingRotation: measurement('angle', 'rad', { description: 'Opening rotation.' }).optional(),
114
- materialPreset: z.string().optional(),
115
- name: z.string().optional(),
116
- };
117
- export const createStairBetweenLevelsOutput = {
118
- stairId: z.string(),
119
- stairSegmentId: z.string(),
120
- destinationSlabId: z.string().nullable(),
121
- sourceCeilingId: z.string().nullable(),
122
- openingPolygon: z.array(Vec2Schema),
123
- ...liveSyncOutput,
124
- };
125
52
  function textResult(payload) {
126
53
  return {
127
54
  content: [{ type: 'text', text: JSON.stringify(payload) }],
@@ -136,310 +63,124 @@ function assertNode(bridge, id, type) {
136
63
  throw new Error(`Node ${id} is a ${node.type}, expected ${type}`);
137
64
  return node;
138
65
  }
139
- function getBuildingIdForLevel(bridge, levelId) {
140
- const building = bridge.getAncestry(levelId).find((node) => node.type === 'building');
141
- if (!building) {
142
- throw new Error(`Building ancestor not found for level: ${levelId}`);
143
- }
144
- return building.id;
66
+ /** Room zones that appeared on the level while this tool call ran. */
67
+ function newRoomZoneIds(bridge, levelId, before) {
68
+ return Object.values(bridge.getNodes())
69
+ .filter((node) => node.type === 'zone' &&
70
+ node.parentId === levelId &&
71
+ node.spaceRole === 'room' &&
72
+ !before.has(node.id))
73
+ .map((node) => node.id)
74
+ .sort();
145
75
  }
146
- function isRoofLevel(level) {
147
- return (level.type === 'level' &&
148
- typeof level.metadata === 'object' &&
149
- level.metadata !== null &&
150
- 'role' in level.metadata &&
151
- level.metadata.role === 'roof');
152
- }
153
- function nextLevelIndex(bridge, buildingId, referenceLevel) {
154
- const existing = bridge
155
- .getChildren(buildingId)
156
- .filter((node) => node.type === 'level')
157
- .map((level) => level.level);
158
- const referenceIndex = referenceLevel.type === 'level' ? referenceLevel.level : 0;
159
- const candidate = referenceIndex + 1;
160
- return existing.includes(candidate) ? Math.max(candidate, ...existing) + 1 : candidate;
161
- }
162
- function nodesOnLevel(bridge, levelId) {
163
- return Object.values(bridge.getNodes()).filter((node) => node.id !== levelId && bridge.resolveLevelId(node.id) === levelId);
164
- }
165
- function firstNodeOnLevel(bridge, levelId, type) {
166
- return nodesOnLevel(bridge, levelId).find((node) => node.type === type) ?? null;
167
- }
168
- function rotatePoint(x, z, rotation) {
169
- const cos = Math.cos(rotation);
170
- const sin = Math.sin(rotation);
171
- return [x * cos + z * sin, -x * sin + z * cos];
172
- }
173
- function rectangularOpening(args) {
174
- const width = args.width + args.offset * 2;
175
- const length = args.length + args.offset * 2;
176
- const center = args.center ?? [
177
- args.position[0],
178
- args.position[2] + args.length / 2,
179
- ];
180
- const rotation = args.openingRotation ?? args.rotation;
181
- const halfW = width / 2;
182
- const halfL = length / 2;
183
- const local = [
184
- [-halfW, -halfL],
185
- [halfW, -halfL],
186
- [halfW, halfL],
187
- [-halfW, halfL],
188
- ];
189
- return local.map(([x, z]) => {
190
- const [rx, rz] = rotatePoint(x, z, rotation);
191
- return [center[0] + rx, center[1] + rz];
192
- });
193
- }
194
- function withHole(surface, hole) {
195
- return {
196
- holes: [...(surface.holes ?? []), hole],
197
- holeMetadata: [...(surface.holeMetadata ?? []), { source: 'manual' }],
198
- };
76
+ function derivedShellSurfaces(bridge, levelId, zoneIds) {
77
+ const children = Object.values(bridge.getNodes()).filter((node) => node.parentId === levelId);
78
+ const plate = children
79
+ .filter((node) => node.type === 'slab')
80
+ .sort((a, b) => Number(a.plateRole === 'base') - Number(b.plateRole === 'base'))
81
+ .find((node) => node.type === 'slab' &&
82
+ node.boundary === 'auto' &&
83
+ (node.zoneIds ?? []).some((id) => zoneIds.includes(id)));
84
+ const ceiling = children.find((node) => node.type === 'ceiling' && node.boundary === 'auto' && zoneIds.includes(node.zoneId ?? ''));
85
+ return { slabId: plate?.id ?? null, ceilingId: ceiling?.id ?? null };
199
86
  }
200
87
  export function registerConstructionTools(server, bridge) {
201
88
  server.registerTool('create_story_shell', {
202
89
  title: 'Create story shell',
203
- description: 'Create one level-owned building shell from a footprint: perimeter walls plus optional slab and ceiling. Use once per story; do not make first-floor walls span multiple stories.',
204
- inputSchema: createStoryShellInput,
205
- outputSchema: createStoryShellOutput,
90
+ description: 'Create one level-owned building shell from a footprint: the perimeter walls. The floor plate and the ceiling are DERIVED from the rooms the walls enclose — never author a slab or a ceiling here, and never pass boundary/autoFromWalls; createSlab / createCeiling / slabElevation are recorded as room intent instead. Use once per story; do not make first-floor walls span multiple stories.',
91
+ inputSchema: z.object(createStoryShellInput),
92
+ outputSchema: z.object(createStoryShellOutput),
206
93
  annotations: ADDITIVE_TOOL_ANNOTATIONS,
207
94
  }, async ({ levelId, footprint, wallHeight, wallThickness, createSlab, createCeiling, slabElevation, ceilingHeight, namePrefix, wallMaterialPreset, slabMaterialPreset, ceilingMaterialPreset, }) => {
208
- const level = assertNode(bridge, levelId, 'level');
209
- if (isRoofLevel(level)) {
210
- throw new Error(`Cannot create a story shell on roof support level ${levelId}; create or choose an occupied story level instead`);
211
- }
95
+ const preset = unknownMaterialPresetRefusal({
96
+ wallMaterialPreset,
97
+ slabMaterialPreset,
98
+ ceilingMaterialPreset,
99
+ });
100
+ if (preset)
101
+ throw new Error(preset);
102
+ assertNode(bridge, levelId, 'level');
103
+ const onRoofLevel = roofLevelRefusal(bridge.getNodes(), levelId, 'a story shell');
104
+ if (onRoofLevel)
105
+ return refusalResult(onRoofLevel);
212
106
  const points = footprint;
213
- const wallIds = [];
214
- const patches = [];
215
- for (let i = 0; i < points.length; i++) {
216
- const wall = WallNode.parse({
217
- name: namePrefix ? `${namePrefix} Wall ${i + 1}` : undefined,
218
- start: points[i],
219
- end: points[(i + 1) % points.length],
107
+ const before = new Set(Object.keys(bridge.getNodes()));
108
+ const plan = createZone(bridge.getNodes(), {
109
+ levelId,
110
+ polygon: points,
111
+ name: namePrefix ?? 'Room',
112
+ enclose: true,
113
+ mintId: generateId,
114
+ wall: {
220
115
  thickness: wallThickness,
221
116
  ...(wallHeight !== undefined ? { height: wallHeight } : {}),
222
- frontSide: 'exterior',
223
- backSide: 'interior',
224
- ...(wallMaterialPreset ? { materialPreset: wallMaterialPreset } : {}),
225
- metadata: { role: 'exterior', storyShell: true },
226
- });
227
- wallIds.push(wall.id);
228
- patches.push({ op: 'create', node: wall, parentId: levelId });
229
- }
230
- let slabId = null;
231
- if (createSlab) {
232
- const slab = SlabNode.parse({
233
- name: namePrefix ? `${namePrefix} Slab` : undefined,
234
- polygon: points,
235
- elevation: slabElevation,
236
- // Grounded solid: underside on the level plane, so the created
237
- // story slab occupies [0, slabElevation] like the legacy
238
- // extrude-from-zero model.
239
- thickness: Math.max(slabElevation, 0),
240
- recessed: slabElevation < 0,
241
- ...(slabMaterialPreset ? { materialPreset: slabMaterialPreset } : {}),
242
- metadata: { role: 'story-slab' },
243
- });
244
- slabId = slab.id;
245
- patches.push({ op: 'create', node: slab, parentId: levelId });
246
- }
247
- let ceilingId = null;
248
- if (createCeiling) {
249
- // Height-less unless the caller pinned one: a new story ceiling
250
- // follows the level top automatically.
251
- const explicitCeilingHeight = ceilingHeight ?? wallHeight;
252
- const ceiling = CeilingNode.parse({
253
- name: namePrefix ? `${namePrefix} Ceiling` : undefined,
254
- polygon: points,
255
- ...(explicitCeilingHeight !== undefined ? { height: explicitCeilingHeight } : {}),
256
- ...(ceilingMaterialPreset ? { materialPreset: ceilingMaterialPreset } : {}),
257
- metadata: { role: 'story-ceiling' },
258
- });
259
- ceilingId = ceiling.id;
260
- patches.push({ op: 'create', node: ceiling, parentId: levelId });
261
- }
262
- const result = bridge.applyPatch(patches);
263
- const persistence = await publishLiveSceneSnapshot(bridge, 'create_story_shell');
264
- return textResult({
265
- levelId,
266
- wallIds,
267
- slabId,
268
- ceilingId,
269
- createdIds: result.createdIds,
270
- ...persistencePayload(persistence),
271
- });
272
- });
273
- server.registerTool('create_roof', {
274
- title: 'Create roof',
275
- description: 'Create a roof container with one roof segment. By default creates a dedicated roof level above the reference level so exploded/solo level views can isolate the roof.',
276
- inputSchema: createRoofInput,
277
- outputSchema: createRoofOutput,
278
- annotations: ADDITIVE_TOOL_ANNOTATIONS,
279
- }, async ({ levelId, roofLevelId, useDedicatedRoofLevel, roofLevelLabel, roofLevelElevation, roofLevelHeight, center, width, depth, roofType, pitch, wallHeight, wallThickness, overhang, materialPreset, name, }) => {
280
- const effectiveWidth = roofType === 'conical' ? Math.max(width, depth) : width;
281
- const effectiveDepth = roofType === 'conical' ? effectiveWidth : depth;
282
- // Peak height is derived from pitch + footprint + type; we still
283
- // need it to size the auto-generated roof level container below.
284
- const peakHeight = getActiveRoofHeight({
285
- roofType,
286
- pitch,
287
- width: effectiveWidth,
288
- depth: effectiveDepth,
289
- });
290
- const referenceLevel = assertNode(bridge, levelId, 'level');
291
- const patches = [];
292
- let targetRoofLevelId = levelId;
293
- let createdRoofLevelId = null;
294
- if (roofLevelId !== undefined) {
295
- const roofLevel = assertNode(bridge, roofLevelId, 'level');
296
- if (!isRoofLevel(roofLevel)) {
297
- throw new Error(`roofLevelId ${roofLevelId} must reference a dedicated roof level with metadata.role = "roof"; omit roofLevelId to create one automatically`);
298
- }
299
- targetRoofLevelId = roofLevelId;
300
- }
301
- else if (useDedicatedRoofLevel && !isRoofLevel(referenceLevel)) {
302
- const buildingId = getBuildingIdForLevel(bridge, levelId);
303
- const roofLevel = LevelNode.parse({
304
- name: roofLevelLabel,
305
- level: roofLevelElevation ?? nextLevelIndex(bridge, buildingId, referenceLevel),
306
- height: roofLevelHeight ?? Math.max(wallHeight + peakHeight, 0.2),
307
- children: [],
308
- metadata: {
309
- role: 'roof',
310
- label: roofLevelLabel,
311
- referenceLevelId: levelId,
312
- },
313
- });
314
- targetRoofLevelId = roofLevel.id;
315
- createdRoofLevelId = roofLevel.id;
316
- patches.push({ op: 'create', node: roofLevel, parentId: buildingId });
317
- }
318
- const segment = RoofSegmentNode.parse({
319
- roofType,
320
- width: effectiveWidth,
321
- depth: effectiveDepth,
322
- wallHeight,
323
- pitch,
324
- wallThickness,
325
- overhang,
326
- ...(materialPreset ? { materialPreset } : {}),
327
- });
328
- const roof = RoofNode.parse({
329
- name: name ?? 'Roof',
330
- position: center ?? [0, 0, 0],
331
- children: [segment.id],
332
- ...(materialPreset ? { materialPreset } : {}),
333
- metadata: {
334
- referenceLevelId: levelId,
335
- roofLevelId: targetRoofLevelId,
336
- },
337
- });
338
- bridge.applyPatch([
339
- ...patches,
340
- { op: 'create', node: roof, parentId: targetRoofLevelId },
341
- { op: 'create', node: segment, parentId: roof.id },
342
- ]);
343
- const persistence = await publishLiveSceneSnapshot(bridge, 'create_roof');
344
- return textResult({
345
- referenceLevelId: levelId,
346
- roofLevelId: targetRoofLevelId,
347
- createdRoofLevelId,
348
- roofId: roof.id,
349
- roofSegmentId: segment.id,
350
- ...persistencePayload(persistence),
351
- });
352
- });
353
- server.registerTool('create_stair_between_levels', {
354
- title: 'Create stair between levels',
355
- description: 'Create a straight stair and a single rectangular manual opening in the destination slab/source ceiling. This disables stair auto-opening mode to avoid duplicate or irregular holes.',
356
- inputSchema: createStairBetweenLevelsInput,
357
- outputSchema: createStairBetweenLevelsOutput,
358
- annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
359
- }, async ({ fromLevelId, toLevelId, position, rotation, width, runLength, totalRise, stepCount, railingMode, destinationSlabId, sourceCeilingId, createDestinationSlabOpening, createSourceCeilingOpening, openingWidth, openingLength, openingOffset, openingCenter, openingRotation, materialPreset, name, }) => {
360
- const fromLevel = assertNode(bridge, fromLevelId, 'level');
361
- const toLevel = assertNode(bridge, toLevelId, 'level');
362
- if (isRoofLevel(fromLevel) || isRoofLevel(toLevel)) {
363
- throw new Error('Roof support levels are not occupied stories; create a separate occupied attic/story level if a stair-accessible attic is required');
364
- }
365
- const stairDraft = StairNode.parse({
366
- name: name ?? 'Stair',
367
- position: position,
368
- rotation,
369
- stairType: 'straight',
370
- fromLevelId,
371
- toLevelId,
372
- slabOpeningMode: 'none',
373
- openingOffset,
374
- width,
375
- ...(totalRise !== undefined ? { totalRise } : {}),
376
- stepCount,
377
- railingMode,
378
- children: [],
379
- ...(materialPreset ? { materialPreset } : {}),
380
- metadata: {
381
- openingManaged: 'manual-rectangular',
382
117
  },
383
- });
384
- const riseNodes = {
385
- ...bridge.getNodes(),
386
- [fromLevel.id]: {
387
- ...fromLevel,
388
- children: [...fromLevel.children, stairDraft.id],
118
+ intent: {
119
+ floor: { elevation: slabElevation },
120
+ hasFloor: createSlab,
121
+ hasCeiling: createCeiling,
389
122
  },
390
- [stairDraft.id]: stairDraft,
391
- };
392
- const resolvedTotalRise = resolveStairTotalRise(stairDraft, riseNodes);
393
- const segment = StairSegmentNode.parse({
394
- segmentType: 'stair',
395
- width,
396
- length: runLength,
397
- height: resolvedTotalRise,
398
- stepCount,
399
- ...(materialPreset ? { materialPreset } : {}),
400
123
  });
401
- const stair = { ...stairDraft, children: [segment.id] };
402
- const openingPolygon = rectangularOpening({
403
- position: position,
404
- rotation,
405
- width: openingWidth ?? width,
406
- length: openingLength ?? runLength,
407
- offset: openingOffset,
408
- center: openingCenter,
409
- openingRotation,
124
+ const wallIds = plan.changes.flatMap((change) => change.op === 'create' && change.node.type === 'wall' ? [change.node.id] : []);
125
+ bridge.runAsSingleHistoryStep(() => {
126
+ bridge.applyPatch(plan.changes.map((change) => change.op === 'create'
127
+ ? {
128
+ ...change,
129
+ parentId: change.node.parentId,
130
+ node: change.node.type === 'wall'
131
+ ? {
132
+ ...change.node,
133
+ ...(namePrefix
134
+ ? { name: `${namePrefix} Wall ${wallIds.indexOf(change.node.id) + 1}` }
135
+ : {}),
136
+ ...(wallMaterialPreset ? { materialPreset: wallMaterialPreset } : {}),
137
+ metadata: { role: 'exterior', storyShell: true },
138
+ }
139
+ : change.node,
140
+ }
141
+ : change));
142
+ bridge.deriveStructure([levelId]);
410
143
  });
411
- const patches = [
412
- { op: 'create', node: stair, parentId: fromLevelId },
413
- { op: 'create', node: segment, parentId: stair.id },
144
+ const zoneIds = newRoomZoneIds(bridge, levelId, before);
145
+ // Finishes and an explicit ceiling height stay editable on derived
146
+ // construction, so they are applied to whatever the reconciler built.
147
+ const derived = derivedShellSurfaces(bridge, levelId, zoneIds);
148
+ const explicitCeilingHeight = ceilingHeight ?? wallHeight;
149
+ const finishes = [
150
+ ...(derived.slabId && slabMaterialPreset
151
+ ? [
152
+ {
153
+ op: 'update',
154
+ id: derived.slabId,
155
+ data: {
156
+ ...(slabMaterialPreset ? { materialPreset: slabMaterialPreset } : {}),
157
+ },
158
+ },
159
+ ]
160
+ : []),
161
+ ...(derived.ceilingId && (ceilingMaterialPreset || explicitCeilingHeight !== undefined)
162
+ ? [
163
+ {
164
+ op: 'update',
165
+ id: derived.ceilingId,
166
+ data: {
167
+ ...(ceilingMaterialPreset ? { materialPreset: ceilingMaterialPreset } : {}),
168
+ ...(explicitCeilingHeight !== undefined ? { height: explicitCeilingHeight } : {}),
169
+ },
170
+ },
171
+ ]
172
+ : []),
414
173
  ];
415
- const destinationSlab = destinationSlabId !== undefined
416
- ? assertNode(bridge, destinationSlabId, 'slab')
417
- : firstNodeOnLevel(bridge, toLevelId, 'slab');
418
- if (createDestinationSlabOpening && destinationSlab?.type === 'slab') {
419
- patches.push({
420
- op: 'update',
421
- id: destinationSlab.id,
422
- data: withHole(destinationSlab, openingPolygon),
423
- });
424
- }
425
- const sourceCeiling = sourceCeilingId !== undefined
426
- ? assertNode(bridge, sourceCeilingId, 'ceiling')
427
- : firstNodeOnLevel(bridge, fromLevelId, 'ceiling');
428
- if (createSourceCeilingOpening && sourceCeiling?.type === 'ceiling') {
429
- patches.push({
430
- op: 'update',
431
- id: sourceCeiling.id,
432
- data: withHole(sourceCeiling, openingPolygon),
433
- });
434
- }
435
- bridge.applyPatch(patches);
436
- const persistence = await publishLiveSceneSnapshot(bridge, 'create_stair_between_levels');
174
+ if (finishes.length > 0)
175
+ bridge.applyPatch(finishes);
176
+ const persistence = await publishLiveSceneSnapshot(bridge, 'create_story_shell');
437
177
  return textResult({
438
- stairId: stair.id,
439
- stairSegmentId: segment.id,
440
- destinationSlabId: destinationSlab?.id ?? null,
441
- sourceCeilingId: sourceCeiling?.id ?? null,
442
- openingPolygon,
178
+ levelId,
179
+ wallIds,
180
+ zoneIds,
181
+ slabId: derived.slabId,
182
+ ceilingId: derived.ceilingId,
183
+ createdIds: Object.keys(bridge.getNodes()).filter((id) => !before.has(id)),
443
184
  ...persistencePayload(persistence),
444
185
  });
445
186
  });
@@ -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 createUnitInput: {
@@ -6,18 +6,20 @@ export declare const createUnitInput: {
6
6
  name: z.ZodString;
7
7
  kind: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
8
8
  apartment: "apartment";
9
- "hotel-room": "hotel-room";
10
9
  commercial: "commercial";
11
10
  common: "common";
11
+ "hotel-room": "hotel-room";
12
12
  }>>>;
13
13
  color: z.ZodOptional<z.ZodString>;
14
14
  memberZoneIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
15
15
  };
16
16
  export declare const createUnitOutput: {
17
+ project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
+ unsaved: z.ZodOptional<z.ZodString>;
17
19
  persistence: z.ZodOptional<z.ZodObject<{
18
20
  status: z.ZodEnum<{
19
- unbound: "unbound";
20
21
  events_unsupported: "events_unsupported";
22
+ unbound: "unbound";
21
23
  }>;
22
24
  warning: z.ZodString;
23
25
  }, z.core.$strip>>;
@@ -1 +1 @@
1
- {"version":3,"file":"create-unit.d.ts","sourceRoot":"","sources":["../../src/tools/create-unit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAMpD,eAAO,MAAM,eAAe;;;;;;;;;;;CAM3B,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;CAG5B,CAAA;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAuBnF"}
1
+ {"version":3,"file":"create-unit.d.ts","sourceRoot":"","sources":["../../src/tools/create-unit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAMpD,eAAO,MAAM,eAAe;IAC1B,UAAU;IACV,IAAI;IACJ,IAAI;;;;;;IACJ,KAAK;IACL,aAAa;CACd,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;CAG5B,CAAA;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAuBnF"}
@@ -19,8 +19,8 @@ export function registerCreateUnit(server, bridge) {
19
19
  server.registerTool('create_unit', {
20
20
  title: 'Create unit',
21
21
  description: 'Create a named unit in a building, optionally referencing zones across its levels.',
22
- inputSchema: createUnitInput,
23
- outputSchema: createUnitOutput,
22
+ inputSchema: z.object(createUnitInput),
23
+ outputSchema: z.object(createUnitOutput),
24
24
  annotations: ADDITIVE_TOOL_ANNOTATIONS,
25
25
  }, async ({ buildingId, name, kind, color, memberZoneIds }) => {
26
26
  const members = validateUnitMembers(bridge, buildingId, memberZoneIds ?? []);
@@ -1,9 +1,9 @@
1
- import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
1
+ import { ProtocolError, ProtocolErrorCode } from '@modelcontextprotocol/server';
2
2
  /**
3
- * Throw a structured MCP error. The SDK translates `McpError` into a
3
+ * Throw a structured MCP error. The SDK translates `ProtocolError` into a
4
4
  * JSON-RPC error response automatically.
5
5
  */
6
- export declare function throwMcpError(code: ErrorCode, message: string, data?: unknown): never;
6
+ export declare function throwMcpError(code: ProtocolErrorCode, message: string, data?: unknown): never;
7
7
  /**
8
8
  * Return a non-throwing tool error payload — used for structured failures that
9
9
  * we want the client to see inline in `content` rather than as a protocol
@@ -16,5 +16,16 @@ export declare function toolError(message: string, data?: Record<string, unknown
16
16
  }[];
17
17
  isError: true;
18
18
  };
19
- export { ErrorCode, McpError };
19
+ /**
20
+ * A core operation's refusal (`AgentRefusal`) as the same `{ error, code, ...details }` answer the
21
+ * hosted chat returns; anything else is a real failure and is rethrown.
22
+ */
23
+ export declare function refusalResult(error: unknown): {
24
+ content: {
25
+ type: 'text';
26
+ text: string;
27
+ }[];
28
+ isError: true;
29
+ };
30
+ export { ProtocolError, ProtocolErrorCode };
20
31
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/tools/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAExE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAErF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;IACD,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,OAAO,EAAE,IAAI,CAAA;CACd,CAUA;AAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/tools/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAG/E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;IACD,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,OAAO,EAAE,IAAI,CAAA;CACd,CAUA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO;aAlBjC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE;aAChC,IAAI;EAoBd;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAA"}