@pascal-app/mcp 1.0.4 → 1.0.6

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
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  import { rehydrateSiteChildren } from '../../lib/rehydrate-site-children.js';
4
4
  import { isTemplateId, TEMPLATES } from '../../templates/index.js';
5
5
  import { DESTRUCTIVE_TOOL_ANNOTATIONS } from '../annotations.js';
6
- import { ErrorCode, throwMcpError } from '../errors.js';
6
+ import { ProtocolErrorCode, throwMcpError } from '../errors.js';
7
7
  import { appendLiveSceneEvent } from '../live-sync.js';
8
8
  import { currentLevelContext, sceneMetaPayload } from '../scene-lifecycle/metadata.js';
9
9
  export const createHouseFromBriefInput = {
@@ -65,8 +65,8 @@ export function registerCreateHouseFromBrief(server, bridge) {
65
65
  server.registerTool('create_house_from_brief', {
66
66
  title: 'Create house from brief',
67
67
  description: 'High-level hosted workflow for external agents: choose a starter house from a brief, create/save/publish it, and return the editor URL. Use semantic tools afterward for exact customization.',
68
- inputSchema: createHouseFromBriefInput,
69
- outputSchema: createHouseFromBriefOutput,
68
+ inputSchema: z.object(createHouseFromBriefInput),
69
+ outputSchema: z.object(createHouseFromBriefOutput),
70
70
  annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
71
71
  }, async ({ brief, projectId, projectName, bedroomCount, rooms, style, landscaping, constraints, }) => {
72
72
  const templateId = chooseTemplate({
@@ -75,7 +75,7 @@ export function registerCreateHouseFromBrief(server, bridge) {
75
75
  ...(landscaping !== undefined ? { landscaping } : {}),
76
76
  });
77
77
  if (!isTemplateId(templateId)) {
78
- throwMcpError(ErrorCode.InternalError, `unknown_template: ${templateId}`);
78
+ throwMcpError(ProtocolErrorCode.InternalError, `unknown_template: ${templateId}`);
79
79
  }
80
80
  const entry = TEMPLATES[templateId];
81
81
  const cloned = rehydrateSiteChildren(cloneSceneGraph(entry.template));
@@ -87,7 +87,7 @@ export function registerCreateHouseFromBrief(server, bridge) {
87
87
  }
88
88
  catch (err) {
89
89
  const msg = err instanceof Error ? err.message : String(err);
90
- throwMcpError(ErrorCode.InternalError, `apply_failed: ${msg}`);
90
+ throwMcpError(ProtocolErrorCode.InternalError, `apply_failed: ${msg}`);
91
91
  }
92
92
  const rawValidation = bridge.validateScene();
93
93
  const validation = {
@@ -166,7 +166,7 @@ export function registerCreateHouseFromBrief(server, bridge) {
166
166
  }
167
167
  catch (err) {
168
168
  const msg = err instanceof Error ? err.message : String(err);
169
- throwMcpError(ErrorCode.InternalError, `save_failed: ${msg}`);
169
+ throwMcpError(ProtocolErrorCode.InternalError, `save_failed: ${msg}`);
170
170
  }
171
171
  });
172
172
  }
@@ -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 template MCP tools (`list_templates`, `create_from_template`)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAItF;AAED,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKvD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAItF;AAED,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GACtB,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
  export declare const listTemplatesInput: {};
4
4
  export declare const listTemplatesOutput: {
@@ -1 +1 @@
1
- {"version":3,"file":"list-templates.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/list-templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,kBAAkB,IAAc,CAAA;AAE7C,eAAO,MAAM,mBAAmB;;;;;;;CAS/B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyB7D"}
1
+ {"version":3,"file":"list-templates.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/list-templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,kBAAkB,IAAc,CAAA;AAE7C,eAAO,MAAM,mBAAmB;IAC9B,SAAS;;;;;;CAQV,CAAA;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyB7D"}
@@ -19,8 +19,8 @@ export function registerListTemplates(server) {
19
19
  server.registerTool('list_templates', {
20
20
  title: 'List scene templates',
21
21
  description: 'List the seed Pascal scene templates available to `create_from_template`. Returns the id, display name, one-line description and node count for each.',
22
- inputSchema: listTemplatesInput,
23
- outputSchema: listTemplatesOutput,
22
+ inputSchema: z.object(listTemplatesInput),
23
+ outputSchema: z.object(listTemplatesOutput),
24
24
  annotations: READ_ONLY_TOOL_ANNOTATIONS,
25
25
  }, async () => {
26
26
  const templates = Object.values(TEMPLATES).map((entry) => ({
@@ -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 undoInput: {
@@ -9,8 +9,8 @@ export declare const undoOutput: {
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":"undo.d.ts","sourceRoot":"","sources":["../../src/tools/undo.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":"undo.d.ts","sourceRoot":"","sources":["../../src/tools/undo.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 registerUndo(server, bridge) {
12
12
  server.registerTool('undo', {
13
13
  title: 'Undo',
14
14
  description: 'Undo the most recent N steps in the scene history (default 1). Returns the number of steps actually undone.',
15
- inputSchema: undoInput,
16
- outputSchema: undoOutput,
15
+ inputSchema: z.object(undoInput),
16
+ outputSchema: z.object(undoOutput),
17
17
  annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
18
18
  }, async ({ steps }) => {
19
19
  const undone = bridge.undo(steps ?? 1);
@@ -1 +1 @@
1
- {"version":3,"file":"unit-members.d.ts","sourceRoot":"","sources":["../../src/tools/unit-members.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,CA6BlB"}
1
+ {"version":3,"file":"unit-members.d.ts","sourceRoot":"","sources":["../../src/tools/unit-members.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAgClB"}
@@ -1,23 +1,23 @@
1
- import { ErrorCode, throwMcpError } from './errors.js';
1
+ import { ProtocolErrorCode, throwMcpError } from './errors.js';
2
2
  export function validateUnitMembers(bridge, buildingId, memberZoneIds) {
3
3
  const building = bridge.getNode(buildingId);
4
4
  if (!building) {
5
- throwMcpError(ErrorCode.InvalidParams, `Building not found: ${buildingId}`);
5
+ throwMcpError(ProtocolErrorCode.InvalidParams, `Building not found: ${buildingId}`);
6
6
  }
7
7
  if (building.type !== 'building') {
8
- throwMcpError(ErrorCode.InvalidParams, `Node ${buildingId} is a ${building.type}, expected building`);
8
+ throwMcpError(ProtocolErrorCode.InvalidParams, `Node ${buildingId} is a ${building.type}, expected building`);
9
9
  }
10
10
  return memberZoneIds.map((zoneId) => {
11
11
  const zone = bridge.getNode(zoneId);
12
12
  if (!zone) {
13
- throwMcpError(ErrorCode.InvalidParams, `Zone not found: ${zoneId}`);
13
+ throwMcpError(ProtocolErrorCode.InvalidParams, `Zone not found: ${zoneId}`);
14
14
  }
15
15
  if (zone.type !== 'zone') {
16
- throwMcpError(ErrorCode.InvalidParams, `Node ${zoneId} is a ${zone.type}, expected zone`);
16
+ throwMcpError(ProtocolErrorCode.InvalidParams, `Node ${zoneId} is a ${zone.type}, expected zone`);
17
17
  }
18
18
  const [, level, parent] = bridge.getAncestry(zone.id);
19
19
  if (level?.type !== 'level' || parent?.id !== building.id) {
20
- throwMcpError(ErrorCode.InvalidParams, `Zone ${zoneId} must belong to a level in building ${buildingId}`);
20
+ throwMcpError(ProtocolErrorCode.InvalidParams, `Zone ${zoneId} must belong to a level in building ${buildingId}`);
21
21
  }
22
22
  return zone.id;
23
23
  });
@@ -1,17 +1,17 @@
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 generateVariantsInput: {
5
5
  baseSceneId: z.ZodOptional<z.ZodString>;
6
6
  count: z.ZodDefault<z.ZodNumber>;
7
7
  vary: z.ZodDefault<z.ZodArray<z.ZodEnum<{
8
- "wall-thickness": "wall-thickness";
9
- "wall-height": "wall-height";
10
- "zone-labels": "zone-labels";
11
- "room-proportions": "room-proportions";
12
- "open-plan": "open-plan";
13
8
  "door-positions": "door-positions";
14
9
  "fence-style": "fence-style";
10
+ "open-plan": "open-plan";
11
+ "room-proportions": "room-proportions";
12
+ "wall-height": "wall-height";
13
+ "wall-thickness": "wall-thickness";
14
+ "zone-labels": "zone-labels";
15
15
  }>>>;
16
16
  seed: z.ZodOptional<z.ZodNumber>;
17
17
  save: z.ZodDefault<z.ZodBoolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"generate-variants.d.ts","sourceRoot":"","sources":["../../../src/tools/variants/generate-variants.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,kBAAkB,CAAA;AAevD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;CAYjC,CAAA;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;CAWlC,CAAA;AAcD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA2FzF"}
1
+ {"version":3,"file":"generate-variants.d.ts","sourceRoot":"","sources":["../../../src/tools/variants/generate-variants.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,kBAAkB,CAAA;AAevD,eAAO,MAAM,qBAAqB;IAChC,WAAW;IAIX,KAAK;IACL,IAAI;;;;;;;;;IACJ,IAAI;IACJ,IAAI;CAIL,CAAA;AAED,eAAO,MAAM,sBAAsB;IACjC,QAAQ;;;;;;;;CAUT,CAAA;AAcD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA2FzF"}
@@ -2,7 +2,7 @@ import { forkSceneGraph } from '@pascal-app/core/clone-scene-graph';
2
2
  import { AnyNode as AnyNodeSchema } from '@pascal-app/core/schema';
3
3
  import { z } from 'zod';
4
4
  import { ADDITIVE_TOOL_ANNOTATIONS } from '../annotations.js';
5
- import { ErrorCode, throwMcpError } from '../errors.js';
5
+ import { ProtocolErrorCode, throwMcpError } from '../errors.js';
6
6
  import { applyMutation, describeVariant, mulberry32 } from './mutations.js';
7
7
  const MUTATION_KINDS = [
8
8
  'wall-thickness',
@@ -52,8 +52,8 @@ export function registerGenerateVariants(server, bridge) {
52
52
  server.registerTool('generate_variants', {
53
53
  title: 'Generate variants',
54
54
  description: 'Generate N variations of a base scene by forking and applying seeded mutations. Example: "give me 5 variations of this kitchen". If `save=true`, each variant is persisted via scene operations and returned with an id + URL; otherwise the graph is returned inline.',
55
- inputSchema: generateVariantsInput,
56
- outputSchema: generateVariantsOutput,
55
+ inputSchema: z.object(generateVariantsInput),
56
+ outputSchema: z.object(generateVariantsOutput),
57
57
  annotations: ADDITIVE_TOOL_ANNOTATIONS,
58
58
  }, async ({ baseSceneId, count, vary, seed, save }) => {
59
59
  // 1. Obtain the base SceneGraph.
@@ -62,7 +62,7 @@ export function registerGenerateVariants(server, bridge) {
62
62
  if (baseSceneId) {
63
63
  const loaded = await bridge.loadStoredScene(baseSceneId);
64
64
  if (!loaded) {
65
- throwMcpError(ErrorCode.InvalidParams, 'scene_not_found', { id: baseSceneId });
65
+ throwMcpError(ProtocolErrorCode.InvalidParams, 'scene_not_found', { id: baseSceneId });
66
66
  }
67
67
  base = loaded.graph;
68
68
  baseName = loaded.name;
@@ -85,7 +85,7 @@ export function registerGenerateVariants(server, bridge) {
85
85
  }
86
86
  const invalidCount = countInvalidNodes(forked);
87
87
  if (invalidCount > 0) {
88
- throwMcpError(ErrorCode.InternalError, `variant_invalid: variant ${i} produced ${invalidCount} invalid node(s)`, { index: i });
88
+ throwMcpError(ProtocolErrorCode.InternalError, `variant_invalid: variant ${i} produced ${invalidCount} invalid node(s)`, { index: i });
89
89
  }
90
90
  const nodeCount = Object.keys(forked.nodes).length;
91
91
  const description = describeVariant(forked, mutations);
@@ -105,7 +105,7 @@ export function registerGenerateVariants(server, bridge) {
105
105
  }
106
106
  catch (err) {
107
107
  const msg = err instanceof Error ? err.message : String(err);
108
- throwMcpError(ErrorCode.InternalError, `save_failed: ${msg}`, { index: i });
108
+ throwMcpError(ProtocolErrorCode.InternalError, `save_failed: ${msg}`, { index: i });
109
109
  }
110
110
  }
111
111
  else {
@@ -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 variant-generation MCP tools against shared scene operations.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/variants/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGvD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAErF;AAED,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,aAAa,EACb,eAAe,EACf,KAAK,YAAY,EACjB,UAAU,EACV,KAAK,GAAG,GACT,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/variants/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGvD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAErF;AAED,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,aAAa,EACb,eAAe,EACf,KAAK,YAAY,EACjB,UAAU,EACV,KAAK,GAAG,GACT,MAAM,aAAa,CAAA"}
@@ -1,5 +1,5 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { type SceneViewCrop, type SceneViewInterior, type SceneViewPose } from '@pascal-app/core/agent-operations';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
+ import { type SceneViewCrop, type SceneViewInterior, type SceneViewLighting, type SceneViewPose, type SceneViewPresentation } from '@pascal-app/core/agent-operations';
3
3
  import type { SceneOperations } from '../operations/index.js';
4
4
  /** A picture of the scene, rendered by an editor tab open on the project. */
5
5
  export type SceneViewCapture = {
@@ -10,6 +10,9 @@ export type SceneViewCapture = {
10
10
  /** Which tab rendered it, and when: the scene as that tab showed it then. */
11
11
  tab: string;
12
12
  capturedAt: string;
13
+ presentation?: SceneViewPresentation;
14
+ /** The host's id of the picture it kept, these exact pixels: a later call can name the frame. */
15
+ viewId?: string;
13
16
  };
14
17
  /**
15
18
  * Asks an editor open on the project for a picture, the MCP having no renderer of its own. Refuses
@@ -25,6 +28,9 @@ export type SceneViewHost = {
25
28
  };
26
29
  /** A look inside this floor: the editor leaves the rest out and cuts everything on it. */
27
30
  interior?: SceneViewInterior;
31
+ presentation?: SceneViewPresentation;
32
+ /** The light to render it in; the scene's own when absent. */
33
+ lighting?: SceneViewLighting;
28
34
  }): Promise<SceneViewCapture>;
29
35
  /** Crops the reference photo to a region; without it a view with a photo is refused. */
30
36
  crop?(request: SceneViewCrop): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"view-scene.d.ts","sourceRoot":"","sources":["../../src/tools/view-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAGnB,MAAM,mCAAmC,CAAA;AAG1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAIpD,6EAA6E;AAC7E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,UAAU,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,OAAO,EAAE;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,IAAI,EAAE,aAAa,CAAA;QACnB,IAAI,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;QAC9B,0FAA0F;QAC1F,QAAQ,CAAC,EAAE,iBAAiB,CAAA;KAC7B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC7B,wFAAwF;IACxF,IAAI,CAAC,CACH,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnF,CAAA;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,eAAe,EAC3B,KAAK,CAAC,EAAE,aAAa,QAuEtB"}
1
+ {"version":3,"file":"view-scene.d.ts","sourceRoot":"","sources":["../../src/tools/view-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAG3B,MAAM,mCAAmC,CAAA;AAI1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAIpD,6EAA6E;AAC7E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,UAAU,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,OAAO,EAAE;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,IAAI,EAAE,aAAa,CAAA;QACnB,IAAI,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;QAC9B,0FAA0F;QAC1F,QAAQ,CAAC,EAAE,iBAAiB,CAAA;QAC5B,YAAY,CAAC,EAAE,qBAAqB,CAAA;QACpC,8DAA8D;QAC9D,QAAQ,CAAC,EAAE,iBAAiB,CAAA;KAC7B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC7B,wFAAwF;IACxF,IAAI,CAAC,CACH,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnF,CAAA;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,eAAe,EAC3B,KAAK,CAAC,EAAE,aAAa,QAkFtB"}
@@ -1,12 +1,13 @@
1
- import { sceneViewNote, sceneViewPlan, } from '@pascal-app/core/agent-operations';
1
+ import { confirmSceneViewPresentation, sceneViewNote, sceneViewPlan, } from '@pascal-app/core/agent-operations';
2
2
  import { refuse, viewSceneTool } from '@pascal-app/core/agent-tools';
3
+ import { z } from 'zod';
3
4
  import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
4
5
  import { refusalResult } from './errors.js';
5
6
  export function registerViewScene(server, operations, views) {
6
7
  server.registerTool(viewSceneTool.name, {
7
8
  title: viewSceneTool.title,
8
9
  description: viewSceneTool.description,
9
- inputSchema: viewSceneTool.input,
10
+ inputSchema: z.object(viewSceneTool.input),
10
11
  annotations: READ_ONLY_TOOL_ANNOTATIONS,
11
12
  }, async (input) => {
12
13
  try {
@@ -15,20 +16,31 @@ export function registerViewScene(server, operations, views) {
15
16
  const projectId = operations.getActiveScene()?.projectId;
16
17
  if (!projectId)
17
18
  refuse('no_project', 'This session has no project open to look at: load or create one.');
18
- const { pose, size, crop, interior } = sceneViewPlan(operations.getNodes(), input);
19
+ // No view of the person's here: core refuses camera 'current' without one.
20
+ const { pose, size, crop, interior, presentation, lighting } = sceneViewPlan(operations.getNodes(), input);
19
21
  if (crop && !views.crop)
20
22
  refuse('photo_crop_unavailable', 'This Pascal server cannot crop a photo: crop the region yourself and lay it beside the view.');
21
23
  const [shot, cropped] = await Promise.all([
22
- views.capture({ projectId: projectId, pose, size, ...(interior ? { interior } : {}) }),
24
+ views.capture({
25
+ projectId: projectId,
26
+ pose,
27
+ size,
28
+ ...(interior ? { interior } : {}),
29
+ ...(presentation ? { presentation } : {}),
30
+ ...(lighting ? { lighting } : {}),
31
+ }),
23
32
  crop ? views.crop(crop) : undefined,
24
33
  ]);
34
+ confirmSceneViewPresentation(presentation, shot.presentation);
25
35
  const payload = {
26
36
  status: 'viewed',
27
37
  camera: pose,
28
38
  size: { width: shot.width, height: shot.height },
29
39
  tab: shot.tab,
30
40
  capturedAt: shot.capturedAt,
31
- note: sceneViewNote(),
41
+ ...(shot.viewId ? { viewId: shot.viewId } : {}),
42
+ ...(shot.presentation ? { presentation: shot.presentation } : {}),
43
+ note: sceneViewNote(operations.getNodes(), interior, pose),
32
44
  ...(crop && cropped
33
45
  ? {
34
46
  photoRegion: crop.region,
@@ -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
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"analyze-floorplan-image.d.ts","sourceRoot":"","sources":["../../../src/tools/vision/analyze-floorplan-image.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,kBAAkB,CAAA;AAGvD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B;;;CAMtC,CAAA;AAED,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;CAoBvC,CAAA;AAgFD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAkE/F"}
1
+ {"version":3,"file":"analyze-floorplan-image.d.ts","sourceRoot":"","sources":["../../../src/tools/vision/analyze-floorplan-image.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,kBAAkB,CAAA;AAGvD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B;IACrC,KAAK;IACL,SAAS;CAIV,CAAA;AAED,eAAO,MAAM,2BAA2B;IACtC,KAAK;;;;;IAOL,KAAK;;;;;IAOL,qBAAqB;;;;IAIrB,UAAU;CACX,CAAA;AAgFD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAkE/F"}
@@ -1,4 +1,4 @@
1
- import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
1
+ import { ProtocolError, ProtocolErrorCode } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import { READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS } from '../annotations.js';
4
4
  /**
@@ -93,13 +93,13 @@ export function registerAnalyzeFloorplanImage(server, _bridge) {
93
93
  server.registerTool('analyze_floorplan_image', {
94
94
  title: 'Analyze floor-plan image',
95
95
  description: 'Defer to the MCP host (via sampling) to extract walls, rooms, and approximate dimensions from a floor-plan image. Requires host support for sampling.',
96
- inputSchema: analyzeFloorplanImageInput,
97
- outputSchema: analyzeFloorplanImageOutput,
96
+ inputSchema: z.object(analyzeFloorplanImageInput),
97
+ outputSchema: z.object(analyzeFloorplanImageOutput),
98
98
  annotations: READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS,
99
99
  }, async ({ image, scaleHint }) => {
100
100
  const caps = server.server.getClientCapabilities();
101
101
  if (!caps?.sampling) {
102
- throw new McpError(ErrorCode.InvalidRequest, 'sampling_unavailable');
102
+ throw new ProtocolError(ProtocolErrorCode.InvalidRequest, 'sampling_unavailable');
103
103
  }
104
104
  const imageBlock = await resolveImageBlock(image);
105
105
  const instruction = scaleHint
@@ -118,7 +118,7 @@ export function registerAnalyzeFloorplanImage(server, _bridge) {
118
118
  });
119
119
  const text = extractText(response.content);
120
120
  if (!text) {
121
- throw new McpError(ErrorCode.InternalError, 'sampling_response_unparseable', {
121
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_unparseable', {
122
122
  reason: 'no text content returned by host',
123
123
  });
124
124
  }
@@ -127,14 +127,14 @@ export function registerAnalyzeFloorplanImage(server, _bridge) {
127
127
  parsed = JSON.parse(text);
128
128
  }
129
129
  catch (err) {
130
- throw new McpError(ErrorCode.InternalError, 'sampling_response_unparseable', {
130
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_unparseable', {
131
131
  raw: text,
132
132
  reason: err instanceof Error ? err.message : String(err),
133
133
  });
134
134
  }
135
135
  const validation = OutputSchema.safeParse(parsed);
136
136
  if (!validation.success) {
137
- throw new McpError(ErrorCode.InternalError, 'sampling_response_invalid', {
137
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_invalid', {
138
138
  raw: text,
139
139
  errors: validation.error.issues,
140
140
  });
@@ -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
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"analyze-room-photo.d.ts","sourceRoot":"","sources":["../../../src/tools/vision/analyze-room-photo.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,kBAAkB,CAAA;AAGvD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;CAEjC,CAAA;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;CAmBlC,CAAA;AAoED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAqE1F"}
1
+ {"version":3,"file":"analyze-room-photo.d.ts","sourceRoot":"","sources":["../../../src/tools/vision/analyze-room-photo.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,kBAAkB,CAAA;AAGvD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;IAChC,KAAK;CACN,CAAA;AAED,eAAO,MAAM,sBAAsB;IACjC,qBAAqB;;;;;IAKrB,kBAAkB;;;;IAMlB,iBAAiB;;;;;CAOlB,CAAA;AAoED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAqE1F"}
@@ -1,4 +1,4 @@
1
- import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
1
+ import { ProtocolError, ProtocolErrorCode } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import { READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS } from '../annotations.js';
4
4
  /**
@@ -74,13 +74,13 @@ export function registerAnalyzeRoomPhoto(server, _bridge) {
74
74
  server.registerTool('analyze_room_photo', {
75
75
  title: 'Analyze room photo',
76
76
  description: 'Defer to the MCP host (via sampling) to extract approximate dimensions, fixtures, and windows from a single-room photograph. Requires host support for sampling.',
77
- inputSchema: analyzeRoomPhotoInput,
78
- outputSchema: analyzeRoomPhotoOutput,
77
+ inputSchema: z.object(analyzeRoomPhotoInput),
78
+ outputSchema: z.object(analyzeRoomPhotoOutput),
79
79
  annotations: READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS,
80
80
  }, async ({ image }) => {
81
81
  const caps = server.server.getClientCapabilities();
82
82
  if (!caps?.sampling) {
83
- throw new McpError(ErrorCode.InvalidRequest, 'sampling_unavailable');
83
+ throw new ProtocolError(ProtocolErrorCode.InvalidRequest, 'sampling_unavailable');
84
84
  }
85
85
  const imageBlock = await resolveImageBlock(image);
86
86
  const response = await server.server.createMessage({
@@ -102,7 +102,7 @@ export function registerAnalyzeRoomPhoto(server, _bridge) {
102
102
  });
103
103
  const text = extractText(response.content);
104
104
  if (!text) {
105
- throw new McpError(ErrorCode.InternalError, 'sampling_response_unparseable', {
105
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_unparseable', {
106
106
  reason: 'no text content returned by host',
107
107
  });
108
108
  }
@@ -111,14 +111,14 @@ export function registerAnalyzeRoomPhoto(server, _bridge) {
111
111
  parsed = JSON.parse(text);
112
112
  }
113
113
  catch (err) {
114
- throw new McpError(ErrorCode.InternalError, 'sampling_response_unparseable', {
114
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_unparseable', {
115
115
  raw: text,
116
116
  reason: err instanceof Error ? err.message : String(err),
117
117
  });
118
118
  }
119
119
  const validation = OutputSchema.safeParse(parsed);
120
120
  if (!validation.success) {
121
- throw new McpError(ErrorCode.InternalError, 'sampling_response_invalid', {
121
+ throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_invalid', {
122
122
  raw: text,
123
123
  errors: validation.error.issues,
124
124
  });
@@ -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 vision-input tools that defer to the MCP host's sampling
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/vision/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIvD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAGxF;AAED,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/vision/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIvD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAGxF;AAED,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA"}
@@ -1,4 +1,4 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
2
  export type HttpTransportHandle = {
3
3
  /** Host interface the server is listening on. */
4
4
  host: string;
@@ -28,10 +28,16 @@ export type HttpTransportOptions = {
28
28
  /**
29
29
  * Attach an `McpServer` to a Streamable HTTP transport bound to a local port.
30
30
  *
31
- * Uses the SDK's Node-flavored `StreamableHTTPServerTransport`, which accepts
31
+ * Uses the SDK's `NodeStreamableHTTPServerTransport`, which accepts
32
32
  * `IncomingMessage`/`ServerResponse` directly via `handleRequest(req, res)`.
33
33
  * A new session ID is generated per connection (stateful mode).
34
34
  *
35
+ * Serves the 2025 sessionful protocol only: a negotiating client falls back
36
+ * to it, and a client pinned to 2026-07-28 is refused. The SDK serves
37
+ * 2026-07-28 over HTTP per request (`createMcpHandler`), with a fresh server
38
+ * from the factory each time, and every server here owns its own scene, so a
39
+ * session is what keeps one client's scene between calls.
40
+ *
35
41
  * Listens on `127.0.0.1:<port>` (pass `0` for an ephemeral port in tests). The
36
42
  * returned handle exposes the actual bound port and a `close()` that stops
37
43
  * the underlying Node HTTP server. To bind a public interface, pass `host` and
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAUxE,MAAM,MAAM,mBAAmB,GAAG;IAChC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAA;IACZ,8DAA8D;IAC9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,8EAA8E;IAC9E,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CACjD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,eAAe,EAAE,MAAM,SAAS,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA2G9B"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAS7D,MAAM,MAAM,mBAAmB,GAAG;IAChC,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAA;IACZ,8DAA8D;IAC9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,8EAA8E;IAC9E,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CACjD,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,eAAe,EAAE,MAAM,SAAS,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA2G9B"}
@@ -1,6 +1,6 @@
1
1
  import { randomUUID, timingSafeEqual } from 'node:crypto';
2
2
  import { createServer } from 'node:http';
3
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
+ import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
4
4
  const DEFAULT_HOST = '127.0.0.1';
5
5
  const DEFAULT_RATE_LIMIT_PER_MINUTE = 120;
6
6
  const WINDOW_MS = 60_000;
@@ -9,10 +9,16 @@ const ALLOWED_HEADERS = 'authorization, content-type, mcp-session-id, mcp-protoc
9
9
  /**
10
10
  * Attach an `McpServer` to a Streamable HTTP transport bound to a local port.
11
11
  *
12
- * Uses the SDK's Node-flavored `StreamableHTTPServerTransport`, which accepts
12
+ * Uses the SDK's `NodeStreamableHTTPServerTransport`, which accepts
13
13
  * `IncomingMessage`/`ServerResponse` directly via `handleRequest(req, res)`.
14
14
  * A new session ID is generated per connection (stateful mode).
15
15
  *
16
+ * Serves the 2025 sessionful protocol only: a negotiating client falls back
17
+ * to it, and a client pinned to 2026-07-28 is refused. The SDK serves
18
+ * 2026-07-28 over HTTP per request (`createMcpHandler`), with a fresh server
19
+ * from the factory each time, and every server here owns its own scene, so a
20
+ * session is what keeps one client's scene between calls.
21
+ *
16
22
  * Listens on `127.0.0.1:<port>` (pass `0` for an ephemeral port in tests). The
17
23
  * returned handle exposes the actual bound port and a `close()` that stops
18
24
  * the underlying Node HTTP server. To bind a public interface, pass `host` and
@@ -66,7 +72,7 @@ export async function connectHttp(createMcpServer, port, options = {}) {
66
72
  let transport = sessionId ? transports.get(sessionId) : undefined;
67
73
  if (!transport && req.method === 'POST' && !sessionId) {
68
74
  let createdTransport;
69
- createdTransport = new StreamableHTTPServerTransport({
75
+ createdTransport = new NodeStreamableHTTPServerTransport({
70
76
  sessionIdGenerator: () => randomUUID(),
71
77
  onsessioninitialized: (id) => {
72
78
  transports.set(id, createdTransport);
@@ -1,14 +1,20 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import type { McpServer } from '@modelcontextprotocol/server';
2
+ import { type ServeStdioOptions, type StdioServerHandle } from '@modelcontextprotocol/server/stdio';
2
3
  /**
3
- * Attach an `McpServer` to the stdio transport.
4
+ * Serve Pascal over stdio from a server factory.
4
5
  *
5
- * The server takes ownership of stdin/stdout for JSON-RPC messaging. Callers
6
- * must send any operator logging to stderr (not stdout) to avoid corrupting
7
- * the protocol stream.
6
+ * The SDK negotiates the protocol era per connection: a client that opens with
7
+ * the 2025 `initialize` handshake and one that opens with the 2026-07-28
8
+ * `server/discover` probe are both served. A server handed to
9
+ * `StdioServerTransport` directly would answer only the first. The factory can
10
+ * be called twice on one connection (a discarded probe instance, then the
11
+ * instance that serves it), so it must build a fresh, unconnected server each
12
+ * time.
8
13
  *
9
- * Resolves once the transport is started. The underlying transport keeps the
10
- * process alive as long as stdin is open, so callers typically just `await`
11
- * this and then let the event loop run.
14
+ * The connection owns stdin/stdout for JSON-RPC messaging. Callers must send
15
+ * any operator logging to stderr (not stdout) to avoid corrupting the protocol
16
+ * stream. The process stays alive while stdin is open; the connection tears
17
+ * itself down when stdin reaches end-of-file.
12
18
  */
13
- export declare function connectStdio(server: McpServer): Promise<void>;
19
+ export declare function connectStdio(createServer: () => McpServer, options?: Pick<ServeStdioOptions, 'transport' | 'onerror'>): StdioServerHandle;
14
20
  //# sourceMappingURL=stdio.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGxE;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnE"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EAEvB,MAAM,oCAAoC,CAAA;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,SAAS,EAC7B,OAAO,GAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,SAAS,CAAM,GAC7D,iBAAiB,CAKnB"}