@happyvertical/smrt-core 0.51.36 → 0.51.38
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/agents/build-knowledge.md +25 -0
- package/agents/generators.md +27 -0
- package/dist/consumer-plugin/artifact-publication.d.ts +2 -0
- package/dist/consumer-plugin/artifact-publication.d.ts.map +1 -1
- package/dist/consumer-plugin/artifact-publication.js +15 -1
- package/dist/consumer-plugin/artifact-publication.js.map +1 -1
- package/dist/consumer-plugin/index.d.ts.map +1 -1
- package/dist/consumer-plugin/index.js +3 -3
- package/dist/consumer-plugin/index.js.map +1 -1
- package/dist/generators/mcp-runtime-template.d.ts +17 -0
- package/dist/generators/mcp-runtime-template.d.ts.map +1 -1
- package/dist/generators/mcp-runtime-template.js +27 -19
- package/dist/generators/mcp-runtime-template.js.map +1 -1
- package/dist/generators/mcp-tool-name.d.ts +17 -0
- package/dist/generators/mcp-tool-name.d.ts.map +1 -0
- package/dist/generators/mcp-tool-name.js +33 -0
- package/dist/generators/mcp-tool-name.js.map +1 -0
- package/dist/generators/mcp.d.ts +46 -1
- package/dist/generators/mcp.d.ts.map +1 -1
- package/dist/generators/mcp.js +105 -53
- package/dist/generators/mcp.js.map +1 -1
- package/dist/generators/tool-schema.d.ts +6 -0
- package/dist/generators/tool-schema.d.ts.map +1 -1
- package/dist/generators/tool-schema.js +8 -3
- package/dist/generators/tool-schema.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/knowledge.d.ts +2 -0
- package/dist/knowledge.d.ts.map +1 -1
- package/dist/knowledge.js +3 -1
- package/dist/knowledge.js.map +1 -1
- package/dist/manifest/discover-base-classes.js +2 -2
- package/dist/manifest/discover-base-classes.js.map +1 -1
- package/dist/manifest/discover-smrt-packages.d.ts.map +1 -1
- package/dist/manifest/discover-smrt-packages.js +3 -2
- package/dist/manifest/discover-smrt-packages.js.map +1 -1
- package/dist/manifest/generator.d.ts +7 -0
- package/dist/manifest/generator.d.ts.map +1 -1
- package/dist/manifest/generator.js +30 -15
- package/dist/manifest/generator.js.map +1 -1
- package/dist/manifest/manager.d.ts.map +1 -1
- package/dist/manifest/manager.js +6 -2
- package/dist/manifest/manager.js.map +1 -1
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/node_modules/.pnpm/{brace-expansion@5.0.9 → brace-expansion@5.0.11}/node_modules/brace-expansion/dist/esm/index.js +32 -19
- package/dist/node_modules/.pnpm/brace-expansion@5.0.11/node_modules/brace-expansion/dist/esm/index.js.map +1 -0
- package/dist/node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/dist/esm/index.js +1 -1
- package/dist/scanner/types.d.ts +2 -0
- package/dist/scanner/types.d.ts.map +1 -1
- package/dist/scanner/types.js.map +1 -1
- package/dist/scripts/generate-manifest.js +44 -44
- package/dist/scripts/generate-test-manifest.js +49 -2
- package/dist/smrt-knowledge.json +7 -7
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +16 -6
- package/dist/vite-plugin/index.js.map +1 -1
- package/package.json +4 -4
- package/dist/node_modules/.pnpm/brace-expansion@5.0.9/node_modules/brace-expansion/dist/esm/index.js.map +0 -1
package/dist/generators/mcp.js
CHANGED
|
@@ -5,8 +5,9 @@ import { ObjectRegistry } from "../registry.js";
|
|
|
5
5
|
import { SmrtCollection } from "../collection.js";
|
|
6
6
|
import { generatedSiblingExtension, renderGeneratedSource, resolveGeneratedSourceLanguage } from "./mcp-emit.js";
|
|
7
7
|
import { generateClaudeConfig, generateMCPDocumentation, generateMCPScript, generateRuntimeBootstrap } from "./mcp-runtime-template.js";
|
|
8
|
+
import { canonicalMcpToolNames } from "./mcp-tool-name.js";
|
|
8
9
|
import { runWithTenantGate } from "./tenant-gate.js";
|
|
9
|
-
import { buildToolInputSchema, fieldTypeToJsonSchema, finalizeMcpJsonSchema, isCrudAction } from "./tool-schema.js";
|
|
10
|
+
import { assertMcpJsonSchemaSafety, buildToolInputSchema, fieldTypeToJsonSchema, finalizeMcpJsonSchema, isCrudAction, resolveToolSemantics } from "./tool-schema.js";
|
|
10
11
|
import { dirname, resolve } from "node:path";
|
|
11
12
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
12
13
|
//#region src/generators/mcp.ts
|
|
@@ -45,6 +46,20 @@ function resolveMCPToolListCacheHint(options, hasTenantScopedTools) {
|
|
|
45
46
|
cacheScope: !hasTenantScopedTools && options?.cacheScope === "public" && options.publicCatalog === true ? "public" : "private"
|
|
46
47
|
};
|
|
47
48
|
}
|
|
49
|
+
/** Map a canonical effect classification into inert MCP capability hints. */
|
|
50
|
+
function mcpToolAnnotations(action, customAction) {
|
|
51
|
+
const semantics = resolveToolSemantics(action, customAction);
|
|
52
|
+
return mcpToolAnnotationsFor(semantics.effect, semantics.idempotent, semantics.openWorld);
|
|
53
|
+
}
|
|
54
|
+
/** Map an explicitly declared canonical classification into inert MCP hints. */
|
|
55
|
+
function mcpToolAnnotationsFor(effect, idempotent, openWorld) {
|
|
56
|
+
return {
|
|
57
|
+
readOnlyHint: effect === "read",
|
|
58
|
+
destructiveHint: effect === "destructive",
|
|
59
|
+
idempotentHint: idempotent,
|
|
60
|
+
openWorldHint: openWorld
|
|
61
|
+
};
|
|
62
|
+
}
|
|
48
63
|
/** Return a copied, canonical tool sequence for byte-stable tools/list output. */
|
|
49
64
|
function sortMCPTools(tools) {
|
|
50
65
|
return [...tools].sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
|
|
@@ -104,6 +119,24 @@ function buildTaskActionInvocationArgs(metadata, args) {
|
|
|
104
119
|
* Generate MCP server from smrt objects
|
|
105
120
|
*/
|
|
106
121
|
var MCPGenerator = class {
|
|
122
|
+
toolTargets = /* @__PURE__ */ new WeakMap();
|
|
123
|
+
toolTarget(tool) {
|
|
124
|
+
const target = this.toolTargets.get(tool);
|
|
125
|
+
if (!target) throw new Error(`Missing MCP tool target: ${tool.name}`);
|
|
126
|
+
return target;
|
|
127
|
+
}
|
|
128
|
+
/** Return the validated source identity for a tool returned by this generator. */
|
|
129
|
+
getToolIdentity(tool) {
|
|
130
|
+
const target = this.toolTarget(tool);
|
|
131
|
+
return {
|
|
132
|
+
objectName: target.objectName,
|
|
133
|
+
action: target.action,
|
|
134
|
+
originalName: target.originalName ?? tool.name
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
runtimeToolTargets(tools) {
|
|
138
|
+
return Object.fromEntries(tools.map((tool) => [tool.name, this.toolTarget(tool)]));
|
|
139
|
+
}
|
|
107
140
|
config;
|
|
108
141
|
context;
|
|
109
142
|
collections = /* @__PURE__ */ new Map();
|
|
@@ -153,6 +186,13 @@ var MCPGenerator = class {
|
|
|
153
186
|
const objectTools = await this.generateObjectTools(simpleName, shouldInclude);
|
|
154
187
|
tools.push(...objectTools);
|
|
155
188
|
}
|
|
189
|
+
const names = canonicalMcpToolNames(tools.map((tool) => ({
|
|
190
|
+
name: tool.name,
|
|
191
|
+
target: this.toolTarget(tool)
|
|
192
|
+
})));
|
|
193
|
+
tools.forEach((tool, index) => {
|
|
194
|
+
tool.name = names[index];
|
|
195
|
+
});
|
|
156
196
|
return sortMCPTools(tools);
|
|
157
197
|
}
|
|
158
198
|
/**
|
|
@@ -167,31 +207,36 @@ var MCPGenerator = class {
|
|
|
167
207
|
name: `${lowerName}_list`,
|
|
168
208
|
description: `List ${objectName} objects with optional filtering`,
|
|
169
209
|
inputSchema: this.buildInputSchema(objectName, "list", fields),
|
|
170
|
-
outputSchema: this.buildOutputSchema(objectName, "list", fields)
|
|
210
|
+
outputSchema: this.buildOutputSchema(objectName, "list", fields),
|
|
211
|
+
annotations: mcpToolAnnotations("list")
|
|
171
212
|
});
|
|
172
213
|
if (shouldInclude("get")) tools.push({
|
|
173
214
|
name: `${lowerName}_get`,
|
|
174
215
|
description: `Get a specific ${objectName} by ID or slug`,
|
|
175
216
|
inputSchema: this.buildInputSchema(objectName, "get", fields),
|
|
176
|
-
outputSchema: this.buildOutputSchema(objectName, "get", fields)
|
|
217
|
+
outputSchema: this.buildOutputSchema(objectName, "get", fields),
|
|
218
|
+
annotations: mcpToolAnnotations("get")
|
|
177
219
|
});
|
|
178
220
|
if (shouldInclude("create")) tools.push({
|
|
179
221
|
name: `${lowerName}_create`,
|
|
180
222
|
description: `Create a new ${objectName}`,
|
|
181
223
|
inputSchema: this.buildInputSchema(objectName, "create", fields),
|
|
182
|
-
outputSchema: this.buildOutputSchema(objectName, "create", fields)
|
|
224
|
+
outputSchema: this.buildOutputSchema(objectName, "create", fields),
|
|
225
|
+
annotations: mcpToolAnnotations("create")
|
|
183
226
|
});
|
|
184
227
|
if (shouldInclude("update")) tools.push({
|
|
185
228
|
name: `${lowerName}_update`,
|
|
186
229
|
description: `Update an existing ${objectName}`,
|
|
187
230
|
inputSchema: this.buildInputSchema(objectName, "update", fields),
|
|
188
|
-
outputSchema: this.buildOutputSchema(objectName, "update", fields)
|
|
231
|
+
outputSchema: this.buildOutputSchema(objectName, "update", fields),
|
|
232
|
+
annotations: mcpToolAnnotations("update")
|
|
189
233
|
});
|
|
190
234
|
if (shouldInclude("delete")) tools.push({
|
|
191
235
|
name: `${lowerName}_delete`,
|
|
192
236
|
description: `Delete a ${objectName} by ID`,
|
|
193
237
|
inputSchema: this.buildInputSchema(objectName, "delete", fields),
|
|
194
|
-
outputSchema: this.buildOutputSchema(objectName, "delete", fields)
|
|
238
|
+
outputSchema: this.buildOutputSchema(objectName, "delete", fields),
|
|
239
|
+
annotations: mcpToolAnnotations("delete")
|
|
195
240
|
});
|
|
196
241
|
if (classInfo) {
|
|
197
242
|
const mcpConfig = ObjectRegistry.getConfig(objectName).mcp;
|
|
@@ -234,6 +279,11 @@ var MCPGenerator = class {
|
|
|
234
279
|
tools.push(tool);
|
|
235
280
|
}
|
|
236
281
|
}
|
|
282
|
+
for (const tool of tools) this.toolTargets.set(tool, {
|
|
283
|
+
objectName,
|
|
284
|
+
action: tool.name.slice(lowerName.length + 1),
|
|
285
|
+
originalName: tool.name
|
|
286
|
+
});
|
|
237
287
|
return tools;
|
|
238
288
|
}
|
|
239
289
|
buildCustomActionTool(objectName, lowerName, methodName, methodDef, collectionReceiver = false) {
|
|
@@ -242,7 +292,8 @@ var MCPGenerator = class {
|
|
|
242
292
|
name: `${lowerName}_${methodName}`.toLowerCase(),
|
|
243
293
|
description: `Execute ${methodName} action on ${objectName}`,
|
|
244
294
|
inputSchema: this.buildInputSchema(objectName, methodName, ObjectRegistry.getFields(objectName), metadata),
|
|
245
|
-
outputSchema: this.buildOutputSchema(objectName, methodName, ObjectRegistry.getFields(objectName))
|
|
295
|
+
outputSchema: this.buildOutputSchema(objectName, methodName, ObjectRegistry.getFields(objectName)),
|
|
296
|
+
annotations: mcpToolAnnotations(methodName, metadata)
|
|
246
297
|
};
|
|
247
298
|
}
|
|
248
299
|
resolveCustomActionMetadata(objectName, action, method, collectionReceiver = false) {
|
|
@@ -457,11 +508,9 @@ var MCPGenerator = class {
|
|
|
457
508
|
async handleToolCall(request) {
|
|
458
509
|
const { name, arguments: args } = request.params;
|
|
459
510
|
try {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const objectName
|
|
463
|
-
const action = firstUnderscore === -1 ? "" : name.slice(firstUnderscore + 1);
|
|
464
|
-
if (!objectName || !action) throw new Error(`Invalid tool name format: ${name}`);
|
|
511
|
+
const tool = (await this.generateTools()).find((candidate) => candidate.name === name);
|
|
512
|
+
if (!tool) throw new Error(`Unknown tool: ${name}`);
|
|
513
|
+
const { objectName, action } = this.toolTarget(tool);
|
|
465
514
|
const registeredClasses = ObjectRegistry.getAllClasses();
|
|
466
515
|
let classInfo = null;
|
|
467
516
|
let actualObjectName = "";
|
|
@@ -536,10 +585,10 @@ var MCPGenerator = class {
|
|
|
536
585
|
};
|
|
537
586
|
}
|
|
538
587
|
async resolveTaskAction(toolName, args) {
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const action =
|
|
588
|
+
const tools = await this.generateTools();
|
|
589
|
+
const tool = tools.find((candidate) => candidate.name === toolName);
|
|
590
|
+
if (!tool) return null;
|
|
591
|
+
const { objectName: objectPrefix, action } = this.toolTarget(tool);
|
|
543
592
|
if (isCrudToolAction(action)) return null;
|
|
544
593
|
const classEntry = Array.from(ObjectRegistry.getAllClasses().entries()).find(([key, info]) => (info.name || key).toLowerCase() === objectPrefix.toLowerCase());
|
|
545
594
|
if (!classEntry) return null;
|
|
@@ -548,7 +597,7 @@ var MCPGenerator = class {
|
|
|
548
597
|
const mcpConfig = ObjectRegistry.getConfig(objectName).mcp;
|
|
549
598
|
const configuredTasks = typeof mcpConfig === "object" ? mcpConfig.tasks : void 0;
|
|
550
599
|
if (configuredTasks !== true && (!Array.isArray(configuredTasks) || !configuredTasks.some((method) => method.toLowerCase() === action.toLowerCase()))) return null;
|
|
551
|
-
if (!
|
|
600
|
+
if (!tools.some((tool) => tool.name === toolName)) return null;
|
|
552
601
|
const [resolvedMethodName, method] = resolveCustomActionMethod(await ObjectRegistry.getAllMethods(objectName), action);
|
|
553
602
|
const methodName = method ? resolvedMethodName : resolveRuntimeMethodName(classInfo.constructor, action);
|
|
554
603
|
const metadata = this.resolveCustomActionMetadata(objectName, methodName, method, this.hasCollectionReceiver(classInfo));
|
|
@@ -712,7 +761,7 @@ var MCPGenerator = class {
|
|
|
712
761
|
if (typeof isTenantScopedClass !== "function") return [];
|
|
713
762
|
const scoped = /* @__PURE__ */ new Set();
|
|
714
763
|
for (const tool of tools) {
|
|
715
|
-
const
|
|
764
|
+
const { objectName } = this.toolTarget(tool);
|
|
716
765
|
if (!objectName) continue;
|
|
717
766
|
for (const [key, info] of ObjectRegistry.getAllClasses()) {
|
|
718
767
|
const simpleName = info.name || key;
|
|
@@ -735,7 +784,7 @@ var MCPGenerator = class {
|
|
|
735
784
|
async hasTenantScopedTools(tools) {
|
|
736
785
|
if ((await this.tenantScopedObjectNames(tools)).length > 0) return true;
|
|
737
786
|
for (const tool of tools) {
|
|
738
|
-
const
|
|
787
|
+
const { objectName } = this.toolTarget(tool);
|
|
739
788
|
if (!objectName) continue;
|
|
740
789
|
for (const [key, info] of ObjectRegistry.getAllClasses()) {
|
|
741
790
|
const simpleName = info.name || key;
|
|
@@ -915,6 +964,7 @@ var MCPGenerator = class {
|
|
|
915
964
|
context: this.context,
|
|
916
965
|
debug,
|
|
917
966
|
tools,
|
|
967
|
+
toolTargets: this.runtimeToolTargets(tools),
|
|
918
968
|
customActions: await this.runtimeCustomActions(tools),
|
|
919
969
|
taskActions: await this.runtimeTaskActions(tools),
|
|
920
970
|
tenantScopedObjects,
|
|
@@ -944,10 +994,9 @@ var MCPGenerator = class {
|
|
|
944
994
|
const metadata = {};
|
|
945
995
|
const classes = ObjectRegistry.getAllClasses();
|
|
946
996
|
for (const tool of tools) {
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
const
|
|
950
|
-
const action = tool.name.slice(separator + 1);
|
|
997
|
+
const target = this.toolTarget(tool);
|
|
998
|
+
const objectPrefix = target.objectName.toLowerCase();
|
|
999
|
+
const action = target.action;
|
|
951
1000
|
if (isCrudToolAction(action)) continue;
|
|
952
1001
|
const matched = Array.from(classes.entries()).find(([key, info]) => (info.name || key).toLowerCase() === objectPrefix);
|
|
953
1002
|
if (!matched) continue;
|
|
@@ -974,9 +1023,7 @@ var MCPGenerator = class {
|
|
|
974
1023
|
const classes = ObjectRegistry.getAllClasses();
|
|
975
1024
|
for (const tool of tools) {
|
|
976
1025
|
if (!await this.supportsTaskTool(tool.name)) continue;
|
|
977
|
-
const
|
|
978
|
-
if (separator <= 0) continue;
|
|
979
|
-
const objectPrefix = tool.name.slice(0, separator).toLowerCase();
|
|
1026
|
+
const objectPrefix = this.toolTarget(tool).objectName.toLowerCase();
|
|
980
1027
|
const matched = Array.from(classes.entries()).find(([key, info]) => (info.name || key).toLowerCase() === objectPrefix);
|
|
981
1028
|
if (!matched) continue;
|
|
982
1029
|
const [key, classInfo] = matched;
|
|
@@ -1020,9 +1067,9 @@ var MCPGenerator = class {
|
|
|
1020
1067
|
const orderings = {};
|
|
1021
1068
|
const classes = ObjectRegistry.getAllClasses();
|
|
1022
1069
|
for (const tool of tools) {
|
|
1023
|
-
const
|
|
1024
|
-
if (
|
|
1025
|
-
const objectPrefix =
|
|
1070
|
+
const target = this.toolTarget(tool);
|
|
1071
|
+
if (target.action !== "list") continue;
|
|
1072
|
+
const objectPrefix = target.objectName.toLowerCase();
|
|
1026
1073
|
if (orderings[objectPrefix]) continue;
|
|
1027
1074
|
const matched = Array.from(classes.entries()).find(([key, info]) => (info.name || key).toLowerCase() === objectPrefix);
|
|
1028
1075
|
if (!matched) continue;
|
|
@@ -1034,9 +1081,9 @@ var MCPGenerator = class {
|
|
|
1034
1081
|
const targets = {};
|
|
1035
1082
|
const classes = ObjectRegistry.getAllClasses();
|
|
1036
1083
|
for (const tool of tools) {
|
|
1037
|
-
const
|
|
1038
|
-
if (
|
|
1039
|
-
const objectPrefix =
|
|
1084
|
+
const target = this.toolTarget(tool);
|
|
1085
|
+
if (target.action !== "create") continue;
|
|
1086
|
+
const objectPrefix = target.objectName.toLowerCase();
|
|
1040
1087
|
const matched = Array.from(classes.entries()).find(([key, info]) => (info.name || key).toLowerCase() === objectPrefix);
|
|
1041
1088
|
if (!matched) continue;
|
|
1042
1089
|
const [key, classInfo] = matched;
|
|
@@ -1113,6 +1160,15 @@ export const tools: Array<{
|
|
|
1113
1160
|
description: string;
|
|
1114
1161
|
inputSchema: any;
|
|
1115
1162
|
outputSchema: any;
|
|
1163
|
+
annotations?: {
|
|
1164
|
+
readOnlyHint: boolean;
|
|
1165
|
+
destructiveHint: boolean;
|
|
1166
|
+
idempotentHint: boolean;
|
|
1167
|
+
openWorldHint: boolean;
|
|
1168
|
+
};
|
|
1169
|
+
title?: string;
|
|
1170
|
+
icons?: Array<{ src: string; mimeType?: string; sizes?: string[]; theme?: 'light' | 'dark' }>;
|
|
1171
|
+
_meta?: Record<string, unknown>;
|
|
1116
1172
|
}> = ${JSON.stringify(tools, null, 2)};
|
|
1117
1173
|
`;
|
|
1118
1174
|
}
|
|
@@ -1121,18 +1177,17 @@ export const tools: Array<{
|
|
|
1121
1177
|
*/
|
|
1122
1178
|
async generateToolSwitchCases(indent = " ", generatedTools) {
|
|
1123
1179
|
const tools = generatedTools ?? await this.generateTools();
|
|
1124
|
-
const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
1125
1180
|
return (await Promise.all(tools.map(async (tool) => {
|
|
1126
|
-
const
|
|
1127
|
-
const objectName =
|
|
1128
|
-
const action =
|
|
1181
|
+
const target = this.toolTarget(tool);
|
|
1182
|
+
const objectName = target.objectName.toLowerCase();
|
|
1183
|
+
const action = target.action;
|
|
1129
1184
|
switch (action) {
|
|
1130
1185
|
case "list": return `${indent}case '${tool.name}': {
|
|
1131
1186
|
${indent} const limit = args.limit ?? 50;
|
|
1132
1187
|
${indent} const offset = args.offset ?? 0;
|
|
1133
1188
|
${indent} const where = args.where ?? {};
|
|
1134
1189
|
|
|
1135
|
-
${indent} const collection = await ObjectRegistry.getCollection(
|
|
1190
|
+
${indent} const collection = await ObjectRegistry.getCollection(${JSON.stringify(target.objectName)}, {
|
|
1136
1191
|
${indent} persistence: { type: process.env.DATABASE_TYPE || 'sqlite', url: process.env.DATABASE_URL || ':memory:' },
|
|
1137
1192
|
${indent} ai: aiConfig
|
|
1138
1193
|
${indent} });
|
|
@@ -1150,7 +1205,7 @@ ${indent} if (!args.id && !args.slug) {
|
|
|
1150
1205
|
${indent} throw new Error('Either id or slug is required');
|
|
1151
1206
|
${indent} }
|
|
1152
1207
|
|
|
1153
|
-
${indent} const collection = await ObjectRegistry.getCollection(
|
|
1208
|
+
${indent} const collection = await ObjectRegistry.getCollection(${JSON.stringify(target.objectName)}, {
|
|
1154
1209
|
${indent} persistence: { type: process.env.DATABASE_TYPE || 'sqlite', url: process.env.DATABASE_URL || ':memory:' },
|
|
1155
1210
|
${indent} ai: aiConfig
|
|
1156
1211
|
${indent} });
|
|
@@ -1165,7 +1220,7 @@ ${indent} }
|
|
|
1165
1220
|
${indent} return successResult(item.toPublicJSON(PUBLIC_JSON_OPTIONS));
|
|
1166
1221
|
${indent}}`;
|
|
1167
1222
|
case "create": return `${indent}case '${tool.name}': {
|
|
1168
|
-
${indent} const { collection, objectName: targetObjectName } = await resolveCreateTarget(
|
|
1223
|
+
${indent} const { collection, objectName: targetObjectName } = await resolveCreateTarget(${JSON.stringify(objectName)}, args, aiConfig);
|
|
1169
1224
|
|
|
1170
1225
|
${indent} const newItem = await collection.create(applyWritablePolicy(targetObjectName, args));
|
|
1171
1226
|
${indent} await newItem.save();
|
|
@@ -1178,7 +1233,7 @@ ${indent} if (!id) {
|
|
|
1178
1233
|
${indent} throw new Error('ID is required for update');
|
|
1179
1234
|
${indent} }
|
|
1180
1235
|
|
|
1181
|
-
${indent} const collection = await ObjectRegistry.getCollection(
|
|
1236
|
+
${indent} const collection = await ObjectRegistry.getCollection(${JSON.stringify(target.objectName)}, {
|
|
1182
1237
|
${indent} persistence: { type: process.env.DATABASE_TYPE || 'sqlite', url: process.env.DATABASE_URL || ':memory:' },
|
|
1183
1238
|
${indent} ai: aiConfig
|
|
1184
1239
|
${indent} });
|
|
@@ -1188,7 +1243,7 @@ ${indent} if (!existing) {
|
|
|
1188
1243
|
${indent} throw new Error('Object not found');
|
|
1189
1244
|
${indent} }
|
|
1190
1245
|
|
|
1191
|
-
${indent} Object.assign(existing, applyWritablePolicy(
|
|
1246
|
+
${indent} Object.assign(existing, applyWritablePolicy(${JSON.stringify(target.objectName)}, updateData));
|
|
1192
1247
|
${indent} await existing.save();
|
|
1193
1248
|
|
|
1194
1249
|
${indent} return successResult(existing.toPublicJSON(PUBLIC_JSON_OPTIONS));
|
|
@@ -1198,7 +1253,7 @@ ${indent} if (!args.id) {
|
|
|
1198
1253
|
${indent} throw new Error('ID is required for delete');
|
|
1199
1254
|
${indent} }
|
|
1200
1255
|
|
|
1201
|
-
${indent} const collection = await ObjectRegistry.getCollection(
|
|
1256
|
+
${indent} const collection = await ObjectRegistry.getCollection(${JSON.stringify(target.objectName)}, {
|
|
1202
1257
|
${indent} persistence: { type: process.env.DATABASE_TYPE || 'sqlite', url: process.env.DATABASE_URL || ':memory:' },
|
|
1203
1258
|
${indent} ai: aiConfig
|
|
1204
1259
|
${indent} });
|
|
@@ -1224,10 +1279,10 @@ ${indent}}`;
|
|
|
1224
1279
|
${indent} const { id, options, ...directArgs } = args;
|
|
1225
1280
|
|
|
1226
1281
|
${indent} if (${JSON.stringify(metadata.scope)} === 'item' && !id) {
|
|
1227
|
-
${indent} throw new Error(
|
|
1282
|
+
${indent} throw new Error(${JSON.stringify(`ID is required for custom action ${action}`)});
|
|
1228
1283
|
${indent} }
|
|
1229
1284
|
${indent} if (${JSON.stringify(metadata.scope)} === 'collection' && id) {
|
|
1230
|
-
${indent} throw new Error(
|
|
1285
|
+
${indent} throw new Error(${JSON.stringify(`Custom action ${action} is collection-scoped and does not accept an ID`)});
|
|
1231
1286
|
${indent} }
|
|
1232
1287
|
|
|
1233
1288
|
${indent} const collection = await ObjectRegistry.getCollection(${JSON.stringify(registeredName)}, {
|
|
@@ -1246,7 +1301,7 @@ ${indent} }
|
|
|
1246
1301
|
|
|
1247
1302
|
${indent} const actionMethod = target[${JSON.stringify(methodName)}];
|
|
1248
1303
|
${indent} if (typeof actionMethod !== 'function') {
|
|
1249
|
-
${indent} throw new Error(
|
|
1304
|
+
${indent} throw new Error(${JSON.stringify(`Method ${methodName} not found on custom action target`)});
|
|
1250
1305
|
${indent} }
|
|
1251
1306
|
|
|
1252
1307
|
${indent} const methodArgs = ${methodArgs.startsWith("[") ? methodArgs : `[${methodArgs}]`};
|
|
@@ -1274,6 +1329,7 @@ ${indent}}`;
|
|
|
1274
1329
|
const tools = await this.generateTools();
|
|
1275
1330
|
const switchCases = await this.generateToolSwitchCases(" ", tools);
|
|
1276
1331
|
const stiTargets = this.runtimeStiTargets(tools);
|
|
1332
|
+
const toolTargets = this.runtimeToolTargets(tools);
|
|
1277
1333
|
const tenantScopedSet = Array.from(new Set(tenantScopedObjects.map((n) => n.toLowerCase())));
|
|
1278
1334
|
const hasTenantScoped = tenantScopedSet.length > 0;
|
|
1279
1335
|
return `/**
|
|
@@ -1301,6 +1357,7 @@ const MCP_TENANT_ID = process.env.SMRT_MCP_TENANT_ID || undefined;
|
|
|
1301
1357
|
const MCP_ALLOW_CROSS_TENANT = process.env.SMRT_MCP_ALLOW_CROSS_TENANT === 'true';
|
|
1302
1358
|
` : ""}
|
|
1303
1359
|
|
|
1360
|
+
const TOOL_TARGETS: Record<string, { objectName: string; action: string }> = ${JSON.stringify(toolTargets)};
|
|
1304
1361
|
const PUBLIC_JSON_OPTIONS = {
|
|
1305
1362
|
permissions: (process.env.SMRT_MCP_PERMISSIONS || '')
|
|
1306
1363
|
.split(',')
|
|
@@ -1420,7 +1477,7 @@ ${switchCases}
|
|
|
1420
1477
|
};
|
|
1421
1478
|
${hasTenantScoped ? `
|
|
1422
1479
|
// Fail-closed tenant context for tenant-scoped tools (#1554).
|
|
1423
|
-
const
|
|
1480
|
+
const toolObject = TOOL_TARGETS[name]?.objectName;
|
|
1424
1481
|
const result =
|
|
1425
1482
|
toolObject && TENANT_SCOPED.has(toolObject.toLowerCase())
|
|
1426
1483
|
? await runTenantScopedEntryPoint(
|
|
@@ -1518,12 +1575,7 @@ export async function createServer() {
|
|
|
1518
1575
|
}
|
|
1519
1576
|
|
|
1520
1577
|
return {
|
|
1521
|
-
tools: [...tools].sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0)
|
|
1522
|
-
name: tool.name,
|
|
1523
|
-
description: tool.description,
|
|
1524
|
-
inputSchema: tool.inputSchema,
|
|
1525
|
-
outputSchema: tool.outputSchema,
|
|
1526
|
-
})),
|
|
1578
|
+
tools: [...tools].sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0),
|
|
1527
1579
|
};
|
|
1528
1580
|
});
|
|
1529
1581
|
|
|
@@ -1570,6 +1622,6 @@ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href)
|
|
|
1570
1622
|
}
|
|
1571
1623
|
};
|
|
1572
1624
|
//#endregion
|
|
1573
|
-
export { MCPGenerator, MCP_STABLE_CATALOG_TTL_MS, resolveMCPToolListCacheHint, sortMCPTools };
|
|
1625
|
+
export { MCPGenerator, MCP_STABLE_CATALOG_TTL_MS, assertMcpJsonSchemaSafety, mcpToolAnnotations, mcpToolAnnotationsFor, resolveMCPToolListCacheHint, sortMCPTools };
|
|
1574
1626
|
|
|
1575
1627
|
//# sourceMappingURL=mcp.js.map
|