@plitzi/sdk-server 0.32.5 → 0.32.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/core/services/mcp.js +1 -1
- package/dist/helpers/buildServerInfo.js +3 -9
- package/dist/index.js +2 -1
- package/dist/modules/mcp/catalogs/builtinCallbacks.js +204 -0
- package/dist/modules/mcp/catalogs/builtinComponents.js +170 -0
- package/dist/modules/mcp/catalogs/builtinElementCallbacks.js +50 -0
- package/dist/modules/mcp/catalogs/builtinTransformers.js +148 -0
- package/dist/modules/mcp/catalogs/builtinUtilities.js +90 -0
- package/dist/modules/mcp/{tools/operations/style → catalogs}/cssCatalog.js +75 -2
- package/dist/modules/mcp/catalogs/observed.js +90 -0
- package/dist/modules/mcp/catalogs/paramSpec.js +69 -0
- package/dist/modules/mcp/catalogs/registry.js +89 -0
- package/dist/modules/mcp/handler.js +12 -2
- package/dist/modules/mcp/helpers/agentPrompt.js +104 -0
- package/dist/modules/mcp/helpers/guide.js +334 -15
- package/dist/modules/mcp/helpers/interactions.js +123 -0
- package/dist/modules/mcp/helpers/log.js +54 -0
- package/dist/modules/mcp/helpers/space.js +158 -33
- package/dist/modules/mcp/helpers/uris.js +44 -0
- package/dist/modules/mcp/resources/canonical.js +6 -21
- package/dist/modules/mcp/resources/core.js +4 -3
- package/dist/modules/mcp/resources/primer.js +13 -8
- package/dist/modules/mcp/resources/register.js +37 -5
- package/dist/modules/mcp/resources/schema.js +30 -20
- package/dist/modules/mcp/resources/style.js +18 -11
- package/dist/modules/mcp/server.js +21 -7
- package/dist/modules/mcp/tools/apply/dispatch.js +38 -18
- package/dist/modules/mcp/tools/apply/index.js +19 -4
- package/dist/modules/mcp/tools/apply/writeResult.js +2 -1
- package/dist/modules/mcp/tools/index.js +1 -1
- package/dist/modules/mcp/tools/operations/index.js +13 -2
- package/dist/modules/mcp/tools/operations/schema/bindings/deleteBinding.js +32 -0
- package/dist/modules/mcp/tools/operations/schema/bindings/patchBinding.js +36 -0
- package/dist/modules/mcp/tools/operations/schema/bindings/upsertBinding.js +47 -0
- package/dist/modules/mcp/tools/operations/schema/{deleteElement.js → elements/deleteElement.js} +10 -6
- package/dist/modules/mcp/tools/operations/schema/{moveElement.js → elements/moveElement.js} +8 -6
- package/dist/modules/mcp/tools/operations/schema/{patchElement.js → elements/patchElement.js} +19 -7
- package/dist/modules/mcp/tools/operations/schema/{upsertElement.js → elements/upsertElement.js} +11 -5
- package/dist/modules/mcp/tools/operations/schema/{deleteFolder.js → folders/deleteFolder.js} +4 -4
- package/dist/modules/mcp/tools/operations/schema/{upsertFolder.js → folders/upsertFolder.js} +4 -4
- package/dist/modules/mcp/tools/operations/schema/interactions/deleteInteraction.js +52 -0
- package/dist/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.js +47 -0
- package/dist/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.js +43 -0
- package/dist/modules/mcp/tools/operations/schema/operations.js +25 -11
- package/dist/modules/mcp/tools/operations/schema/{deletePage.js → pages/deletePage.js} +8 -5
- package/dist/modules/mcp/tools/operations/schema/pages/upsertPage.js +75 -0
- package/dist/modules/mcp/tools/operations/schema/settings/patchSettings.js +45 -0
- package/dist/modules/mcp/tools/operations/schema/shared.js +94 -2
- package/dist/modules/mcp/tools/operations/schema/translator.js +77 -10
- package/dist/modules/mcp/tools/operations/schema/{deleteVariable.js → variables/deleteVariable.js} +3 -3
- package/dist/modules/mcp/tools/operations/schema/{upsertVariable.js → variables/upsertVariable.js} +4 -4
- package/dist/modules/mcp/tools/operations/schema/write.js +78 -13
- package/dist/modules/mcp/tools/operations/style/{deleteDefinition.js → definitions/deleteDefinition.js} +4 -3
- package/dist/modules/mcp/tools/operations/style/{patchDefinition.js → definitions/patchDefinition.js} +6 -5
- package/dist/modules/mcp/tools/operations/style/{upsertDefinition.js → definitions/upsertDefinition.js} +5 -4
- package/dist/modules/mcp/tools/operations/style/{deleteGlobalStyle.js → globalStyles/deleteGlobalStyle.js} +4 -3
- package/dist/modules/mcp/tools/operations/style/{patchGlobalStyle.js → globalStyles/patchGlobalStyle.js} +6 -5
- package/dist/modules/mcp/tools/operations/style/{upsertGlobalStyle.js → globalStyles/upsertGlobalStyle.js} +5 -4
- package/dist/modules/mcp/tools/operations/style/idStyles/deleteIdStyle.js +21 -0
- package/dist/modules/mcp/tools/operations/style/idStyles/patchIdStyle.js +28 -0
- package/dist/modules/mcp/tools/operations/style/idStyles/upsertIdStyle.js +24 -0
- package/dist/modules/mcp/tools/operations/style/operations.js +14 -8
- package/dist/modules/mcp/tools/operations/style/translator.js +25 -1
- package/dist/modules/mcp/tools/operations/style/{deleteStyleVariable.js → variables/deleteStyleVariable.js} +4 -4
- package/dist/modules/mcp/tools/operations/style/{upsertStyleVariable.js → variables/upsertStyleVariable.js} +4 -4
- package/dist/modules/mcp/tools/operations/style/write.js +19 -11
- package/dist/modules/mcp/tools/read.js +1 -1
- package/dist/modules/mcp/tools/search.js +34 -27
- package/dist/modules/mcp/tools/shared/validator/audit.js +124 -0
- package/dist/modules/mcp/tools/shared/validator/batch.js +30 -0
- package/dist/modules/mcp/tools/shared/validator/bindings.js +70 -0
- package/dist/modules/mcp/tools/shared/validator/context.js +35 -0
- package/dist/modules/mcp/tools/shared/validator/css.js +47 -0
- package/dist/modules/mcp/tools/shared/validator/elements.js +55 -0
- package/dist/modules/mcp/tools/shared/validator/index.js +226 -0
- package/dist/modules/mcp/tools/shared/validator/interactions.js +106 -0
- package/dist/modules/mcp/tools/shared/validator/refs.js +28 -0
- package/dist/modules/mcp/tools/validate.js +23 -3
- package/dist/modules/ssr/preview.js +1 -1
- package/dist/modules/ssr/views/template.ejs +2 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/modules/mcp/catalogs/builtinCallbacks.d.ts +23 -0
- package/dist/src/modules/mcp/catalogs/builtinComponents.d.ts +4 -0
- package/dist/src/modules/mcp/catalogs/builtinElementCallbacks.d.ts +20 -0
- package/dist/src/modules/mcp/catalogs/builtinTransformers.d.ts +28 -0
- package/dist/src/modules/mcp/catalogs/builtinTransformers.test.d.ts +1 -0
- package/dist/src/modules/mcp/catalogs/builtinUtilities.d.ts +18 -0
- package/dist/src/modules/mcp/{tools/operations/style → catalogs}/cssCatalog.d.ts +5 -1
- package/dist/src/modules/mcp/catalogs/index.d.ts +9 -0
- package/dist/src/modules/mcp/catalogs/observed.d.ts +48 -0
- package/dist/src/modules/mcp/catalogs/paramSpec.d.ts +42 -0
- package/dist/src/modules/mcp/catalogs/registry.d.ts +35 -0
- package/dist/src/modules/mcp/handler.d.ts +2 -2
- package/dist/src/modules/mcp/helpers/agentPrompt.d.ts +4 -0
- package/dist/src/modules/mcp/helpers/guide.d.ts +2 -1
- package/dist/src/modules/mcp/helpers/index.d.ts +4 -0
- package/dist/src/modules/mcp/helpers/interactions.d.ts +30 -0
- package/dist/src/modules/mcp/helpers/log.d.ts +8 -0
- package/dist/src/modules/mcp/helpers/log.test.d.ts +1 -0
- package/dist/src/modules/mcp/helpers/space.d.ts +67 -11
- package/dist/src/modules/mcp/helpers/uris.d.ts +28 -0
- package/dist/src/modules/mcp/index.d.ts +1 -1
- package/dist/src/modules/mcp/mcp.bench.d.ts +1 -0
- package/dist/src/modules/mcp/resources/canonical.d.ts +0 -1
- package/dist/src/modules/mcp/resources/index.d.ts +2 -3
- package/dist/src/modules/mcp/resources/primer.d.ts +2 -1
- package/dist/src/modules/mcp/resources/register.d.ts +2 -2
- package/dist/src/modules/mcp/server.d.ts +5 -2
- package/dist/src/modules/mcp/tools/apply/index.d.ts +191 -2
- package/dist/src/modules/mcp/tools/operations/index.d.ts +383 -4
- package/dist/src/modules/mcp/tools/operations/schema/bindings/deleteBinding.d.ts +17 -0
- package/dist/src/modules/mcp/tools/operations/schema/bindings/patchBinding.d.ts +25 -0
- package/dist/src/modules/mcp/tools/operations/schema/bindings/upsertBinding.d.ts +27 -0
- package/dist/src/modules/mcp/tools/operations/schema/{deleteElement.d.ts → elements/deleteElement.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/schema/{moveElement.d.ts → elements/moveElement.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/schema/{patchElement.d.ts → elements/patchElement.d.ts} +7 -2
- package/dist/src/modules/mcp/tools/operations/schema/{upsertElement.d.ts → elements/upsertElement.d.ts} +3 -3
- package/dist/src/modules/mcp/tools/operations/schema/{deleteFolder.d.ts → folders/deleteFolder.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/schema/{upsertFolder.d.ts → folders/upsertFolder.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/schema/index.d.ts +17 -11
- package/dist/src/modules/mcp/tools/operations/schema/interactions/deleteInteraction.d.ts +12 -0
- package/dist/src/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.d.ts +18 -0
- package/dist/src/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.d.ts +27 -0
- package/dist/src/modules/mcp/tools/operations/schema/operations.d.ts +131 -0
- package/dist/src/modules/mcp/tools/operations/schema/{deletePage.d.ts → pages/deletePage.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/schema/{upsertPage.d.ts → pages/upsertPage.d.ts} +3 -2
- package/dist/src/modules/mcp/tools/operations/schema/settings/patchSettings.d.ts +34 -0
- package/dist/src/modules/mcp/tools/operations/schema/shared.d.ts +53 -0
- package/dist/src/modules/mcp/tools/operations/schema/translator.d.ts +5 -2
- package/dist/src/modules/mcp/tools/operations/schema/{deleteVariable.d.ts → variables/deleteVariable.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/schema/{upsertVariable.d.ts → variables/upsertVariable.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/schema/write.d.ts +38 -8
- package/dist/src/modules/mcp/tools/operations/style/{deleteDefinition.d.ts → definitions/deleteDefinition.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/style/{patchDefinition.d.ts → definitions/patchDefinition.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/style/{upsertDefinition.d.ts → definitions/upsertDefinition.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/style/{deleteGlobalStyle.d.ts → globalStyles/deleteGlobalStyle.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/style/{patchGlobalStyle.d.ts → globalStyles/patchGlobalStyle.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/style/{upsertGlobalStyle.d.ts → globalStyles/upsertGlobalStyle.d.ts} +2 -2
- package/dist/src/modules/mcp/tools/operations/style/idStyles/deleteIdStyle.d.ts +9 -0
- package/dist/src/modules/mcp/tools/operations/style/idStyles/patchIdStyle.d.ts +37 -0
- package/dist/src/modules/mcp/tools/operations/style/idStyles/upsertIdStyle.d.ts +37 -0
- package/dist/src/modules/mcp/tools/operations/style/index.d.ts +11 -9
- package/dist/src/modules/mcp/tools/operations/style/operations.d.ts +70 -2
- package/dist/src/modules/mcp/tools/operations/style/shared.d.ts +1 -1
- package/dist/src/modules/mcp/tools/operations/style/translator.d.ts +4 -1
- package/dist/src/modules/mcp/tools/operations/style/{deleteStyleVariable.d.ts → variables/deleteStyleVariable.d.ts} +3 -3
- package/dist/src/modules/mcp/tools/operations/style/{upsertStyleVariable.d.ts → variables/upsertStyleVariable.d.ts} +3 -3
- package/dist/src/modules/mcp/tools/operations/style/write.d.ts +2 -7
- package/dist/src/modules/mcp/tools/preview.d.ts +191 -2
- package/dist/src/modules/mcp/tools/screenshot.d.ts +191 -2
- package/dist/src/modules/mcp/tools/shared/validator/audit.d.ts +4 -0
- package/dist/src/modules/mcp/tools/shared/validator/batch.d.ts +5 -0
- package/dist/src/modules/mcp/tools/shared/validator/bindings.d.ts +6 -0
- package/dist/src/modules/mcp/tools/shared/validator/context.d.ts +34 -0
- package/dist/src/modules/mcp/tools/shared/validator/css.d.ts +4 -0
- package/dist/src/modules/mcp/tools/shared/validator/elements.d.ts +6 -0
- package/dist/src/modules/mcp/tools/shared/validator/index.d.ts +8 -0
- package/dist/src/modules/mcp/tools/shared/validator/interactions.d.ts +3 -0
- package/dist/src/modules/mcp/tools/shared/validator/refs.d.ts +4 -0
- package/dist/src/modules/mcp/tools/validate.d.ts +191 -2
- package/dist/src/modules/mcp/types/aiSchema.d.ts +93 -1
- package/package.json +12 -10
- package/dist/modules/mcp/tools/operations/schema/registry.js +0 -55
- package/dist/modules/mcp/tools/operations/schema/upsertPage.js +0 -64
- package/dist/modules/mcp/tools/shared/validator.js +0 -262
- package/dist/src/modules/mcp/tools/operations/schema/registry.d.ts +0 -22
- package/dist/src/modules/mcp/tools/shared/validator.d.ts +0 -4
|
@@ -1,20 +1,158 @@
|
|
|
1
1
|
//#region src/modules/mcp/helpers/space.ts
|
|
2
|
-
var cloneSpace = (space) =>
|
|
2
|
+
var cloneSpace = (space) => ({
|
|
3
|
+
schema: structuredClone(space.schema),
|
|
4
|
+
style: structuredClone(space.style),
|
|
5
|
+
...space.catalog ? { catalog: space.catalog } : {}
|
|
6
|
+
});
|
|
3
7
|
var slugify = (value) => value.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
/** A value when it is a string, otherwise undefined — for the many attributes typed as `unknown` that are strings
|
|
9
|
+
* in practice (name, slug, subType, dom id…). */
|
|
10
|
+
var strOr = (value) => typeof value === "string" ? value : void 0;
|
|
11
|
+
/** Display name of a page or element: its `name` attribute when set, otherwise its definition label. */
|
|
12
|
+
var nameOf = (el) => strOr(el.attributes.name) ?? el.definition.label;
|
|
13
|
+
/** Stable, human-readable ref for a page: its idRef, then slug, then a slugified label. A page without an idRef is
|
|
14
|
+
* still addressable — unlike a data source, a page ref has meaningful fallbacks the agent can read off the tree. */
|
|
7
15
|
var pageRefOf = (el) => {
|
|
8
|
-
if (el.
|
|
9
|
-
const slug =
|
|
16
|
+
if (el.idRef) return el.idRef;
|
|
17
|
+
const slug = strOr(el.attributes.slug)?.trim();
|
|
10
18
|
if (slug) return slugify(slug);
|
|
11
19
|
if (el.attributes.default === true) return "home";
|
|
12
|
-
return slugify(
|
|
20
|
+
return slugify(nameOf(el)) || el.id;
|
|
13
21
|
};
|
|
14
|
-
/** Stable ref for a non-page element
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
/** Stable ref for ADDRESSING a non-page element in the tree: its idRef when present, otherwise the opaque id so an
|
|
23
|
+
* element without one is still reachable — the agent needs to name it to give it an idRef in the first place.
|
|
24
|
+
* This is not the wiring key: the runtime wires interactions and data sources by idRef only, so an element
|
|
25
|
+
* addressed here by its id alone publishes no source and takes no interactions (see `getSourceName`). */
|
|
26
|
+
var elementRefOf = (el) => el.idRef ?? el.id;
|
|
27
|
+
var buildIndex = (schema) => {
|
|
28
|
+
const flat = schema.flat;
|
|
29
|
+
const lookup = (id) => flat[id];
|
|
30
|
+
const pageIds = new Set(schema.pages);
|
|
31
|
+
for (const el of Object.values(flat)) if (el.definition.type === "page") pageIds.add(el.id);
|
|
32
|
+
const pageElements = [];
|
|
33
|
+
const pageByRef = /* @__PURE__ */ new Map();
|
|
34
|
+
const elementByRef = /* @__PURE__ */ new Map();
|
|
35
|
+
for (const el of Object.values(flat)) if (pageIds.has(el.id)) {
|
|
36
|
+
pageElements.push(el);
|
|
37
|
+
const ref = pageRefOf(el);
|
|
38
|
+
if (!pageByRef.has(ref)) pageByRef.set(ref, el);
|
|
39
|
+
if (!pageByRef.has(el.id)) pageByRef.set(el.id, el);
|
|
40
|
+
} else {
|
|
41
|
+
const ref = elementRefOf(el);
|
|
42
|
+
if (!elementByRef.has(ref)) elementByRef.set(ref, el);
|
|
43
|
+
if (!elementByRef.has(el.id)) elementByRef.set(el.id, el);
|
|
44
|
+
}
|
|
45
|
+
const pageOf = /* @__PURE__ */ new Map();
|
|
46
|
+
for (const page of pageElements) {
|
|
47
|
+
pageOf.set(page.id, page.id);
|
|
48
|
+
const stack = [...page.definition.items ?? []];
|
|
49
|
+
while (stack.length > 0) {
|
|
50
|
+
const id = stack.pop();
|
|
51
|
+
if (id === void 0 || pageOf.has(id)) continue;
|
|
52
|
+
const el = lookup(id);
|
|
53
|
+
if (!el) continue;
|
|
54
|
+
pageOf.set(id, page.id);
|
|
55
|
+
for (const childId of el.definition.items ?? []) stack.push(childId);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
pageIds,
|
|
60
|
+
pageElements,
|
|
61
|
+
pageByRef,
|
|
62
|
+
elementByRef,
|
|
63
|
+
pageOf,
|
|
64
|
+
detailCache: /* @__PURE__ */ new Map()
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
var indexCache = /* @__PURE__ */ new WeakMap();
|
|
68
|
+
/** The index for a schema, built once and memoized on the schema object. */
|
|
69
|
+
var spaceIndex = (schema) => {
|
|
70
|
+
let index = indexCache.get(schema);
|
|
71
|
+
if (!index) {
|
|
72
|
+
index = buildIndex(schema);
|
|
73
|
+
indexCache.set(schema, index);
|
|
74
|
+
}
|
|
75
|
+
return index;
|
|
76
|
+
};
|
|
77
|
+
var cachedIndex = (schema) => indexCache.get(schema);
|
|
78
|
+
/** A new non-page element was created under `pageId`. */
|
|
79
|
+
var indexAddElement = (schema, el, pageId) => {
|
|
80
|
+
const index = cachedIndex(schema);
|
|
81
|
+
if (!index) return;
|
|
82
|
+
index.elementByRef.set(el.id, el);
|
|
83
|
+
if (el.idRef) index.elementByRef.set(el.idRef, el);
|
|
84
|
+
index.pageOf.set(el.id, pageId);
|
|
85
|
+
index.detailCache.clear();
|
|
86
|
+
};
|
|
87
|
+
/** These non-page elements were deleted (an element and its descendants). */
|
|
88
|
+
var indexRemoveElements = (schema, els) => {
|
|
89
|
+
const index = cachedIndex(schema);
|
|
90
|
+
if (!index) return;
|
|
91
|
+
for (const el of els) {
|
|
92
|
+
index.elementByRef.delete(el.id);
|
|
93
|
+
if (el.idRef) index.elementByRef.delete(el.idRef);
|
|
94
|
+
index.pageOf.delete(el.id);
|
|
95
|
+
}
|
|
96
|
+
index.detailCache.clear();
|
|
97
|
+
};
|
|
98
|
+
/** An existing element was just given an idRef (it had none), so it becomes addressable by that ref. */
|
|
99
|
+
var indexReRefElement = (schema, el) => {
|
|
100
|
+
const index = cachedIndex(schema);
|
|
101
|
+
if (!index) return;
|
|
102
|
+
if (el.idRef) index.elementByRef.set(el.idRef, el);
|
|
103
|
+
index.detailCache.clear();
|
|
104
|
+
};
|
|
105
|
+
/** A new page element was created. */
|
|
106
|
+
var indexAddPage = (schema, page) => {
|
|
107
|
+
const index = cachedIndex(schema);
|
|
108
|
+
if (!index) return;
|
|
109
|
+
index.pageIds.add(page.id);
|
|
110
|
+
index.pageElements.push(page);
|
|
111
|
+
index.pageByRef.set(page.id, page);
|
|
112
|
+
index.pageByRef.set(pageRefOf(page), page);
|
|
113
|
+
index.pageOf.set(page.id, page.id);
|
|
114
|
+
index.detailCache.clear();
|
|
115
|
+
};
|
|
116
|
+
/** A page and its `descendants` (its non-page elements) were deleted. */
|
|
117
|
+
var indexRemovePage = (schema, page, descendants) => {
|
|
118
|
+
const index = cachedIndex(schema);
|
|
119
|
+
if (!index) return;
|
|
120
|
+
index.pageIds.delete(page.id);
|
|
121
|
+
const at = index.pageElements.findIndex((p) => p.id === page.id);
|
|
122
|
+
if (at >= 0) index.pageElements.splice(at, 1);
|
|
123
|
+
index.pageByRef.delete(page.id);
|
|
124
|
+
index.pageByRef.delete(pageRefOf(page));
|
|
125
|
+
index.pageOf.delete(page.id);
|
|
126
|
+
for (const el of descendants) {
|
|
127
|
+
index.elementByRef.delete(el.id);
|
|
128
|
+
if (el.idRef) index.elementByRef.delete(el.idRef);
|
|
129
|
+
index.pageOf.delete(el.id);
|
|
130
|
+
}
|
|
131
|
+
index.detailCache.clear();
|
|
132
|
+
};
|
|
133
|
+
/** A page's slug/name/default changed; re-key its pageByRef entry if that changed its ref. `oldRef` is the ref
|
|
134
|
+
* computed BEFORE the attribute change. */
|
|
135
|
+
var indexReRefPage = (schema, page, oldRef) => {
|
|
136
|
+
const index = cachedIndex(schema);
|
|
137
|
+
if (!index) return;
|
|
138
|
+
const newRef = pageRefOf(page);
|
|
139
|
+
if (newRef !== oldRef) {
|
|
140
|
+
index.pageByRef.delete(oldRef);
|
|
141
|
+
index.pageByRef.set(newRef, page);
|
|
142
|
+
index.detailCache.clear();
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
/** A move reparented an element within its page: the ref/page maps are unchanged, but the moved element's
|
|
146
|
+
* parentRef and both parents' childRefs did change, so their memoized detail must be dropped. */
|
|
147
|
+
var indexInvalidateDetails = (schema) => {
|
|
148
|
+
cachedIndex(schema)?.detailCache.clear();
|
|
149
|
+
};
|
|
150
|
+
var isPageElement = (schema, el) => spaceIndex(schema).pageIds.has(el.id) || el.definition.type === "page";
|
|
151
|
+
var getPageElements = (schema) => spaceIndex(schema).pageElements;
|
|
152
|
+
/** Finds a page by its semantic ref (idRef/slug/…) or its raw id, so legacy schemas without an idRef still resolve. */
|
|
153
|
+
var findPageByRef = (schema, pageRef) => spaceIndex(schema).pageByRef.get(pageRef);
|
|
154
|
+
/** Find any non-page element by its semantic ref (idRef) or raw id, across the whole space. */
|
|
155
|
+
var findElementByRef = (schema, ref) => spaceIndex(schema).elementByRef.get(ref);
|
|
18
156
|
var pageFoldersOf = (schema) => {
|
|
19
157
|
schema.pageFolders ??= [];
|
|
20
158
|
return schema.pageFolders;
|
|
@@ -96,35 +234,22 @@ var descendantIds = (schema, pageRootId) => {
|
|
|
96
234
|
return acc;
|
|
97
235
|
};
|
|
98
236
|
/** Resolve a ref to a concrete element within a page subtree (or the page root itself). Accepts either the
|
|
99
|
-
* semantic ref (
|
|
237
|
+
* semantic ref (idRef) or the raw element id, so schemas predating idRef keep working through their ids. */
|
|
100
238
|
var resolveRef = (schema, page, ref) => {
|
|
101
239
|
if (elementRefOf(page) === ref || pageRefOf(page) === ref || page.id === ref) return page;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
240
|
+
const index = spaceIndex(schema);
|
|
241
|
+
const el = index.elementByRef.get(ref);
|
|
242
|
+
return el && index.pageOf.get(el.id) === page.id ? el : void 0;
|
|
106
243
|
};
|
|
107
244
|
/** Ordered children of an element, honoring definition.items and skipping dangling ids. */
|
|
108
245
|
var orderedChildren = (schema, el) => {
|
|
109
246
|
return (el.definition.items ?? []).map((id) => schema.flat[id]).filter((child) => Boolean(child));
|
|
110
247
|
};
|
|
111
|
-
/** The page ref an element belongs to
|
|
248
|
+
/** The page ref an element belongs to. 'unknown' when it has no page ancestor. */
|
|
112
249
|
var pageRefOfElement = (schema, el) => {
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
guard.add(current.id);
|
|
117
|
-
if (isPageElement(schema, current)) return pageRefOf(current);
|
|
118
|
-
current = current.definition.parentId ? schema.flat[current.definition.parentId] : void 0;
|
|
119
|
-
}
|
|
120
|
-
return "unknown";
|
|
121
|
-
};
|
|
122
|
-
/** Find any non-page element by its semantic ref (aiRef) or raw id, across the whole space. */
|
|
123
|
-
var findElementByRef = (schema, ref) => {
|
|
124
|
-
for (const el of Object.values(schema.flat)) {
|
|
125
|
-
if (isPageElement(schema, el)) continue;
|
|
126
|
-
if (elementRefOf(el) === ref || el.id === ref) return el;
|
|
127
|
-
}
|
|
250
|
+
const pageId = spaceIndex(schema).pageOf.get(el.id);
|
|
251
|
+
const page = pageId ? schema.flat[pageId] : void 0;
|
|
252
|
+
return page ? pageRefOf(page) : "unknown";
|
|
128
253
|
};
|
|
129
254
|
/** Total number of descendant elements under a subtree (excluding the root). */
|
|
130
255
|
var descendantCount = (schema, rootId) => descendantIds(schema, rootId).length;
|
|
@@ -134,4 +259,4 @@ var generateObjectId = () => {
|
|
|
134
259
|
return `${Math.floor(Date.now() / 1e3).toString(16).padStart(8, "0")}${Array.from({ length: 16 }, () => Math.floor(Math.random() * 16).toString(16)).join("")}`;
|
|
135
260
|
};
|
|
136
261
|
//#endregion
|
|
137
|
-
export { cloneSpace, descendantCount, descendantIds, elementById, elementRefOf, emptySpaceMessage, findElementByRef, findFolderByRef, findPageByRef, folderAncestorIds, generateObjectId, getPageElements, isPageElement, orderedChildren, pageFoldersOf, pageRefOf, pageRefOfElement, resolveRef, routeParamNames, slugRouteParams, slugify, sortFolders, unauthorizedSpaceMessage };
|
|
262
|
+
export { cloneSpace, descendantCount, descendantIds, elementById, elementRefOf, emptySpaceMessage, findElementByRef, findFolderByRef, findPageByRef, folderAncestorIds, generateObjectId, getPageElements, indexAddElement, indexAddPage, indexInvalidateDetails, indexReRefElement, indexReRefPage, indexRemoveElements, indexRemovePage, isPageElement, nameOf, orderedChildren, pageFoldersOf, pageRefOf, pageRefOfElement, resolveRef, routeParamNames, slugRouteParams, slugify, sortFolders, spaceIndex, strOr, unauthorizedSpaceMessage };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/modules/mcp/helpers/uris.ts
|
|
2
|
+
var guideUri = "plitzi://guide";
|
|
3
|
+
var typesUri = "plitzi://types";
|
|
4
|
+
var cssPropertiesUri = "plitzi://css-properties";
|
|
5
|
+
var primerUri = (env) => `plitzi://primer/${env}`;
|
|
6
|
+
var pagesUri = (env) => `plitzi://schema/${env}/pages`;
|
|
7
|
+
var pageUri = (env, ref) => `plitzi://schema/${env}/pages/${ref}`;
|
|
8
|
+
var elementUri = (env, ref) => `plitzi://schema/${env}/elements/${ref}`;
|
|
9
|
+
var schemaVarsUri = (env) => `plitzi://schema-variables/${env}`;
|
|
10
|
+
var settingsUri = (env) => `plitzi://settings/${env}`;
|
|
11
|
+
var interactionsUri = (env) => `plitzi://interactions/${env}`;
|
|
12
|
+
var dataSourcesUri = (env) => `plitzi://data-sources/${env}`;
|
|
13
|
+
var foldersUri = (env) => `plitzi://folders/${env}`;
|
|
14
|
+
var folderUri = (env, ref) => `plitzi://folders/${env}/${ref}`;
|
|
15
|
+
var defsUri = (env) => `plitzi://definitions/${env}`;
|
|
16
|
+
var defUri = (env, ref) => `plitzi://definitions/${env}/${ref}`;
|
|
17
|
+
var globalsUri = (env) => `plitzi://global-styles/${env}`;
|
|
18
|
+
var globalUri = (env, componentType) => `plitzi://global-styles/${env}/${componentType}`;
|
|
19
|
+
var idsUri = (env) => `plitzi://id-styles/${env}`;
|
|
20
|
+
var idUri = (env, targetId) => `plitzi://id-styles/${env}/${targetId}`;
|
|
21
|
+
var styleVarsUri = (env) => `plitzi://style-variables/${env}`;
|
|
22
|
+
var styleVarUri = (env, category) => `plitzi://style-variables/${env}/${category}`;
|
|
23
|
+
var aliasedRoots = [
|
|
24
|
+
"definitions",
|
|
25
|
+
"global-styles",
|
|
26
|
+
"id-styles",
|
|
27
|
+
"style-variables",
|
|
28
|
+
"schema-variables",
|
|
29
|
+
"folders"
|
|
30
|
+
];
|
|
31
|
+
var itemTemplates = (env) => [
|
|
32
|
+
pageUri(env, "{ref}"),
|
|
33
|
+
elementUri(env, "{ref}"),
|
|
34
|
+
defUri(env, "{ref}"),
|
|
35
|
+
globalUri(env, "{componentType}"),
|
|
36
|
+
idUri(env, "{targetId}"),
|
|
37
|
+
styleVarUri(env, "{category}"),
|
|
38
|
+
folderUri(env, "{ref}")
|
|
39
|
+
];
|
|
40
|
+
/** The remainder of `uri` after `prefix`, or undefined when it does not start with it — so a resolver matches a
|
|
41
|
+
* family and extracts its ref in one step, without repeating the prefix string for both the startsWith and slice. */
|
|
42
|
+
var afterPrefix = (uri, prefix) => uri.startsWith(prefix) ? uri.slice(prefix.length) : void 0;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { afterPrefix, aliasedRoots, cssPropertiesUri, dataSourcesUri, defUri, defsUri, elementUri, folderUri, foldersUri, globalUri, globalsUri, guideUri, idUri, idsUri, interactionsUri, itemTemplates, pageUri, pagesUri, primerUri, schemaVarsUri, settingsUri, styleVarUri, styleVarsUri, typesUri };
|
|
@@ -1,29 +1,14 @@
|
|
|
1
|
+
import { afterPrefix, aliasedRoots, itemTemplates, primerUri } from "../helpers/uris.js";
|
|
1
2
|
//#region src/modules/mcp/resources/canonical.ts
|
|
2
|
-
var ALIASED_ROOTS = [
|
|
3
|
-
"definitions",
|
|
4
|
-
"global-styles",
|
|
5
|
-
"style-variables",
|
|
6
|
-
"schema-variables",
|
|
7
|
-
"folders"
|
|
8
|
-
];
|
|
9
3
|
var canonicalUri = (env, uri) => {
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
const
|
|
13
|
-
for (const root of ALIASED_ROOTS) {
|
|
4
|
+
const rest = afterPrefix(uri, `plitzi://schema/${env}/`);
|
|
5
|
+
if (rest === void 0) return uri;
|
|
6
|
+
for (const root of aliasedRoots) {
|
|
14
7
|
if (rest === root) return `plitzi://${root}/${env}`;
|
|
15
8
|
if (rest.startsWith(`${root}/`)) return `plitzi://${root}/${env}/${rest.slice(root.length + 1)}`;
|
|
16
9
|
}
|
|
17
10
|
return uri;
|
|
18
11
|
};
|
|
19
|
-
var itemTemplates = (env) => [
|
|
20
|
-
`plitzi://schema/${env}/pages/{ref}`,
|
|
21
|
-
`plitzi://schema/${env}/elements/{ref}`,
|
|
22
|
-
`plitzi://definitions/${env}/{ref}`,
|
|
23
|
-
`plitzi://global-styles/${env}/{componentType}`,
|
|
24
|
-
`plitzi://style-variables/${env}/{category}`,
|
|
25
|
-
`plitzi://folders/${env}/{ref}`
|
|
26
|
-
];
|
|
27
12
|
/** Teachable message for a URI that read as null. Distinguishes a well-formed URI whose ref does not resolve (the
|
|
28
13
|
* resource may be stale/deleted) from a URI whose shape matches no template at all (malformed — echo the valid
|
|
29
14
|
* templates so the agent stops hand-building URIs). See RFC 0004 I2. */
|
|
@@ -38,8 +23,8 @@ var resourceErrorMessage = (env, uri) => {
|
|
|
38
23
|
error: "MALFORMED_URI",
|
|
39
24
|
message: `'${uri}' matches no resource template.`,
|
|
40
25
|
hint: "Do not hand-build element URIs — take the ready-made uri from plitzi_search or a write response.",
|
|
41
|
-
validTemplates: [
|
|
26
|
+
validTemplates: [primerUri(env), ...itemTemplates(env)]
|
|
42
27
|
});
|
|
43
28
|
};
|
|
44
29
|
//#endregion
|
|
45
|
-
export { canonicalUri,
|
|
30
|
+
export { canonicalUri, resourceErrorMessage };
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { cssProperties } from "../catalogs/cssCatalog.js";
|
|
2
|
+
import { buildTypeRegistry } from "../catalogs/registry.js";
|
|
3
|
+
import "../helpers/uris.js";
|
|
1
4
|
import { guideText } from "../helpers/guide.js";
|
|
2
5
|
import { envelope } from "./envelope.js";
|
|
3
|
-
import { cssProperties } from "../tools/operations/style/cssCatalog.js";
|
|
4
|
-
import { buildTypeRegistry } from "../tools/operations/schema/registry.js";
|
|
5
6
|
//#region src/modules/mcp/resources/core.ts
|
|
6
7
|
/** Space-independent singletons: the usage guide, the observed type registry and the CSS property catalog.
|
|
7
8
|
* Returns undefined when the URI is not one of these, so the router falls through to the next resolver. */
|
|
8
9
|
var readCoreResource = (space, uri) => {
|
|
9
10
|
if (uri === "plitzi://guide") return envelope(guideText);
|
|
10
|
-
if (uri === "plitzi://types") return envelope(buildTypeRegistry(space.schema));
|
|
11
|
+
if (uri === "plitzi://types") return envelope(buildTypeRegistry(space.schema, space.catalog));
|
|
11
12
|
if (uri === "plitzi://css-properties") return envelope(cssProperties);
|
|
12
13
|
};
|
|
13
14
|
//#endregion
|
|
@@ -1,24 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cssProperties } from "../catalogs/cssCatalog.js";
|
|
2
|
+
import { buildDataSourceCatalog, buildInteractionCatalog } from "../catalogs/observed.js";
|
|
3
|
+
import { buildTypeRegistry } from "../catalogs/registry.js";
|
|
4
|
+
import { guideQuickstart } from "../helpers/guide.js";
|
|
2
5
|
import { envelope } from "./envelope.js";
|
|
3
|
-
import { cssProperties } from "../tools/operations/style/cssCatalog.js";
|
|
4
|
-
import { buildTypeRegistry } from "../tools/operations/schema/registry.js";
|
|
5
6
|
import { definitionRefs, styleVariablesToAI } from "../tools/operations/style/translator.js";
|
|
6
|
-
import { foldersToAI, pageSummariesToAI, schemaVariablesToAI } from "../tools/operations/schema/translator.js";
|
|
7
|
+
import { foldersToAI, pageSummariesToAI, schemaVariablesToAI, settingsToAI } from "../tools/operations/schema/translator.js";
|
|
7
8
|
//#region src/modules/mcp/resources/primer.ts
|
|
8
9
|
/** The cold-start bundle: everything the guide says to read before the first write, in one round-trip.
|
|
9
10
|
* Summaries only — never full page/element trees (those are opened on demand), so it stays cheap even on a
|
|
10
|
-
* large space.
|
|
11
|
+
* large space. Carries the condensed `guideQuickstart` (not the full guideText, which the agent reads on demand at
|
|
12
|
+
* plitzi://guide) to keep the bundle small. Returns undefined when the URI is not the primer. */
|
|
11
13
|
var readPrimerResource = (space, env, uri) => {
|
|
12
14
|
if (uri !== `plitzi://primer/${env}`) return;
|
|
13
15
|
return envelope({
|
|
14
|
-
guide:
|
|
15
|
-
types: buildTypeRegistry(space.schema),
|
|
16
|
+
guide: guideQuickstart,
|
|
17
|
+
types: buildTypeRegistry(space.schema, space.catalog),
|
|
16
18
|
cssProperties,
|
|
17
19
|
pages: pageSummariesToAI(space.schema),
|
|
18
20
|
folders: foldersToAI(space.schema),
|
|
19
21
|
definitions: definitionRefs(space.style),
|
|
20
22
|
styleVariables: styleVariablesToAI(space.style),
|
|
21
|
-
schemaVariables: schemaVariablesToAI(space.schema, false)
|
|
23
|
+
schemaVariables: schemaVariablesToAI(space.schema, false),
|
|
24
|
+
settings: settingsToAI(space.schema),
|
|
25
|
+
interactions: buildInteractionCatalog(space.schema),
|
|
26
|
+
dataSources: buildDataSourceCatalog(space.schema)
|
|
22
27
|
});
|
|
23
28
|
};
|
|
24
29
|
//#endregion
|
|
@@ -1,17 +1,24 @@
|
|
|
1
|
+
import { cssProperties } from "../catalogs/cssCatalog.js";
|
|
1
2
|
import { guideText } from "../helpers/guide.js";
|
|
2
3
|
import { resourceErrorMessage } from "./canonical.js";
|
|
3
4
|
import { envelope, jsonContents } from "./envelope.js";
|
|
4
|
-
import { cssProperties } from "../tools/operations/style/cssCatalog.js";
|
|
5
5
|
import { readResource } from "./router.js";
|
|
6
6
|
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp";
|
|
7
7
|
//#region src/modules/mcp/resources/register.ts
|
|
8
8
|
/** Register every resource on the MCP server: fixed listings plus templated per-item reads. The space is
|
|
9
9
|
* loaded lazily via getSpace, so listing resources never touches the store — only reading one does. */
|
|
10
|
-
var registerResources = (server, getSpace, env) => {
|
|
10
|
+
var registerResources = (server, getSpace, env, log) => {
|
|
11
11
|
const emit = async (uri) => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const start = performance.now();
|
|
13
|
+
try {
|
|
14
|
+
const result = readResource(await getSpace(), env, uri);
|
|
15
|
+
if (!result) throw new Error(resourceErrorMessage(env, uri));
|
|
16
|
+
log.resourceRead(uri, performance.now() - start);
|
|
17
|
+
return jsonContents(uri, result);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
log.resourceRead(uri, performance.now() - start, error);
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
15
22
|
};
|
|
16
23
|
server.registerResource("Guide", "plitzi://guide", {
|
|
17
24
|
description: "How to read and write this space with mcp-ai",
|
|
@@ -56,6 +63,11 @@ var registerResources = (server, getSpace, env) => {
|
|
|
56
63
|
`plitzi://global-styles/${env}`,
|
|
57
64
|
"Element types that have a site-wide global style"
|
|
58
65
|
],
|
|
66
|
+
[
|
|
67
|
+
"Id styles",
|
|
68
|
+
`plitzi://id-styles/${env}`,
|
|
69
|
+
"DOM ids that have an id rule (#id) targeting a single element"
|
|
70
|
+
],
|
|
59
71
|
[
|
|
60
72
|
"Style variables",
|
|
61
73
|
`plitzi://style-variables/${env}`,
|
|
@@ -66,6 +78,21 @@ var registerResources = (server, getSpace, env) => {
|
|
|
66
78
|
`plitzi://schema-variables/${env}`,
|
|
67
79
|
"Space-level values referenced via {{name}}"
|
|
68
80
|
],
|
|
81
|
+
[
|
|
82
|
+
"Settings",
|
|
83
|
+
`plitzi://settings/${env}`,
|
|
84
|
+
"Space-level settings: global customCss and state/auth configuration"
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
"Interactions catalog",
|
|
88
|
+
`plitzi://interactions/${env}`,
|
|
89
|
+
"Interaction actions (observed, grouped by node type) plus the built-in vocabularies — globalCallbacks (with their source module), element callbacks and utilities — each with its full param schema, the vocabulary for upsertInteractionFlow"
|
|
90
|
+
],
|
|
91
|
+
[
|
|
92
|
+
"Data sources catalog",
|
|
93
|
+
`plitzi://data-sources/${env}`,
|
|
94
|
+
"Data-source paths and binding targets observed in this space — the vocabulary for upsertBinding"
|
|
95
|
+
],
|
|
69
96
|
[
|
|
70
97
|
"Style definitions (schema alias)",
|
|
71
98
|
`plitzi://schema/${env}/definitions`,
|
|
@@ -117,6 +144,11 @@ var registerResources = (server, getSpace, env) => {
|
|
|
117
144
|
`plitzi://global-styles/${env}/{componentType}`,
|
|
118
145
|
"The site-wide CSS applied to every element of one type"
|
|
119
146
|
],
|
|
147
|
+
[
|
|
148
|
+
"Id style",
|
|
149
|
+
`plitzi://id-styles/${env}/{targetId}`,
|
|
150
|
+
"The CSS of an id rule (#id) targeting a single element"
|
|
151
|
+
],
|
|
120
152
|
[
|
|
121
153
|
"Style variables by category",
|
|
122
154
|
`plitzi://style-variables/${env}/{category}`,
|
|
@@ -1,33 +1,43 @@
|
|
|
1
|
+
import { buildDataSourceCatalog, buildInteractionCatalog } from "../catalogs/observed.js";
|
|
1
2
|
import { findElementByRef, findPageByRef } from "../helpers/space.js";
|
|
3
|
+
import { afterPrefix, dataSourcesUri, elementUri, folderUri, foldersUri, interactionsUri, pageUri, pagesUri, schemaVarsUri, settingsUri } from "../helpers/uris.js";
|
|
2
4
|
import { envelope } from "./envelope.js";
|
|
3
|
-
import {
|
|
5
|
+
import { elementView, folderRefToAI, foldersToAI, pageSkeletonToAI, pageStylesToAI, pageSummariesToAI, schemaVariablesToAI, settingsToAI } from "../tools/operations/schema/translator.js";
|
|
4
6
|
//#region src/modules/mcp/resources/schema.ts
|
|
5
7
|
/** Element-schema reads: page listings/skeletons/styles, folders, single elements and schema variables. Returns
|
|
6
8
|
* undefined when the URI belongs to another domain, null when the shape is ours but the ref does not resolve. */
|
|
7
9
|
var readSchemaResource = (space, env, uri) => {
|
|
8
|
-
if (uri ===
|
|
9
|
-
if (uri ===
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const folder = folderRefToAI(space.schema,
|
|
10
|
+
if (uri === pagesUri(env)) return envelope(pageSummariesToAI(space.schema));
|
|
11
|
+
if (uri === foldersUri(env)) return envelope(foldersToAI(space.schema));
|
|
12
|
+
const folderRef = afterPrefix(uri, folderUri(env, ""));
|
|
13
|
+
if (folderRef !== void 0) {
|
|
14
|
+
const folder = folderRefToAI(space.schema, folderRef);
|
|
13
15
|
return folder ? envelope(folder) : null;
|
|
14
16
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const pageItem = afterPrefix(uri, pageUri(env, ""));
|
|
18
|
+
if (pageItem !== void 0) {
|
|
19
|
+
if (pageItem.endsWith("/styles")) {
|
|
20
|
+
const ref = pageItem.slice(0, -7);
|
|
21
|
+
const page = findPageByRef(space.schema, ref);
|
|
22
|
+
return page ? envelope(pageStylesToAI(space.schema, space.style, page)) : null;
|
|
23
|
+
}
|
|
24
|
+
const page = findPageByRef(space.schema, pageItem);
|
|
25
|
+
return page ? envelope(pageSkeletonToAI(space.schema, page, space.style)) : null;
|
|
19
26
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
27
|
+
const elementRef = afterPrefix(uri, elementUri(env, ""));
|
|
28
|
+
if (elementRef !== void 0) {
|
|
29
|
+
const el = findElementByRef(space.schema, elementRef);
|
|
30
|
+
if (!el) return null;
|
|
31
|
+
const view = elementView(space.schema, el, space.style);
|
|
32
|
+
return {
|
|
33
|
+
stateVersion: view.version,
|
|
34
|
+
data: view.detail
|
|
35
|
+
};
|
|
24
36
|
}
|
|
25
|
-
if (uri
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
if (uri === `plitzi://schema-variables/${env}`) return envelope(schemaVariablesToAI(space.schema));
|
|
37
|
+
if (uri === schemaVarsUri(env)) return envelope(schemaVariablesToAI(space.schema));
|
|
38
|
+
if (uri === settingsUri(env)) return envelope(settingsToAI(space.schema));
|
|
39
|
+
if (uri === interactionsUri(env)) return envelope(buildInteractionCatalog(space.schema));
|
|
40
|
+
if (uri === dataSourcesUri(env)) return envelope(buildDataSourceCatalog(space.schema));
|
|
31
41
|
};
|
|
32
42
|
//#endregion
|
|
33
43
|
export { readSchemaResource };
|
|
@@ -1,24 +1,31 @@
|
|
|
1
|
+
import { afterPrefix, defUri, defsUri, globalUri, globalsUri, idUri, idsUri, styleVarUri, styleVarsUri } from "../helpers/uris.js";
|
|
1
2
|
import { envelope } from "./envelope.js";
|
|
2
|
-
import { definitionRefs, definitionToAI, globalStyleToAI, globalStyleTypes, styleVariablesToAI } from "../tools/operations/style/translator.js";
|
|
3
|
+
import { definitionRefs, definitionToAI, globalStyleToAI, globalStyleTypes, idStyleIds, idStyleToAI, styleVariablesToAI } from "../tools/operations/style/translator.js";
|
|
3
4
|
//#region src/modules/mcp/resources/style.ts
|
|
4
5
|
/** Style-schema reads: definitions, global (per-type) styles and design-token variables by category. Returns
|
|
5
6
|
* undefined when the URI belongs to another domain, null when the shape is ours but the ref does not resolve. */
|
|
6
7
|
var readStyleResource = (space, env, uri) => {
|
|
7
|
-
if (uri ===
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const def = definitionToAI(space.style,
|
|
8
|
+
if (uri === defsUri(env)) return envelope(definitionRefs(space.style));
|
|
9
|
+
const defRef = afterPrefix(uri, defUri(env, ""));
|
|
10
|
+
if (defRef !== void 0) {
|
|
11
|
+
const def = definitionToAI(space.style, defRef);
|
|
11
12
|
return def ? envelope(def) : null;
|
|
12
13
|
}
|
|
13
|
-
if (uri ===
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (uri === globalsUri(env)) return envelope(globalStyleTypes(space.style));
|
|
15
|
+
const componentType = afterPrefix(uri, globalUri(env, ""));
|
|
16
|
+
if (componentType !== void 0) {
|
|
16
17
|
const global = globalStyleToAI(space.style, componentType);
|
|
17
18
|
return global ? envelope(global) : null;
|
|
18
19
|
}
|
|
19
|
-
if (uri ===
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
if (uri === idsUri(env)) return envelope(idStyleIds(space.style));
|
|
21
|
+
const targetId = afterPrefix(uri, idUri(env, ""));
|
|
22
|
+
if (targetId !== void 0) {
|
|
23
|
+
const idStyle = idStyleToAI(space.style, targetId);
|
|
24
|
+
return idStyle ? envelope(idStyle) : null;
|
|
25
|
+
}
|
|
26
|
+
if (uri === styleVarsUri(env)) return envelope(styleVariablesToAI(space.style));
|
|
27
|
+
const category = afterPrefix(uri, styleVarUri(env, ""));
|
|
28
|
+
if (category !== void 0) {
|
|
22
29
|
const byCategory = styleVariablesToAI(space.style);
|
|
23
30
|
return envelope(Object.hasOwn(byCategory, category) ? byCategory[category] : []);
|
|
24
31
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { emptySpaceMessage, unauthorizedSpaceMessage } from "./helpers/space.js";
|
|
2
2
|
import { serverInstructions } from "./helpers/guide.js";
|
|
3
|
+
import { createMcpLog } from "./helpers/log.js";
|
|
3
4
|
import { registerResources } from "./resources/register.js";
|
|
4
5
|
import { tools } from "./tools/index.js";
|
|
5
6
|
import { isCallToolResult } from "../ai/toolkit.js";
|
|
@@ -10,7 +11,8 @@ var asText = (data) => ({ content: [{
|
|
|
10
11
|
type: "text",
|
|
11
12
|
text: JSON.stringify(data)
|
|
12
13
|
}] });
|
|
13
|
-
var createMcpServer = ({ adapters, getSpaceId, preview, screenshot }) => {
|
|
14
|
+
var createMcpServer = ({ adapters, getSpaceId, preview, screenshot, logger }) => {
|
|
15
|
+
const log = createMcpLog(logger);
|
|
14
16
|
let spaceIdPromise;
|
|
15
17
|
const requireSpaceId = () => spaceIdPromise ??= getSpaceId().then((id) => {
|
|
16
18
|
if (!id) throw new Error(unauthorizedSpaceMessage);
|
|
@@ -18,11 +20,16 @@ var createMcpServer = ({ adapters, getSpaceId, preview, screenshot }) => {
|
|
|
18
20
|
});
|
|
19
21
|
const loadSpace = async () => {
|
|
20
22
|
const spaceId = await requireSpaceId();
|
|
21
|
-
const [schema, style] = await Promise.all([
|
|
23
|
+
const [schema, style, catalog] = await Promise.all([
|
|
24
|
+
adapters.getSchema?.(spaceId, MCP_ENV),
|
|
25
|
+
adapters.getStyle?.(spaceId, MCP_ENV),
|
|
26
|
+
adapters.getComponentCatalog?.(spaceId, MCP_ENV).catch(() => void 0)
|
|
27
|
+
]);
|
|
22
28
|
if (!schema || !style) throw new Error(emptySpaceMessage);
|
|
23
29
|
return {
|
|
24
30
|
schema,
|
|
25
|
-
style
|
|
31
|
+
style,
|
|
32
|
+
catalog
|
|
26
33
|
};
|
|
27
34
|
};
|
|
28
35
|
const { saveSchema, saveStyle } = adapters;
|
|
@@ -34,9 +41,9 @@ var createMcpServer = ({ adapters, getSpaceId, preview, screenshot }) => {
|
|
|
34
41
|
const getSpace = () => spacePromise ??= loadSpace();
|
|
35
42
|
const server = new McpServer({
|
|
36
43
|
name: "plitzi-mcp",
|
|
37
|
-
version: "0.
|
|
44
|
+
version: "0.32.6"
|
|
38
45
|
}, { instructions: serverInstructions });
|
|
39
|
-
registerResources(server, getSpace, MCP_ENV);
|
|
46
|
+
registerResources(server, getSpace, MCP_ENV, log);
|
|
40
47
|
const toolContext = async () => ({
|
|
41
48
|
space: await getSpace(),
|
|
42
49
|
env: MCP_ENV,
|
|
@@ -52,8 +59,15 @@ var createMcpServer = ({ adapters, getSpaceId, preview, screenshot }) => {
|
|
|
52
59
|
description: tool.description,
|
|
53
60
|
inputSchema: tool.inputShape
|
|
54
61
|
}, async (args) => {
|
|
55
|
-
const
|
|
56
|
-
|
|
62
|
+
const start = performance.now();
|
|
63
|
+
try {
|
|
64
|
+
const result = await tool.execute(args, await toolContext());
|
|
65
|
+
log.toolCall(tool.name, args, performance.now() - start);
|
|
66
|
+
return isCallToolResult(result) ? result : asText(result);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
log.toolCall(tool.name, args, performance.now() - start, error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
57
71
|
});
|
|
58
72
|
}
|
|
59
73
|
return server;
|