@pascal-app/mcp 0.2.0
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 +39 -0
- package/README.md +330 -0
- package/dist/bin/pascal-mcp.d.ts +3 -0
- package/dist/bin/pascal-mcp.d.ts.map +1 -0
- package/dist/bin/pascal-mcp.js +91 -0
- package/dist/bridge/index.d.ts +3 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +1 -0
- package/dist/bridge/node-shims.d.ts +16 -0
- package/dist/bridge/node-shims.d.ts.map +1 -0
- package/dist/bridge/node-shims.js +25 -0
- package/dist/bridge/scene-bridge.d.ts +158 -0
- package/dist/bridge/scene-bridge.d.ts.map +1 -0
- package/dist/bridge/scene-bridge.js +482 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/lib/rehydrate-site-children.d.ts +12 -0
- package/dist/lib/rehydrate-site-children.d.ts.map +1 -0
- package/dist/lib/rehydrate-site-children.js +40 -0
- package/dist/lib/safe-fetch.d.ts +19 -0
- package/dist/lib/safe-fetch.d.ts.map +1 -0
- package/dist/lib/safe-fetch.js +221 -0
- package/dist/operations/index.d.ts +2 -0
- package/dist/operations/index.d.ts.map +1 -0
- package/dist/operations/index.js +1 -0
- package/dist/operations/scene-operations.d.ts +67 -0
- package/dist/operations/scene-operations.d.ts.map +1 -0
- package/dist/operations/scene-operations.js +192 -0
- package/dist/prompts/from-brief.d.ts +11 -0
- package/dist/prompts/from-brief.d.ts.map +1 -0
- package/dist/prompts/from-brief.js +48 -0
- package/dist/prompts/index.d.ts +10 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +14 -0
- package/dist/prompts/iterate-on-feedback.d.ts +11 -0
- package/dist/prompts/iterate-on-feedback.d.ts.map +1 -0
- package/dist/prompts/iterate-on-feedback.js +41 -0
- package/dist/prompts/renovation-from-photos.d.ts +24 -0
- package/dist/prompts/renovation-from-photos.d.ts.map +1 -0
- package/dist/prompts/renovation-from-photos.js +135 -0
- package/dist/prompts/scene-guidance.d.ts +2 -0
- package/dist/prompts/scene-guidance.d.ts.map +1 -0
- package/dist/prompts/scene-guidance.js +24 -0
- package/dist/resources/agent-guide.d.ts +5 -0
- package/dist/resources/agent-guide.d.ts.map +1 -0
- package/dist/resources/agent-guide.js +85 -0
- package/dist/resources/catalog-items.d.ts +10 -0
- package/dist/resources/catalog-items.d.ts.map +1 -0
- package/dist/resources/catalog-items.js +29 -0
- package/dist/resources/constraints.d.ts +9 -0
- package/dist/resources/constraints.d.ts.map +1 -0
- package/dist/resources/constraints.js +69 -0
- package/dist/resources/index.d.ts +15 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +23 -0
- package/dist/resources/scene-current.d.ts +9 -0
- package/dist/resources/scene-current.d.ts.map +1 -0
- package/dist/resources/scene-current.js +20 -0
- package/dist/resources/scene-summary.d.ts +10 -0
- package/dist/resources/scene-summary.d.ts.map +1 -0
- package/dist/resources/scene-summary.js +196 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +18 -0
- package/dist/storage/index.d.ts +13 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +14 -0
- package/dist/storage/slug.d.ts +21 -0
- package/dist/storage/slug.d.ts.map +1 -0
- package/dist/storage/slug.js +62 -0
- package/dist/storage/sqlite-driver.d.ts +18 -0
- package/dist/storage/sqlite-driver.d.ts.map +1 -0
- package/dist/storage/sqlite-driver.js +32 -0
- package/dist/storage/sqlite-scene-store.d.ts +51 -0
- package/dist/storage/sqlite-scene-store.d.ts.map +1 -0
- package/dist/storage/sqlite-scene-store.js +526 -0
- package/dist/storage/types.d.ts +136 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +28 -0
- package/dist/templates/empty-studio.d.ts +8 -0
- package/dist/templates/empty-studio.d.ts.map +1 -0
- package/dist/templates/empty-studio.js +230 -0
- package/dist/templates/garden-house.d.ts +8 -0
- package/dist/templates/garden-house.d.ts.map +1 -0
- package/dist/templates/garden-house.js +242 -0
- package/dist/templates/index.d.ts +23 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +20 -0
- package/dist/templates/two-bedroom.d.ts +8 -0
- package/dist/templates/two-bedroom.d.ts.map +1 -0
- package/dist/templates/two-bedroom.js +270 -0
- package/dist/tools/apply-patch.d.ts +25 -0
- package/dist/tools/apply-patch.d.ts.map +1 -0
- package/dist/tools/apply-patch.js +59 -0
- package/dist/tools/asset-catalog.d.ts +16 -0
- package/dist/tools/asset-catalog.d.ts.map +1 -0
- package/dist/tools/asset-catalog.js +308 -0
- package/dist/tools/check-collisions.d.ts +15 -0
- package/dist/tools/check-collisions.d.ts.map +1 -0
- package/dist/tools/check-collisions.js +61 -0
- package/dist/tools/construction-tools.d.ts +93 -0
- package/dist/tools/construction-tools.d.ts.map +1 -0
- package/dist/tools/construction-tools.js +369 -0
- package/dist/tools/create-level.d.ts +14 -0
- package/dist/tools/create-level.d.ts.map +1 -0
- package/dist/tools/create-level.js +48 -0
- package/dist/tools/create-wall.d.ts +15 -0
- package/dist/tools/create-wall.d.ts.map +1 -0
- package/dist/tools/create-wall.js +50 -0
- package/dist/tools/cut-opening.d.ts +18 -0
- package/dist/tools/cut-opening.d.ts.map +1 -0
- package/dist/tools/cut-opening.js +57 -0
- package/dist/tools/delete-node.d.ts +12 -0
- package/dist/tools/delete-node.d.ts.map +1 -0
- package/dist/tools/delete-node.js +37 -0
- package/dist/tools/describe-node.d.ts +17 -0
- package/dist/tools/describe-node.d.ts.map +1 -0
- package/dist/tools/describe-node.js +86 -0
- package/dist/tools/duplicate-level.d.ts +12 -0
- package/dist/tools/duplicate-level.d.ts.map +1 -0
- package/dist/tools/duplicate-level.js +56 -0
- package/dist/tools/errors.d.ts +20 -0
- package/dist/tools/errors.d.ts.map +1 -0
- package/dist/tools/errors.js +25 -0
- package/dist/tools/export-glb.d.ts +10 -0
- package/dist/tools/export-glb.d.ts.map +1 -0
- package/dist/tools/export-glb.js +24 -0
- package/dist/tools/export-json.d.ts +11 -0
- package/dist/tools/export-json.d.ts.map +1 -0
- package/dist/tools/export-json.js +23 -0
- package/dist/tools/find-nodes.d.ts +32 -0
- package/dist/tools/find-nodes.d.ts.map +1 -0
- package/dist/tools/find-nodes.js +105 -0
- package/dist/tools/geometry.d.ts +24 -0
- package/dist/tools/geometry.d.ts.map +1 -0
- package/dist/tools/geometry.js +94 -0
- package/dist/tools/get-node.d.ts +11 -0
- package/dist/tools/get-node.d.ts.map +1 -0
- package/dist/tools/get-node.js +27 -0
- package/dist/tools/get-scene.d.ts +11 -0
- package/dist/tools/get-scene.d.ts.map +1 -0
- package/dist/tools/get-scene.js +26 -0
- package/dist/tools/index.d.ts +12 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +64 -0
- package/dist/tools/live-sync.d.ts +11 -0
- package/dist/tools/live-sync.d.ts.map +1 -0
- package/dist/tools/live-sync.js +62 -0
- package/dist/tools/measure.d.ts +14 -0
- package/dist/tools/measure.d.ts.map +1 -0
- package/dist/tools/measure.js +137 -0
- package/dist/tools/photo-to-scene/index.d.ts +11 -0
- package/dist/tools/photo-to-scene/index.d.ts.map +1 -0
- package/dist/tools/photo-to-scene/index.js +11 -0
- package/dist/tools/photo-to-scene/photo-to-scene.d.ts +26 -0
- package/dist/tools/photo-to-scene/photo-to-scene.d.ts.map +1 -0
- package/dist/tools/photo-to-scene/photo-to-scene.js +323 -0
- package/dist/tools/place-item.d.ts +15 -0
- package/dist/tools/place-item.d.ts.map +1 -0
- package/dist/tools/place-item.js +84 -0
- package/dist/tools/redo.d.ts +11 -0
- package/dist/tools/redo.d.ts.map +1 -0
- package/dist/tools/redo.js +25 -0
- package/dist/tools/room-tools.d.ts +97 -0
- package/dist/tools/room-tools.d.ts.map +1 -0
- package/dist/tools/room-tools.js +510 -0
- package/dist/tools/scene-lifecycle/create-project.d.ts +33 -0
- package/dist/tools/scene-lifecycle/create-project.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/create-project.js +70 -0
- package/dist/tools/scene-lifecycle/delete-scene.d.ts +12 -0
- package/dist/tools/scene-lifecycle/delete-scene.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/delete-scene.js +42 -0
- package/dist/tools/scene-lifecycle/get-project-status.d.ts +31 -0
- package/dist/tools/scene-lifecycle/get-project-status.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/get-project-status.js +69 -0
- package/dist/tools/scene-lifecycle/index.d.ts +17 -0
- package/dist/tools/scene-lifecycle/index.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/index.js +29 -0
- package/dist/tools/scene-lifecycle/list-scenes.d.ts +27 -0
- package/dist/tools/scene-lifecycle/list-scenes.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/list-scenes.js +49 -0
- package/dist/tools/scene-lifecycle/load-scene.d.ts +31 -0
- package/dist/tools/scene-lifecycle/load-scene.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/load-scene.js +55 -0
- package/dist/tools/scene-lifecycle/metadata.d.ts +49 -0
- package/dist/tools/scene-lifecycle/metadata.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/metadata.js +68 -0
- package/dist/tools/scene-lifecycle/rename-scene.d.ts +22 -0
- package/dist/tools/scene-lifecycle/rename-scene.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/rename-scene.js +63 -0
- package/dist/tools/scene-lifecycle/save-scene.d.ts +42 -0
- package/dist/tools/scene-lifecycle/save-scene.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/save-scene.js +130 -0
- package/dist/tools/scene-lifecycle/test-utils.d.ts +39 -0
- package/dist/tools/scene-lifecycle/test-utils.d.ts.map +1 -0
- package/dist/tools/scene-lifecycle/test-utils.js +211 -0
- package/dist/tools/scene-query.d.ts +57 -0
- package/dist/tools/scene-query.d.ts.map +1 -0
- package/dist/tools/scene-query.js +645 -0
- package/dist/tools/schemas.d.ts +52 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +42 -0
- package/dist/tools/set-zone.d.ts +14 -0
- package/dist/tools/set-zone.d.ts.map +1 -0
- package/dist/tools/set-zone.js +48 -0
- package/dist/tools/templates/create-from-template.d.ts +54 -0
- package/dist/tools/templates/create-from-template.d.ts.map +1 -0
- package/dist/tools/templates/create-from-template.js +145 -0
- package/dist/tools/templates/create-house-from-brief.d.ts +35 -0
- package/dist/tools/templates/create-house-from-brief.d.ts.map +1 -0
- package/dist/tools/templates/create-house-from-brief.js +170 -0
- package/dist/tools/templates/index.d.ts +14 -0
- package/dist/tools/templates/index.d.ts.map +1 -0
- package/dist/tools/templates/index.js +18 -0
- package/dist/tools/templates/list-templates.d.ts +18 -0
- package/dist/tools/templates/list-templates.d.ts.map +1 -0
- package/dist/tools/templates/list-templates.js +36 -0
- package/dist/tools/undo.d.ts +11 -0
- package/dist/tools/undo.d.ts.map +1 -0
- package/dist/tools/undo.js +25 -0
- package/dist/tools/validate-scene.d.ts +14 -0
- package/dist/tools/validate-scene.d.ts.map +1 -0
- package/dist/tools/validate-scene.js +24 -0
- package/dist/tools/variants/generate-variants.d.ts +30 -0
- package/dist/tools/variants/generate-variants.d.ts.map +1 -0
- package/dist/tools/variants/generate-variants.js +160 -0
- package/dist/tools/variants/index.d.ts +9 -0
- package/dist/tools/variants/index.d.ts.map +1 -0
- package/dist/tools/variants/index.js +9 -0
- package/dist/tools/variants/mutations.d.ts +18 -0
- package/dist/tools/variants/mutations.d.ts.map +1 -0
- package/dist/tools/variants/mutations.js +324 -0
- package/dist/tools/vision/analyze-floorplan-image.d.ts +33 -0
- package/dist/tools/vision/analyze-floorplan-image.d.ts.map +1 -0
- package/dist/tools/vision/analyze-floorplan-image.js +146 -0
- package/dist/tools/vision/analyze-room-photo.d.ts +29 -0
- package/dist/tools/vision/analyze-room-photo.d.ts.map +1 -0
- package/dist/tools/vision/analyze-room-photo.js +130 -0
- package/dist/tools/vision/index.d.ts +12 -0
- package/dist/tools/vision/index.d.ts.map +1 -0
- package/dist/tools/vision/index.js +14 -0
- package/dist/transports/http.d.ts +36 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +203 -0
- package/dist/transports/stdio.d.ts +14 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +16 -0
- package/package.json +86 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iterate-on-feedback.d.ts","sourceRoot":"","sources":["../../src/prompts/iterate-on-feedback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAiBpD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE/E;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAuB3F"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SCENE_DESIGN_GUIDANCE } from './scene-guidance';
|
|
3
|
+
const PREAMBLE = [
|
|
4
|
+
'You are iterating on an existing Pascal scene based on user feedback.',
|
|
5
|
+
'Given the current state (read via the `pascal://scene/current` resource) and the user feedback below, propose the MINIMUM set of `apply_patch` operations that satisfies the feedback.',
|
|
6
|
+
'Rules:',
|
|
7
|
+
' - Prefer updates over create+delete pairs when a field change will do.',
|
|
8
|
+
' - Do not re-create nodes that already exist.',
|
|
9
|
+
' - Do not touch nodes that are unrelated to the feedback.',
|
|
10
|
+
' - Prefer semantic tools such as create_room, add_door, add_window, furnish_room, and place_item when they match the request.',
|
|
11
|
+
' - Bundle related mutations into a single `apply_patch` call so they share one undo step.',
|
|
12
|
+
' - For multi-room changes, call verify_scene after the mutation and fix reported issues.',
|
|
13
|
+
SCENE_DESIGN_GUIDANCE,
|
|
14
|
+
' - Respond ONLY with tool calls. No prose.',
|
|
15
|
+
].join('\n');
|
|
16
|
+
/**
|
|
17
|
+
* Build the user-facing prompt text for `iterate_on_feedback`.
|
|
18
|
+
* Pure function for testability.
|
|
19
|
+
*/
|
|
20
|
+
export function buildIterateOnFeedbackPrompt(args) {
|
|
21
|
+
return [PREAMBLE, '', '## User feedback', args.feedback.trim()].join('\n');
|
|
22
|
+
}
|
|
23
|
+
export function registerIterateOnFeedback(server, _bridge) {
|
|
24
|
+
server.registerPrompt('iterate_on_feedback', {
|
|
25
|
+
title: 'Iterate on a scene from user feedback',
|
|
26
|
+
description: 'Produces a minimal-diff plan of apply_patch calls in response to user feedback on the current scene.',
|
|
27
|
+
argsSchema: {
|
|
28
|
+
feedback: z.string(),
|
|
29
|
+
},
|
|
30
|
+
}, async ({ feedback }) => ({
|
|
31
|
+
messages: [
|
|
32
|
+
{
|
|
33
|
+
role: 'user',
|
|
34
|
+
content: {
|
|
35
|
+
type: 'text',
|
|
36
|
+
text: buildIterateOnFeedbackPrompt({ feedback }),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SceneOperations } from '../operations';
|
|
3
|
+
type PromptContent = {
|
|
4
|
+
type: 'text';
|
|
5
|
+
text: string;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'image';
|
|
8
|
+
data: string;
|
|
9
|
+
mimeType: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Build the full messages array. Pure function for testability.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildRenovationMessages(args: {
|
|
15
|
+
currentPhotos: string[] | string | undefined;
|
|
16
|
+
referencePhotos: string[] | string | undefined;
|
|
17
|
+
goals: string;
|
|
18
|
+
}): Array<{
|
|
19
|
+
role: 'user';
|
|
20
|
+
content: PromptContent;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function registerRenovationFromPhotos(server: McpServer, _bridge: SceneOperations): void;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=renovation-from-photos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renovation-from-photos.d.ts","sourceRoot":"","sources":["../../src/prompts/renovation-from-photos.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAgCpD,KAAK,aAAa,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AA6CrD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAA;IAC5C,eAAe,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAA;IAC9C,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,KAAK,CAAC;IACR,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,aAAa,CAAA;CACvB,CAAC,CA+CD;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAmB9F"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const PREAMBLE = [
|
|
3
|
+
'You are renovating an existing room based on photos of the current space and reference photos of the target aesthetic.',
|
|
4
|
+
'',
|
|
5
|
+
'Follow this procedure:',
|
|
6
|
+
' 1. Call `analyze_floorplan_image` and/or `analyze_room_photo` on EACH current photo to extract walls, rooms, fixtures, and approximate dimensions. Do the same for reference photos.',
|
|
7
|
+
' 2. Compare the current-state analyses to the reference-state analyses. Identify concrete deltas (materials, fixtures, layout changes) that align with the renovation goals.',
|
|
8
|
+
' 3. Emit a single `apply_patch` call containing the minimum set of patches needed to converge the current scene toward the goals.',
|
|
9
|
+
'',
|
|
10
|
+
'Rules:',
|
|
11
|
+
' - Do not invent dimensions. Pull them from the analysis tool results.',
|
|
12
|
+
' - Do not modify nodes that are unrelated to the goals.',
|
|
13
|
+
' - Respond ONLY with tool calls. No prose.',
|
|
14
|
+
].join('\n');
|
|
15
|
+
function isDataUrl(s) {
|
|
16
|
+
return s.startsWith('data:');
|
|
17
|
+
}
|
|
18
|
+
function isHttpUrl(s) {
|
|
19
|
+
return s.startsWith('http://') || s.startsWith('https://');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Rough base64 detector: length multiple of 4, only base64 chars, at least 32 chars long.
|
|
23
|
+
* Deliberately conservative — when in doubt we fall back to text `URL: ...`.
|
|
24
|
+
*/
|
|
25
|
+
function looksLikeBase64(s) {
|
|
26
|
+
if (s.length < 32)
|
|
27
|
+
return false;
|
|
28
|
+
if (s.length % 4 !== 0)
|
|
29
|
+
return false;
|
|
30
|
+
return /^[A-Za-z0-9+/=]+$/.test(s);
|
|
31
|
+
}
|
|
32
|
+
/** Extract a base64 payload from a data-URL, or return the raw string. */
|
|
33
|
+
function toImageContent(source) {
|
|
34
|
+
if (isDataUrl(source)) {
|
|
35
|
+
const match = /^data:([^;,]+)?(?:;base64)?,(.*)$/.exec(source);
|
|
36
|
+
if (match) {
|
|
37
|
+
const mimeType = match[1] && match[1].length > 0 ? match[1] : 'image/jpeg';
|
|
38
|
+
const data = match[2] ?? '';
|
|
39
|
+
return { type: 'image', data, mimeType };
|
|
40
|
+
}
|
|
41
|
+
return { type: 'text', text: `URL: ${source}` };
|
|
42
|
+
}
|
|
43
|
+
if (isHttpUrl(source)) {
|
|
44
|
+
return { type: 'text', text: `URL: ${source}` };
|
|
45
|
+
}
|
|
46
|
+
if (looksLikeBase64(source)) {
|
|
47
|
+
return { type: 'image', data: source, mimeType: 'image/jpeg' };
|
|
48
|
+
}
|
|
49
|
+
return { type: 'text', text: `URL: ${source}` };
|
|
50
|
+
}
|
|
51
|
+
/** Parse the stringified list argument (JSON array or comma-separated fallback). */
|
|
52
|
+
function parsePhotoList(raw) {
|
|
53
|
+
if (Array.isArray(raw)) {
|
|
54
|
+
return raw.map((s) => String(s)).filter((s) => s.length > 0);
|
|
55
|
+
}
|
|
56
|
+
const str = (raw ?? '').trim();
|
|
57
|
+
if (str.length === 0)
|
|
58
|
+
return [];
|
|
59
|
+
if (str.startsWith('[')) {
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(str);
|
|
62
|
+
if (Array.isArray(parsed)) {
|
|
63
|
+
return parsed.map((s) => String(s)).filter((s) => s.length > 0);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
/* fall through to comma-split */
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return str
|
|
71
|
+
.split(',')
|
|
72
|
+
.map((s) => s.trim())
|
|
73
|
+
.filter((s) => s.length > 0);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the full messages array. Pure function for testability.
|
|
77
|
+
*/
|
|
78
|
+
export function buildRenovationMessages(args) {
|
|
79
|
+
const current = parsePhotoList(args.currentPhotos);
|
|
80
|
+
const reference = parsePhotoList(args.referencePhotos);
|
|
81
|
+
const intro = [
|
|
82
|
+
PREAMBLE,
|
|
83
|
+
'',
|
|
84
|
+
'## Goals',
|
|
85
|
+
args.goals.trim(),
|
|
86
|
+
'',
|
|
87
|
+
'## Inputs',
|
|
88
|
+
`Current photos: ${current.length} item(s)`,
|
|
89
|
+
`Reference photos: ${reference.length} item(s)`,
|
|
90
|
+
].join('\n');
|
|
91
|
+
const messages = [
|
|
92
|
+
{ role: 'user', content: { type: 'text', text: intro } },
|
|
93
|
+
];
|
|
94
|
+
if (current.length > 0) {
|
|
95
|
+
messages.push({
|
|
96
|
+
role: 'user',
|
|
97
|
+
content: { type: 'text', text: '## Current photos' },
|
|
98
|
+
});
|
|
99
|
+
for (const src of current) {
|
|
100
|
+
messages.push({ role: 'user', content: toImageContent(src) });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (reference.length > 0) {
|
|
104
|
+
messages.push({
|
|
105
|
+
role: 'user',
|
|
106
|
+
content: { type: 'text', text: '## Reference photos' },
|
|
107
|
+
});
|
|
108
|
+
for (const src of reference) {
|
|
109
|
+
messages.push({ role: 'user', content: toImageContent(src) });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
messages.push({
|
|
113
|
+
role: 'user',
|
|
114
|
+
content: {
|
|
115
|
+
type: 'text',
|
|
116
|
+
text: '## Task\nProduce `apply_patch` operations that drive the current scene toward the goals, using only dimensions and fixtures you derived from the analysis tools.',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
return messages;
|
|
120
|
+
}
|
|
121
|
+
export function registerRenovationFromPhotos(server, _bridge) {
|
|
122
|
+
server.registerPrompt('renovation_from_photos', {
|
|
123
|
+
title: 'Plan a renovation from photos',
|
|
124
|
+
description: 'Plan a minimal-patch renovation given current-state photos, reference-state photos, and free-form goals.',
|
|
125
|
+
argsSchema: {
|
|
126
|
+
// MCP prompt arguments are stringly-typed; accept a JSON array or a
|
|
127
|
+
// comma-separated list of base64 payloads / data URLs / http(s) URLs.
|
|
128
|
+
currentPhotos: z.string(),
|
|
129
|
+
referencePhotos: z.string(),
|
|
130
|
+
goals: z.string(),
|
|
131
|
+
},
|
|
132
|
+
}, async ({ currentPhotos, referencePhotos, goals }) => ({
|
|
133
|
+
messages: buildRenovationMessages({ currentPhotos, referencePhotos, goals }),
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-guidance.d.ts","sourceRoot":"","sources":["../../src/prompts/scene-guidance.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,QAuBtB,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const SCENE_DESIGN_GUIDANCE = [
|
|
2
|
+
'Scene design workflow:',
|
|
3
|
+
' - Use meters. X/Z are horizontal floor-plan axes; Y is vertical.',
|
|
4
|
+
' - Read `pascal://agent/guide` when you need construction rules; do not inspect repository code for ordinary scene editing.',
|
|
5
|
+
' - Door default: 0.9m wide by 2.1m high, floor-mounted.',
|
|
6
|
+
' - Window default: 1.5m wide by 1.5m high with a 0.9m sill height.',
|
|
7
|
+
' - For clear concrete requests, act with reasonable defaults instead of asking for clarification.',
|
|
8
|
+
' - For full homes/apartments, include realistic support spaces: kitchen, living/dining, bathrooms, hallway/entry, storage/laundry where appropriate.',
|
|
9
|
+
' - For multi-story buildings, create separate level-owned story shells. Do not stretch first-floor exterior walls to cover upper floors.',
|
|
10
|
+
' - Treat requested story count as occupied stories, not raw level count; dedicated roof/support levels are allowed and must not be deleted just to match a story count.',
|
|
11
|
+
'',
|
|
12
|
+
'Preferred phased tool workflow:',
|
|
13
|
+
' - Query first with list_levels, get_level_summary, get_walls, or get_zones when editing an existing scene.',
|
|
14
|
+
' - Create visible massing early: create_level as needed, then create_story_shell once per story.',
|
|
15
|
+
' - For rooms, prefer create_room, then add_door/add_window, then furnish_room.',
|
|
16
|
+
' - For stairs between floors, prefer create_stair_between_levels so slab/ceiling openings stay rectangular and do not duplicate auto-generated holes.',
|
|
17
|
+
' - For roofs, prefer create_roof and let it create/use a dedicated roof level above the top occupied story so solo/exploded level views can isolate the roof.',
|
|
18
|
+
' - verify_scene reports both levelCount and occupiedStoryCount. Use occupiedStoryCount when checking whether a one-story/two-story brief was satisfied.',
|
|
19
|
+
' - add_door/add_window use t = 0..1 along a wall: 0 is start, 0.5 is center, 1 is end.',
|
|
20
|
+
' - Use search_assets before place_item when placing a specific catalog item.',
|
|
21
|
+
' - Use apply_patch for precise bulk edits that the semantic tools cannot express.',
|
|
22
|
+
' - After each major phase, call get_level_summary or pascal://scene/current/summary so progress is visible and errors are easier to localize.',
|
|
23
|
+
' - After multi-room or full-floor work, call validate_scene and verify_scene, then fix reported issues before finishing.',
|
|
24
|
+
].join('\n');
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SceneOperations } from '../operations';
|
|
3
|
+
export declare const AGENT_GUIDE: string;
|
|
4
|
+
export declare function registerAgentGuide(server: McpServer, _bridge: SceneOperations): void;
|
|
5
|
+
//# sourceMappingURL=agent-guide.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-guide.d.ts","sourceRoot":"","sources":["../../src/resources/agent-guide.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,eAAO,MAAM,WAAW,QAwDZ,CAAA;AAEZ,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAuCpF"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export const AGENT_GUIDE = [
|
|
2
|
+
'# Pascal MCP Agent Guide',
|
|
3
|
+
'',
|
|
4
|
+
'You are editing Pascal architectural projects. Use MCP tools only; do not inspect the Pascal repository unless the user explicitly asks.',
|
|
5
|
+
'',
|
|
6
|
+
'## Standard Workflow',
|
|
7
|
+
'',
|
|
8
|
+
'1. Read this guide or call `get_capabilities` if available.',
|
|
9
|
+
'2. If the user asks for a new project, call `create_project` first.',
|
|
10
|
+
'3. For quick starts, call `create_house_from_brief`. For precise edits, build with semantic tools: `create_story_shell`, `create_room`, `add_door`, `add_window`, `furnish_room`, `create_roof`, `place_item`.',
|
|
11
|
+
'4. Let semantic tools update the browser-visible draft. Call `save_scene` with `saveMode: "draft"` for autosave-style progress, or `saveMode: "checkpoint"` only for meaningful milestones.',
|
|
12
|
+
'5. Call `validate_scene`, `verify_scene`, then `get_project_status`.',
|
|
13
|
+
'6. Return the final `editorUrl` from tool output. Do not infer routes.',
|
|
14
|
+
'',
|
|
15
|
+
'## Important Concepts',
|
|
16
|
+
'',
|
|
17
|
+
'- A project is the browser-visible container.',
|
|
18
|
+
'- A scene graph is the architectural model.',
|
|
19
|
+
'- A draft is the browser-visible working model and may be overwritten many times.',
|
|
20
|
+
'- A version/checkpoint is a meaningful saved model revision.',
|
|
21
|
+
'- The browser editor opens the current draft when one exists, otherwise the published version.',
|
|
22
|
+
'- Always return the `editorUrl`, not an internal API URL.',
|
|
23
|
+
'',
|
|
24
|
+
'## URLs',
|
|
25
|
+
'',
|
|
26
|
+
'- Use `editorUrl` returned by tools.',
|
|
27
|
+
'- If a tool returns only an id, call `get_project_status` to get the browser URL.',
|
|
28
|
+
'- Hosted editor URLs use `/editor/<projectId>`.',
|
|
29
|
+
'',
|
|
30
|
+
'## Scene Creation Rules',
|
|
31
|
+
'',
|
|
32
|
+
'- Prefer semantic tools over raw graph patches.',
|
|
33
|
+
'- Do not hand-write node graphs unless no semantic tool exists.',
|
|
34
|
+
'- For rooms, use `create_room` -> `add_door` -> `add_window` -> `furnish_room`.',
|
|
35
|
+
'- For complete homes, create exterior shell, interior rooms, openings, roof, furniture, then landscaping.',
|
|
36
|
+
'- For doors/windows, use `t` or `position` from 0 to 1 along the wall unless a tool explicitly says otherwise.',
|
|
37
|
+
'- X/Z are floor-plan axes and Y is vertical; dimensions are meters.',
|
|
38
|
+
'- Use `create_roof` for roofs. A dedicated roof support level is valid and should not count as an occupied story.',
|
|
39
|
+
'',
|
|
40
|
+
'## Required Final Checks',
|
|
41
|
+
'',
|
|
42
|
+
'- `save_scene` must succeed. Use `saveMode: "checkpoint"` before final handoff only if the user asked for a durable version.',
|
|
43
|
+
'- `verify_scene.hasIssues` should be false; otherwise explain remaining issues.',
|
|
44
|
+
'- `get_project_status.nodeCount` must be greater than 0 for a non-empty design.',
|
|
45
|
+
'- Return `editorUrl` in the final user response.',
|
|
46
|
+
'',
|
|
47
|
+
'## If Something Looks Empty',
|
|
48
|
+
'',
|
|
49
|
+
'1. Call `get_project_status`.',
|
|
50
|
+
'2. Compare `publishedVersion`, `latestVersion`, `browserVisibleVersion`, `nodeCount`, and `graphHash`.',
|
|
51
|
+
'3. If the graph is non-empty but the browser appears empty, call `get_project_status` to re-bind the session, then `save_scene` with `saveMode: "draft"`.',
|
|
52
|
+
'4. Re-run `verify_scene`.',
|
|
53
|
+
'',
|
|
54
|
+
'## Output Contract',
|
|
55
|
+
'',
|
|
56
|
+
'Final user response should include: project name, `editorUrl`, version, node/room summary, and any known limitations.',
|
|
57
|
+
].join('\n');
|
|
58
|
+
export function registerAgentGuide(server, _bridge) {
|
|
59
|
+
server.registerResource('agent-guide', 'pascal://agent-guide', {
|
|
60
|
+
title: 'Pascal MCP agent guide',
|
|
61
|
+
description: 'Short MCP-first project creation, save/publish, validation, and output workflow for external agents.',
|
|
62
|
+
mimeType: 'text/markdown',
|
|
63
|
+
}, async (uri) => ({
|
|
64
|
+
contents: [
|
|
65
|
+
{
|
|
66
|
+
uri: uri.href,
|
|
67
|
+
mimeType: 'text/markdown',
|
|
68
|
+
text: AGENT_GUIDE,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
}));
|
|
72
|
+
server.registerResource('agent-guide-legacy', 'pascal://agent/guide', {
|
|
73
|
+
title: 'Pascal MCP agent guide',
|
|
74
|
+
description: 'Legacy URI for the Pascal MCP agent guide. Prefer pascal://agent-guide.',
|
|
75
|
+
mimeType: 'text/markdown',
|
|
76
|
+
}, async (uri) => ({
|
|
77
|
+
contents: [
|
|
78
|
+
{
|
|
79
|
+
uri: uri.href,
|
|
80
|
+
mimeType: 'text/markdown',
|
|
81
|
+
text: AGENT_GUIDE,
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SceneOperations } from '../operations';
|
|
3
|
+
/**
|
|
4
|
+
* `pascal://catalog/items` — small built-in item catalog for standalone MCP.
|
|
5
|
+
*
|
|
6
|
+
* The editor UI owns the full catalog. MCP intentionally keeps a dependency-free
|
|
7
|
+
* subset so headless agents can still place realistic furniture and fixtures.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerCatalogItems(server: McpServer, _bridge: SceneOperations): void;
|
|
10
|
+
//# sourceMappingURL=catalog-items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-items.d.ts","sourceRoot":"","sources":["../../src/resources/catalog-items.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CA2BtF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MCP_CATALOG_ITEMS } from '../tools/asset-catalog';
|
|
2
|
+
/**
|
|
3
|
+
* `pascal://catalog/items` — small built-in item catalog for standalone MCP.
|
|
4
|
+
*
|
|
5
|
+
* The editor UI owns the full catalog. MCP intentionally keeps a dependency-free
|
|
6
|
+
* subset so headless agents can still place realistic furniture and fixtures.
|
|
7
|
+
*/
|
|
8
|
+
export function registerCatalogItems(server, _bridge) {
|
|
9
|
+
server.registerResource('catalog-items', 'pascal://catalog/items', {
|
|
10
|
+
title: 'Item catalog',
|
|
11
|
+
description: 'Dependency-free catalog subset of placeable items available in standalone MCP mode.',
|
|
12
|
+
mimeType: 'application/json',
|
|
13
|
+
}, async (uri) => {
|
|
14
|
+
const payload = {
|
|
15
|
+
status: 'ok',
|
|
16
|
+
items: MCP_CATALOG_ITEMS,
|
|
17
|
+
note: 'Standalone MCP catalog subset; host applications can still expose a larger catalog separately.',
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
contents: [
|
|
21
|
+
{
|
|
22
|
+
uri: uri.href,
|
|
23
|
+
mimeType: 'application/json',
|
|
24
|
+
text: JSON.stringify(payload),
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SceneOperations } from '../operations';
|
|
3
|
+
/**
|
|
4
|
+
* `pascal://constraints/{levelId}` — per-level geometric constraints used as
|
|
5
|
+
* input hints for agents: slab nodes (with polygons/holes/elevation) + each
|
|
6
|
+
* wall's plan-view footprint polygon.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerConstraints(server: McpServer, bridge: SceneOperations): void;
|
|
9
|
+
//# sourceMappingURL=constraints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraints.d.ts","sourceRoot":"","sources":["../../src/resources/constraints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAIxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAoEpD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAyBpF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { getWallPlanFootprint } from '@pascal-app/core/wall';
|
|
3
|
+
/**
|
|
4
|
+
* Empty `WallMiterData` — we don't compute junctions here. The footprint
|
|
5
|
+
* falls back to a simple rectangle based on start/end + thickness, which is
|
|
6
|
+
* correct for non-intersecting walls and an acceptable approximation for
|
|
7
|
+
* constraint hints.
|
|
8
|
+
*
|
|
9
|
+
* Typed via `Parameters<typeof getWallPlanFootprint>[1]` to avoid `any` and
|
|
10
|
+
* to stay in sync with the core signature.
|
|
11
|
+
*/
|
|
12
|
+
const EMPTY_MITER_DATA = {
|
|
13
|
+
junctionData: new Map(),
|
|
14
|
+
junctions: new Map(),
|
|
15
|
+
};
|
|
16
|
+
function buildPayload(bridge, levelId) {
|
|
17
|
+
const level = bridge.getNode(levelId);
|
|
18
|
+
if (!level || level.type !== 'level') {
|
|
19
|
+
return {
|
|
20
|
+
error: 'level_not_found',
|
|
21
|
+
levelId,
|
|
22
|
+
slabs: [],
|
|
23
|
+
wallPolygons: [],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const all = bridge.findNodes({ levelId: levelId });
|
|
27
|
+
const slabs = [];
|
|
28
|
+
const walls = [];
|
|
29
|
+
for (const n of all) {
|
|
30
|
+
if (n.type === 'slab')
|
|
31
|
+
slabs.push(n);
|
|
32
|
+
else if (n.type === 'wall')
|
|
33
|
+
walls.push(n);
|
|
34
|
+
}
|
|
35
|
+
const wallPolygons = [];
|
|
36
|
+
for (const wall of walls) {
|
|
37
|
+
const points = getWallPlanFootprint(wall, EMPTY_MITER_DATA);
|
|
38
|
+
wallPolygons.push({
|
|
39
|
+
wallId: wall.id,
|
|
40
|
+
footprint: points.map((p) => [p.x, p.y]),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return { levelId, slabs, wallPolygons };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `pascal://constraints/{levelId}` — per-level geometric constraints used as
|
|
47
|
+
* input hints for agents: slab nodes (with polygons/holes/elevation) + each
|
|
48
|
+
* wall's plan-view footprint polygon.
|
|
49
|
+
*/
|
|
50
|
+
export function registerConstraints(server, bridge) {
|
|
51
|
+
server.registerResource('constraints', new ResourceTemplate('pascal://constraints/{levelId}', { list: undefined }), {
|
|
52
|
+
title: 'Level constraints',
|
|
53
|
+
description: 'Per-level constraints: slab nodes and wall plan footprints. Returns {error:"level_not_found"} if the level id is unknown.',
|
|
54
|
+
mimeType: 'application/json',
|
|
55
|
+
}, async (uri, variables) => {
|
|
56
|
+
const rawLevelId = variables.levelId;
|
|
57
|
+
const levelId = Array.isArray(rawLevelId) ? rawLevelId[0] : rawLevelId;
|
|
58
|
+
const payload = buildPayload(bridge, levelId ?? '');
|
|
59
|
+
return {
|
|
60
|
+
contents: [
|
|
61
|
+
{
|
|
62
|
+
uri: uri.href,
|
|
63
|
+
mimeType: 'application/json',
|
|
64
|
+
text: JSON.stringify(payload),
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SceneOperations } from '../operations';
|
|
3
|
+
/**
|
|
4
|
+
* Registers all MCP resources exposed by `@pascal-app/mcp`.
|
|
5
|
+
*
|
|
6
|
+
* Resources:
|
|
7
|
+
* - `pascal://scene/current` — application/json, full snapshot
|
|
8
|
+
* - `pascal://scene/current/summary` — text/markdown, human summary
|
|
9
|
+
* - `pascal://catalog/items` — application/json, host-supplied catalog
|
|
10
|
+
* - `pascal://constraints/{levelId}` — application/json, per-level constraints
|
|
11
|
+
* - `pascal://agent-guide` — text/markdown, MCP-first agent guide
|
|
12
|
+
* - `pascal://agent/guide` — text/markdown, legacy alias
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerResources(server: McpServer, operations: SceneOperations): void;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAOpD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,GAAG,IAAI,CAMtF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { registerAgentGuide } from './agent-guide';
|
|
2
|
+
import { registerCatalogItems } from './catalog-items';
|
|
3
|
+
import { registerConstraints } from './constraints';
|
|
4
|
+
import { registerSceneCurrent } from './scene-current';
|
|
5
|
+
import { registerSceneSummary } from './scene-summary';
|
|
6
|
+
/**
|
|
7
|
+
* Registers all MCP resources exposed by `@pascal-app/mcp`.
|
|
8
|
+
*
|
|
9
|
+
* Resources:
|
|
10
|
+
* - `pascal://scene/current` — application/json, full snapshot
|
|
11
|
+
* - `pascal://scene/current/summary` — text/markdown, human summary
|
|
12
|
+
* - `pascal://catalog/items` — application/json, host-supplied catalog
|
|
13
|
+
* - `pascal://constraints/{levelId}` — application/json, per-level constraints
|
|
14
|
+
* - `pascal://agent-guide` — text/markdown, MCP-first agent guide
|
|
15
|
+
* - `pascal://agent/guide` — text/markdown, legacy alias
|
|
16
|
+
*/
|
|
17
|
+
export function registerResources(server, operations) {
|
|
18
|
+
registerAgentGuide(server, operations);
|
|
19
|
+
registerSceneCurrent(server, operations);
|
|
20
|
+
registerSceneSummary(server, operations);
|
|
21
|
+
registerCatalogItems(server, operations);
|
|
22
|
+
registerConstraints(server, operations);
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SceneOperations } from '../operations';
|
|
3
|
+
/**
|
|
4
|
+
* `pascal://scene/current` — full `{ nodes, rootNodeIds, collections }` snapshot.
|
|
5
|
+
*
|
|
6
|
+
* Static URI (not a template). MIME `application/json`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerSceneCurrent(server: McpServer, bridge: SceneOperations): void;
|
|
9
|
+
//# sourceMappingURL=scene-current.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-current.d.ts","sourceRoot":"","sources":["../../src/resources/scene-current.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAoBrF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pascal://scene/current` — full `{ nodes, rootNodeIds, collections }` snapshot.
|
|
3
|
+
*
|
|
4
|
+
* Static URI (not a template). MIME `application/json`.
|
|
5
|
+
*/
|
|
6
|
+
export function registerSceneCurrent(server, bridge) {
|
|
7
|
+
server.registerResource('scene-current', 'pascal://scene/current', {
|
|
8
|
+
title: 'Current scene',
|
|
9
|
+
description: 'Complete snapshot of the live Pascal scene: nodes dict, rootNodeIds, collections.',
|
|
10
|
+
mimeType: 'application/json',
|
|
11
|
+
}, async (uri) => ({
|
|
12
|
+
contents: [
|
|
13
|
+
{
|
|
14
|
+
uri: uri.href,
|
|
15
|
+
mimeType: 'application/json',
|
|
16
|
+
text: JSON.stringify(bridge.exportJSON()),
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { SceneOperations } from '../operations';
|
|
3
|
+
/** Build the markdown summary. Pure over the SceneGraph snapshot. */
|
|
4
|
+
export declare function buildSceneSummaryMarkdown(snapshot: ReturnType<SceneOperations['exportJSON']>): string;
|
|
5
|
+
/**
|
|
6
|
+
* `pascal://scene/current/summary` — human-readable scene overview.
|
|
7
|
+
* MIME `text/markdown`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerSceneSummary(server: McpServer, bridge: SceneOperations): void;
|
|
10
|
+
//# sourceMappingURL=scene-summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-summary.d.ts","sourceRoot":"","sources":["../../src/resources/scene-summary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AA4EpD,qEAAqE;AACrE,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,UAAU,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,GAClD,MAAM,CAgGR;AAgBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAoBrF"}
|