@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.
- package/CHANGELOG.md +76 -0
- package/README.md +166 -62
- package/dist/bin/pascal-mcp.js +1 -1
- 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 +3 -0
- package/dist/bridge/scene-bridge.d.ts.map +1 -1
- package/dist/bridge/scene-bridge.js +7 -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 +18 -0
- package/dist/operations/scene-operations.d.ts.map +1 -1
- package/dist/operations/scene-operations.js +11 -0
- 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 +2 -2
- 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 +10 -3
- 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 +52 -44
- package/dist/resources/catalog-items.d.ts +1 -1
- package/dist/resources/catalog-items.d.ts.map +1 -1
- 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 +1 -1
- package/dist/resources/design-schema.d.ts.map +1 -1
- package/dist/resources/index.d.ts +1 -1
- package/dist/resources/index.d.ts.map +1 -1
- 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 +7 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +59 -21
- package/dist/storage/disk-artifact-store.d.ts.map +1 -1
- package/dist/storage/sqlite-scene-store.d.ts +1 -1
- package/dist/storage/sqlite-scene-store.d.ts.map +1 -1
- package/dist/storage/types.d.ts +4 -4
- package/dist/storage/types.d.ts.map +1 -1
- 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 +1 -1
- package/dist/tools/add-column.d.ts.map +1 -1
- package/dist/tools/add-column.js +3 -2
- package/dist/tools/add-object.d.ts +19 -3
- package/dist/tools/add-object.d.ts.map +1 -1
- package/dist/tools/add-object.js +66 -35
- package/dist/tools/annotations.d.ts.map +1 -1
- package/dist/tools/apply-patch.d.ts +6 -2
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +13 -8
- package/dist/tools/asset-catalog.d.ts.map +1 -1
- package/dist/tools/asset-catalog.js +23 -0
- 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 +6 -6
- package/dist/tools/check-collisions.d.ts.map +1 -1
- package/dist/tools/check-collisions.js +6 -6
- package/dist/tools/clear-scene.d.ts +1 -1
- package/dist/tools/clear-scene.d.ts.map +1 -1
- package/dist/tools/clear-scene.js +3 -3
- package/dist/tools/collections.d.ts +1 -1
- package/dist/tools/collections.d.ts.map +1 -1
- package/dist/tools/collections.js +3 -2
- package/dist/tools/construction-tools.d.ts +6 -49
- package/dist/tools/construction-tools.d.ts.map +1 -1
- package/dist/tools/construction-tools.js +9 -158
- package/dist/tools/create-unit.d.ts +3 -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 +5 -5
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +4 -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/get-scene.d.ts +1 -1
- package/dist/tools/get-scene.d.ts.map +1 -1
- package/dist/tools/get-scene.js +2 -2
- package/dist/tools/hosted-services.d.ts +1 -1
- package/dist/tools/hosted-services.d.ts.map +1 -1
- package/dist/tools/hosted-services.js +13 -3
- package/dist/tools/index.d.ts +4 -3
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +8 -13
- 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 +1 -1
- package/dist/tools/live-sync.d.ts.map +1 -1
- package/dist/tools/live-sync.js +4 -4
- package/dist/tools/measure.d.ts +1 -1
- package/dist/tools/measure.d.ts.map +1 -1
- package/dist/tools/measure.js +7 -7
- package/dist/tools/node-world-point.d.ts +1 -1
- package/dist/tools/node-world-point.d.ts.map +1 -1
- 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 +2 -3
- package/dist/tools/patch-guards.d.ts +6 -4
- package/dist/tools/patch-guards.d.ts.map +1 -1
- package/dist/tools/patch-guards.js +5 -2
- 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 +7 -7
- 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 +2 -2
- package/dist/tools/redo.d.ts.map +1 -1
- package/dist/tools/redo.js +2 -2
- 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 +47 -46
- package/dist/tools/room-tools.d.ts.map +1 -1
- package/dist/tools/room-tools.js +6 -5
- 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 +5 -5
- package/dist/tools/scene-lifecycle/delete-scene.d.ts +1 -1
- package/dist/tools/scene-lifecycle/delete-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/delete-scene.js +6 -6
- 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 +5 -3
- package/dist/tools/scene-lifecycle/save-scene.d.ts.map +1 -1
- package/dist/tools/scene-lifecycle/save-scene.js +80 -12
- package/dist/tools/scene-lifecycle/test-utils.d.ts +1 -1
- package/dist/tools/scene-lifecycle/test-utils.d.ts.map +1 -1
- package/dist/tools/set-unit-members.d.ts +2 -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 +2 -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 +15 -5
- package/dist/tools/shared-tools.d.ts.map +1 -1
- package/dist/tools/shared-tools.js +242 -29
- package/dist/tools/structure-tools.d.ts +3 -3
- 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 +2 -2
- package/dist/tools/undo.d.ts.map +1 -1
- package/dist/tools/undo.js +2 -2
- 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/view-scene.d.ts +8 -2
- package/dist/tools/view-scene.d.ts.map +1 -1
- package/dist/tools/view-scene.js +17 -5
- 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/examples/coordinate-conventions-demo.md +12 -13
- package/examples/embed-in-agent.ts +5 -6
- package/examples/generate-apartment.md +4 -4
- package/examples/photo-to-scene.md +2 -3
- package/examples/renovate-from-photos.md +3 -5
- package/package.json +13 -9
- 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 -99
- package/dist/tools/find-nodes.d.ts +0 -16
- package/dist/tools/find-nodes.d.ts.map +0 -1
- package/dist/tools/find-nodes.js +0 -204
- package/dist/tools/place-design.d.ts +0 -34
- package/dist/tools/place-design.d.ts.map +0 -1
- package/dist/tools/place-design.js +0 -91
- package/dist/tools/validate-design.d.ts +0 -136
- package/dist/tools/validate-design.d.ts.map +0 -1
- package/dist/tools/validate-design.js +0 -28
- 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,8 +1,10 @@
|
|
|
1
1
|
import { isAgentRefusal } from '@pascal-app/core/agent-tools';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { DESTRUCTIVE_TOOL_ANNOTATIONS } from './annotations.js';
|
|
4
|
-
import {
|
|
4
|
+
import { ProtocolError, ProtocolErrorCode, refusalResult, throwMcpError } from './errors.js';
|
|
5
5
|
import './honest-patch-guard.js';
|
|
6
|
+
import './level-height-guard.js';
|
|
7
|
+
import './roof-level-guard.js';
|
|
6
8
|
import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
|
|
7
9
|
import { assertPatchKeepsIdentity, PatchRefusedError, runPatchGuards } from './patch-guards.js';
|
|
8
10
|
import { PatchSchema } from './schemas.js';
|
|
@@ -13,14 +15,16 @@ export const applyPatchOutput = {
|
|
|
13
15
|
appliedOps: z.number(),
|
|
14
16
|
deletedIds: z.array(z.string()),
|
|
15
17
|
createdIds: z.array(z.string()),
|
|
18
|
+
/** What the server changed in the patch before writing it, one line each. */
|
|
19
|
+
notes: z.array(z.string()).optional(),
|
|
16
20
|
...liveSyncOutput,
|
|
17
21
|
};
|
|
18
22
|
export function registerApplyPatch(server, bridge) {
|
|
19
23
|
server.registerTool('apply_patch', {
|
|
20
24
|
title: 'Apply patch',
|
|
21
|
-
description: "Apply a batch of create/update/delete operations atomically. All patches are validated before any are applied; the entire batch forms a single undo step. Batch-first is the default: prefer one apply_patch call containing all create/update/delete ops for a build step, in stable order so later ops can reference ids created by earlier ops. A single call is atomic (all or nothing) and pays the snapshot and save cost once; do not loop one-op calls. A create whose id already exists fails the whole patch with node_exists; to replace a node, delete it earlier in the same patch. An update cannot change id or type (identity_change) or object or children (immutable_field); restating the current value is fine. A parentId change must name an existing node that holds children (invalid_parent). An update cannot add schema issues to a node (invalid_update). After a delete or a roof update that regenerates a roof's default gutters, those gutters and their downspouts are addressable only in a later call (regenerated_default). Refusals come back as a tool error whose text is JSON {code, patchIndex, id, message}.",
|
|
22
|
-
inputSchema: applyPatchInput,
|
|
23
|
-
outputSchema: applyPatchOutput,
|
|
25
|
+
description: "Apply a batch of create/update/delete operations atomically. All patches are validated before any are applied; the entire batch forms a single undo step. Batch-first is the default: prefer one apply_patch call containing all create/update/delete ops for a build step, in stable order so later ops can reference ids created by earlier ops. A single call is atomic (all or nothing) and pays the snapshot and save cost once; do not loop one-op calls. A create whose id already exists fails the whole patch with node_exists; to replace a node, delete it earlier in the same patch. An update cannot change id or type (identity_change) or object or children (immutable_field); restating the current value is fine. A parentId change must name an existing node that holds children (invalid_parent). An update cannot add schema issues to a node (invalid_update). After a delete or a roof update that regenerates a roof's default gutters, those gutters and their downspouts are addressable only in a later call (regenerated_default). A roof created or moved onto the storey whose walls carry it goes to the level above them (the roof level over a top storey), said in notes; storey content (walls, zones, slabs, ceilings, items, stairs) on a roof level (roof_level), a walled level declared the roof level (roof_level_holds_storey) and floor indexes putting a roof level under a storey (roof_level_on_top) are refused. Refusals come back as a tool error whose text is JSON {code, patchIndex, id, message}.",
|
|
26
|
+
inputSchema: z.object(applyPatchInput),
|
|
27
|
+
outputSchema: z.object(applyPatchOutput),
|
|
24
28
|
annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
|
|
25
29
|
}, async ({ patches }) => {
|
|
26
30
|
const bridgePatches = patches.map((p) => {
|
|
@@ -45,7 +49,7 @@ export function registerApplyPatch(server, bridge) {
|
|
|
45
49
|
};
|
|
46
50
|
});
|
|
47
51
|
try {
|
|
48
|
-
runPatchGuards(bridgePatches, bridge.getNodes());
|
|
52
|
+
const notes = runPatchGuards(bridgePatches, bridge.getNodes());
|
|
49
53
|
const planDeletion = bridge
|
|
50
54
|
.planDeletion;
|
|
51
55
|
assertPatchKeepsIdentity(bridgePatches, bridge.getNodes(), bridge.getRootNodeIds(), typeof planDeletion === 'function' ? planDeletion.bind(bridge) : undefined);
|
|
@@ -55,6 +59,7 @@ export function registerApplyPatch(server, bridge) {
|
|
|
55
59
|
appliedOps: result.appliedOps,
|
|
56
60
|
deletedIds: result.deletedIds,
|
|
57
61
|
createdIds: result.createdIds,
|
|
62
|
+
...(notes.length ? { notes } : {}),
|
|
58
63
|
...persistencePayload(persistence),
|
|
59
64
|
};
|
|
60
65
|
return {
|
|
@@ -64,7 +69,7 @@ export function registerApplyPatch(server, bridge) {
|
|
|
64
69
|
}
|
|
65
70
|
catch (err) {
|
|
66
71
|
if (err instanceof PatchRefusedError) {
|
|
67
|
-
// A tool error, not an
|
|
72
|
+
// A tool error, not an ProtocolError: the SDK keeps only an ProtocolError's
|
|
68
73
|
// message, and clients need the code, index and id to act on it.
|
|
69
74
|
const refusal = {
|
|
70
75
|
code: err.code,
|
|
@@ -80,10 +85,10 @@ export function registerApplyPatch(server, bridge) {
|
|
|
80
85
|
// A refusal the store made (an accidental wipe) answers with its code, as the shared tools'.
|
|
81
86
|
if (isAgentRefusal(err))
|
|
82
87
|
return refusalResult(err);
|
|
83
|
-
if (err instanceof
|
|
88
|
+
if (err instanceof ProtocolError)
|
|
84
89
|
throw err;
|
|
85
90
|
const msg = err instanceof Error ? err.message : String(err);
|
|
86
|
-
throwMcpError(
|
|
91
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, msg);
|
|
87
92
|
}
|
|
88
93
|
});
|
|
89
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-catalog.d.ts","sourceRoot":"","sources":["../../src/tools/asset-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"asset-catalog.d.ts","sourceRoot":"","sources":["../../src/tools/asset-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAAU,EAoTzC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAA;AAE/D,eAAO,MAAM,cAAc,EAAE,YAA4C,CAAA;AAEzE,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CAO9D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEhG"}
|
|
@@ -10,6 +10,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
10
10
|
{
|
|
11
11
|
id: 'double-bed',
|
|
12
12
|
category: 'furniture',
|
|
13
|
+
functionTags: ['double-beds'],
|
|
13
14
|
tags: ['floor', 'bedroom'],
|
|
14
15
|
name: 'Double Bed',
|
|
15
16
|
thumbnail: '/items/double-bed/thumbnail.webp',
|
|
@@ -22,6 +23,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
22
23
|
{
|
|
23
24
|
id: 'single-bed',
|
|
24
25
|
category: 'furniture',
|
|
26
|
+
functionTags: ['single-beds'],
|
|
25
27
|
tags: ['floor', 'bedroom'],
|
|
26
28
|
name: 'Single Bed',
|
|
27
29
|
thumbnail: '/items/single-bed/thumbnail.webp',
|
|
@@ -34,6 +36,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
34
36
|
{
|
|
35
37
|
id: 'bedside-table',
|
|
36
38
|
category: 'furniture',
|
|
39
|
+
functionTags: ['coffee-tables'],
|
|
37
40
|
tags: ['floor', 'bedroom'],
|
|
38
41
|
name: 'Bedside Table',
|
|
39
42
|
thumbnail: '/items/bedside-table/thumbnail.webp',
|
|
@@ -47,6 +50,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
47
50
|
{
|
|
48
51
|
id: 'dresser',
|
|
49
52
|
category: 'furniture',
|
|
53
|
+
functionTags: ['dressers'],
|
|
50
54
|
tags: ['floor', 'storage', 'bedroom'],
|
|
51
55
|
name: 'Dresser',
|
|
52
56
|
thumbnail: '/items/dresser/thumbnail.webp',
|
|
@@ -60,6 +64,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
60
64
|
{
|
|
61
65
|
id: 'closet',
|
|
62
66
|
category: 'furniture',
|
|
67
|
+
functionTags: ['wardrobes'],
|
|
63
68
|
tags: ['floor', 'storage', 'bedroom'],
|
|
64
69
|
name: 'Closet',
|
|
65
70
|
thumbnail: '/items/closet/thumbnail.webp',
|
|
@@ -72,6 +77,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
72
77
|
{
|
|
73
78
|
id: 'sofa',
|
|
74
79
|
category: 'furniture',
|
|
80
|
+
functionTags: ['sofas'],
|
|
75
81
|
tags: ['floor', 'seating', 'living'],
|
|
76
82
|
name: 'Sofa',
|
|
77
83
|
thumbnail: '/items/sofa/thumbnail.webp',
|
|
@@ -84,6 +90,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
84
90
|
{
|
|
85
91
|
id: 'livingroom-chair',
|
|
86
92
|
category: 'furniture',
|
|
93
|
+
functionTags: ['armchairs'],
|
|
87
94
|
tags: ['floor', 'seating', 'living'],
|
|
88
95
|
name: 'Livingroom Chair',
|
|
89
96
|
thumbnail: '/items/livingroom-chair/thumbnail.webp',
|
|
@@ -96,6 +103,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
96
103
|
{
|
|
97
104
|
id: 'coffee-table',
|
|
98
105
|
category: 'furniture',
|
|
106
|
+
functionTags: ['coffee-tables'],
|
|
99
107
|
tags: ['floor', 'table', 'living'],
|
|
100
108
|
name: 'Coffee Table',
|
|
101
109
|
thumbnail: '/items/coffee-table/thumbnail.webp',
|
|
@@ -109,6 +117,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
109
117
|
{
|
|
110
118
|
id: 'tv-stand',
|
|
111
119
|
category: 'furniture',
|
|
120
|
+
functionTags: ['cabinets'],
|
|
112
121
|
tags: ['floor', 'storage', 'living'],
|
|
113
122
|
name: 'TV Stand',
|
|
114
123
|
thumbnail: '/items/tv-stand/thumbnail.webp',
|
|
@@ -122,6 +131,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
122
131
|
{
|
|
123
132
|
id: 'shelf',
|
|
124
133
|
category: 'furniture',
|
|
134
|
+
functionTags: ['shelves'],
|
|
125
135
|
tags: ['wall', 'storage'],
|
|
126
136
|
name: 'Shelf',
|
|
127
137
|
thumbnail: '/items/shelf/thumbnail.webp',
|
|
@@ -136,6 +146,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
136
146
|
{
|
|
137
147
|
id: 'dining-table',
|
|
138
148
|
category: 'furniture',
|
|
149
|
+
functionTags: ['dining-tables'],
|
|
139
150
|
tags: ['floor', 'table', 'dining'],
|
|
140
151
|
name: 'Dining Table',
|
|
141
152
|
thumbnail: '/items/dining-table/thumbnail.webp',
|
|
@@ -149,6 +160,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
149
160
|
{
|
|
150
161
|
id: 'dining-chair',
|
|
151
162
|
category: 'furniture',
|
|
163
|
+
functionTags: ['dining-chairs'],
|
|
152
164
|
tags: ['floor', 'seating', 'dining'],
|
|
153
165
|
name: 'Dining Chair',
|
|
154
166
|
thumbnail: '/items/dining-chair/thumbnail.webp',
|
|
@@ -161,6 +173,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
161
173
|
{
|
|
162
174
|
id: 'kitchen',
|
|
163
175
|
category: 'kitchen',
|
|
176
|
+
functionTags: ['cabinets'],
|
|
164
177
|
tags: ['floor', 'large', 'kitchen'],
|
|
165
178
|
name: 'Kitchen',
|
|
166
179
|
thumbnail: '/items/kitchen/thumbnail.webp',
|
|
@@ -173,6 +186,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
173
186
|
{
|
|
174
187
|
id: 'kitchen-counter',
|
|
175
188
|
category: 'kitchen',
|
|
189
|
+
functionTags: ['counters'],
|
|
176
190
|
tags: ['floor', 'large', 'storage', 'kitchen'],
|
|
177
191
|
name: 'Kitchen Counter',
|
|
178
192
|
thumbnail: '/items/kitchen-counter/thumbnail.webp',
|
|
@@ -186,6 +200,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
186
200
|
{
|
|
187
201
|
id: 'stove',
|
|
188
202
|
category: 'kitchen',
|
|
203
|
+
functionTags: ['kitchen-appliances'],
|
|
189
204
|
tags: ['floor', 'large', 'kitchen'],
|
|
190
205
|
name: 'Stove',
|
|
191
206
|
thumbnail: '/items/stove/thumbnail.webp',
|
|
@@ -198,6 +213,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
198
213
|
{
|
|
199
214
|
id: 'fridge',
|
|
200
215
|
category: 'kitchen',
|
|
216
|
+
functionTags: ['kitchen-appliances'],
|
|
201
217
|
tags: ['floor', 'large', 'kitchen'],
|
|
202
218
|
name: 'Fridge',
|
|
203
219
|
thumbnail: '/items/fridge/thumbnail.webp',
|
|
@@ -210,6 +226,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
210
226
|
{
|
|
211
227
|
id: 'toilet',
|
|
212
228
|
category: 'bathroom',
|
|
229
|
+
functionTags: ['toilets'],
|
|
213
230
|
tags: ['floor', 'large', 'bathroom'],
|
|
214
231
|
name: 'Toilet',
|
|
215
232
|
thumbnail: '/items/toilet/thumbnail.webp',
|
|
@@ -222,6 +239,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
222
239
|
{
|
|
223
240
|
id: 'bathroom-sink',
|
|
224
241
|
category: 'bathroom',
|
|
242
|
+
functionTags: ['sinks'],
|
|
225
243
|
tags: ['floor', 'large', 'bathroom'],
|
|
226
244
|
name: 'Bathroom Sink',
|
|
227
245
|
thumbnail: '/items/bathroom-sink/thumbnail.webp',
|
|
@@ -234,6 +252,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
234
252
|
{
|
|
235
253
|
id: 'shower-square',
|
|
236
254
|
category: 'bathroom',
|
|
255
|
+
functionTags: ['showers'],
|
|
237
256
|
tags: ['floor', 'large', 'bathroom'],
|
|
238
257
|
name: 'Squared Shower',
|
|
239
258
|
thumbnail: '/items/shower-square/thumbnail.webp',
|
|
@@ -246,6 +265,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
246
265
|
{
|
|
247
266
|
id: 'bathtub',
|
|
248
267
|
category: 'bathroom',
|
|
268
|
+
functionTags: ['bathtubs'],
|
|
249
269
|
tags: ['floor', 'large', 'bathroom'],
|
|
250
270
|
name: 'Bathtub',
|
|
251
271
|
thumbnail: '/items/bathtub/thumbnail.webp',
|
|
@@ -258,6 +278,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
258
278
|
{
|
|
259
279
|
id: 'washing-machine',
|
|
260
280
|
category: 'bathroom',
|
|
281
|
+
functionTags: ['laundry-appliances'],
|
|
261
282
|
tags: ['floor', 'large', 'electronics', 'laundry'],
|
|
262
283
|
name: 'Washing Machine',
|
|
263
284
|
thumbnail: '/items/washing-machine/thumbnail.webp',
|
|
@@ -270,6 +291,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
270
291
|
{
|
|
271
292
|
id: 'drying-rack',
|
|
272
293
|
category: 'bathroom',
|
|
294
|
+
functionTags: ['laundry-appliances'],
|
|
273
295
|
tags: ['floor', 'laundry'],
|
|
274
296
|
name: 'Drying Rack',
|
|
275
297
|
thumbnail: '/items/drying-rack/thumbnail.webp',
|
|
@@ -282,6 +304,7 @@ export const MCP_CATALOG_ITEMS = [
|
|
|
282
304
|
{
|
|
283
305
|
id: 'coat-rack',
|
|
284
306
|
category: 'furniture',
|
|
307
|
+
functionTags: ['racks'],
|
|
285
308
|
tags: ['floor', 'storage', 'entry'],
|
|
286
309
|
name: 'Coat Rack',
|
|
287
310
|
thumbnail: '/items/coat-rack/thumbnail.webp',
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
+
import type { SceneOperations } from '../operations/index.js';
|
|
3
|
+
import { type GeometryScriptHost } from './add-object.js';
|
|
4
|
+
/**
|
|
5
|
+
* `author_scene` on the MCP: every item's module compiled and stored through the host, the
|
|
6
|
+
* module and the adapter kept as the scene's provenance, the operation applied, Pascal's checks
|
|
7
|
+
* run, and the gate report answered. Replay is the same payload through the same operation.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerAuthorScene(server: McpServer, bridge: SceneOperations, host: GeometryScriptHost | undefined): void;
|
|
10
|
+
//# sourceMappingURL=author-scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author-scene.d.ts","sourceRoot":"","sources":["../../src/tools/author-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAe7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAevE;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,kBAAkB,GAAG,SAAS,GACnC,IAAI,CA0HN"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { achievedChanges, verifyScene, } from '@pascal-app/core/agent-operations';
|
|
2
|
+
import { authorSceneTool, isAgentRefusal, } from '@pascal-app/core/agent-tools';
|
|
3
|
+
import { GEOMETRY_SCRIPT_MIME_TYPES } from '@pascal-app/core/schema';
|
|
4
|
+
import { compileAuthorScene } from '@pascal-app/geometry-script/author-scene';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { compileAndStore } from './add-object.js';
|
|
7
|
+
import { DESTRUCTIVE_TOOL_ANNOTATIONS } from './annotations.js';
|
|
8
|
+
import { refusalResult, toolError } from './errors.js';
|
|
9
|
+
import { persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
|
|
10
|
+
import { toPatches } from './shared-tools.js';
|
|
11
|
+
/**
|
|
12
|
+
* `author_scene` on the MCP: every item's module compiled and stored through the host, the
|
|
13
|
+
* module and the adapter kept as the scene's provenance, the operation applied, Pascal's checks
|
|
14
|
+
* run, and the gate report answered. Replay is the same payload through the same operation.
|
|
15
|
+
*/
|
|
16
|
+
export function registerAuthorScene(server, bridge, host) {
|
|
17
|
+
server.registerTool(authorSceneTool.name, {
|
|
18
|
+
title: authorSceneTool.title,
|
|
19
|
+
description: authorSceneTool.description,
|
|
20
|
+
inputSchema: z.object(authorSceneTool.input),
|
|
21
|
+
annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
|
|
22
|
+
}, async (input) => {
|
|
23
|
+
if (!host) {
|
|
24
|
+
return toolError('This Pascal server cannot run geometry scripts.', {
|
|
25
|
+
code: 'scripts_unavailable',
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const args = input;
|
|
29
|
+
const scene = bridge.getActiveScene();
|
|
30
|
+
if (!scene) {
|
|
31
|
+
return toolError('Open or save a scene first: a conversion is stored with a scene.', {
|
|
32
|
+
code: 'no_active_scene',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (args.sceneId && args.sceneId !== scene.id) {
|
|
36
|
+
return toolError('Open the requested scene before converting it.', {
|
|
37
|
+
code: 'scene_mismatch',
|
|
38
|
+
mutationApplied: false,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const before = bridge.getNodes();
|
|
42
|
+
const beforeJson = JSON.stringify(before);
|
|
43
|
+
const context = {
|
|
44
|
+
activeLevelId: bridge.activeLevelId?.() ?? null,
|
|
45
|
+
...(bridge.supportsMaterialUpserts && bridge.getMaterials
|
|
46
|
+
? { materials: bridge.getMaterials() }
|
|
47
|
+
: {}),
|
|
48
|
+
};
|
|
49
|
+
let outcome;
|
|
50
|
+
try {
|
|
51
|
+
outcome = await compileAuthorScene(before, args, context, ({ code, kind, inputs, nodeId }) => compileAndStore(host, scene.id, { code, language: 'three', params: undefined, inputs }, kind, { nodeId }), host.signal);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (isAgentRefusal(error))
|
|
55
|
+
return refusalResult(error);
|
|
56
|
+
return toolError(error instanceof Error ? error.message : String(error), {
|
|
57
|
+
code: 'conversion_failed',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// Provenance: the design's module and the program that read it, kept as scripts of the scene.
|
|
61
|
+
const provenance = {};
|
|
62
|
+
for (const [kind, text] of [
|
|
63
|
+
['module', args.module],
|
|
64
|
+
['adapter', args.adapter],
|
|
65
|
+
]) {
|
|
66
|
+
if (!text)
|
|
67
|
+
continue;
|
|
68
|
+
provenance[kind] = await host.storeArtifact({
|
|
69
|
+
sceneId: scene.id,
|
|
70
|
+
sha256: await sha256(text),
|
|
71
|
+
bytes: new TextEncoder().encode(text),
|
|
72
|
+
mimeType: GEOMETRY_SCRIPT_MIME_TYPES.three,
|
|
73
|
+
metadata: { kind: 'item' },
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
host.signal?.throwIfAborted();
|
|
77
|
+
await host.assertActive?.();
|
|
78
|
+
if (JSON.stringify(bridge.getNodes()) !== beforeJson) {
|
|
79
|
+
return toolError('The scene changed while its candidate was compiling. Read the current scene and retry the conversion.', { code: 'scene_changed', mutationApplied: false });
|
|
80
|
+
}
|
|
81
|
+
const buildingUpdate = outcome.changes.update.find((change) => change.id === outcome.buildingId);
|
|
82
|
+
buildingUpdate.data.metadata = {
|
|
83
|
+
...buildingUpdate.data.metadata,
|
|
84
|
+
authorScene: {
|
|
85
|
+
...provenance,
|
|
86
|
+
payload: withoutCode(args.payload),
|
|
87
|
+
report: outcome.result,
|
|
88
|
+
at: new Date().toISOString(),
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
const patches = toPatches(outcome.changes);
|
|
92
|
+
if (patches.length)
|
|
93
|
+
bridge.applyPatch(patches);
|
|
94
|
+
const checks = verifyScene(bridge.getNodes(), undefined, {
|
|
95
|
+
activeLevelId: null,
|
|
96
|
+
}).result;
|
|
97
|
+
const byType = new Map();
|
|
98
|
+
for (const issue of checks.issues)
|
|
99
|
+
byType.set(issue.type ?? 'unknown', (byType.get(issue.type ?? 'unknown') ?? 0) + 1);
|
|
100
|
+
const payload = {
|
|
101
|
+
...outcome.result,
|
|
102
|
+
itemTriangles: outcome.itemTriangles,
|
|
103
|
+
itemsCompiled: outcome.itemsCompiled,
|
|
104
|
+
green: outcome.result.defects.length === 0,
|
|
105
|
+
verify: {
|
|
106
|
+
valid: checks.valid,
|
|
107
|
+
issues: checks.issues.length,
|
|
108
|
+
byType: Object.fromEntries(byType),
|
|
109
|
+
first: checks.issues.slice(0, 40).map((i) => i.message),
|
|
110
|
+
},
|
|
111
|
+
achieved: achievedChanges(before, outcome.changes ?? {}),
|
|
112
|
+
...persistencePayload(await publishLiveSceneSnapshot(bridge, authorSceneTool.name)),
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: 'text', text: JSON.stringify(payload) }],
|
|
116
|
+
structuredContent: payload,
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/** The payload as kept with the scene: every module is already its own artifact. */
|
|
121
|
+
function withoutCode(payload) {
|
|
122
|
+
return {
|
|
123
|
+
...payload,
|
|
124
|
+
levels: payload.levels.map((level) => ({
|
|
125
|
+
...level,
|
|
126
|
+
walls: (level.walls ?? []).map(({ faceLeft, faceRight, ...wall }) => ({
|
|
127
|
+
...wall,
|
|
128
|
+
openings: (wall.openings ?? []).map(({ code: _, ...opening }) => opening),
|
|
129
|
+
...(faceLeft ? { faceLeft: { toHeight: faceLeft.toHeight } } : {}),
|
|
130
|
+
...(faceRight ? { faceRight: { toHeight: faceRight.toHeight } } : {}),
|
|
131
|
+
})),
|
|
132
|
+
items: (level.items ?? []).map(({ code: _, ...item }) => item),
|
|
133
|
+
rooms: level.rooms.map(({ floorCode: _, wallCode: _w, ...room }) => room),
|
|
134
|
+
})),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async function sha256(text) {
|
|
138
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(text));
|
|
139
|
+
return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
140
|
+
}
|
|
@@ -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 checkCollisionsInput: {
|
|
5
5
|
levelId: z.ZodOptional<z.ZodString>;
|
|
6
|
-
minimumClearance: z.ZodDefault<z.ZodPipe<z.ZodUnion<
|
|
6
|
+
minimumClearance: z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
7
7
|
floorOnly: z.ZodDefault<z.ZodBoolean>;
|
|
8
8
|
candidate: z.ZodOptional<z.ZodObject<{
|
|
9
9
|
id: z.ZodDefault<z.ZodString>;
|
|
10
10
|
name: z.ZodDefault<z.ZodString>;
|
|
11
11
|
levelId: z.ZodString;
|
|
12
|
-
position: z.ZodPipe<z.ZodArray<z.ZodPipe<z.ZodUnion<
|
|
13
|
-
dimensions: z.ZodPipe<z.ZodArray<z.ZodPipe<z.ZodUnion<
|
|
14
|
-
rotationY: z.ZodDefault<z.ZodPipe<z.ZodUnion<
|
|
12
|
+
position: z.ZodPipe<z.ZodArray<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>> | z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>>, z.ZodTransform<[number, number, number], number[]>>;
|
|
13
|
+
dimensions: z.ZodPipe<z.ZodArray<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>> | z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>>, z.ZodTransform<[number, number, number], number[]>>;
|
|
14
|
+
rotationY: z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
15
15
|
source: z.ZodOptional<z.ZodObject<{
|
|
16
16
|
assetId: z.ZodOptional<z.ZodString>;
|
|
17
17
|
uri: z.ZodOptional<z.ZodString>;
|
|
@@ -21,8 +21,8 @@ export declare const checkCollisionsInput: {
|
|
|
21
21
|
export declare const checkCollisionsOutput: {
|
|
22
22
|
status: z.ZodEnum<{
|
|
23
23
|
checked: "checked";
|
|
24
|
-
partial: "partial";
|
|
25
24
|
insufficient_evidence: "insufficient_evidence";
|
|
25
|
+
partial: "partial";
|
|
26
26
|
}>;
|
|
27
27
|
units: z.ZodLiteral<"meters">;
|
|
28
28
|
method: z.ZodLiteral<"rotation-aware-plan-aabb">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-collisions.d.ts","sourceRoot":"","sources":["../../src/tools/check-collisions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"check-collisions.d.ts","sourceRoot":"","sources":["../../src/tools/check-collisions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAO7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AA4BpD,eAAO,MAAM,oBAAoB;IAC/B,OAAO;IACP,gBAAgB;IAIhB,SAAS;IAIT,SAAS;;;;;;;;;;;;CAqBV,CAAA;AAED,eAAO,MAAM,qBAAqB;IAChC,MAAM;;;;;IACN,KAAK;IACL,MAAM;IACN,mBAAmB;IACnB,sBAAsB;IACtB,SAAS;IACT,eAAe;IACf,YAAY;;;;;;;;;;;;;;;;;;;;IAsBZ,YAAY;;;;;IAOZ,iBAAiB;;;;IAMjB,UAAU;;;;;;;;;;CASX,CAAA;AA6BD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA4KxF"}
|
|
@@ -2,7 +2,7 @@ import { findItemItemCollisions, inspectItemPlanFootprint, resolveNodeLevelId, }
|
|
|
2
2
|
import { ItemNode } from '@pascal-app/core/schema';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
|
|
5
|
-
import {
|
|
5
|
+
import { ProtocolErrorCode, throwMcpError } from './errors.js';
|
|
6
6
|
import { measurement } from './measurement.js';
|
|
7
7
|
import { computeGraphHash } from './scene-lifecycle/metadata.js';
|
|
8
8
|
import { NodeIdSchema } from './schemas.js';
|
|
@@ -130,24 +130,24 @@ export function registerCheckCollisions(server, bridge) {
|
|
|
130
130
|
server.registerTool('check_collisions', {
|
|
131
131
|
title: 'Check collisions',
|
|
132
132
|
description: 'Assess declared item footprints with a rotation-aware plan AABB test. Supports an explicit minimum clearance and reports units, source dimensions, skipped evidence, and unsupported checks. Optionally scope to one level or floor-standing items.',
|
|
133
|
-
inputSchema: checkCollisionsInput,
|
|
134
|
-
outputSchema: checkCollisionsOutput,
|
|
133
|
+
inputSchema: z.object(checkCollisionsInput),
|
|
134
|
+
outputSchema: z.object(checkCollisionsOutput),
|
|
135
135
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
136
136
|
}, async ({ levelId, minimumClearance, floorOnly, candidate }) => {
|
|
137
137
|
const sceneNodes = Object.values(bridge.getNodes());
|
|
138
138
|
if (candidate && levelId && candidate.levelId !== levelId) {
|
|
139
|
-
throwMcpError(
|
|
139
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, 'candidate.levelId must match levelId when both are provided');
|
|
140
140
|
}
|
|
141
141
|
const scopeLevelId = candidate?.levelId ?? levelId;
|
|
142
142
|
if (scopeLevelId) {
|
|
143
143
|
const target = sceneNodes.find((node) => node.id === scopeLevelId);
|
|
144
144
|
if (target?.type !== 'level') {
|
|
145
|
-
throwMcpError(
|
|
145
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, `Level not found: ${scopeLevelId}`);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
if (candidate) {
|
|
149
149
|
if (sceneNodes.some((node) => node.id === candidate.id)) {
|
|
150
|
-
throwMcpError(
|
|
150
|
+
throwMcpError(ProtocolErrorCode.InvalidParams, `Candidate id already exists: ${candidate.id}`);
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
const candidateNode = candidate
|
|
@@ -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
|
* `clear_scene`: the scene goes back to the host's default scaffold (a site, a building, a level),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clear-scene.d.ts","sourceRoot":"","sources":["../../src/tools/clear-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"clear-scene.d.ts","sourceRoot":"","sources":["../../src/tools/clear-scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAKpD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAmDvF"}
|
|
@@ -12,13 +12,13 @@ export function registerClearScene(server, operations) {
|
|
|
12
12
|
server.registerTool(clearSceneTool.name, {
|
|
13
13
|
title: clearSceneTool.title,
|
|
14
14
|
description: clearSceneTool.description,
|
|
15
|
-
inputSchema: clearSceneTool.input,
|
|
16
|
-
outputSchema: {
|
|
15
|
+
inputSchema: z.object(clearSceneTool.input),
|
|
16
|
+
outputSchema: z.object({
|
|
17
17
|
cleared: z.object({ removed: z.number() }),
|
|
18
18
|
version: z.number().nullable(),
|
|
19
19
|
graphHash: z.string().nullable(),
|
|
20
20
|
...liveSyncOutput,
|
|
21
|
-
},
|
|
21
|
+
}),
|
|
22
22
|
annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
|
|
23
23
|
}, async () => {
|
|
24
24
|
try {
|
|
@@ -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
|
export declare function registerCollectionTools(server: McpServer, bridge: SceneOperations): void;
|
|
4
4
|
//# sourceMappingURL=collections.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../src/tools/collections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../../src/tools/collections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAY7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAgBpD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA+CxF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { editCollection, listCollections, writeCollections, } from '@pascal-app/core/agent-operations';
|
|
2
2
|
import { editCollectionTool, listCollectionsTool } from '@pascal-app/core/agent-tools';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
import { DESTRUCTIVE_TOOL_ANNOTATIONS, READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
|
|
4
5
|
import { refusalResult } from './errors.js';
|
|
5
6
|
import { persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
|
|
@@ -15,7 +16,7 @@ export function registerCollectionTools(server, bridge) {
|
|
|
15
16
|
server.registerTool(listCollectionsTool.name, {
|
|
16
17
|
title: listCollectionsTool.title,
|
|
17
18
|
description: listCollectionsTool.description,
|
|
18
|
-
inputSchema: listCollectionsTool.input,
|
|
19
|
+
inputSchema: z.object(listCollectionsTool.input),
|
|
19
20
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
20
21
|
}, async (input) => {
|
|
21
22
|
try {
|
|
@@ -28,7 +29,7 @@ export function registerCollectionTools(server, bridge) {
|
|
|
28
29
|
server.registerTool(editCollectionTool.name, {
|
|
29
30
|
title: editCollectionTool.title,
|
|
30
31
|
description: editCollectionTool.description,
|
|
31
|
-
inputSchema: editCollectionTool.input,
|
|
32
|
+
inputSchema: z.object(editCollectionTool.input),
|
|
32
33
|
annotations: DESTRUCTIVE_TOOL_ANNOTATIONS,
|
|
33
34
|
}, async (input) => {
|
|
34
35
|
let outcome;
|
|
@@ -1,15 +1,15 @@
|
|
|
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 createStoryShellInput: {
|
|
5
5
|
levelId: z.ZodString;
|
|
6
6
|
footprint: z.ZodArray<z.ZodArray<z.ZodNumber>>;
|
|
7
|
-
wallHeight: z.ZodOptional<z.ZodPipe<z.ZodUnion<
|
|
8
|
-
wallThickness: z.ZodDefault<z.ZodPipe<z.ZodUnion<
|
|
7
|
+
wallHeight: z.ZodOptional<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
8
|
+
wallThickness: z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
9
9
|
createSlab: z.ZodDefault<z.ZodBoolean>;
|
|
10
10
|
createCeiling: z.ZodDefault<z.ZodBoolean>;
|
|
11
|
-
slabElevation: z.ZodDefault<z.ZodPipe<z.ZodUnion<
|
|
12
|
-
ceilingHeight: z.ZodOptional<z.ZodPipe<z.ZodUnion<
|
|
11
|
+
slabElevation: z.ZodDefault<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
12
|
+
ceilingHeight: z.ZodOptional<z.ZodPipe<z.ZodUnion<[z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
13
13
|
namePrefix: z.ZodOptional<z.ZodString>;
|
|
14
14
|
wallMaterialPreset: z.ZodOptional<z.ZodString>;
|
|
15
15
|
slabMaterialPreset: z.ZodOptional<z.ZodString>;
|
|
@@ -20,8 +20,8 @@ export declare const createStoryShellOutput: {
|
|
|
20
20
|
unsaved: z.ZodOptional<z.ZodString>;
|
|
21
21
|
persistence: z.ZodOptional<z.ZodObject<{
|
|
22
22
|
status: z.ZodEnum<{
|
|
23
|
-
unbound: "unbound";
|
|
24
23
|
events_unsupported: "events_unsupported";
|
|
24
|
+
unbound: "unbound";
|
|
25
25
|
}>;
|
|
26
26
|
warning: z.ZodString;
|
|
27
27
|
}, z.core.$strip>>;
|
|
@@ -35,48 +35,5 @@ export declare const createStoryShellOutput: {
|
|
|
35
35
|
ceilingId: z.ZodNullable<z.ZodString>;
|
|
36
36
|
createdIds: z.ZodArray<z.ZodString>;
|
|
37
37
|
};
|
|
38
|
-
export declare const createRoofInput: {
|
|
39
|
-
levelId: z.ZodString;
|
|
40
|
-
roofLevelId: z.ZodOptional<z.ZodString>;
|
|
41
|
-
useDedicatedRoofLevel: z.ZodDefault<z.ZodBoolean>;
|
|
42
|
-
roofLevelLabel: z.ZodDefault<z.ZodString>;
|
|
43
|
-
roofLevelElevation: z.ZodOptional<z.ZodNumber>;
|
|
44
|
-
roofLevelHeight: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
45
|
-
center: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
46
|
-
width: z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
|
|
47
|
-
depth: z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
|
|
48
|
-
roofType: z.ZodDefault<z.ZodEnum<{
|
|
49
|
-
gable: "gable";
|
|
50
|
-
flat: "flat";
|
|
51
|
-
hip: "hip";
|
|
52
|
-
shed: "shed";
|
|
53
|
-
gambrel: "gambrel";
|
|
54
|
-
dutch: "dutch";
|
|
55
|
-
mansard: "mansard";
|
|
56
|
-
conical: "conical";
|
|
57
|
-
}>>;
|
|
58
|
-
pitch: z.ZodDefault<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
59
|
-
wallHeight: z.ZodDefault<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
60
|
-
wallThickness: z.ZodDefault<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
61
|
-
overhang: z.ZodDefault<z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>>;
|
|
62
|
-
materialPreset: z.ZodOptional<z.ZodString>;
|
|
63
|
-
name: z.ZodOptional<z.ZodString>;
|
|
64
|
-
};
|
|
65
|
-
export declare const createRoofOutput: {
|
|
66
|
-
project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
67
|
-
unsaved: z.ZodOptional<z.ZodString>;
|
|
68
|
-
persistence: z.ZodOptional<z.ZodObject<{
|
|
69
|
-
status: z.ZodEnum<{
|
|
70
|
-
unbound: "unbound";
|
|
71
|
-
events_unsupported: "events_unsupported";
|
|
72
|
-
}>;
|
|
73
|
-
warning: z.ZodString;
|
|
74
|
-
}, z.core.$strip>>;
|
|
75
|
-
referenceLevelId: z.ZodString;
|
|
76
|
-
roofLevelId: z.ZodString;
|
|
77
|
-
createdRoofLevelId: z.ZodNullable<z.ZodString>;
|
|
78
|
-
roofId: z.ZodString;
|
|
79
|
-
roofSegmentId: z.ZodString;
|
|
80
|
-
};
|
|
81
38
|
export declare function registerConstructionTools(server: McpServer, bridge: SceneOperations): void;
|
|
82
39
|
//# sourceMappingURL=construction-tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"construction-tools.d.ts","sourceRoot":"","sources":["../../src/tools/construction-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"construction-tools.d.ts","sourceRoot":"","sources":["../../src/tools/construction-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAI7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAOpD,eAAO,MAAM,qBAAqB;IAChC,OAAO;IACP,SAAS;IACT,UAAU;IAIV,aAAa;IAIb,UAAU;IAIV,aAAa;IAIb,aAAa;IAGb,aAAa;IAIb,UAAU;IACV,kBAAkB;IAClB,kBAAkB;IAClB,qBAAqB;CACtB,CAAA;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;IAGjC,2DAA2D;;IAE3D,mFAAmF;;IAEnF,iFAAiF;;;CAIlF,CAAA;AAgDD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA4H1F"}
|