@plitzi/sdk-mcp 0.38.3 → 0.38.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +540 -0
  2. package/README.md +38 -12
  3. package/dist/createServer.d.ts +1 -1
  4. package/dist/createServer.js +1 -1
  5. package/dist/index.d.ts +3 -4
  6. package/dist/index.js +1 -4
  7. package/dist/modules/mcp/apps/render/styles.d.ts +4 -8
  8. package/dist/modules/mcp/apps/render/styles.js +16 -47
  9. package/dist/modules/mcp/apps/render/view/index.tsx +1 -1
  10. package/dist/modules/mcp/catalogs/index.js +2 -2
  11. package/dist/modules/mcp/catalogs/pluginCatalog.js +2 -2
  12. package/dist/modules/mcp/e2e/mcpEndpoint.d.ts +2 -1
  13. package/dist/modules/mcp/handler.d.ts +2 -2
  14. package/dist/modules/mcp/helpers/callToolResult.d.ts +2 -0
  15. package/dist/modules/mcp/helpers/callToolResult.js +4 -0
  16. package/dist/modules/mcp/helpers/guide.js +68 -14
  17. package/dist/modules/mcp/helpers/index.d.ts +1 -1
  18. package/dist/modules/mcp/helpers/space.d.ts +4 -1
  19. package/dist/modules/mcp/helpers/space.js +1 -0
  20. package/dist/modules/mcp/helpers/uris.d.ts +2 -0
  21. package/dist/modules/mcp/helpers/uris.js +3 -1
  22. package/dist/modules/mcp/index.d.ts +1 -1
  23. package/dist/modules/mcp/localScreenshotClient.d.ts +3 -0
  24. package/dist/modules/mcp/localScreenshotClient.js +2 -0
  25. package/dist/modules/mcp/resources/connectors.d.ts +1 -1
  26. package/dist/modules/mcp/resources/core.js +2 -2
  27. package/dist/modules/mcp/resources/data.d.ts +8 -0
  28. package/dist/modules/mcp/resources/data.js +46 -0
  29. package/dist/modules/mcp/resources/explain.js +1 -1
  30. package/dist/modules/mcp/resources/primer.js +3 -3
  31. package/dist/modules/mcp/resources/register.js +12 -2
  32. package/dist/modules/mcp/resources/renderGuide.js +6 -6
  33. package/dist/modules/mcp/resources/router.js +3 -1
  34. package/dist/modules/mcp/resources/schema.js +1 -1
  35. package/dist/modules/mcp/server.d.ts +3 -3
  36. package/dist/modules/mcp/server.js +12 -8
  37. package/dist/modules/mcp/tools/apply/dispatch.js +9 -1
  38. package/dist/modules/mcp/tools/apply/index.d.ts +12 -2
  39. package/dist/modules/mcp/tools/apply/index.js +27 -1
  40. package/dist/modules/mcp/tools/index.d.ts +2 -2
  41. package/dist/modules/mcp/tools/index.js +2 -2
  42. package/dist/modules/mcp/tools/operations/connectors/index.d.ts +2 -2
  43. package/dist/modules/mcp/tools/operations/connectors/manifest.d.ts +1 -1
  44. package/dist/modules/mcp/tools/operations/connectors/patchConnector.d.ts +1 -1
  45. package/dist/modules/mcp/tools/operations/connectors/upsertConnector.d.ts +1 -1
  46. package/dist/modules/mcp/tools/operations/data/data.test.d.ts +1 -0
  47. package/dist/modules/mcp/tools/operations/data/index.d.ts +32 -0
  48. package/dist/modules/mcp/tools/operations/data/index.js +54 -0
  49. package/dist/modules/mcp/tools/operations/index.d.ts +30 -4
  50. package/dist/modules/mcp/tools/operations/index.js +4 -1
  51. package/dist/modules/mcp/tools/operations/schema/elements/patchElement.d.ts +1 -0
  52. package/dist/modules/mcp/tools/operations/schema/elements/patchElement.js +5 -2
  53. package/dist/modules/mcp/tools/operations/schema/elements/upsertElement.js +1 -0
  54. package/dist/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.d.ts +1 -0
  55. package/dist/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.d.ts +1 -0
  56. package/dist/modules/mcp/tools/operations/schema/operations.d.ts +3 -0
  57. package/dist/modules/mcp/tools/operations/schema/shared.d.ts +5 -0
  58. package/dist/modules/mcp/tools/operations/schema/shared.js +13 -7
  59. package/dist/modules/mcp/tools/operations/schema/translator.js +1 -1
  60. package/dist/modules/mcp/tools/operations/schema/write.js +3 -2
  61. package/dist/modules/mcp/tools/operations/schemaIds.js +3 -3
  62. package/dist/modules/mcp/tools/operations/style/write.js +1 -1
  63. package/dist/modules/mcp/tools/preview.d.ts +3 -0
  64. package/dist/modules/mcp/tools/render.d.ts +3 -0
  65. package/dist/modules/mcp/tools/screenshot.d.ts +12 -2
  66. package/dist/modules/mcp/tools/shared/newSuggestions.d.ts +2 -2
  67. package/dist/modules/mcp/tools/shared/newSuggestions.js +10 -5
  68. package/dist/modules/mcp/tools/shared/newSuggestions.test.d.ts +1 -0
  69. package/dist/modules/mcp/tools/shared/tool.d.ts +7 -6
  70. package/dist/modules/mcp/tools/shared/validator/index.js +2 -2
  71. package/dist/modules/mcp/tools/tryFunction.js +1 -1
  72. package/dist/modules/mcp/tools/validate.d.ts +12 -2
  73. package/dist/modules/mcp/types/appTypes.d.ts +2 -2
  74. package/dist/modules/mcp/types/toolTypes.d.ts +5 -1
  75. package/package.json +7 -9
  76. package/dist/modules/ai/AIEngine.d.ts +0 -20
  77. package/dist/modules/ai/AIEngine.js +0 -120
  78. package/dist/modules/ai/index.d.ts +0 -4
  79. package/dist/modules/ai/toolkit.d.ts +0 -17
  80. package/dist/modules/ai/toolkit.js +0 -59
  81. package/dist/modules/mcp/helpers/agentPrompt.d.ts +0 -4
  82. package/dist/modules/mcp/helpers/agentPrompt.js +0 -123
  83. /package/dist/modules/{ai/toolkit.test.d.ts → mcp/helpers/callToolResult.test.d.ts} +0 -0
@@ -14,7 +14,7 @@ var tryFunctionShape = {
14
14
  var tryFunction = async (input, ctx) => {
15
15
  if (input.dryRun) return {
16
16
  ran: false,
17
- reason: "Trying a function runs its code for real — its fetches and its writes — so not in plan mode"
17
+ reason: "Trying a function runs its code for real — its fetches and its writes — so a dry run does not run it"
18
18
  };
19
19
  if (!ctx.tryFunction) return {
20
20
  ran: false,
@@ -54,6 +54,7 @@ export declare const validateShape: {
54
54
  flag: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
55
55
  anchor: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
56
56
  motion: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>>;
57
+ quiet: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodArray<import('zod').ZodString>>>;
57
58
  }, import('zod/v4/core').$strip>, import('zod').ZodObject<{
58
59
  type: import('zod').ZodLiteral<"deleteElement">;
59
60
  pageRef: import('zod').ZodString;
@@ -208,6 +209,7 @@ export declare const validateShape: {
208
209
  skip: "skip";
209
210
  parallel: "parallel";
210
211
  queue: "queue";
212
+ latest: "latest";
211
213
  }>>;
212
214
  elementId: import('zod').ZodOptional<import('zod').ZodString>;
213
215
  preview: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
@@ -226,6 +228,7 @@ export declare const validateShape: {
226
228
  skip: "skip";
227
229
  parallel: "parallel";
228
230
  queue: "queue";
231
+ latest: "latest";
229
232
  }>>;
230
233
  elementId: import('zod').ZodOptional<import('zod').ZodString>;
231
234
  preview: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
@@ -814,11 +817,11 @@ export declare const validateShape: {
814
817
  file: "file";
815
818
  text: "text";
816
819
  color: "color";
820
+ image: "image";
817
821
  switch: "switch";
818
822
  email: "email";
819
823
  date: "date";
820
824
  richText: "richText";
821
- image: "image";
822
825
  multiImage: "multiImage";
823
826
  video: "video";
824
827
  link: "link";
@@ -902,11 +905,11 @@ export declare const validateShape: {
902
905
  file: "file";
903
906
  text: "text";
904
907
  color: "color";
908
+ image: "image";
905
909
  switch: "switch";
906
910
  email: "email";
907
911
  date: "date";
908
912
  richText: "richText";
909
- image: "image";
910
913
  multiImage: "multiImage";
911
914
  video: "video";
912
915
  link: "link";
@@ -1053,6 +1056,13 @@ export declare const validateShape: {
1053
1056
  }, import('zod/v4/core').$strip>, import('zod').ZodObject<{
1054
1057
  type: import('zod').ZodLiteral<"deleteFunctionFile">;
1055
1058
  path: import('zod').ZodString;
1059
+ }, import('zod/v4/core').$strip>, import('zod').ZodObject<{
1060
+ type: import('zod').ZodLiteral<"upsertDataFile">;
1061
+ path: import('zod').ZodString;
1062
+ content: import('zod').ZodString;
1063
+ }, import('zod/v4/core').$strip>, import('zod').ZodObject<{
1064
+ type: import('zod').ZodLiteral<"deleteDataFile">;
1065
+ path: import('zod').ZodString;
1056
1066
  }, import('zod/v4/core').$strip>], "type">>;
1057
1067
  };
1058
1068
  export declare const validate: (input: ValidateInput, space: Space) => ValidationResult;
@@ -16,9 +16,9 @@ export interface McpApp {
16
16
  * that serves both settings still builds the (expensive) browser bundle once. The view reads them off
17
17
  * `window.__PLITZI_VIEW__`, and must treat every one as optional: an older page carries none. */
18
18
  export interface McpViewSettings {
19
- /** May the view paint from tool arguments the host is still streaming? See `mcpAi.renderStreaming`. */
19
+ /** May the view paint from tool arguments the host is still streaming? See `McpOptions.renderStreaming`. */
20
20
  streaming: boolean;
21
- /** Absolute resource endpoint of the server that served the page, when it serves one (see `mcpAi.proxy`). It
21
+ /** Absolute resource endpoint of the server that served the page, when it serves one (see `McpOptions.proxy`). It
22
22
  * shapes the PAGE rather than the view: its origin is what the resource CSP declares, so the URLs a render
23
23
  * rewrote to it are allowed to load. The view needs nothing from it — every URL is rewritten server-side,
24
24
  * where the signing secret is. */
@@ -1,6 +1,6 @@
1
1
  import { AIDefinition, AIElementDetail, ValidationError } from './aiSchema';
2
2
  import { Operation } from '../tools/operations';
3
- import { ActionEntry, ConnectorEntry, FunctionsSaveResult, Schema, Style } from '@plitzi/sdk-shared';
3
+ import { ActionEntry, ConnectorEntry, DataSaveResult, FunctionsSaveResult, Schema, Style } from '@plitzi/sdk-shared';
4
4
  /** The element schema, the style schema and the connectors persist independently (Space model / Style model / one
5
5
  * row per connector), so each has its own optional persister. When one is absent, that store is applied in memory
6
6
  * but reported unsaved. Connectors save and delete a row at a time — a batch touching two of them saves those two
@@ -14,6 +14,8 @@ export interface Persisters {
14
14
  deleteAction?: (actionId: string) => Promise<void>;
15
15
  /** Saves the functions' files whole, against the version the batch read; answers what is wrong where it is. */
16
16
  saveFunctions?: (files: Record<string, string>, base: string) => Promise<FunctionsSaveResult>;
17
+ /** Saves the data's files whole, against the version the batch read; answers what is wrong by file. */
18
+ saveData?: (files: Record<string, string>, base: string) => Promise<DataSaveResult>;
17
19
  }
18
20
  export interface Conflict {
19
21
  resourceUri: string;
@@ -72,6 +74,8 @@ export interface MutationOutcome {
72
74
  deletedActions: string[];
73
75
  /** The functions' files changed: they are saved whole, as one store. */
74
76
  changedFunctions: boolean;
77
+ /** The data's files changed: saved whole too, as a store of their own. */
78
+ changedData: boolean;
75
79
  }
76
80
  export interface ApplyInput {
77
81
  environment?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plitzi/sdk-mcp",
3
- "version": "0.38.3",
3
+ "version": "0.38.5",
4
4
  "license": "AGPL-3.0",
5
5
  "files": [
6
6
  "dist",
@@ -30,14 +30,12 @@
30
30
  "dependencies": {
31
31
  "@modelcontextprotocol/ext-apps": "^1.7.5",
32
32
  "@modelcontextprotocol/sdk": "^1.32.0",
33
- "@plitzi/plitzi-sdk": "0.38.3",
34
- "@plitzi/sdk-authoring": "0.38.3",
35
- "@plitzi/sdk-elements": "0.38.3",
36
- "@plitzi/sdk-interactions": "0.38.3",
37
- "@plitzi/sdk-schema": "0.38.3",
38
- "@plitzi/sdk-server": "0.38.3",
39
- "@plitzi/sdk-shared": "0.38.3",
40
- "@plitzi/sdk-style": "0.38.3",
33
+ "@plitzi/plitzi-sdk": "0.38.5",
34
+ "@plitzi/sdk-authoring": "0.38.5",
35
+ "@plitzi/sdk-schema": "0.38.5",
36
+ "@plitzi/sdk-server": "0.38.5",
37
+ "@plitzi/sdk-shared": "0.38.5",
38
+ "@plitzi/sdk-style": "0.38.5",
41
39
  "ejs": "^6.0.1",
42
40
  "esbuild": "^0.28.2",
43
41
  "zod": "^4.6.5"
@@ -1,20 +0,0 @@
1
- import { AiMode, AiContext, McpPromptHandler, McpToolHandler, McpToolLifecycleHooks, StreamCallbacks, McpTool, McpToolHandlerResult } from '@plitzi/sdk-shared';
2
- declare class AIEngine implements McpToolLifecycleHooks {
3
- private readonly mode;
4
- readonly callbacks: StreamCallbacks;
5
- private toolsAvailables;
6
- private toolsAvailablesMap;
7
- ctx: AiContext;
8
- constructor(mode: AiMode | undefined, callbacks: StreamCallbacks, ctx: Omit<AiContext, 'mode'>);
9
- readonly readResource: (name: string, uri: string) => void;
10
- readonly setToolsAvailables: (tools: McpTool[]) => void;
11
- readonly can: (name: string) => boolean;
12
- readonly before: (name: string, args: Record<string, unknown>) => Promise<boolean>;
13
- readonly after: (name: string, args: Record<string, unknown>, result: McpToolHandlerResult) => Promise<void>;
14
- private readonly validateToolInput;
15
- private readonly validateToolOutput;
16
- private readonly runPipeline;
17
- readonly execute: (name: string, handlerFn?: McpToolHandler) => (args: Record<string, unknown>) => Promise<McpToolHandlerResult>;
18
- readonly executePrompt: (_name: string, handlerFn: McpPromptHandler) => (args: Record<string, unknown>) => Promise<import('@plitzi/sdk-shared').McpPromptHandlerResult>;
19
- }
20
- export default AIEngine;
@@ -1,120 +0,0 @@
1
- import { firstText, toolResponseErr } from "./toolkit.js";
2
- //#region src/modules/ai/AIEngine.ts
3
- var AIEngine = class {
4
- mode;
5
- callbacks;
6
- toolsAvailables = /* @__PURE__ */ new Map();
7
- toolsAvailablesMap = /* @__PURE__ */ new Map();
8
- ctx;
9
- constructor(mode, callbacks, ctx) {
10
- this.mode = mode;
11
- this.callbacks = callbacks;
12
- this.ctx = {
13
- ...ctx,
14
- mode: mode || "plan"
15
- };
16
- }
17
- readResource = (name, uri) => {
18
- this.callbacks.onResourceRead?.(name, uri);
19
- };
20
- setToolsAvailables = (tools) => {
21
- this.toolsAvailables = new Map(tools.map((t) => [t.name, t]));
22
- this.toolsAvailablesMap = new Map(tools.map((t) => [t.name, t.definition.allowedModes]));
23
- };
24
- can = (name) => {
25
- if (!this.mode || !this.toolsAvailablesMap.has(name)) return false;
26
- const allowedModes = this.toolsAvailablesMap.get(name);
27
- return !allowedModes || allowedModes.includes(this.mode);
28
- };
29
- before = async (name, args) => {
30
- this.callbacks.onBeforeTool?.(name, args);
31
- if (!this.toolsAvailables.has(name)) {
32
- this.callbacks.onLog?.("error", `tool rejected: '${name}' has no definition — possible security violation`);
33
- await this.after(name, args, toolResponseErr(`Tool '${name}' is not defined and cannot be executed`));
34
- return false;
35
- }
36
- if (!this.can(name)) {
37
- this.callbacks.onLog?.("info", `tool blocked: '${name}' is not permitted in ${this.mode} mode`);
38
- await this.after(name, args, toolResponseErr(`Tool '${name}' is not permitted in ${this.mode} mode`));
39
- return false;
40
- }
41
- return true;
42
- };
43
- after = (name, args, result) => {
44
- let resultParsed;
45
- if (result.data !== void 0) resultParsed = result.data;
46
- else try {
47
- resultParsed = JSON.parse(firstText(result.content) ?? "");
48
- } catch {}
49
- if (result.isError) this.callbacks.onToolError?.({
50
- name,
51
- args,
52
- result: resultParsed ?? { error: firstText(result.content) ?? "Tool failed" }
53
- });
54
- else this.callbacks.onToolSuccess?.({
55
- name,
56
- args,
57
- result: resultParsed
58
- });
59
- return Promise.resolve();
60
- };
61
- validateToolInput = (name, args) => {
62
- const tool = this.toolsAvailables.get(name);
63
- if (!tool || !tool.mcpDefinition.inputSchema) return {
64
- success: true,
65
- data: args
66
- };
67
- const parsed = tool.mcpDefinition.inputSchema.safeParse(args);
68
- if (!parsed.success) return {
69
- success: false,
70
- error: parsed.error.message
71
- };
72
- return {
73
- success: true,
74
- data: parsed.data
75
- };
76
- };
77
- validateToolOutput = (name, result) => {
78
- const tool = this.toolsAvailables.get(name);
79
- if (!tool || !tool.mcpDefinition.outputSchema || result.isError) return;
80
- if (result.data === void 0) return;
81
- const parsed = tool.mcpDefinition.outputSchema.safeParse(result.data);
82
- if (!parsed.success) return parsed.error.message;
83
- };
84
- runPipeline = async (name, args, handler) => {
85
- const parsedArgs = this.validateToolInput(name, args);
86
- if (!parsedArgs.success) {
87
- this.callbacks.onLog?.("error", `tool validation error: ${name} error=${parsedArgs.error}`);
88
- const err = toolResponseErr(parsedArgs.error);
89
- await this.after(name, args, err);
90
- return err;
91
- }
92
- const t0 = Date.now();
93
- const result = await handler(parsedArgs.data, this.ctx);
94
- this.callbacks.onLog?.("debug", `tool done: ${name} ms=${Date.now() - t0} result=${JSON.stringify(result).slice(0, 200)}`);
95
- const outputError = this.validateToolOutput(name, result);
96
- if (outputError) this.callbacks.onLog?.("info", `tool output schema drift: ${name} — ${outputError}`);
97
- const tool = this.toolsAvailables.get(name);
98
- if (!result.isError && tool?.mcpDefinition.outputSchema && result.data !== void 0 && result.data !== null) result.structuredContent = typeof result.data === "object" && !Array.isArray(result.data) ? result.data : { data: result.data };
99
- if (result.isError) this.callbacks.onLog?.("error", `tool failed: ${name} error=${firstText(result.content) ?? "unknown"}`);
100
- await this.after(name, args, result);
101
- return result;
102
- };
103
- execute = (name, handlerFn) => async (args) => {
104
- if (!await this.before(name, args)) return toolResponseErr(`Tool '${name}' execution was blocked`);
105
- const handler = handlerFn ?? this.toolsAvailables.get(name)?.handler;
106
- if (!handler) {
107
- this.callbacks.onLog?.("error", `no handler registered for tool: ${name}`);
108
- const err = toolResponseErr(`Tool '${name}' has no handler`);
109
- await this.after(name, args, err);
110
- return err;
111
- }
112
- this.callbacks.onLog?.("debug", `tool exec: ${name} args=${JSON.stringify(args).slice(0, 200)}`);
113
- return this.runPipeline(name, args, handler);
114
- };
115
- executePrompt = (_name, handlerFn) => async (args) => {
116
- return handlerFn(args, this.ctx);
117
- };
118
- };
119
- //#endregion
120
- export { AIEngine as default };
@@ -1,4 +0,0 @@
1
- import { default as AIEngine } from './AIEngine';
2
- export * from './AIEngine';
3
- export { zodToJsonSchema, getAllowedModes, toolResponseOk, toolResponseErr, bindTools, isToolActive, resolveToolHandler, isCallToolResult, toolResponseFromResult } from './toolkit';
4
- export { AIEngine };
@@ -1,17 +0,0 @@
1
- import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
- import { AiMode, McpContent, McpTool, McpToolHandler, McpToolHandlerResult, ToolOperationType } from '@plitzi/sdk-shared';
3
- /** Convert a Zod schema to the JSON Schema an AI provider (Anthropic / OpenAI) expects in a tool definition.
4
- * Delegates to Zod v4's built-in converter — one implementation, so descriptions, literal discriminators,
5
- * enums, nested objects and recursive (z.lazy) shapes all survive and the provider sees the same contract an
6
- * MCP client does. `io: 'input'` describes what the agent must SEND; `unrepresentable: 'any'` degrades an
7
- * exotic type to an empty schema instead of throwing, so one unusual tool never breaks the whole tool list. */
8
- export declare const zodToJsonSchema: (schema: unknown) => Record<string, unknown>;
9
- export declare const firstText: (content: McpContent[]) => string | undefined;
10
- export declare const getAllowedModes: (operationType: ToolOperationType) => AiMode[];
11
- export declare const toolResponseOk: (data: unknown, agentMessage?: string) => McpToolHandlerResult;
12
- export declare const toolResponseErr: (error: Error | string) => McpToolHandlerResult;
13
- export declare const isCallToolResult: (result: unknown) => result is CallToolResult;
14
- export declare const toolResponseFromResult: (result: CallToolResult) => McpToolHandlerResult;
15
- export declare const isToolActive: (tool: McpTool) => boolean;
16
- export declare const resolveToolHandler: (tool: McpTool) => McpToolHandler | undefined;
17
- export declare const bindTools: (tools: McpTool[]) => McpTool[];
@@ -1,59 +0,0 @@
1
- import { z } from "zod";
2
- //#region src/modules/ai/toolkit.ts
3
- /** Convert a Zod schema to the JSON Schema an AI provider (Anthropic / OpenAI) expects in a tool definition.
4
- * Delegates to Zod v4's built-in converter — one implementation, so descriptions, literal discriminators,
5
- * enums, nested objects and recursive (z.lazy) shapes all survive and the provider sees the same contract an
6
- * MCP client does. `io: 'input'` describes what the agent must SEND; `unrepresentable: 'any'` degrades an
7
- * exotic type to an empty schema instead of throwing, so one unusual tool never breaks the whole tool list. */
8
- var zodToJsonSchema = (schema) => {
9
- const json = z.toJSONSchema(schema, {
10
- target: "draft-7",
11
- io: "input",
12
- unrepresentable: "any"
13
- });
14
- delete json.$schema;
15
- return json;
16
- };
17
- var firstText = (content) => content.find((block) => block.type === "text")?.text;
18
- var getAllowedModes = (operationType) => {
19
- return operationType === "write" ? ["build"] : ["plan", "build"];
20
- };
21
- var toolResponseOk = (data, agentMessage) => {
22
- return {
23
- content: [{
24
- type: "text",
25
- text: agentMessage ?? JSON.stringify(data ?? null, null, 2)
26
- }],
27
- data
28
- };
29
- };
30
- var toolResponseErr = (error) => ({
31
- content: [{
32
- type: "text",
33
- text: error instanceof Error ? error.message : error
34
- }],
35
- isError: true
36
- });
37
- var isCallToolResult = (result) => typeof result === "object" && result !== null && Array.isArray(result.content);
38
- var toolResponseFromResult = (result) => {
39
- const content = [];
40
- for (const block of result.content) if (block.type === "text") content.push({
41
- type: "text",
42
- text: block.text
43
- });
44
- else if (block.type === "image") content.push({
45
- type: "image",
46
- data: block.data,
47
- mimeType: block.mimeType
48
- });
49
- return {
50
- content,
51
- data: result.structuredContent,
52
- isError: result.isError ? true : void 0
53
- };
54
- };
55
- var isToolActive = (tool) => Boolean(tool.handler);
56
- var resolveToolHandler = (tool) => tool.handler;
57
- var bindTools = (tools) => tools.filter(isToolActive);
58
- //#endregion
59
- export { bindTools, firstText, getAllowedModes, isCallToolResult, isToolActive, resolveToolHandler, toolResponseErr, toolResponseFromResult, toolResponseOk, zodToJsonSchema };
@@ -1,4 +0,0 @@
1
- /** The MCP-owned guidance block a consumer concatenates into its system prompt. Covers what the MCP is
2
- * authoritative about: its editing model, tools, resources and interaction vocabulary. It intentionally does NOT
3
- * cover a consumer’s own tools (previews, design helpers) or product framing (modes, identity, security). */
4
- export declare const buildAgentGuide: () => string;
@@ -1,123 +0,0 @@
1
- import { BUILTIN_ELEMENT_CALLBACKS, BUILTIN_GLOBAL_CALLBACKS, BUILTIN_UTILITIES } from "../catalogs/index.js";
2
- //#region src/modules/mcp/helpers/agentPrompt.ts
3
- var EDITING_MODEL = [
4
- "━━ PLITZI MCP — EDITING MODEL ━━",
5
- "A Plitzi space is TWO schemas you edit together in one atomic plitzi_apply batch:",
6
- "• Element schema — the tree of pages/elements (type, label, props, and which style classes each uses).",
7
- "• Style schema — reusable definitions (CSS classes), design tokens (variables), theme.",
8
- "To style an element: write a definition AND attach it via the element’s style.base in the same batch.",
9
- "style.base is a LIST — an element can attach several classes (plus non-base slots); ALL of them apply together",
10
- "(they cascade), so when a style looks wrong inspect EVERY attached class + its global/id styles, not just one.",
11
- "Every element and page has ONE name, which IS its id: you choose it ([A-Za-z0-9_-] starting with a letter,",
12
- "unique in the space), you address it by it, and the runtime wires by it (a provider source is",
13
- "`<type>_<id>.<field>` — a dot is not allowed in a name, an underscore is). Nothing hands out opaque ids, so",
14
- "never invent one: name the thing. CSS is kebab-case; style vars are var(--name), schema",
15
- "vars are {{name}}. Use patchElement/patchDefinition to change SOME props/CSS; the upsert variants replace them all.",
16
- "Reads are cheap by design — list to navigate, read one item for detail; never fetch a whole tree you do not need."
17
- ].join("\n");
18
- var TOOLS = [
19
- "━━ MCP TOOLS ━━",
20
- "• plitzi_search — find elements by label/type/attribute; a hit carries the NAME every op takes (include:\"detail\"",
21
- " also returns its style + versions).",
22
- "• plitzi_read — batch-read one or more resource URIs you already hold (from search or a write response).",
23
- "• plitzi_validate — check a batch of operations without executing; returns teachable errors and warnings, and",
24
- " suggestions: a shorter way to the same page (a layout, a component, the content of a link) — never blocking.",
25
- "• plitzi_apply — persist a batch of operations. Pass dryRun to preview the full diff without writing, and",
26
- " expectedResourceVersions to guard against concurrent edits (apply and search hand back the versions you need).",
27
- "• plitzi_preview / plitzi_screenshot — render a page (HTML / PNG), with unsaved operations applied if you pass them.",
28
- " plitzi_screenshot view:\"accessibility\" reads it as a screen reader or a browser agent does, listing what has no name.",
29
- "• plitzi_render — show the user an offline widget; it never touches the space (read plitzi://render/guide).",
30
- "Discover → browse resources. Find a name → plitzi_search. Fetch known URIs → plitzi_read. Do not confuse them."
31
- ].join("\n");
32
- var RESOURCES = [
33
- "━━ MCP RESOURCES (read) ━━",
34
- "Read plitzi://primer/{env} FIRST — a cold-start bundle: the guide’s quickstart + types + css-properties +",
35
- "page/definition/variable summaries in one call. Then, on demand:",
36
- "• plitzi://guide — full usage reference.",
37
- "• plitzi://types — element types observed in this space (props, slots, subTypes, label/description/category).",
38
- "• plitzi://css-properties — valid kebab-case CSS property keys.",
39
- "• plitzi://schema/{env}/pages , /{ref} — page summaries, then one page as a skeleton tree.",
40
- "• plitzi://schema/{env}/layouts — shared layout shells (header/sidebar/footer) and the pages inside each.",
41
- "• plitzi://folders/{env} — page folders (the sidebar tree).",
42
- "• plitzi://definitions/{env} , plitzi://style-variables/{env} , plitzi://fonts/{env} — style classes, design",
43
- " tokens and the font families the space loads.",
44
- "• plitzi://interactions/{env} — interaction actions + built-in globalCallbacks with their source + param schema.",
45
- "• plitzi://data-sources/{env} — data-source paths and binding targets (vocabulary for upsertBinding).",
46
- "• plitzi://connectors/{env} , plitzi://connector-presets — CMS/API connectors (this space’s, and working ones).",
47
- "• plitzi://actions/{env} , /tasks — server actions, and the tasks this deployment can build them from.",
48
- "• plitzi://changes/{env} , /{id} — the change history (read-only): who changed what, before and after.",
49
- "• plitzi://settings/{env} — space-level settings."
50
- ].join("\n");
51
- var ACCESSIBILITY = [
52
- "━━ ACCESSIBILITY ━━",
53
- "Screen readers and browser agents (Claude in Chrome) work a page through its accessibility tree, so build every page",
54
- "to be usable without sight: a button or link has words (an icon-only button a `title`; a link wrapping a card a",
55
- "`label`), a field a `label` (`hideLabel: true` keeps it out of sight), an image an `alt` or `decorative: true`.",
56
- "Clicks go on a button (it holds children) or a link — never on a container, text or image. Toggles bind",
57
- "`ariaPressed`, openers `ariaExpanded`. Headings step down one level at a time. The linter warns on each of these."
58
- ].join("\n");
59
- var NAVIGATION = [
60
- "━━ NAVIGATION & DYNAMIC PAGES ━━",
61
- "To move between pages, PREFER the Link element over an interaction — its words are its `content`, and it can wrap",
62
- "any children too. The link to the page being shown is styled by its class's `current` state. mode \"page\" links",
63
- "to another space page (href = the target page); mode \"internal\" takes a path inside the space and resolves",
64
- "{{token}} templates in it (e.g. posts/{{postId}}); mode \"external\" is a full URL. Reach for the navigate",
65
- "globalCallback only when navigation must be one step inside a larger flow.",
66
- "A page slug is RELATIVE — never start it with \"/\" (the runtime prepends it). Folder slugs PREPEND to the page",
67
- "slug, so a page at slug \"post\" inside folders \"blog\" > \"2024\" resolves to /blog/2024/post.",
68
- "A slug segment \":name\" (e.g. \"posts/:postId\") declares a ROUTE PARAM, react-router style. It is readable on that",
69
- "page as {{name}} in props AND as the binding source navigation.routeParams.name — so a dynamic detail page is a",
70
- "\"posts/:postId\" page whose apiContainer query binds navigation.routeParams.postId."
71
- ].join("\n");
72
- var paramList = (params) => {
73
- const names = Object.keys(params);
74
- return names.length > 0 ? names.join(", ") : "(no params)";
75
- };
76
- var globalCallbackLines = () => Object.entries(BUILTIN_GLOBAL_CALLBACKS).map(([action, { source, params }]) => ` • ${action} → source "${source}"; params: ${paramList(params)}`);
77
- var elementCallbackLines = () => Object.entries(BUILTIN_ELEMENT_CALLBACKS).map(([action, { params }]) => ` • ${action}; params: ${paramList(params)}`);
78
- var utilityLines = () => Object.entries(BUILTIN_UTILITIES).map(([action, { params }]) => ` • ${action}; params: ${paramList(params)}`);
79
- var INTERACTIONS = () => [
80
- "━━ INTERACTIONS ━━",
81
- "A flow is a trigger (onClick, onPageLoad…) followed by ordered callbacks/utilities; each step has an enabled",
82
- "flag. Write one with upsertInteractionFlow (first node MUST be a trigger); change one step with",
83
- "patchInteractionNode; remove a step (nodeId) or a whole flow (flowId) with deleteInteraction.",
84
- "Disable ≠ delete: to turn a step off without removing it use patchInteractionNode { enabled: false }.",
85
- "deleteInteraction is destructive — confirm with the user first.",
86
- "Pick the RIGHT node type for an action: the wrong type resolves against nothing and the step silently no-ops.",
87
- "Any param VALUE can be a data-binding token {{ source }} — e.g. addNotification content",
88
- "\"{{ list_<name>.item.name }}\" shows the clicked row’s field; it resolves at runtime just like a prop binding.",
89
- "",
90
- "globalCallback (nodeType \"globalCallback\") — provided by a SOURCE MODULE, not the host element: OMIT elementId",
91
- "and the MCP pins the right source and fills the builder’s param defaults. Use ONLY each callback’s declared",
92
- "params (exact spelling) — for addNotification the text goes in `content` (NO title/message/type). Built-ins:",
93
- ...globalCallbackLines(),
94
- "",
95
- "callback (nodeType \"callback\") — a callback ON an element; elementId is that element (host by default). Every",
96
- "element has a built-in `setState` that changes ITS OWN attribute/state (category/key/value/revertOnFinish). Set",
97
- "revertOnFinish:true for a TEMPORARY change (e.g. a \"loading…\" label) so it auto-reverts at flow end — do NOT add",
98
- "manual restore steps. This element setState has NO `type` param (that is the global state setState). Built-ins:",
99
- ...elementCallbackLines(),
100
- "",
101
- "utility (nodeType \"utility\") — no element/source. Use the EXACT param names (delayTime waits `time` ms, not",
102
- "`delay`). Built-ins:",
103
- ...utilityLines(),
104
- "The full param schema (types, options, defaults) for each is in plitzi://interactions/{env}."
105
- ].join("\n");
106
- /** The MCP-owned guidance block a consumer concatenates into its system prompt. Covers what the MCP is
107
- * authoritative about: its editing model, tools, resources and interaction vocabulary. It intentionally does NOT
108
- * cover a consumer’s own tools (previews, design helpers) or product framing (modes, identity, security). */
109
- var buildAgentGuide = () => [
110
- EDITING_MODEL,
111
- "",
112
- TOOLS,
113
- "",
114
- RESOURCES,
115
- "",
116
- ACCESSIBILITY,
117
- "",
118
- NAVIGATION,
119
- "",
120
- INTERACTIONS()
121
- ].join("\n");
122
- //#endregion
123
- export { buildAgentGuide };