@vritti/api-sdk 0.4.7 → 0.4.9
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/dist/auth.cjs +70 -4
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +16 -1
- package/dist/auth.d.ts +16 -1
- package/dist/auth.js +70 -4
- package/dist/auth.js.map +1 -1
- package/dist/bad-request.exception-D-KmhiXQ.d.cts +18 -0
- package/dist/bad-request.exception-Db94kZxY.d.ts +18 -0
- package/dist/data-table.cjs +3 -4
- package/dist/data-table.cjs.map +1 -1
- package/dist/data-table.js +3 -4
- package/dist/data-table.js.map +1 -1
- package/dist/database.cjs +11 -2
- package/dist/database.cjs.map +1 -1
- package/dist/database.d.cts +1 -0
- package/dist/database.d.ts +1 -0
- package/dist/database.js +26 -17
- package/dist/database.js.map +1 -1
- package/dist/decimal.d.cts +1 -0
- package/dist/decimal.d.ts +1 -0
- package/dist/exceptions.d.cts +4 -17
- package/dist/exceptions.d.ts +4 -17
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/mcp.cjs +814 -0
- package/dist/mcp.cjs.map +1 -0
- package/dist/mcp.d.cts +135 -0
- package/dist/mcp.d.ts +135 -0
- package/dist/mcp.js +771 -0
- package/dist/mcp.js.map +1 -0
- package/dist/root.cjs +1 -0
- package/dist/root.cjs.map +1 -1
- package/dist/root.js +1 -0
- package/dist/root.js.map +1 -1
- package/dist/zod.cjs +25 -0
- package/dist/zod.cjs.map +1 -0
- package/dist/zod.d.cts +1 -0
- package/dist/zod.d.ts +1 -0
- package/dist/zod.js +3 -0
- package/dist/zod.js.map +1 -0
- package/package.json +24 -2
package/dist/mcp.cjs
ADDED
|
@@ -0,0 +1,814 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/mcp/index.ts
|
|
22
|
+
var mcp_exports = {};
|
|
23
|
+
__export(mcp_exports, {
|
|
24
|
+
MCP_PRINCIPAL_FACTORY: () => MCP_PRINCIPAL_FACTORY,
|
|
25
|
+
MCP_SERVER_OPTIONS: () => MCP_SERVER_OPTIONS,
|
|
26
|
+
MCP_TOOL_PROVIDER_KEY: () => MCP_TOOL_PROVIDER_KEY,
|
|
27
|
+
McpModule: () => McpModule,
|
|
28
|
+
McpPrincipal: () => McpPrincipal,
|
|
29
|
+
McpRequestHandler: () => McpRequestHandler,
|
|
30
|
+
McpSchemaRegistry: () => McpSchemaRegistry,
|
|
31
|
+
McpServerFactory: () => McpServerFactory,
|
|
32
|
+
McpTools: () => McpTools,
|
|
33
|
+
McpTransportFactory: () => McpTransportFactory,
|
|
34
|
+
McpValidationError: () => McpValidationError,
|
|
35
|
+
ToolRegistry: () => ToolRegistry,
|
|
36
|
+
collectOperationIds: () => collectOperationIds,
|
|
37
|
+
defineTool: () => defineTool,
|
|
38
|
+
principalFromOAuth: () => principalFromOAuth,
|
|
39
|
+
problemFromError: () => problemFromError,
|
|
40
|
+
toolError: () => toolError,
|
|
41
|
+
toolOk: () => toolOk,
|
|
42
|
+
validateDto: () => validateDto
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(mcp_exports);
|
|
45
|
+
|
|
46
|
+
// src/mcp/coverage.ts
|
|
47
|
+
var import_constants = require("@nestjs/common/constants");
|
|
48
|
+
function collectOperationIds(modules) {
|
|
49
|
+
const ids = [];
|
|
50
|
+
for (const module2 of modules) {
|
|
51
|
+
const controllers = Reflect.getMetadata(import_constants.MODULE_METADATA.CONTROLLERS, module2) ?? [];
|
|
52
|
+
for (const controller of controllers) {
|
|
53
|
+
const prototype = controller.prototype;
|
|
54
|
+
for (const method of Object.getOwnPropertyNames(prototype)) {
|
|
55
|
+
if (method === "constructor") continue;
|
|
56
|
+
const handler = prototype[method];
|
|
57
|
+
if (typeof handler !== "function") continue;
|
|
58
|
+
if (Reflect.getMetadata(import_constants.METHOD_METADATA, handler) === void 0) continue;
|
|
59
|
+
ids.push(`${controller.name}_${method}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return ids;
|
|
64
|
+
}
|
|
65
|
+
__name(collectOperationIds, "collectOperationIds");
|
|
66
|
+
|
|
67
|
+
// src/mcp/mcp.module.ts
|
|
68
|
+
var import_common27 = require("@nestjs/common");
|
|
69
|
+
var import_core2 = require("@nestjs/core");
|
|
70
|
+
|
|
71
|
+
// src/mcp/mcp.options.ts
|
|
72
|
+
var MCP_SERVER_OPTIONS = /* @__PURE__ */ Symbol("MCP_SERVER_OPTIONS");
|
|
73
|
+
|
|
74
|
+
// src/exceptions/bad-gateway.exception.ts
|
|
75
|
+
var import_common2 = require("@nestjs/common");
|
|
76
|
+
|
|
77
|
+
// src/exceptions/base-field.exception.ts
|
|
78
|
+
var import_common = require("@nestjs/common");
|
|
79
|
+
var HttpProblemException = class extends import_common.HttpException {
|
|
80
|
+
static {
|
|
81
|
+
__name(this, "HttpProblemException");
|
|
82
|
+
}
|
|
83
|
+
constructor(detailOrOptions, httpStatus) {
|
|
84
|
+
const options = typeof detailOrOptions === "string" ? {
|
|
85
|
+
detail: detailOrOptions
|
|
86
|
+
} : detailOrOptions;
|
|
87
|
+
super({
|
|
88
|
+
type: options.type ?? "about:blank",
|
|
89
|
+
label: options.label,
|
|
90
|
+
detail: options.detail,
|
|
91
|
+
errors: options.errors ?? []
|
|
92
|
+
}, httpStatus);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/exceptions/bad-request.exception.ts
|
|
97
|
+
var import_common3 = require("@nestjs/common");
|
|
98
|
+
var BadRequestException = class extends HttpProblemException {
|
|
99
|
+
static {
|
|
100
|
+
__name(this, "BadRequestException");
|
|
101
|
+
}
|
|
102
|
+
constructor(detailOrOptions) {
|
|
103
|
+
super(detailOrOptions ?? "Bad Request", import_common3.HttpStatus.BAD_REQUEST);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// src/exceptions/conflict.exception.ts
|
|
108
|
+
var import_common4 = require("@nestjs/common");
|
|
109
|
+
|
|
110
|
+
// src/exceptions/forbidden.exception.ts
|
|
111
|
+
var import_common5 = require("@nestjs/common");
|
|
112
|
+
|
|
113
|
+
// src/exceptions/gone.exception.ts
|
|
114
|
+
var import_common6 = require("@nestjs/common");
|
|
115
|
+
|
|
116
|
+
// src/exceptions/internal-server-error.exception.ts
|
|
117
|
+
var import_common7 = require("@nestjs/common");
|
|
118
|
+
|
|
119
|
+
// src/exceptions/method-not-allowed.exception.ts
|
|
120
|
+
var import_common8 = require("@nestjs/common");
|
|
121
|
+
|
|
122
|
+
// src/exceptions/not-acceptable.exception.ts
|
|
123
|
+
var import_common9 = require("@nestjs/common");
|
|
124
|
+
|
|
125
|
+
// src/exceptions/not-found.exception.ts
|
|
126
|
+
var import_common10 = require("@nestjs/common");
|
|
127
|
+
|
|
128
|
+
// src/exceptions/not-implemented.exception.ts
|
|
129
|
+
var import_common11 = require("@nestjs/common");
|
|
130
|
+
|
|
131
|
+
// src/exceptions/payload-too-large.exception.ts
|
|
132
|
+
var import_common12 = require("@nestjs/common");
|
|
133
|
+
|
|
134
|
+
// src/exceptions/request-timeout.exception.ts
|
|
135
|
+
var import_common13 = require("@nestjs/common");
|
|
136
|
+
|
|
137
|
+
// src/exceptions/service-unavailable.exception.ts
|
|
138
|
+
var import_common14 = require("@nestjs/common");
|
|
139
|
+
|
|
140
|
+
// src/exceptions/too-many-requests.exception.ts
|
|
141
|
+
var import_common15 = require("@nestjs/common");
|
|
142
|
+
|
|
143
|
+
// src/exceptions/unauthorized.exception.ts
|
|
144
|
+
var import_common16 = require("@nestjs/common");
|
|
145
|
+
var UnauthorizedException = class extends HttpProblemException {
|
|
146
|
+
static {
|
|
147
|
+
__name(this, "UnauthorizedException");
|
|
148
|
+
}
|
|
149
|
+
constructor(detailOrOptions) {
|
|
150
|
+
super(detailOrOptions ?? "Unauthorized", import_common16.HttpStatus.UNAUTHORIZED);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// src/exceptions/unprocessable-entity.exception.ts
|
|
155
|
+
var import_common17 = require("@nestjs/common");
|
|
156
|
+
|
|
157
|
+
// src/exceptions/unsupported-media-type.exception.ts
|
|
158
|
+
var import_common18 = require("@nestjs/common");
|
|
159
|
+
|
|
160
|
+
// src/exceptions/validation.exception.ts
|
|
161
|
+
var import_common19 = require("@nestjs/common");
|
|
162
|
+
|
|
163
|
+
// src/mcp/mcp-principal.ts
|
|
164
|
+
var McpPrincipal = class {
|
|
165
|
+
static {
|
|
166
|
+
__name(this, "McpPrincipal");
|
|
167
|
+
}
|
|
168
|
+
userId;
|
|
169
|
+
scopes;
|
|
170
|
+
clientId;
|
|
171
|
+
grantId;
|
|
172
|
+
organizationId;
|
|
173
|
+
constructor(userId, scopes, clientId, grantId, organizationId) {
|
|
174
|
+
this.userId = userId;
|
|
175
|
+
this.scopes = scopes;
|
|
176
|
+
this.clientId = clientId;
|
|
177
|
+
this.grantId = grantId;
|
|
178
|
+
this.organizationId = organizationId;
|
|
179
|
+
}
|
|
180
|
+
hasScope(scope) {
|
|
181
|
+
return this.scopes.includes(scope);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
var MCP_PRINCIPAL_FACTORY = /* @__PURE__ */ Symbol("MCP_PRINCIPAL_FACTORY");
|
|
185
|
+
function principalFromOAuth(request) {
|
|
186
|
+
const auth = request.auth;
|
|
187
|
+
if (!auth || auth.kind !== "oauth" || !auth.userId || !auth.grantId) {
|
|
188
|
+
throw new UnauthorizedException("MCP request is not authenticated.");
|
|
189
|
+
}
|
|
190
|
+
return new McpPrincipal(auth.userId, auth.scopes ?? [], auth.clientId, auth.grantId, auth.organizationId);
|
|
191
|
+
}
|
|
192
|
+
__name(principalFromOAuth, "principalFromOAuth");
|
|
193
|
+
|
|
194
|
+
// src/mcp/mcp-request.handler.ts
|
|
195
|
+
var import_common25 = require("@nestjs/common");
|
|
196
|
+
|
|
197
|
+
// src/mcp/mcp-server.factory.ts
|
|
198
|
+
var import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
199
|
+
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
200
|
+
var import_common23 = require("@nestjs/common");
|
|
201
|
+
|
|
202
|
+
// src/mcp/tool-registry.ts
|
|
203
|
+
var import_common22 = require("@nestjs/common");
|
|
204
|
+
var import_core = require("@nestjs/core");
|
|
205
|
+
var import_zod2 = require("zod");
|
|
206
|
+
|
|
207
|
+
// src/mcp/tool-definition.ts
|
|
208
|
+
var import_common20 = require("@nestjs/common");
|
|
209
|
+
var MCP_TOOL_PROVIDER_KEY = "mcp:tool-provider";
|
|
210
|
+
var McpTools = /* @__PURE__ */ __name(() => (0, import_common20.SetMetadata)(MCP_TOOL_PROVIDER_KEY, true), "McpTools");
|
|
211
|
+
function defineTool(definition) {
|
|
212
|
+
return definition;
|
|
213
|
+
}
|
|
214
|
+
__name(defineTool, "defineTool");
|
|
215
|
+
|
|
216
|
+
// src/mcp/tool-result.ts
|
|
217
|
+
var import_common21 = require("@nestjs/common");
|
|
218
|
+
var import_zod = require("zod");
|
|
219
|
+
var PG_UNIQUE_VIOLATION = "23505";
|
|
220
|
+
var logger = new import_common21.Logger("McpTool");
|
|
221
|
+
function isRecord(value) {
|
|
222
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
223
|
+
}
|
|
224
|
+
__name(isRecord, "isRecord");
|
|
225
|
+
function isHttpExceptionLike(value) {
|
|
226
|
+
return isRecord(value) && typeof value.getStatus === "function" && typeof value.getResponse === "function";
|
|
227
|
+
}
|
|
228
|
+
__name(isHttpExceptionLike, "isHttpExceptionLike");
|
|
229
|
+
function findPgUniqueViolation(error, depth = 0) {
|
|
230
|
+
if (!isRecord(error) || depth > 5) return void 0;
|
|
231
|
+
if (error.code === PG_UNIQUE_VIOLATION) return {
|
|
232
|
+
detail: typeof error.detail === "string" ? error.detail : void 0
|
|
233
|
+
};
|
|
234
|
+
return findPgUniqueViolation(error.cause, depth + 1);
|
|
235
|
+
}
|
|
236
|
+
__name(findPgUniqueViolation, "findPgUniqueViolation");
|
|
237
|
+
function normalizeFieldErrors(value) {
|
|
238
|
+
if (!Array.isArray(value)) return [];
|
|
239
|
+
return value.filter(isRecord).map((entry) => ({
|
|
240
|
+
field: typeof entry.field === "string" ? entry.field : void 0,
|
|
241
|
+
message: typeof entry.message === "string" ? entry.message : "Invalid value"
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
__name(normalizeFieldErrors, "normalizeFieldErrors");
|
|
245
|
+
function toolOk(payload) {
|
|
246
|
+
const structuredContent = isRecord(payload) ? payload : {
|
|
247
|
+
result: payload
|
|
248
|
+
};
|
|
249
|
+
return {
|
|
250
|
+
content: [
|
|
251
|
+
{
|
|
252
|
+
type: "text",
|
|
253
|
+
text: JSON.stringify(payload)
|
|
254
|
+
}
|
|
255
|
+
],
|
|
256
|
+
structuredContent
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
__name(toolOk, "toolOk");
|
|
260
|
+
function toolError(problem) {
|
|
261
|
+
return {
|
|
262
|
+
isError: true,
|
|
263
|
+
content: [
|
|
264
|
+
{
|
|
265
|
+
type: "text",
|
|
266
|
+
text: JSON.stringify(problem)
|
|
267
|
+
}
|
|
268
|
+
],
|
|
269
|
+
structuredContent: {
|
|
270
|
+
...problem
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
__name(toolError, "toolError");
|
|
275
|
+
function problemFromError(error) {
|
|
276
|
+
if (error instanceof import_zod.ZodError) {
|
|
277
|
+
return {
|
|
278
|
+
status: 400,
|
|
279
|
+
label: "Invalid Arguments",
|
|
280
|
+
detail: "The tool arguments did not match the schema.",
|
|
281
|
+
errors: error.issues.map((issue) => ({
|
|
282
|
+
field: issue.path.join("."),
|
|
283
|
+
message: issue.message
|
|
284
|
+
}))
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
if (isHttpExceptionLike(error)) {
|
|
288
|
+
const status = error.getStatus();
|
|
289
|
+
const body = error.getResponse();
|
|
290
|
+
if (isRecord(body)) {
|
|
291
|
+
const detail = typeof body.detail === "string" ? body.detail : typeof body.message === "string" ? body.message : "Request failed.";
|
|
292
|
+
return {
|
|
293
|
+
status,
|
|
294
|
+
label: typeof body.label === "string" ? body.label : void 0,
|
|
295
|
+
detail,
|
|
296
|
+
errors: normalizeFieldErrors(body.errors)
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
status,
|
|
301
|
+
detail: typeof body === "string" ? body : "Request failed.",
|
|
302
|
+
errors: []
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
const duplicate = findPgUniqueViolation(error);
|
|
306
|
+
if (duplicate) {
|
|
307
|
+
return {
|
|
308
|
+
status: 409,
|
|
309
|
+
label: "Duplicate Entry",
|
|
310
|
+
detail: duplicate.detail ?? "A record with these values already exists.",
|
|
311
|
+
errors: []
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
logger.error(`Unhandled tool error: ${error instanceof Error ? error.stack : String(error)}`);
|
|
315
|
+
return {
|
|
316
|
+
status: 500,
|
|
317
|
+
detail: "An unexpected error occurred.",
|
|
318
|
+
errors: []
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
__name(problemFromError, "problemFromError");
|
|
322
|
+
|
|
323
|
+
// src/mcp/tool-registry.ts
|
|
324
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
325
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
326
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
327
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
328
|
+
} else {
|
|
329
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
330
|
+
if (d = decorators[i]) {
|
|
331
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
336
|
+
}
|
|
337
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
338
|
+
function _ts_metadata(metadataKey, metadataValue) {
|
|
339
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
340
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
344
|
+
var TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
345
|
+
var ToolRegistry = class _ToolRegistry {
|
|
346
|
+
static {
|
|
347
|
+
__name(this, "ToolRegistry");
|
|
348
|
+
}
|
|
349
|
+
discovery;
|
|
350
|
+
reflector;
|
|
351
|
+
logger = new import_common22.Logger(_ToolRegistry.name);
|
|
352
|
+
definitions = /* @__PURE__ */ new Map();
|
|
353
|
+
catalog = [];
|
|
354
|
+
constructor(discovery, reflector) {
|
|
355
|
+
this.discovery = discovery;
|
|
356
|
+
this.reflector = reflector;
|
|
357
|
+
}
|
|
358
|
+
// After every module has initialised, so providers from any module are instantiated and discoverable
|
|
359
|
+
onApplicationBootstrap() {
|
|
360
|
+
for (const provider of this.findProviders()) {
|
|
361
|
+
for (const definition of provider.tools()) this.register(definition);
|
|
362
|
+
}
|
|
363
|
+
this.catalog = [
|
|
364
|
+
...this.definitions.values()
|
|
365
|
+
].map((definition) => this.toCatalogEntry(definition));
|
|
366
|
+
this.logger.log(`Registered ${this.catalog.length} MCP tools`);
|
|
367
|
+
}
|
|
368
|
+
listTools() {
|
|
369
|
+
return this.catalog;
|
|
370
|
+
}
|
|
371
|
+
// Every REST operation the tools stand in for — a coverage test compares this with the live route set
|
|
372
|
+
coveredOperationIds() {
|
|
373
|
+
return [
|
|
374
|
+
...this.definitions.values()
|
|
375
|
+
].flatMap((definition) => [
|
|
376
|
+
...definition.covers
|
|
377
|
+
]);
|
|
378
|
+
}
|
|
379
|
+
async execute(name, rawArgs, principal) {
|
|
380
|
+
const started = Date.now();
|
|
381
|
+
const definition = this.definitions.get(name);
|
|
382
|
+
if (!definition) {
|
|
383
|
+
return toolError({
|
|
384
|
+
status: 404,
|
|
385
|
+
label: "Unknown Tool",
|
|
386
|
+
detail: `No tool named "${name}".`,
|
|
387
|
+
errors: []
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
let status = 200;
|
|
391
|
+
let result;
|
|
392
|
+
if (!principal.hasScope(definition.requiredScope)) {
|
|
393
|
+
status = 403;
|
|
394
|
+
result = toolError({
|
|
395
|
+
status,
|
|
396
|
+
label: "Insufficient Scope",
|
|
397
|
+
detail: `Tool "${name}" requires the ${definition.requiredScope} scope. Reconnect the client and grant it.`,
|
|
398
|
+
errors: []
|
|
399
|
+
});
|
|
400
|
+
} else {
|
|
401
|
+
try {
|
|
402
|
+
const args = definition.inputSchema.parse(rawArgs ?? {});
|
|
403
|
+
result = toolOk(await definition.handler(principal, args));
|
|
404
|
+
} catch (error) {
|
|
405
|
+
const problem = problemFromError(error);
|
|
406
|
+
status = problem.status;
|
|
407
|
+
result = toolError(problem);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
this.logger.log(`mcp tool=${name} user=${principal.userId} grant=${principal.grantId ?? "-"} client=${principal.clientId ?? "-"} scope=${definition.requiredScope} ok=${status < 400} status=${status} ms=${Date.now() - started}`);
|
|
411
|
+
return result;
|
|
412
|
+
}
|
|
413
|
+
findProviders() {
|
|
414
|
+
return this.discovery.getProviders().filter((wrapper) => typeof wrapper.metatype === "function" && wrapper.instance).filter((wrapper) => this.reflector.get(MCP_TOOL_PROVIDER_KEY, wrapper.metatype) === true).map((wrapper) => wrapper.instance);
|
|
415
|
+
}
|
|
416
|
+
register(definition) {
|
|
417
|
+
if (!TOOL_NAME_PATTERN.test(definition.name)) {
|
|
418
|
+
throw new Error(`MCP tool name "${definition.name}" is invalid (letters, digits, _ and -, max 64 chars).`);
|
|
419
|
+
}
|
|
420
|
+
if (this.definitions.has(definition.name)) {
|
|
421
|
+
throw new Error(`MCP tool "${definition.name}" is registered twice.`);
|
|
422
|
+
}
|
|
423
|
+
this.definitions.set(definition.name, definition);
|
|
424
|
+
}
|
|
425
|
+
toCatalogEntry(definition) {
|
|
426
|
+
return {
|
|
427
|
+
name: definition.name,
|
|
428
|
+
title: definition.title,
|
|
429
|
+
description: definition.description,
|
|
430
|
+
inputSchema: this.toInputSchema(definition),
|
|
431
|
+
annotations: {
|
|
432
|
+
title: definition.title,
|
|
433
|
+
readOnlyHint: definition.annotations.readOnlyHint,
|
|
434
|
+
destructiveHint: definition.annotations.destructiveHint,
|
|
435
|
+
idempotentHint: definition.annotations.idempotentHint,
|
|
436
|
+
openWorldHint: false
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
// MCP wants a bare JSON Schema object at the root; zod adds a $schema marker the catalog does not need
|
|
441
|
+
toInputSchema(definition) {
|
|
442
|
+
const schema = import_zod2.z.toJSONSchema(definition.inputSchema, {
|
|
443
|
+
io: "input"
|
|
444
|
+
});
|
|
445
|
+
delete schema.$schema;
|
|
446
|
+
if (schema.type !== "object") {
|
|
447
|
+
throw new Error(`MCP tool "${definition.name}" must declare an object input schema.`);
|
|
448
|
+
}
|
|
449
|
+
return schema;
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
ToolRegistry = _ts_decorate([
|
|
453
|
+
(0, import_common22.Injectable)(),
|
|
454
|
+
_ts_metadata("design:type", Function),
|
|
455
|
+
_ts_metadata("design:paramtypes", [
|
|
456
|
+
typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
|
|
457
|
+
typeof import_core.Reflector === "undefined" ? Object : import_core.Reflector
|
|
458
|
+
])
|
|
459
|
+
], ToolRegistry);
|
|
460
|
+
|
|
461
|
+
// src/mcp/mcp-server.factory.ts
|
|
462
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
463
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
464
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
465
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
466
|
+
} else {
|
|
467
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
468
|
+
if (d = decorators[i]) {
|
|
469
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
474
|
+
}
|
|
475
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
476
|
+
function _ts_metadata2(metadataKey, metadataValue) {
|
|
477
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
478
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
__name(_ts_metadata2, "_ts_metadata");
|
|
482
|
+
function _ts_param(paramIndex, decorator) {
|
|
483
|
+
return function(target, key) {
|
|
484
|
+
decorator(target, key, paramIndex);
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
__name(_ts_param, "_ts_param");
|
|
488
|
+
var McpServerFactory = class {
|
|
489
|
+
static {
|
|
490
|
+
__name(this, "McpServerFactory");
|
|
491
|
+
}
|
|
492
|
+
options;
|
|
493
|
+
toolRegistry;
|
|
494
|
+
constructor(options, toolRegistry) {
|
|
495
|
+
this.options = options;
|
|
496
|
+
this.toolRegistry = toolRegistry;
|
|
497
|
+
}
|
|
498
|
+
create(principal) {
|
|
499
|
+
const server = new import_server.Server({
|
|
500
|
+
name: this.options.name,
|
|
501
|
+
version: this.options.version
|
|
502
|
+
}, {
|
|
503
|
+
capabilities: {
|
|
504
|
+
tools: {}
|
|
505
|
+
},
|
|
506
|
+
instructions: this.options.instructions
|
|
507
|
+
});
|
|
508
|
+
server.setRequestHandler(import_types.ListToolsRequestSchema, async () => ({
|
|
509
|
+
tools: this.toolRegistry.listTools()
|
|
510
|
+
}));
|
|
511
|
+
server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => this.toolRegistry.execute(request.params.name, request.params.arguments, principal));
|
|
512
|
+
return server;
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
McpServerFactory = _ts_decorate2([
|
|
516
|
+
(0, import_common23.Injectable)(),
|
|
517
|
+
_ts_param(0, (0, import_common23.Inject)(MCP_SERVER_OPTIONS)),
|
|
518
|
+
_ts_metadata2("design:type", Function),
|
|
519
|
+
_ts_metadata2("design:paramtypes", [
|
|
520
|
+
typeof McpServerOptions === "undefined" ? Object : McpServerOptions,
|
|
521
|
+
typeof ToolRegistry === "undefined" ? Object : ToolRegistry
|
|
522
|
+
])
|
|
523
|
+
], McpServerFactory);
|
|
524
|
+
|
|
525
|
+
// src/mcp/mcp-transport.factory.ts
|
|
526
|
+
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
527
|
+
var import_common24 = require("@nestjs/common");
|
|
528
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
529
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
530
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
531
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
532
|
+
} else {
|
|
533
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
534
|
+
if (d = decorators[i]) {
|
|
535
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
540
|
+
}
|
|
541
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
542
|
+
var McpTransportFactory = class {
|
|
543
|
+
static {
|
|
544
|
+
__name(this, "McpTransportFactory");
|
|
545
|
+
}
|
|
546
|
+
create() {
|
|
547
|
+
return new import_streamableHttp.StreamableHTTPServerTransport({
|
|
548
|
+
sessionIdGenerator: void 0,
|
|
549
|
+
enableJsonResponse: true
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
McpTransportFactory = _ts_decorate3([
|
|
554
|
+
(0, import_common24.Injectable)()
|
|
555
|
+
], McpTransportFactory);
|
|
556
|
+
|
|
557
|
+
// src/mcp/mcp-request.handler.ts
|
|
558
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
559
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
560
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
561
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
562
|
+
} else {
|
|
563
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
564
|
+
if (d = decorators[i]) {
|
|
565
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
570
|
+
}
|
|
571
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
572
|
+
function _ts_metadata3(metadataKey, metadataValue) {
|
|
573
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") {
|
|
574
|
+
return Reflect.metadata(metadataKey, metadataValue);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
578
|
+
function _ts_param2(paramIndex, decorator) {
|
|
579
|
+
return function(target, key) {
|
|
580
|
+
decorator(target, key, paramIndex);
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
__name(_ts_param2, "_ts_param");
|
|
584
|
+
var McpRequestHandler = class {
|
|
585
|
+
static {
|
|
586
|
+
__name(this, "McpRequestHandler");
|
|
587
|
+
}
|
|
588
|
+
serverFactory;
|
|
589
|
+
transportFactory;
|
|
590
|
+
principalFactory;
|
|
591
|
+
constructor(serverFactory, transportFactory, principalFactory) {
|
|
592
|
+
this.serverFactory = serverFactory;
|
|
593
|
+
this.transportFactory = transportFactory;
|
|
594
|
+
this.principalFactory = principalFactory;
|
|
595
|
+
}
|
|
596
|
+
async handle(request, reply, body) {
|
|
597
|
+
const principal = this.principalFactory(request);
|
|
598
|
+
reply.hijack();
|
|
599
|
+
const transport = this.transportFactory.create();
|
|
600
|
+
const server = this.serverFactory.create(principal);
|
|
601
|
+
reply.raw.on("close", () => {
|
|
602
|
+
void transport.close();
|
|
603
|
+
void server.close();
|
|
604
|
+
});
|
|
605
|
+
await server.connect(transport);
|
|
606
|
+
await transport.handleRequest(request.raw, reply.raw, body);
|
|
607
|
+
}
|
|
608
|
+
// The JSON-RPC answer for verbs a stateless server does not serve (GET streams, DELETE session teardown)
|
|
609
|
+
methodNotAllowed(reply) {
|
|
610
|
+
reply.status(405).header("Allow", "POST").send({
|
|
611
|
+
jsonrpc: "2.0",
|
|
612
|
+
error: {
|
|
613
|
+
code: -32e3,
|
|
614
|
+
message: "Method not allowed."
|
|
615
|
+
},
|
|
616
|
+
id: null
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
McpRequestHandler = _ts_decorate4([
|
|
621
|
+
(0, import_common25.Injectable)(),
|
|
622
|
+
_ts_param2(2, (0, import_common25.Inject)(MCP_PRINCIPAL_FACTORY)),
|
|
623
|
+
_ts_metadata3("design:type", Function),
|
|
624
|
+
_ts_metadata3("design:paramtypes", [
|
|
625
|
+
typeof McpServerFactory === "undefined" ? Object : McpServerFactory,
|
|
626
|
+
typeof McpTransportFactory === "undefined" ? Object : McpTransportFactory,
|
|
627
|
+
typeof McpPrincipalFactory === "undefined" ? Object : McpPrincipalFactory
|
|
628
|
+
])
|
|
629
|
+
], McpRequestHandler);
|
|
630
|
+
|
|
631
|
+
// src/mcp/mcp-schema-registry.ts
|
|
632
|
+
var import_common26 = require("@nestjs/common");
|
|
633
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
634
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
635
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
636
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
637
|
+
} else {
|
|
638
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
639
|
+
if (d = decorators[i]) {
|
|
640
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
645
|
+
}
|
|
646
|
+
__name(_ts_decorate5, "_ts_decorate");
|
|
647
|
+
var COMPONENT_REF = "#/components/schemas/";
|
|
648
|
+
var McpSchemaRegistry = class {
|
|
649
|
+
static {
|
|
650
|
+
__name(this, "McpSchemaRegistry");
|
|
651
|
+
}
|
|
652
|
+
schemas = {};
|
|
653
|
+
setDocument(document) {
|
|
654
|
+
this.schemas = document.components?.schemas ?? {};
|
|
655
|
+
}
|
|
656
|
+
// The schema for a DTO class, with its component references inlined as local $defs
|
|
657
|
+
schemaFor(dto) {
|
|
658
|
+
const root = this.schemas[dto.name];
|
|
659
|
+
if (!root) return {
|
|
660
|
+
type: "object",
|
|
661
|
+
description: `The schema for ${dto.name} is unavailable.`
|
|
662
|
+
};
|
|
663
|
+
const defs = {};
|
|
664
|
+
const rewritten = this.rewrite(root, defs);
|
|
665
|
+
return Object.keys(defs).length > 0 ? {
|
|
666
|
+
...rewritten,
|
|
667
|
+
$defs: defs
|
|
668
|
+
} : rewritten;
|
|
669
|
+
}
|
|
670
|
+
rewrite(node, defs) {
|
|
671
|
+
if (Array.isArray(node)) return node.map((item) => this.rewrite(item, defs));
|
|
672
|
+
if (typeof node !== "object" || node === null) return node;
|
|
673
|
+
const record = node;
|
|
674
|
+
if (typeof record.$ref === "string" && record.$ref.startsWith(COMPONENT_REF)) {
|
|
675
|
+
const name = record.$ref.slice(COMPONENT_REF.length);
|
|
676
|
+
if (!(name in defs)) {
|
|
677
|
+
defs[name] = {};
|
|
678
|
+
defs[name] = this.rewrite(this.schemas[name] ?? {}, defs);
|
|
679
|
+
}
|
|
680
|
+
return {
|
|
681
|
+
$ref: `#/$defs/${name}`
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
const out = {};
|
|
685
|
+
for (const [key, value] of Object.entries(record)) out[key] = this.rewrite(value, defs);
|
|
686
|
+
return out;
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
McpSchemaRegistry = _ts_decorate5([
|
|
690
|
+
(0, import_common26.Injectable)()
|
|
691
|
+
], McpSchemaRegistry);
|
|
692
|
+
|
|
693
|
+
// src/mcp/mcp.module.ts
|
|
694
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
695
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
696
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
697
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
698
|
+
} else {
|
|
699
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
700
|
+
if (d = decorators[i]) {
|
|
701
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
706
|
+
}
|
|
707
|
+
__name(_ts_decorate6, "_ts_decorate");
|
|
708
|
+
var McpModule = class _McpModule {
|
|
709
|
+
static {
|
|
710
|
+
__name(this, "McpModule");
|
|
711
|
+
}
|
|
712
|
+
static forRoot(options) {
|
|
713
|
+
const serverOptions = {
|
|
714
|
+
name: options.name,
|
|
715
|
+
version: options.version,
|
|
716
|
+
instructions: options.instructions
|
|
717
|
+
};
|
|
718
|
+
return {
|
|
719
|
+
module: _McpModule,
|
|
720
|
+
imports: [
|
|
721
|
+
import_core2.DiscoveryModule
|
|
722
|
+
],
|
|
723
|
+
providers: [
|
|
724
|
+
{
|
|
725
|
+
provide: MCP_SERVER_OPTIONS,
|
|
726
|
+
useValue: serverOptions
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
provide: MCP_PRINCIPAL_FACTORY,
|
|
730
|
+
useValue: options.principal ?? principalFromOAuth
|
|
731
|
+
},
|
|
732
|
+
McpTransportFactory,
|
|
733
|
+
McpServerFactory,
|
|
734
|
+
McpRequestHandler,
|
|
735
|
+
McpSchemaRegistry,
|
|
736
|
+
ToolRegistry
|
|
737
|
+
],
|
|
738
|
+
exports: [
|
|
739
|
+
McpRequestHandler,
|
|
740
|
+
McpSchemaRegistry,
|
|
741
|
+
ToolRegistry
|
|
742
|
+
]
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
McpModule = _ts_decorate6([
|
|
747
|
+
(0, import_common27.Module)({})
|
|
748
|
+
], McpModule);
|
|
749
|
+
|
|
750
|
+
// src/mcp/validate-dto.ts
|
|
751
|
+
var import_class_transformer = require("class-transformer");
|
|
752
|
+
var import_class_validator = require("class-validator");
|
|
753
|
+
var McpValidationError = class extends BadRequestException {
|
|
754
|
+
static {
|
|
755
|
+
__name(this, "McpValidationError");
|
|
756
|
+
}
|
|
757
|
+
constructor(errors) {
|
|
758
|
+
super({
|
|
759
|
+
label: "Validation Failed",
|
|
760
|
+
detail: "Please check your input and try again.",
|
|
761
|
+
errors
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
function flattenValidationErrors(errors, parent = "") {
|
|
766
|
+
return errors.flatMap((error) => {
|
|
767
|
+
const field = parent ? `${parent}.${error.property}` : error.property;
|
|
768
|
+
const own = Object.values(error.constraints ?? {}).map((message) => ({
|
|
769
|
+
field,
|
|
770
|
+
message
|
|
771
|
+
}));
|
|
772
|
+
const nested = error.children?.length ? flattenValidationErrors(error.children, field) : [];
|
|
773
|
+
return [
|
|
774
|
+
...own,
|
|
775
|
+
...nested
|
|
776
|
+
];
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
__name(flattenValidationErrors, "flattenValidationErrors");
|
|
780
|
+
async function validateDto(cls, input) {
|
|
781
|
+
const instance = (0, import_class_transformer.plainToInstance)(cls, input ?? {}, {
|
|
782
|
+
enableImplicitConversion: true
|
|
783
|
+
});
|
|
784
|
+
const errors = await (0, import_class_validator.validate)(instance, {
|
|
785
|
+
whitelist: true,
|
|
786
|
+
forbidNonWhitelisted: true
|
|
787
|
+
});
|
|
788
|
+
if (errors.length > 0) throw new McpValidationError(flattenValidationErrors(errors));
|
|
789
|
+
return instance;
|
|
790
|
+
}
|
|
791
|
+
__name(validateDto, "validateDto");
|
|
792
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
793
|
+
0 && (module.exports = {
|
|
794
|
+
MCP_PRINCIPAL_FACTORY,
|
|
795
|
+
MCP_SERVER_OPTIONS,
|
|
796
|
+
MCP_TOOL_PROVIDER_KEY,
|
|
797
|
+
McpModule,
|
|
798
|
+
McpPrincipal,
|
|
799
|
+
McpRequestHandler,
|
|
800
|
+
McpSchemaRegistry,
|
|
801
|
+
McpServerFactory,
|
|
802
|
+
McpTools,
|
|
803
|
+
McpTransportFactory,
|
|
804
|
+
McpValidationError,
|
|
805
|
+
ToolRegistry,
|
|
806
|
+
collectOperationIds,
|
|
807
|
+
defineTool,
|
|
808
|
+
principalFromOAuth,
|
|
809
|
+
problemFromError,
|
|
810
|
+
toolError,
|
|
811
|
+
toolOk,
|
|
812
|
+
validateDto
|
|
813
|
+
});
|
|
814
|
+
//# sourceMappingURL=mcp.cjs.map
|