@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.
- package/CHANGELOG.md +76 -0
- package/README.md +181 -56
- package/dist/bin/pascal-mcp.js +9 -3
- package/dist/bridge/agent-session.d.ts +18 -0
- package/dist/bridge/agent-session.d.ts.map +1 -0
- package/dist/bridge/agent-session.js +15 -0
- package/dist/bridge/index.d.ts +1 -1
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/scene-bridge.d.ts +42 -6
- package/dist/bridge/scene-bridge.d.ts.map +1 -1
- package/dist/bridge/scene-bridge.js +232 -45
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/safe-fetch.d.ts +22 -4
- package/dist/lib/safe-fetch.d.ts.map +1 -1
- package/dist/lib/safe-fetch.js +233 -134
- package/dist/operations/scene-operations.d.ts +41 -3
- package/dist/operations/scene-operations.d.ts.map +1 -1
- package/dist/operations/scene-operations.js +42 -1
- package/dist/prompts/from-brief.d.ts +1 -1
- package/dist/prompts/from-brief.d.ts.map +1 -1
- package/dist/prompts/from-brief.js +3 -3
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/iterate-on-feedback.d.ts +1 -1
- package/dist/prompts/iterate-on-feedback.d.ts.map +1 -1
- package/dist/prompts/iterate-on-feedback.js +3 -3
- package/dist/prompts/renovation-from-photos.d.ts +1 -1
- package/dist/prompts/renovation-from-photos.d.ts.map +1 -1
- package/dist/prompts/renovation-from-photos.js +2 -2
- package/dist/prompts/scene-guidance.d.ts.map +1 -1
- package/dist/prompts/scene-guidance.js +13 -6
- package/dist/resources/agent-guide.d.ts +1 -1
- package/dist/resources/agent-guide.d.ts.map +1 -1
- package/dist/resources/agent-guide.js +62 -33
- package/dist/resources/catalog-items.d.ts +5 -6
- package/dist/resources/catalog-items.d.ts.map +1 -1
- package/dist/resources/catalog-items.js +7 -9
- package/dist/resources/constraints.d.ts +1 -1
- package/dist/resources/constraints.d.ts.map +1 -1
- package/dist/resources/constraints.js +1 -1
- package/dist/resources/design-schema.d.ts +9 -0
- package/dist/resources/design-schema.d.ts.map +1 -0
- package/dist/resources/design-schema.js +21 -0
- package/dist/resources/index.d.ts +4 -2
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +5 -2
- package/dist/resources/scene-current.d.ts +1 -1
- package/dist/resources/scene-current.d.ts.map +1 -1
- package/dist/resources/scene-summary.d.ts +1 -1
- package/dist/resources/scene-summary.d.ts.map +1 -1
- package/dist/server.d.ts +25 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +71 -25
- package/dist/storage/disk-artifact-store.d.ts +9 -0
- package/dist/storage/disk-artifact-store.d.ts.map +1 -0
- package/dist/storage/disk-artifact-store.js +46 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/sqlite-scene-store.d.ts +3 -3
- package/dist/storage/sqlite-scene-store.d.ts.map +1 -1
- package/dist/storage/sqlite-scene-store.js +4 -3
- package/dist/storage/types.d.ts +36 -7
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js +12 -0
- package/dist/templates/empty-studio.d.ts +3 -3
- package/dist/templates/empty-studio.d.ts.map +1 -1
- package/dist/templates/garden-house.d.ts +3 -3
- package/dist/templates/garden-house.d.ts.map +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/two-bedroom.d.ts +3 -3
- package/dist/templates/two-bedroom.d.ts.map +1 -1
- package/dist/tools/add-column.d.ts +5 -0
- package/dist/tools/add-column.d.ts.map +1 -0
- package/dist/tools/add-column.js +59 -0
- package/dist/tools/add-object.d.ts +76 -0
- package/dist/tools/add-object.d.ts.map +1 -0
- package/dist/tools/add-object.js +187 -0
- package/dist/tools/annotations.d.ts.map +1 -1
- package/dist/tools/apply-patch.d.ts +9 -2
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +36 -5
- package/dist/tools/asset-catalog.d.ts +9 -5
- package/dist/tools/asset-catalog.d.ts.map +1 -1
- package/dist/tools/asset-catalog.js +33 -12
- package/dist/tools/author-scene.d.ts +10 -0
- package/dist/tools/author-scene.d.ts.map +1 -0
- package/dist/tools/author-scene.js +140 -0
- package/dist/tools/check-collisions.d.ts +7 -7
- package/dist/tools/check-collisions.d.ts.map +1 -1
- package/dist/tools/check-collisions.js +7 -8
- package/dist/tools/clear-scene.d.ts +9 -0
- package/dist/tools/clear-scene.d.ts.map +1 -0
- package/dist/tools/clear-scene.js +59 -0
- package/dist/tools/collections.d.ts +4 -0
- package/dist/tools/collections.d.ts.map +1 -0
- package/dist/tools/collections.js +53 -0
- package/dist/tools/construction-tools.d.ts +12 -88
- package/dist/tools/construction-tools.d.ts.map +1 -1
- package/dist/tools/construction-tools.js +122 -381
- package/dist/tools/create-unit.d.ts +5 -3
- package/dist/tools/create-unit.d.ts.map +1 -1
- package/dist/tools/create-unit.js +2 -2
- package/dist/tools/errors.d.ts +15 -4
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +14 -4
- package/dist/tools/export-glb.d.ts +1 -1
- package/dist/tools/export-glb.d.ts.map +1 -1
- package/dist/tools/export-glb.js +2 -2
- package/dist/tools/export-json.d.ts +1 -1
- package/dist/tools/export-json.d.ts.map +1 -1
- package/dist/tools/export-json.js +2 -2
- package/dist/tools/geometry-script-worker.d.ts +2 -0
- package/dist/tools/geometry-script-worker.d.ts.map +1 -0
- package/dist/tools/geometry-script-worker.js +21 -0
- package/dist/tools/get-scene.d.ts +2 -1
- package/dist/tools/get-scene.d.ts.map +1 -1
- package/dist/tools/get-scene.js +5 -3
- package/dist/tools/honest-patch-guard.d.ts +2 -0
- package/dist/tools/honest-patch-guard.d.ts.map +1 -0
- package/dist/tools/honest-patch-guard.js +32 -0
- package/dist/tools/hosted-services.d.ts +4 -0
- package/dist/tools/hosted-services.d.ts.map +1 -0
- package/dist/tools/hosted-services.js +40 -0
- package/dist/tools/index.d.ts +12 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +18 -32
- package/dist/tools/level-height-guard.d.ts +2 -0
- package/dist/tools/level-height-guard.d.ts.map +1 -0
- package/dist/tools/level-height-guard.js +11 -0
- package/dist/tools/list-units.d.ts +2 -2
- package/dist/tools/list-units.d.ts.map +1 -1
- package/dist/tools/list-units.js +2 -2
- package/dist/tools/live-sync.d.ts +25 -6
- package/dist/tools/live-sync.d.ts.map +1 -1
- package/dist/tools/live-sync.js +48 -27
- package/dist/tools/local-geometry-scripts.d.ts +8 -0
- package/dist/tools/local-geometry-scripts.d.ts.map +1 -0
- package/dist/tools/local-geometry-scripts.js +67 -0
- package/dist/tools/measure.d.ts +7 -1
- package/dist/tools/measure.d.ts.map +1 -1
- package/dist/tools/measure.js +38 -70
- package/dist/tools/measurement.d.ts +1 -36
- package/dist/tools/measurement.d.ts.map +1 -1
- package/dist/tools/measurement.js +2 -94
- package/dist/tools/node-world-point.d.ts +37 -0
- package/dist/tools/node-world-point.d.ts.map +1 -0
- package/dist/tools/node-world-point.js +457 -0
- package/dist/tools/normalize-schema-dialect.d.ts +1 -1
- package/dist/tools/normalize-schema-dialect.d.ts.map +1 -1
- package/dist/tools/normalize-schema-dialect.js +22 -3
- package/dist/tools/patch-guards.d.ts +60 -0
- package/dist/tools/patch-guards.d.ts.map +1 -0
- package/dist/tools/patch-guards.js +256 -0
- package/dist/tools/photo-to-scene/index.d.ts +1 -1
- package/dist/tools/photo-to-scene/index.d.ts.map +1 -1
- package/dist/tools/photo-to-scene/photo-to-scene.d.ts +3 -3
- package/dist/tools/photo-to-scene/photo-to-scene.d.ts.map +1 -1
- package/dist/tools/photo-to-scene/photo-to-scene.js +10 -9
- package/dist/tools/project-files.d.ts +4 -0
- package/dist/tools/project-files.d.ts.map +1 -0
- package/dist/tools/project-files.js +30 -0
- package/dist/tools/redo.d.ts +4 -2
- package/dist/tools/redo.d.ts.map +1 -1
- package/dist/tools/redo.js +4 -4
- package/dist/tools/retired-tools.d.ts +10 -0
- package/dist/tools/retired-tools.d.ts.map +1 -0
- package/dist/tools/retired-tools.js +22 -0
- package/dist/tools/roof-level-guard.d.ts +2 -0
- package/dist/tools/roof-level-guard.d.ts.map +1 -0
- package/dist/tools/roof-level-guard.js +22 -0
- package/dist/tools/room-tools.d.ts +36 -98
- package/dist/tools/room-tools.d.ts.map +1 -1
- package/dist/tools/room-tools.js +130 -565
- package/dist/tools/scene-lifecycle/create-project.d.ts +1 -1
- package/dist/tools/scene-lifecycle/create-project.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/create-project.js +31 -6
- package/dist/tools/scene-lifecycle/delete-scene.d.ts +3 -1
- package/dist/tools/scene-lifecycle/delete-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/delete-scene.js +10 -9
- package/dist/tools/scene-lifecycle/get-project-status.d.ts +1 -1
- package/dist/tools/scene-lifecycle/get-project-status.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/get-project-status.js +6 -6
- package/dist/tools/scene-lifecycle/index.d.ts +1 -1
- package/dist/tools/scene-lifecycle/index.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/list-scenes.d.ts +1 -1
- package/dist/tools/scene-lifecycle/list-scenes.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/list-scenes.js +4 -4
- package/dist/tools/scene-lifecycle/load-scene.d.ts +2 -2
- package/dist/tools/scene-lifecycle/load-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/load-scene.js +5 -5
- package/dist/tools/scene-lifecycle/metadata.d.ts +1 -1
- package/dist/tools/scene-lifecycle/rename-scene.d.ts +1 -1
- package/dist/tools/scene-lifecycle/rename-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/rename-scene.js +6 -6
- package/dist/tools/scene-lifecycle/save-scene.d.ts +6 -3
- package/dist/tools/scene-lifecycle/save-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/save-scene.js +124 -16
- package/dist/tools/scene-lifecycle/test-utils.d.ts +3 -3
- package/dist/tools/scene-lifecycle/test-utils.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/test-utils.js +2 -1
- package/dist/tools/set-unit-members.d.ts +4 -2
- package/dist/tools/set-unit-members.d.ts.map +1 -1
- package/dist/tools/set-unit-members.js +6 -6
- package/dist/tools/set-zone.d.ts +4 -2
- package/dist/tools/set-zone.d.ts.map +1 -1
- package/dist/tools/set-zone.js +30 -18
- package/dist/tools/shared-tools.d.ts +40 -0
- package/dist/tools/shared-tools.d.ts.map +1 -0
- package/dist/tools/shared-tools.js +574 -0
- package/dist/tools/structure-tools.d.ts +57 -0
- package/dist/tools/structure-tools.d.ts.map +1 -0
- package/dist/tools/structure-tools.js +57 -0
- package/dist/tools/templates/create-from-template.d.ts +2 -2
- package/dist/tools/templates/create-from-template.d.ts.map +1 -1
- package/dist/tools/templates/create-from-template.js +6 -6
- package/dist/tools/templates/create-house-from-brief.d.ts +1 -1
- package/dist/tools/templates/create-house-from-brief.d.ts.map +1 -1
- package/dist/tools/templates/create-house-from-brief.js +6 -6
- package/dist/tools/templates/index.d.ts +1 -1
- package/dist/tools/templates/index.d.ts.map +1 -1
- package/dist/tools/templates/list-templates.d.ts +1 -1
- package/dist/tools/templates/list-templates.d.ts.map +1 -1
- package/dist/tools/templates/list-templates.js +2 -2
- package/dist/tools/undo.d.ts +4 -2
- package/dist/tools/undo.d.ts.map +1 -1
- package/dist/tools/undo.js +4 -4
- package/dist/tools/unit-members.d.ts.map +1 -1
- package/dist/tools/unit-members.js +6 -6
- package/dist/tools/variants/generate-variants.d.ts +6 -6
- package/dist/tools/variants/generate-variants.d.ts.map +1 -1
- package/dist/tools/variants/generate-variants.js +6 -6
- package/dist/tools/variants/index.d.ts +1 -1
- package/dist/tools/variants/index.d.ts.map +1 -1
- package/dist/tools/variants/mutations.js +1 -1
- package/dist/tools/view-scene.d.ts +44 -0
- package/dist/tools/view-scene.d.ts.map +1 -0
- package/dist/tools/view-scene.js +75 -0
- package/dist/tools/vision/analyze-floorplan-image.d.ts +1 -1
- package/dist/tools/vision/analyze-floorplan-image.d.ts.map +1 -1
- package/dist/tools/vision/analyze-floorplan-image.js +7 -7
- package/dist/tools/vision/analyze-room-photo.d.ts +1 -1
- package/dist/tools/vision/analyze-room-photo.d.ts.map +1 -1
- package/dist/tools/vision/analyze-room-photo.js +7 -7
- package/dist/tools/vision/index.d.ts +1 -1
- package/dist/tools/vision/index.d.ts.map +1 -1
- package/dist/transports/http.d.ts +8 -2
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +9 -3
- package/dist/transports/stdio.d.ts +15 -9
- package/dist/transports/stdio.d.ts.map +1 -1
- package/dist/transports/stdio.js +18 -11
- package/dist/version.d.ts +5 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +17 -3
- package/examples/coordinate-conventions-demo.md +12 -13
- package/examples/embed-in-agent.ts +6 -7
- package/examples/generate-apartment.md +13 -15
- package/examples/photo-to-scene.md +3 -4
- package/examples/renovate-from-photos.md +6 -9
- package/package.json +19 -9
- package/dist/tools/create-level.d.ts +0 -21
- package/dist/tools/create-level.d.ts.map +0 -1
- package/dist/tools/create-level.js +0 -63
- package/dist/tools/create-wall.d.ts +0 -22
- package/dist/tools/create-wall.d.ts.map +0 -1
- package/dist/tools/create-wall.js +0 -57
- package/dist/tools/cut-opening.d.ts +0 -25
- package/dist/tools/cut-opening.d.ts.map +0 -1
- package/dist/tools/cut-opening.js +0 -61
- package/dist/tools/delete-node.d.ts +0 -19
- package/dist/tools/delete-node.d.ts.map +0 -1
- package/dist/tools/delete-node.js +0 -40
- package/dist/tools/describe-node.d.ts +0 -17
- package/dist/tools/describe-node.d.ts.map +0 -1
- package/dist/tools/describe-node.js +0 -97
- package/dist/tools/door-clearance.d.ts +0 -135
- package/dist/tools/door-clearance.d.ts.map +0 -1
- package/dist/tools/door-clearance.js +0 -334
- package/dist/tools/duplicate-level.d.ts +0 -19
- package/dist/tools/duplicate-level.d.ts.map +0 -1
- package/dist/tools/duplicate-level.js +0 -60
- package/dist/tools/find-nodes.d.ts +0 -32
- package/dist/tools/find-nodes.d.ts.map +0 -1
- package/dist/tools/find-nodes.js +0 -107
- package/dist/tools/geometry.d.ts +0 -24
- package/dist/tools/geometry.d.ts.map +0 -1
- package/dist/tools/geometry.js +0 -94
- package/dist/tools/get-node.d.ts +0 -11
- package/dist/tools/get-node.d.ts.map +0 -1
- package/dist/tools/get-node.js +0 -29
- package/dist/tools/layout-clearance.d.ts +0 -105
- package/dist/tools/layout-clearance.d.ts.map +0 -1
- package/dist/tools/layout-clearance.js +0 -190
- package/dist/tools/place-item.d.ts +0 -22
- package/dist/tools/place-item.d.ts.map +0 -1
- package/dist/tools/place-item.js +0 -89
- package/dist/tools/scene-query.d.ts +0 -62
- package/dist/tools/scene-query.d.ts.map +0 -1
- package/dist/tools/scene-query.js +0 -670
- package/dist/tools/validate-scene.d.ts +0 -19
- package/dist/tools/validate-scene.d.ts.map +0 -1
- package/dist/tools/validate-scene.js +0 -28
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
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 createFromTemplateInput: {
|
|
@@ -36,8 +36,8 @@ export declare const createFromTemplateOutput: {
|
|
|
36
36
|
published: z.ZodBoolean;
|
|
37
37
|
isDraft: z.ZodBoolean;
|
|
38
38
|
saveMode: z.ZodEnum<{
|
|
39
|
-
draft: "draft";
|
|
40
39
|
checkpoint: "checkpoint";
|
|
40
|
+
draft: "draft";
|
|
41
41
|
}>;
|
|
42
42
|
graphHash: z.ZodOptional<z.ZodString>;
|
|
43
43
|
levelIds: z.ZodArray<z.ZodString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-from-template.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/create-from-template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"create-from-template.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/create-from-template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAOvD,eAAO,MAAM,uBAAuB;IAClC,EAAE;IAKF,IAAI;IAMJ;;;;;OAKG;IACH,IAAI;IACJ,SAAS;CACV,CAAA;AAED,eAAO,MAAM,wBAAwB;IACnC,UAAU;IACV,WAAW;IACX,SAAS;IACT,yEAAyE;IACzE,WAAW;IACX,6DAA6D;IAC7D,KAAK;;;;;;;;;;;;;;;;;;;;;;;CAsBN,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA+F3F"}
|
|
@@ -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 {
|
|
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 createFromTemplateInput = {
|
|
@@ -67,12 +67,12 @@ export function registerCreateFromTemplate(server, bridge) {
|
|
|
67
67
|
server.registerTool('create_from_template', {
|
|
68
68
|
title: 'Create scene from template',
|
|
69
69
|
description: 'Instantiate a seed Pascal scene template into the bridge. Regenerates all ids before applying. When `save: true` and a SceneStore is wired, also persists the new scene and returns the SceneMeta.',
|
|
70
|
-
inputSchema: createFromTemplateInput,
|
|
71
|
-
outputSchema: createFromTemplateOutput,
|
|
70
|
+
inputSchema: z.object(createFromTemplateInput),
|
|
71
|
+
outputSchema: z.object(createFromTemplateOutput),
|
|
72
72
|
annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
|
|
73
73
|
}, async ({ id, name, save, projectId }) => {
|
|
74
74
|
if (!isTemplateId(id)) {
|
|
75
|
-
throwMcpError(
|
|
75
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, `unknown_template: ${id}. Call list_templates for the set of valid ids.`);
|
|
76
76
|
}
|
|
77
77
|
const entry = TEMPLATES[id];
|
|
78
78
|
// Clone: regenerate ids so each instantiation is independent.
|
|
@@ -87,7 +87,7 @@ export function registerCreateFromTemplate(server, bridge) {
|
|
|
87
87
|
}
|
|
88
88
|
catch (err) {
|
|
89
89
|
const msg = err instanceof Error ? err.message : String(err);
|
|
90
|
-
throwMcpError(
|
|
90
|
+
throwMcpError(ProtocolErrorCode.InternalError, `apply_failed: ${msg}`);
|
|
91
91
|
}
|
|
92
92
|
const basePayload = {
|
|
93
93
|
templateId: entry.id,
|
|
@@ -143,7 +143,7 @@ export function registerCreateFromTemplate(server, bridge) {
|
|
|
143
143
|
}
|
|
144
144
|
catch (err) {
|
|
145
145
|
const msg = err instanceof Error ? err.message : String(err);
|
|
146
|
-
throwMcpError(
|
|
146
|
+
throwMcpError(ProtocolErrorCode.InternalError, `save_failed: ${msg}`);
|
|
147
147
|
}
|
|
148
148
|
});
|
|
149
149
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
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 createHouseFromBriefInput: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-house-from-brief.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/create-house-from-brief.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"create-house-from-brief.d.ts","sourceRoot":"","sources":["../../../src/tools/templates/create-house-from-brief.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAOvD,eAAO,MAAM,yBAAyB;IACpC,KAAK;IACL,SAAS;IACT,WAAW;IACX,YAAY;IACZ,KAAK;IACL,KAAK;IACL,WAAW;IACX,WAAW;CACZ,CAAA;AAED,eAAO,MAAM,0BAA0B;IACrC,SAAS;IACT,SAAS;IACT,GAAG;IACH,OAAO;IACP,SAAS;IACT,OAAO;IACP,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,cAAc;IACd,UAAU;;;;IAIV,OAAO;IACP,WAAW;IACX,QAAQ;CACT,CAAA;AAmCD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAsI7F"}
|
|
@@ -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 {
|
|
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(
|
|
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(
|
|
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(
|
|
169
|
+
throwMcpError(ProtocolErrorCode.InternalError, `save_failed: ${msg}`);
|
|
170
170
|
}
|
|
171
171
|
});
|
|
172
172
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
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,
|
|
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 +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,
|
|
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) => ({
|
package/dist/tools/undo.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/
|
|
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: {
|
|
5
5
|
steps: z.ZodOptional<z.ZodNumber>;
|
|
6
6
|
};
|
|
7
7
|
export declare const undoOutput: {
|
|
8
|
+
project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
9
|
+
unsaved: z.ZodOptional<z.ZodString>;
|
|
8
10
|
persistence: z.ZodOptional<z.ZodObject<{
|
|
9
11
|
status: z.ZodEnum<{
|
|
10
|
-
unbound: "unbound";
|
|
11
12
|
events_unsupported: "events_unsupported";
|
|
13
|
+
unbound: "unbound";
|
|
12
14
|
}>;
|
|
13
15
|
warning: z.ZodString;
|
|
14
16
|
}, z.core.$strip>>;
|
package/dist/tools/undo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"undo.d.ts","sourceRoot":"","sources":["../../src/tools/undo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
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"}
|
package/dist/tools/undo.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { DESTRUCTIVE_TOOL_ANNOTATIONS } from './annotations.js';
|
|
3
|
-
import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
|
|
3
|
+
import { currentLiveSync, liveSyncOutput, persistencePayload, publishLiveSceneSnapshot, } from './live-sync.js';
|
|
4
4
|
export const undoInput = {
|
|
5
5
|
steps: z.number().int().positive().optional(),
|
|
6
6
|
};
|
|
@@ -12,12 +12,12 @@ 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);
|
|
20
|
-
const persistence = undone > 0 ? await publishLiveSceneSnapshot(bridge, 'undo') :
|
|
20
|
+
const persistence = undone > 0 ? await publishLiveSceneSnapshot(bridge, 'undo') : currentLiveSync(bridge);
|
|
21
21
|
const payload = { undone, ...persistencePayload(persistence) };
|
|
22
22
|
return {
|
|
23
23
|
content: [{ type: 'text', text: JSON.stringify(payload) }],
|
|
@@ -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,
|
|
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 {
|
|
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(
|
|
5
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, `Building not found: ${buildingId}`);
|
|
6
6
|
}
|
|
7
7
|
if (building.type !== 'building') {
|
|
8
|
-
throwMcpError(
|
|
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(
|
|
13
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, `Zone not found: ${zoneId}`);
|
|
14
14
|
}
|
|
15
15
|
if (zone.type !== 'zone') {
|
|
16
|
-
throwMcpError(
|
|
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(
|
|
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/
|
|
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,
|
|
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 {
|
|
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(
|
|
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(
|
|
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(
|
|
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/
|
|
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,
|
|
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"}
|
|
@@ -31,7 +31,7 @@ function cloneGraph(graph) {
|
|
|
31
31
|
}
|
|
32
32
|
const WALL_THICKNESS_OPTIONS = [0.1, 0.15, 0.2, 0.25];
|
|
33
33
|
const WALL_HEIGHT_OPTIONS = [2.4, 2.6, 2.7, 3.0];
|
|
34
|
-
const FENCE_STYLES = ['privacy', 'slat', 'rail'];
|
|
34
|
+
const FENCE_STYLES = ['privacy', 'slat', 'rail', 'picket'];
|
|
35
35
|
/** Fisher–Yates shuffle in place using the provided RNG. */
|
|
36
36
|
function shuffleInPlace(arr, rng) {
|
|
37
37
|
for (let i = arr.length - 1; i > 0; i--) {
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
import type { SceneOperations } from '../operations/index.js';
|
|
4
|
+
/** A picture of the scene, rendered by an editor tab open on the project. */
|
|
5
|
+
export type SceneViewCapture = {
|
|
6
|
+
image: Uint8Array;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
/** Which tab rendered it, and when: the scene as that tab showed it then. */
|
|
11
|
+
tab: string;
|
|
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;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Asks an editor open on the project for a picture, the MCP having no renderer of its own. Refuses
|
|
19
|
+
* `editor_tab_required` when none answers.
|
|
20
|
+
*/
|
|
21
|
+
export type SceneViewHost = {
|
|
22
|
+
capture(request: {
|
|
23
|
+
projectId: string;
|
|
24
|
+
pose: SceneViewPose;
|
|
25
|
+
size: {
|
|
26
|
+
w: number;
|
|
27
|
+
h: number;
|
|
28
|
+
};
|
|
29
|
+
/** A look inside this floor: the editor leaves the rest out and cuts everything on it. */
|
|
30
|
+
interior?: SceneViewInterior;
|
|
31
|
+
presentation?: SceneViewPresentation;
|
|
32
|
+
/** The light to render it in; the scene's own when absent. */
|
|
33
|
+
lighting?: SceneViewLighting;
|
|
34
|
+
}): Promise<SceneViewCapture>;
|
|
35
|
+
/** Crops the reference photo to a region; without it a view with a photo is refused. */
|
|
36
|
+
crop?(request: SceneViewCrop): Promise<{
|
|
37
|
+
image: Uint8Array;
|
|
38
|
+
mimeType: string;
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
export declare function registerViewScene(server: McpServer, operations: SceneOperations, views?: SceneViewHost): void;
|
|
44
|
+
//# sourceMappingURL=view-scene.d.ts.map
|
|
@@ -0,0 +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,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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { confirmSceneViewPresentation, sceneViewNote, sceneViewPlan, } from '@pascal-app/core/agent-operations';
|
|
2
|
+
import { refuse, viewSceneTool } from '@pascal-app/core/agent-tools';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
|
|
5
|
+
import { refusalResult } from './errors.js';
|
|
6
|
+
export function registerViewScene(server, operations, views) {
|
|
7
|
+
server.registerTool(viewSceneTool.name, {
|
|
8
|
+
title: viewSceneTool.title,
|
|
9
|
+
description: viewSceneTool.description,
|
|
10
|
+
inputSchema: z.object(viewSceneTool.input),
|
|
11
|
+
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
12
|
+
}, async (input) => {
|
|
13
|
+
try {
|
|
14
|
+
if (!views)
|
|
15
|
+
refuse('view_unavailable', 'This Pascal server has no editor to render with: take sizes and counts from the tools.');
|
|
16
|
+
const projectId = operations.getActiveScene()?.projectId;
|
|
17
|
+
if (!projectId)
|
|
18
|
+
refuse('no_project', 'This session has no project open to look at: load or create one.');
|
|
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);
|
|
21
|
+
if (crop && !views.crop)
|
|
22
|
+
refuse('photo_crop_unavailable', 'This Pascal server cannot crop a photo: crop the region yourself and lay it beside the view.');
|
|
23
|
+
const [shot, cropped] = await Promise.all([
|
|
24
|
+
views.capture({
|
|
25
|
+
projectId: projectId,
|
|
26
|
+
pose,
|
|
27
|
+
size,
|
|
28
|
+
...(interior ? { interior } : {}),
|
|
29
|
+
...(presentation ? { presentation } : {}),
|
|
30
|
+
...(lighting ? { lighting } : {}),
|
|
31
|
+
}),
|
|
32
|
+
crop ? views.crop(crop) : undefined,
|
|
33
|
+
]);
|
|
34
|
+
confirmSceneViewPresentation(presentation, shot.presentation);
|
|
35
|
+
const payload = {
|
|
36
|
+
status: 'viewed',
|
|
37
|
+
camera: pose,
|
|
38
|
+
size: { width: shot.width, height: shot.height },
|
|
39
|
+
tab: shot.tab,
|
|
40
|
+
capturedAt: shot.capturedAt,
|
|
41
|
+
...(shot.viewId ? { viewId: shot.viewId } : {}),
|
|
42
|
+
...(shot.presentation ? { presentation: shot.presentation } : {}),
|
|
43
|
+
note: sceneViewNote(operations.getNodes(), interior, pose),
|
|
44
|
+
...(crop && cropped
|
|
45
|
+
? {
|
|
46
|
+
photoRegion: crop.region,
|
|
47
|
+
photoCropSize: { width: cropped.width, height: cropped.height },
|
|
48
|
+
}
|
|
49
|
+
: {}),
|
|
50
|
+
};
|
|
51
|
+
const image = (data, mimeType) => ({
|
|
52
|
+
type: 'image',
|
|
53
|
+
data: Buffer.from(data).toString('base64'),
|
|
54
|
+
mimeType,
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
content: cropped
|
|
58
|
+
? [
|
|
59
|
+
{ type: 'text', text: JSON.stringify(payload) },
|
|
60
|
+
{ type: 'text', text: 'The model, from the view:' },
|
|
61
|
+
image(shot.image, shot.mimeType),
|
|
62
|
+
{ type: 'text', text: 'The photo, cropped to the region:' },
|
|
63
|
+
image(cropped.image, cropped.mimeType),
|
|
64
|
+
]
|
|
65
|
+
: [
|
|
66
|
+
image(shot.image, shot.mimeType),
|
|
67
|
+
{ type: 'text', text: JSON.stringify(payload) },
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
return refusalResult(error);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -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,
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
137
|
+
throw new ProtocolError(ProtocolErrorCode.InternalError, 'sampling_response_invalid', {
|
|
138
138
|
raw: text,
|
|
139
139
|
errors: validation.error.issues,
|
|
140
140
|
});
|
|
@@ -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,
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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,
|
|
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"}
|