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