@pascal-app/mcp 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +31 -10
  2. package/dist/bin/pascal-mcp.js +2 -0
  3. package/dist/bridge/agent-session.d.ts +2 -1
  4. package/dist/bridge/agent-session.d.ts.map +1 -1
  5. package/dist/bridge/agent-session.js +0 -1
  6. package/dist/bridge/scene-bridge.d.ts +21 -10
  7. package/dist/bridge/scene-bridge.d.ts.map +1 -1
  8. package/dist/bridge/scene-bridge.js +178 -194
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/lib/safe-fetch.d.ts +6 -0
  12. package/dist/lib/safe-fetch.d.ts.map +1 -1
  13. package/dist/lib/safe-fetch.js +135 -41
  14. package/dist/operations/scene-operations.d.ts +7 -0
  15. package/dist/operations/scene-operations.d.ts.map +1 -1
  16. package/dist/operations/scene-operations.js +4 -0
  17. package/dist/prompts/from-brief.js +1 -1
  18. package/dist/prompts/iterate-on-feedback.js +1 -1
  19. package/dist/prompts/renovation-from-photos.js +1 -1
  20. package/dist/prompts/scene-guidance.js +2 -2
  21. package/dist/resources/agent-guide.d.ts.map +1 -1
  22. package/dist/resources/agent-guide.js +8 -3
  23. package/dist/resources/catalog-items.d.ts +4 -1
  24. package/dist/resources/catalog-items.d.ts.map +1 -1
  25. package/dist/resources/catalog-items.js +14 -6
  26. package/dist/server.d.ts +9 -5
  27. package/dist/server.d.ts.map +1 -1
  28. package/dist/server.js +21 -5
  29. package/dist/templates/empty-studio.d.ts.map +1 -1
  30. package/dist/templates/empty-studio.js +2 -3
  31. package/dist/templates/garden-house.d.ts.map +1 -1
  32. package/dist/templates/garden-house.js +2 -3
  33. package/dist/templates/two-bedroom.d.ts.map +1 -1
  34. package/dist/templates/two-bedroom.js +2 -3
  35. package/dist/tools/add-column.d.ts.map +1 -1
  36. package/dist/tools/add-column.js +9 -6
  37. package/dist/tools/add-object.d.ts +44 -5
  38. package/dist/tools/add-object.d.ts.map +1 -1
  39. package/dist/tools/add-object.js +75 -21
  40. package/dist/tools/asset-catalog.d.ts +5 -6
  41. package/dist/tools/asset-catalog.d.ts.map +1 -1
  42. package/dist/tools/asset-catalog.js +1 -9
  43. package/dist/tools/author-scene.d.ts +8 -5
  44. package/dist/tools/author-scene.d.ts.map +1 -1
  45. package/dist/tools/author-scene.js +302 -51
  46. package/dist/tools/clear-scene.js +2 -2
  47. package/dist/tools/collections.d.ts.map +1 -1
  48. package/dist/tools/collections.js +8 -5
  49. package/dist/tools/honest-patch-guard.js +6 -5
  50. package/dist/tools/hosted-services.d.ts.map +1 -1
  51. package/dist/tools/hosted-services.js +2 -2
  52. package/dist/tools/index.d.ts +7 -2
  53. package/dist/tools/index.d.ts.map +1 -1
  54. package/dist/tools/index.js +3 -9
  55. package/dist/tools/local-geometry-scripts.d.ts.map +1 -1
  56. package/dist/tools/local-geometry-scripts.js +7 -2
  57. package/dist/tools/patch-guards.d.ts.map +1 -1
  58. package/dist/tools/patch-guards.js +24 -14
  59. package/dist/tools/project-files.d.ts.map +1 -1
  60. package/dist/tools/project-files.js +2 -2
  61. package/dist/tools/room-tools.d.ts +1 -0
  62. package/dist/tools/room-tools.d.ts.map +1 -1
  63. package/dist/tools/room-tools.js +11 -8
  64. package/dist/tools/scene-scope.d.ts +4 -0
  65. package/dist/tools/scene-scope.d.ts.map +1 -0
  66. package/dist/tools/scene-scope.js +4 -0
  67. package/dist/tools/shared-tools.d.ts +0 -2
  68. package/dist/tools/shared-tools.d.ts.map +1 -1
  69. package/dist/tools/shared-tools.js +146 -31
  70. package/dist/tools/templates/create-house-from-brief.js +1 -1
  71. package/dist/tools/view-scene.js +2 -2
  72. package/examples/coordinate-conventions-demo.md +1 -0
  73. package/examples/photo-to-scene.md +1 -0
  74. package/examples/renovate-from-photos.md +2 -0
  75. package/package.json +10 -10
  76. package/dist/tools/create-unit.d.ts +0 -29
  77. package/dist/tools/create-unit.d.ts.map +0 -1
  78. package/dist/tools/create-unit.js +0 -36
  79. package/dist/tools/list-units.d.ts +0 -38
  80. package/dist/tools/list-units.d.ts.map +0 -1
  81. package/dist/tools/list-units.js +0 -61
  82. package/dist/tools/set-unit-members.d.ts +0 -22
  83. package/dist/tools/set-unit-members.d.ts.map +0 -1
  84. package/dist/tools/set-unit-members.js +0 -43
  85. package/dist/tools/unit-members.d.ts +0 -4
  86. package/dist/tools/unit-members.d.ts.map +0 -1
  87. package/dist/tools/unit-members.js +0 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pascal-app/mcp",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Model Context Protocol server for Pascal 3D editor",
5
5
  "mcpName": "app.pascal/editor",
6
6
  "type": "module",
@@ -62,21 +62,21 @@
62
62
  "prepublishOnly": "bun run build && bun test && bun run smoke:node"
63
63
  },
64
64
  "peerDependencies": {
65
- "@pascal-app/core": "^1.0.6"
65
+ "@pascal-app/core": "^1.0.7"
66
66
  },
67
67
  "dependencies": {
68
- "@hono/node-server": "^1.19.15",
69
- "@modelcontextprotocol/node": "^2.1.1",
70
- "@modelcontextprotocol/server": "^2.3.1",
71
- "@pascal-app/geometry-script": "^1.0.6",
68
+ "@hono/node-server": "^2.1.6",
69
+ "@modelcontextprotocol/node": "^2.1.2",
70
+ "@modelcontextprotocol/server": "^2.4.0",
71
+ "@pascal-app/geometry-script": "^1.0.7",
72
72
  "@pascal-app/lingo": "^0.5.0",
73
73
  "zod": ">=4.6.7 <4.7"
74
74
  },
75
75
  "devDependencies": {
76
- "@modelcontextprotocol/client": "^2.3.1",
77
- "@pascal-app/core": "^1.0.6",
76
+ "@modelcontextprotocol/client": "^2.4.0",
77
+ "@pascal-app/core": "^1.0.7",
78
78
  "@pascal/typescript-config": "*",
79
- "@types/node": "^26.6.5",
79
+ "@types/node": "^26.6.6",
80
80
  "typescript": "7.0.2"
81
81
  },
82
82
  "keywords": [
@@ -94,6 +94,6 @@
94
94
  "directory": "packages/mcp"
95
95
  },
96
96
  "license": "MIT",
97
- "homepage": "https://github.com/pascalorg/editor/tree/main/packages/mcp#readme",
97
+ "homepage": "https://editor.pascal.app/docs/developers/mcp",
98
98
  "bugs": "https://github.com/pascalorg/editor/issues"
99
99
  }
@@ -1,29 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/server';
2
- import { z } from 'zod';
3
- import type { SceneOperations } from '../operations/index.js';
4
- export declare const createUnitInput: {
5
- buildingId: z.ZodString;
6
- name: z.ZodString;
7
- kind: z.ZodOptional<z.ZodDefault<z.ZodEnum<{
8
- apartment: "apartment";
9
- commercial: "commercial";
10
- common: "common";
11
- "hotel-room": "hotel-room";
12
- }>>>;
13
- color: z.ZodOptional<z.ZodString>;
14
- memberZoneIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
15
- };
16
- export declare const createUnitOutput: {
17
- project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
- unsaved: z.ZodOptional<z.ZodString>;
19
- persistence: z.ZodOptional<z.ZodObject<{
20
- status: z.ZodEnum<{
21
- events_unsupported: "events_unsupported";
22
- unbound: "unbound";
23
- }>;
24
- warning: z.ZodString;
25
- }, z.core.$strip>>;
26
- unitId: z.ZodString;
27
- };
28
- export declare function registerCreateUnit(server: McpServer, bridge: SceneOperations): void;
29
- //# sourceMappingURL=create-unit.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-unit.d.ts","sourceRoot":"","sources":["../../src/tools/create-unit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAMpD,eAAO,MAAM,eAAe;IAC1B,UAAU;IACV,IAAI;IACJ,IAAI;;;;;;IACJ,KAAK;IACL,aAAa;CACd,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;CAG5B,CAAA;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAuBnF"}
@@ -1,36 +0,0 @@
1
- import { UnitNode } from '@pascal-app/core/schema';
2
- import { z } from 'zod';
3
- import { ADDITIVE_TOOL_ANNOTATIONS } from './annotations.js';
4
- import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
5
- import { NodeIdSchema } from './schemas.js';
6
- import { validateUnitMembers } from './unit-members.js';
7
- export const createUnitInput = {
8
- buildingId: NodeIdSchema,
9
- name: z.string(),
10
- kind: UnitNode.shape.kind.optional(),
11
- color: z.string().optional(),
12
- memberZoneIds: z.array(NodeIdSchema).optional(),
13
- };
14
- export const createUnitOutput = {
15
- unitId: z.string(),
16
- ...liveSyncOutput,
17
- };
18
- export function registerCreateUnit(server, bridge) {
19
- server.registerTool('create_unit', {
20
- title: 'Create unit',
21
- description: 'Create a named unit in a building, optionally referencing zones across its levels.',
22
- inputSchema: z.object(createUnitInput),
23
- outputSchema: z.object(createUnitOutput),
24
- annotations: ADDITIVE_TOOL_ANNOTATIONS,
25
- }, async ({ buildingId, name, kind, color, memberZoneIds }) => {
26
- const members = validateUnitMembers(bridge, buildingId, memberZoneIds ?? []);
27
- const unit = UnitNode.parse({ name, kind, color, members });
28
- const id = bridge.createNode(unit, buildingId);
29
- const persistence = await publishLiveSceneSnapshot(bridge, 'create_unit');
30
- const payload = { unitId: id, ...persistencePayload(persistence) };
31
- return {
32
- content: [{ type: 'text', text: JSON.stringify(payload) }],
33
- structuredContent: payload,
34
- };
35
- });
36
- }
@@ -1,38 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/server';
2
- import { z } from 'zod';
3
- import type { SceneOperations } from '../operations/index.js';
4
- export declare const listUnitsInput: {
5
- buildingId: z.ZodOptional<z.ZodString>;
6
- };
7
- export declare const listUnitsOutput: {
8
- units: z.ZodArray<z.ZodObject<{
9
- unitId: z.ZodString;
10
- name: z.ZodString;
11
- kind: z.ZodDefault<z.ZodEnum<{
12
- apartment: "apartment";
13
- commercial: "commercial";
14
- common: "common";
15
- "hotel-room": "hotel-room";
16
- }>>;
17
- color: z.ZodString;
18
- members: z.ZodArray<z.ZodString>;
19
- report: z.ZodObject<{
20
- memberCount: z.ZodNumber;
21
- levelSpan: z.ZodNullable<z.ZodObject<{
22
- minOrdinal: z.ZodNumber;
23
- maxOrdinal: z.ZodNumber;
24
- count: z.ZodNumber;
25
- }, z.core.$strip>>;
26
- grossAreaM2: z.ZodNumber;
27
- members: z.ZodArray<z.ZodObject<{
28
- zoneId: z.ZodString;
29
- name: z.ZodString;
30
- levelId: z.ZodNullable<z.ZodString>;
31
- levelOrdinal: z.ZodNullable<z.ZodNumber>;
32
- areaM2: z.ZodNumber;
33
- }, z.core.$strip>>;
34
- }, z.core.$strip>;
35
- }, z.core.$strip>>;
36
- };
37
- export declare function registerListUnits(server: McpServer, bridge: SceneOperations): void;
38
- //# sourceMappingURL=list-units.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list-units.d.ts","sourceRoot":"","sources":["../../src/tools/list-units.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAKpD,eAAO,MAAM,cAAc;IACzB,UAAU;CACX,CAAA;AAED,eAAO,MAAM,eAAe;IAC1B,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyBN,CAAA;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAgClF"}
@@ -1,61 +0,0 @@
1
- import { buildUnitReport } from '@pascal-app/core';
2
- import { UnitNode } from '@pascal-app/core/schema';
3
- import { z } from 'zod';
4
- import { READ_ONLY_TOOL_ANNOTATIONS } from './annotations.js';
5
- import { NodeIdSchema } from './schemas.js';
6
- import { validateUnitMembers } from './unit-members.js';
7
- export const listUnitsInput = {
8
- buildingId: NodeIdSchema.optional(),
9
- };
10
- export const listUnitsOutput = {
11
- units: z.array(z.object({
12
- unitId: z.string(),
13
- name: z.string(),
14
- kind: UnitNode.shape.kind,
15
- color: z.string(),
16
- members: z.array(z.string()),
17
- report: z.object({
18
- memberCount: z.number(),
19
- levelSpan: z
20
- .object({ minOrdinal: z.number(), maxOrdinal: z.number(), count: z.number() })
21
- .nullable(),
22
- grossAreaM2: z.number(),
23
- members: z.array(z.object({
24
- zoneId: z.string(),
25
- name: z.string(),
26
- levelId: z.string().nullable(),
27
- levelOrdinal: z.number().nullable(),
28
- areaM2: z.number(),
29
- })),
30
- }),
31
- })),
32
- };
33
- export function registerListUnits(server, bridge) {
34
- server.registerTool('list_units', {
35
- title: 'List units',
36
- description: 'List units with their member zones and current area reports, optionally filtered by building.',
37
- inputSchema: z.object(listUnitsInput),
38
- outputSchema: z.object(listUnitsOutput),
39
- annotations: READ_ONLY_TOOL_ANNOTATIONS,
40
- }, async ({ buildingId }) => {
41
- if (buildingId !== undefined)
42
- validateUnitMembers(bridge, buildingId, []);
43
- const nodes = bridge.getNodes();
44
- const units = Object.values(nodes)
45
- .filter((node) => node.type === 'unit')
46
- .filter((unit) => buildingId === undefined || unit.parentId === buildingId)
47
- .map((unit) => ({
48
- unitId: unit.id,
49
- name: unit.name,
50
- kind: unit.kind,
51
- color: unit.color,
52
- members: unit.members,
53
- report: buildUnitReport(unit, nodes),
54
- }));
55
- const payload = { units };
56
- return {
57
- content: [{ type: 'text', text: JSON.stringify(payload) }],
58
- structuredContent: payload,
59
- };
60
- });
61
- }
@@ -1,22 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/server';
2
- import { z } from 'zod';
3
- import type { SceneOperations } from '../operations/index.js';
4
- export declare const setUnitMembersInput: {
5
- unitId: z.ZodString;
6
- memberZoneIds: z.ZodArray<z.ZodString>;
7
- };
8
- export declare const setUnitMembersOutput: {
9
- project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
10
- unsaved: z.ZodOptional<z.ZodString>;
11
- persistence: z.ZodOptional<z.ZodObject<{
12
- status: z.ZodEnum<{
13
- events_unsupported: "events_unsupported";
14
- unbound: "unbound";
15
- }>;
16
- warning: z.ZodString;
17
- }, z.core.$strip>>;
18
- unitId: z.ZodString;
19
- memberCount: z.ZodNumber;
20
- };
21
- export declare function registerSetUnitMembers(server: McpServer, bridge: SceneOperations): void;
22
- //# sourceMappingURL=set-unit-members.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"set-unit-members.d.ts","sourceRoot":"","sources":["../../src/tools/set-unit-members.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;AAOpD,eAAO,MAAM,mBAAmB;IAC9B,MAAM;IACN,aAAa;CACd,CAAA;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;CAIhC,CAAA;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAmCvF"}
@@ -1,43 +0,0 @@
1
- import { z } from 'zod';
2
- import { DESTRUCTIVE_TOOL_ANNOTATIONS } from './annotations.js';
3
- import { ProtocolErrorCode, throwMcpError } from './errors.js';
4
- import { liveSyncOutput, persistencePayload, publishLiveSceneSnapshot } from './live-sync.js';
5
- import { NodeIdSchema } from './schemas.js';
6
- import { validateUnitMembers } from './unit-members.js';
7
- export const setUnitMembersInput = {
8
- unitId: NodeIdSchema,
9
- memberZoneIds: z.array(NodeIdSchema),
10
- };
11
- export const setUnitMembersOutput = {
12
- unitId: z.string(),
13
- memberCount: z.number(),
14
- ...liveSyncOutput,
15
- };
16
- export function registerSetUnitMembers(server, bridge) {
17
- server.registerTool('set_unit_members', {
18
- title: 'Set unit members',
19
- description: 'Replace the zones referenced by a unit. Every zone must belong to a level in the same building.',
20
- inputSchema: z.object(setUnitMembersInput),
21
- outputSchema: z.object(setUnitMembersOutput),
22
- annotations: { ...DESTRUCTIVE_TOOL_ANNOTATIONS, idempotentHint: true },
23
- }, async ({ unitId, memberZoneIds }) => {
24
- const unit = bridge.getNode(unitId);
25
- if (!unit) {
26
- throwMcpError(ProtocolErrorCode.InvalidParams, `Unit not found: ${unitId}`);
27
- }
28
- if (unit.type !== 'unit') {
29
- throwMcpError(ProtocolErrorCode.InvalidParams, `Node ${unitId} is a ${unit.type}, expected unit`);
30
- }
31
- if (!unit.parentId) {
32
- throwMcpError(ProtocolErrorCode.InvalidParams, `Unit ${unitId} must belong to a building`);
33
- }
34
- const members = validateUnitMembers(bridge, unit.parentId, memberZoneIds);
35
- bridge.updateNode(unit.id, { members });
36
- const persistence = await publishLiveSceneSnapshot(bridge, 'set_unit_members');
37
- const payload = { unitId, memberCount: members.length, ...persistencePayload(persistence) };
38
- return {
39
- content: [{ type: 'text', text: JSON.stringify(payload) }],
40
- structuredContent: payload,
41
- };
42
- });
43
- }
@@ -1,4 +0,0 @@
1
- import type { ZoneNode } from '@pascal-app/core/schema';
2
- import type { SceneOperations } from '../operations/index.js';
3
- export declare function validateUnitMembers(bridge: SceneOperations, buildingId: string, memberZoneIds: string[]): ZoneNode['id'][];
4
- //# sourceMappingURL=unit-members.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"unit-members.d.ts","sourceRoot":"","sources":["../../src/tools/unit-members.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGpD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,CAgClB"}
@@ -1,24 +0,0 @@
1
- import { ProtocolErrorCode, throwMcpError } from './errors.js';
2
- export function validateUnitMembers(bridge, buildingId, memberZoneIds) {
3
- const building = bridge.getNode(buildingId);
4
- if (!building) {
5
- throwMcpError(ProtocolErrorCode.InvalidParams, `Building not found: ${buildingId}`);
6
- }
7
- if (building.type !== 'building') {
8
- throwMcpError(ProtocolErrorCode.InvalidParams, `Node ${buildingId} is a ${building.type}, expected building`);
9
- }
10
- return memberZoneIds.map((zoneId) => {
11
- const zone = bridge.getNode(zoneId);
12
- if (!zone) {
13
- throwMcpError(ProtocolErrorCode.InvalidParams, `Zone not found: ${zoneId}`);
14
- }
15
- if (zone.type !== 'zone') {
16
- throwMcpError(ProtocolErrorCode.InvalidParams, `Node ${zoneId} is a ${zone.type}, expected zone`);
17
- }
18
- const [, level, parent] = bridge.getAncestry(zone.id);
19
- if (level?.type !== 'level' || parent?.id !== building.id) {
20
- throwMcpError(ProtocolErrorCode.InvalidParams, `Zone ${zoneId} must belong to a level in building ${buildingId}`);
21
- }
22
- return zone.id;
23
- });
24
- }