@nestia/sdk 11.2.0 → 11.3.0

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 (62) hide show
  1. package/assets/bundle/distribute/package.json +1 -1
  2. package/lib/NestiaSdkApplication.js +17 -2
  3. package/lib/NestiaSdkApplication.js.map +1 -1
  4. package/lib/NestiaSwaggerComposer.js +2 -0
  5. package/lib/NestiaSwaggerComposer.js.map +1 -1
  6. package/lib/analyses/AccessorAnalyzer.d.ts +4 -1
  7. package/lib/analyses/AccessorAnalyzer.js.map +1 -1
  8. package/lib/analyses/ReflectControllerAnalyzer.js +3 -2
  9. package/lib/analyses/ReflectControllerAnalyzer.js.map +1 -1
  10. package/lib/analyses/ReflectMcpOperationAnalyzer.d.ts +20 -0
  11. package/lib/analyses/ReflectMcpOperationAnalyzer.js +84 -0
  12. package/lib/analyses/ReflectMcpOperationAnalyzer.js.map +1 -0
  13. package/lib/analyses/TypedMcpRouteAnalyzer.d.ts +15 -0
  14. package/lib/analyses/TypedMcpRouteAnalyzer.js +40 -0
  15. package/lib/analyses/TypedMcpRouteAnalyzer.js.map +1 -0
  16. package/lib/executable/internal/NestiaConfigLoader.js +3 -2
  17. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  18. package/lib/generates/SdkGenerator.js +48 -0
  19. package/lib/generates/SdkGenerator.js.map +1 -1
  20. package/lib/generates/internal/ImportDictionary.d.ts +1 -0
  21. package/lib/generates/internal/ImportDictionary.js +5 -4
  22. package/lib/generates/internal/ImportDictionary.js.map +1 -1
  23. package/lib/generates/internal/SdkDistributionComposer.d.ts +1 -0
  24. package/lib/generates/internal/SdkDistributionComposer.js +8 -1
  25. package/lib/generates/internal/SdkDistributionComposer.js.map +1 -1
  26. package/lib/generates/internal/SdkFileProgrammer.js +4 -1
  27. package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
  28. package/lib/generates/internal/SdkMcpRouteProgrammer.d.ts +25 -0
  29. package/lib/generates/internal/SdkMcpRouteProgrammer.js +192 -0
  30. package/lib/generates/internal/SdkMcpRouteProgrammer.js.map +1 -0
  31. package/lib/generates/internal/SdkRouteDirectory.d.ts +2 -1
  32. package/lib/generates/internal/SdkRouteDirectory.js.map +1 -1
  33. package/lib/structures/IReflectController.d.ts +2 -1
  34. package/lib/structures/IReflectMcpOperation.d.ts +37 -0
  35. package/lib/structures/IReflectMcpOperation.js +3 -0
  36. package/lib/structures/IReflectMcpOperation.js.map +1 -0
  37. package/lib/structures/IReflectMcpOperationParameter.d.ts +21 -0
  38. package/lib/structures/IReflectMcpOperationParameter.js +3 -0
  39. package/lib/structures/IReflectMcpOperationParameter.js.map +1 -0
  40. package/lib/structures/ITypedApplication.d.ts +2 -1
  41. package/lib/structures/ITypedMcpRoute.d.ts +33 -0
  42. package/lib/structures/ITypedMcpRoute.js +3 -0
  43. package/lib/structures/ITypedMcpRoute.js.map +1 -0
  44. package/package.json +5 -4
  45. package/src/NestiaSdkApplication.ts +23 -3
  46. package/src/NestiaSwaggerComposer.ts +1 -0
  47. package/src/analyses/AccessorAnalyzer.ts +7 -10
  48. package/src/analyses/ReflectControllerAnalyzer.ts +8 -1
  49. package/src/analyses/ReflectMcpOperationAnalyzer.ts +124 -0
  50. package/src/analyses/TypedMcpRouteAnalyzer.ts +40 -0
  51. package/src/executable/internal/NestiaConfigLoader.ts +2 -1
  52. package/src/generates/SdkGenerator.ts +55 -0
  53. package/src/generates/internal/ImportDictionary.ts +10 -8
  54. package/src/generates/internal/SdkDistributionComposer.ts +6 -0
  55. package/src/generates/internal/SdkFileProgrammer.ts +6 -2
  56. package/src/generates/internal/SdkMcpRouteProgrammer.ts +469 -0
  57. package/src/generates/internal/SdkRouteDirectory.ts +4 -1
  58. package/src/structures/IReflectController.ts +4 -1
  59. package/src/structures/IReflectMcpOperation.ts +40 -0
  60. package/src/structures/IReflectMcpOperationParameter.ts +29 -0
  61. package/src/structures/ITypedApplication.ts +2 -1
  62. package/src/structures/ITypedMcpRoute.ts +35 -0
@@ -0,0 +1,469 @@
1
+ import ts from "typescript";
2
+
3
+ import { INestiaProject } from "../../structures/INestiaProject";
4
+ import { ITypedMcpRoute } from "../../structures/ITypedMcpRoute";
5
+ import { FilePrinter } from "./FilePrinter";
6
+ import { ImportDictionary } from "./ImportDictionary";
7
+
8
+ /**
9
+ * Emits a typed client wrapper for an MCP tool.
10
+ *
11
+ * Output mirrors `SdkHttpRouteProgrammer` conventions: a top-level async
12
+ * function paired with a namespace that exposes `Input`, `Output`, and
13
+ * `METADATA`. Object output types are wrapped in `Primitive<T>` from typia
14
+ * because MCP round-trips values through JSON, matching the semantics of
15
+ * `Primitive`. Void MCP tools return `Promise<void>`.
16
+ *
17
+ * The response is typed via `CallToolResult` from `@modelcontextprotocol/sdk`
18
+ * and narrowed structurally (`isError === true`, `type === "text"`) rather than
19
+ * asserted with `as any`. The single unavoidable cast is on the `arguments`
20
+ * field of `client.callTool(...)`, which the MCP SDK types as `Record<string,
21
+ * unknown> | undefined`; a user interface without an index signature is not
22
+ * structurally assignable to that record.
23
+ *
24
+ * @author wildduck - https://github.com/wildduck2
25
+ */
26
+ export namespace SdkMcpRouteProgrammer {
27
+ export const write =
28
+ (project: INestiaProject) =>
29
+ (importer: ImportDictionary) =>
30
+ (route: ITypedMcpRoute): ts.Statement[] => [
31
+ FilePrinter.description(
32
+ writeFunction(project)(importer)(route),
33
+ writeDescription(route),
34
+ ),
35
+ writeNamespace(project)(importer)(route),
36
+ ];
37
+
38
+ /* ---------------------------------------------------------
39
+ FUNCTION
40
+ --------------------------------------------------------- */
41
+ const writeFunction =
42
+ (_project: INestiaProject) =>
43
+ (importer: ImportDictionary) =>
44
+ (route: ITypedMcpRoute): ts.FunctionDeclaration => {
45
+ const clientType = ts.factory.createTypeReferenceNode(
46
+ importer.external({
47
+ declaration: true,
48
+ file: "@modelcontextprotocol/sdk/client/index.js",
49
+ type: "element",
50
+ name: "Client",
51
+ alias: "McpClient",
52
+ }),
53
+ );
54
+ const callToolResultTypeName = importer.external({
55
+ declaration: true,
56
+ file: "@modelcontextprotocol/sdk/types.js",
57
+ type: "element",
58
+ name: "CallToolResult",
59
+ alias: "McpCallToolResult",
60
+ });
61
+ const isVoid = isVoidReturn(route);
62
+ // Register Primitive import so Output type resolves.
63
+ if (!isVoid)
64
+ importer.external({
65
+ declaration: true,
66
+ file: "typia",
67
+ type: "element",
68
+ name: "Primitive",
69
+ });
70
+
71
+ const inputRef: ts.TypeNode = route.input
72
+ ? ts.factory.createTypeReferenceNode(`${route.name}.Input`)
73
+ : ts.factory.createTypeLiteralNode([]);
74
+ const outputRef: ts.TypeNode = ts.factory.createTypeReferenceNode(
75
+ `${route.name}.Output`,
76
+ );
77
+
78
+ const params: ts.ParameterDeclaration[] = [
79
+ ts.factory.createParameterDeclaration(
80
+ undefined,
81
+ undefined,
82
+ "client",
83
+ undefined,
84
+ clientType,
85
+ ),
86
+ ];
87
+ if (route.input) {
88
+ params.push(
89
+ ts.factory.createParameterDeclaration(
90
+ undefined,
91
+ undefined,
92
+ "args",
93
+ undefined,
94
+ inputRef,
95
+ ),
96
+ );
97
+ }
98
+
99
+ const toolNameExpr = ts.factory.createPropertyAccessExpression(
100
+ ts.factory.createPropertyAccessExpression(
101
+ ts.factory.createIdentifier(route.name),
102
+ "METADATA",
103
+ ),
104
+ "tool",
105
+ );
106
+
107
+ const callToolParams: ts.ObjectLiteralElementLike[] = [
108
+ ts.factory.createPropertyAssignment("name", toolNameExpr),
109
+ ];
110
+ if (route.input) {
111
+ callToolParams.push(
112
+ ts.factory.createPropertyAssignment(
113
+ "arguments",
114
+ ts.factory.createAsExpression(
115
+ ts.factory.createAsExpression(
116
+ ts.factory.createIdentifier("args"),
117
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword),
118
+ ),
119
+ ts.factory.createTypeReferenceNode("Record", [
120
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
121
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword),
122
+ ]),
123
+ ),
124
+ ),
125
+ );
126
+ }
127
+
128
+ const body = ts.factory.createBlock(
129
+ [
130
+ // const raw = await client.callTool({ ... });
131
+ // NOTE: callTool returns `CallToolResult | CompatibilityCallToolResult`
132
+ // (the pre-2024-11-05 compat variant has `toolResult`, no
133
+ // `content`). TypeScript cannot narrow the union structurally
134
+ // because both variants carry an `[x: string]: unknown` index
135
+ // signature. Branch at runtime, then cast to CallToolResult
136
+ // once for the modern path.
137
+ ts.factory.createVariableStatement(
138
+ undefined,
139
+ ts.factory.createVariableDeclarationList(
140
+ [
141
+ ts.factory.createVariableDeclaration(
142
+ "raw",
143
+ undefined,
144
+ undefined,
145
+ ts.factory.createAwaitExpression(
146
+ ts.factory.createCallExpression(
147
+ ts.factory.createPropertyAccessExpression(
148
+ ts.factory.createIdentifier("client"),
149
+ "callTool",
150
+ ),
151
+ undefined,
152
+ [
153
+ ts.factory.createObjectLiteralExpression(
154
+ callToolParams,
155
+ true,
156
+ ),
157
+ ],
158
+ ),
159
+ ),
160
+ ),
161
+ ],
162
+ ts.NodeFlags.Const,
163
+ ),
164
+ ),
165
+ // if ("toolResult" in raw) throw ...;
166
+ ts.factory.createIfStatement(
167
+ ts.factory.createBinaryExpression(
168
+ ts.factory.createStringLiteral("toolResult"),
169
+ ts.factory.createToken(ts.SyntaxKind.InKeyword),
170
+ ts.factory.createIdentifier("raw"),
171
+ ),
172
+ ts.factory.createThrowStatement(
173
+ ts.factory.createNewExpression(
174
+ ts.factory.createIdentifier("Error"),
175
+ undefined,
176
+ [
177
+ ts.factory.createTemplateExpression(
178
+ ts.factory.createTemplateHead('MCP tool "'),
179
+ [
180
+ ts.factory.createTemplateSpan(
181
+ toolNameExpr,
182
+ ts.factory.createTemplateTail(
183
+ '" returned a legacy (pre-2024-11-05) compatibility result',
184
+ ),
185
+ ),
186
+ ],
187
+ ),
188
+ ],
189
+ ),
190
+ ),
191
+ ),
192
+ // const result: CallToolResult = raw;
193
+ // Safe: preceding branch rejected the compat variant.
194
+ ts.factory.createVariableStatement(
195
+ undefined,
196
+ ts.factory.createVariableDeclarationList(
197
+ [
198
+ ts.factory.createVariableDeclaration(
199
+ "result",
200
+ undefined,
201
+ ts.factory.createTypeReferenceNode(callToolResultTypeName),
202
+ ts.factory.createAsExpression(
203
+ ts.factory.createIdentifier("raw"),
204
+ ts.factory.createTypeReferenceNode(callToolResultTypeName),
205
+ ),
206
+ ),
207
+ ],
208
+ ts.NodeFlags.Const,
209
+ ),
210
+ ),
211
+ // if (result.isError === true) throw ...;
212
+ ts.factory.createIfStatement(
213
+ ts.factory.createBinaryExpression(
214
+ ts.factory.createPropertyAccessExpression(
215
+ ts.factory.createIdentifier("result"),
216
+ "isError",
217
+ ),
218
+ ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
219
+ ts.factory.createTrue(),
220
+ ),
221
+ ts.factory.createThrowStatement(
222
+ ts.factory.createNewExpression(
223
+ ts.factory.createIdentifier("Error"),
224
+ undefined,
225
+ [
226
+ ts.factory.createTemplateExpression(
227
+ ts.factory.createTemplateHead('MCP tool "'),
228
+ [
229
+ ts.factory.createTemplateSpan(
230
+ toolNameExpr,
231
+ ts.factory.createTemplateTail('" returned isError'),
232
+ ),
233
+ ],
234
+ ),
235
+ ],
236
+ ),
237
+ ),
238
+ ),
239
+ ...(isVoid
240
+ ? [ts.factory.createReturnStatement()]
241
+ : [
242
+ // const first = result.content[0];
243
+ ts.factory.createVariableStatement(
244
+ undefined,
245
+ ts.factory.createVariableDeclarationList(
246
+ [
247
+ ts.factory.createVariableDeclaration(
248
+ "first",
249
+ undefined,
250
+ undefined,
251
+ ts.factory.createElementAccessExpression(
252
+ ts.factory.createPropertyAccessExpression(
253
+ ts.factory.createIdentifier("result"),
254
+ "content",
255
+ ),
256
+ ts.factory.createNumericLiteral(0),
257
+ ),
258
+ ),
259
+ ],
260
+ ts.NodeFlags.Const,
261
+ ),
262
+ ),
263
+ ts.factory.createIfStatement(
264
+ ts.factory.createBinaryExpression(
265
+ ts.factory.createBinaryExpression(
266
+ ts.factory.createIdentifier("first"),
267
+ ts.factory.createToken(
268
+ ts.SyntaxKind.EqualsEqualsEqualsToken,
269
+ ),
270
+ ts.factory.createIdentifier("undefined"),
271
+ ),
272
+ ts.factory.createToken(ts.SyntaxKind.BarBarToken),
273
+ ts.factory.createBinaryExpression(
274
+ ts.factory.createPropertyAccessExpression(
275
+ ts.factory.createIdentifier("first"),
276
+ "type",
277
+ ),
278
+ ts.factory.createToken(
279
+ ts.SyntaxKind.ExclamationEqualsEqualsToken,
280
+ ),
281
+ ts.factory.createStringLiteral("text"),
282
+ ),
283
+ ),
284
+ ts.factory.createThrowStatement(
285
+ ts.factory.createNewExpression(
286
+ ts.factory.createIdentifier("Error"),
287
+ undefined,
288
+ [
289
+ ts.factory.createTemplateExpression(
290
+ ts.factory.createTemplateHead('MCP tool "'),
291
+ [
292
+ ts.factory.createTemplateSpan(
293
+ toolNameExpr,
294
+ ts.factory.createTemplateTail(
295
+ '" returned no text content',
296
+ ),
297
+ ),
298
+ ],
299
+ ),
300
+ ],
301
+ ),
302
+ ),
303
+ ),
304
+ ts.factory.createReturnStatement(
305
+ ts.factory.createAsExpression(
306
+ ts.factory.createCallExpression(
307
+ ts.factory.createPropertyAccessExpression(
308
+ ts.factory.createIdentifier("JSON"),
309
+ "parse",
310
+ ),
311
+ undefined,
312
+ [
313
+ ts.factory.createPropertyAccessExpression(
314
+ ts.factory.createIdentifier("first"),
315
+ "text",
316
+ ),
317
+ ],
318
+ ),
319
+ outputRef,
320
+ ),
321
+ ),
322
+ ]),
323
+ ],
324
+ true,
325
+ );
326
+
327
+ return ts.factory.createFunctionDeclaration(
328
+ [
329
+ ts.factory.createModifier(ts.SyntaxKind.ExportKeyword),
330
+ ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword),
331
+ ],
332
+ undefined,
333
+ route.name,
334
+ undefined,
335
+ params,
336
+ ts.factory.createTypeReferenceNode("Promise", [outputRef]),
337
+ body,
338
+ );
339
+ };
340
+
341
+ /* ---------------------------------------------------------
342
+ NAMESPACE
343
+ --------------------------------------------------------- */
344
+ const writeNamespace =
345
+ (_project: INestiaProject) =>
346
+ (importer: ImportDictionary) =>
347
+ (route: ITypedMcpRoute): ts.ModuleDeclaration => {
348
+ const statements: ts.Statement[] = [];
349
+
350
+ // Input type alias
351
+ if (route.input) {
352
+ statements.push(
353
+ ts.factory.createTypeAliasDeclaration(
354
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
355
+ "Input",
356
+ undefined,
357
+ ts.factory.createTypeReferenceNode(route.input.type.name),
358
+ ),
359
+ );
360
+ }
361
+
362
+ // Output type alias
363
+ const isVoid = isVoidReturn(route);
364
+ const outputType: ts.TypeNode =
365
+ !isVoid && route.returnType !== null
366
+ ? ts.factory.createTypeReferenceNode(
367
+ importer.external({
368
+ declaration: true,
369
+ file: "typia",
370
+ type: "element",
371
+ name: "Primitive",
372
+ }),
373
+ [
374
+ ts.factory.createTypeReferenceNode(
375
+ unwrapPromise(route.returnType.name),
376
+ ),
377
+ ],
378
+ )
379
+ : ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword);
380
+ statements.push(
381
+ ts.factory.createTypeAliasDeclaration(
382
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
383
+ "Output",
384
+ undefined,
385
+ outputType,
386
+ ),
387
+ );
388
+
389
+ // METADATA const
390
+ const metadataProps: ts.ObjectLiteralElementLike[] = [
391
+ ts.factory.createPropertyAssignment(
392
+ "protocol",
393
+ ts.factory.createStringLiteral("mcp"),
394
+ ),
395
+ ts.factory.createPropertyAssignment(
396
+ "tool",
397
+ ts.factory.createStringLiteral(route.toolName),
398
+ ),
399
+ ts.factory.createPropertyAssignment(
400
+ "title",
401
+ route.title === null
402
+ ? ts.factory.createNull()
403
+ : ts.factory.createStringLiteral(route.title),
404
+ ),
405
+ ts.factory.createPropertyAssignment(
406
+ "description",
407
+ route.toolDescription === null
408
+ ? ts.factory.createNull()
409
+ : ts.factory.createStringLiteral(route.toolDescription),
410
+ ),
411
+ ];
412
+ statements.push(
413
+ ts.factory.createVariableStatement(
414
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
415
+ ts.factory.createVariableDeclarationList(
416
+ [
417
+ ts.factory.createVariableDeclaration(
418
+ "METADATA",
419
+ undefined,
420
+ undefined,
421
+ ts.factory.createAsExpression(
422
+ ts.factory.createObjectLiteralExpression(metadataProps, true),
423
+ ts.factory.createTypeReferenceNode("const"),
424
+ ),
425
+ ),
426
+ ],
427
+ ts.NodeFlags.Const,
428
+ ),
429
+ ),
430
+ );
431
+
432
+ return ts.factory.createModuleDeclaration(
433
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
434
+ ts.factory.createIdentifier(route.name),
435
+ ts.factory.createModuleBlock(statements),
436
+ ts.NodeFlags.Namespace,
437
+ );
438
+ };
439
+
440
+ /* ---------------------------------------------------------
441
+ DESCRIPTION
442
+ --------------------------------------------------------- */
443
+ const writeDescription = (route: ITypedMcpRoute): string => {
444
+ const lines: string[] = [];
445
+ if (route.toolDescription) lines.push(...route.toolDescription.split("\n"));
446
+ else if (route.description) lines.push(...route.description.split("\n"));
447
+ if (lines.length) lines.push("");
448
+ lines.push(
449
+ `@controller ${route.controller.class.name}.${route.function.name || route.name}`,
450
+ `@tool ${route.toolName}`,
451
+ `@accessor ${["api", "functional", ...route.accessor].join(".")}`,
452
+ `@protocol mcp`,
453
+ `@nestia Generated by Nestia - https://github.com/samchon/nestia`,
454
+ );
455
+ return lines.join("\n");
456
+ };
457
+
458
+ const unwrapPromise = (name: string): string => {
459
+ const m = /^Promise<(.+)>$/.exec(name);
460
+ return m ? m[1]! : name;
461
+ };
462
+
463
+ const isVoidReturn = (route: ITypedMcpRoute): boolean =>
464
+ route.returnType === null ||
465
+ isVoidName(unwrapPromise(route.returnType.name));
466
+
467
+ const isVoidName = (name: string): boolean =>
468
+ name === "void" || name === "undefined";
469
+ }
@@ -1,10 +1,13 @@
1
1
  import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
2
+ import { ITypedMcpRoute } from "../../structures/ITypedMcpRoute";
2
3
  import { ITypedWebSocketRoute } from "../../structures/ITypedWebSocketRoute";
3
4
 
4
5
  export class SdkRouteDirectory {
5
6
  public readonly module: string;
6
7
  public readonly children: Map<string, SdkRouteDirectory>;
7
- public readonly routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>;
8
+ public readonly routes: Array<
9
+ ITypedHttpRoute | ITypedWebSocketRoute | ITypedMcpRoute
10
+ >;
8
11
 
9
12
  public constructor(
10
13
  readonly parent: SdkRouteDirectory | null,
@@ -1,6 +1,7 @@
1
1
  import type { VERSION_NEUTRAL } from "@nestjs/common/interfaces";
2
2
 
3
3
  import { IReflectHttpOperation } from "./IReflectHttpOperation";
4
+ import { IReflectMcpOperation } from "./IReflectMcpOperation";
4
5
  import { IReflectWebSocketOperation } from "./IReflectWebSocketOperation";
5
6
 
6
7
  export interface IReflectController {
@@ -9,7 +10,9 @@ export interface IReflectController {
9
10
  paths: string[];
10
11
  file: string;
11
12
  versions: Array<string | typeof VERSION_NEUTRAL> | undefined;
12
- operations: Array<IReflectHttpOperation | IReflectWebSocketOperation>;
13
+ operations: Array<
14
+ IReflectHttpOperation | IReflectWebSocketOperation | IReflectMcpOperation
15
+ >;
13
16
  security: Record<string, string[]>[];
14
17
  tags: string[];
15
18
  }
@@ -0,0 +1,40 @@
1
+ import ts from "typescript";
2
+
3
+ import { IReflectImport } from "./IReflectImport";
4
+ import { IReflectMcpOperationParameter } from "./IReflectMcpOperationParameter";
5
+ import { IReflectType } from "./IReflectType";
6
+
7
+ /**
8
+ * Reflected operation metadata for a method decorated with `@McpRoute`.
9
+ *
10
+ * Produced by {@link ReflectMcpOperationAnalyzer.analyze}; consumed by
11
+ * {@link TypedMcpRouteAnalyzer.analyze} to produce the final
12
+ * {@link ITypedMcpRoute}.
13
+ *
14
+ * @author wildduck - https://github.com/wildduck2
15
+ */
16
+ export interface IReflectMcpOperation {
17
+ protocol: "mcp";
18
+ name: string;
19
+ toolName: string;
20
+ title: string | null;
21
+ toolDescription: string | null;
22
+ inputSchema: object;
23
+ outputSchema: object | null;
24
+ annotations: IReflectMcpOperation.IAnnotations | null;
25
+ function: Function;
26
+ parameters: IReflectMcpOperationParameter[];
27
+ returnType: IReflectType | null;
28
+ imports: IReflectImport[];
29
+ description: string | null;
30
+ jsDocTags: ts.JSDocTagInfo[];
31
+ }
32
+
33
+ export namespace IReflectMcpOperation {
34
+ export interface IAnnotations {
35
+ readOnlyHint?: boolean;
36
+ destructiveHint?: boolean;
37
+ idempotentHint?: boolean;
38
+ openWorldHint?: boolean;
39
+ }
40
+ }
@@ -0,0 +1,29 @@
1
+ import { IJsDocTagInfo } from "typia";
2
+
3
+ import { IReflectImport } from "./IReflectImport";
4
+ import { IReflectType } from "./IReflectType";
5
+
6
+ /**
7
+ * Parameter descriptor for an MCP tool method. Reflected from
8
+ * `"nestia/McpRoute/Parameters"` metadata plus compile-time type information
9
+ * collected by the nestia transformer.
10
+ *
11
+ * @author wildduck - https://github.com/wildduck2
12
+ */
13
+ export interface IReflectMcpOperationParameter {
14
+ category: "params";
15
+ name: string;
16
+ index: number;
17
+ type: IReflectType;
18
+ imports: IReflectImport[];
19
+ description: string | null;
20
+ jsDocTags: IJsDocTagInfo[];
21
+ }
22
+
23
+ export namespace IReflectMcpOperationParameter {
24
+ /** @internal */
25
+ export interface IPreconfigured {
26
+ category: "params";
27
+ index: number;
28
+ }
29
+ }
@@ -2,10 +2,11 @@ import { IMetadataDictionary } from "@typia/core";
2
2
 
3
3
  import { INestiaProject } from "./INestiaProject";
4
4
  import { ITypedHttpRoute } from "./ITypedHttpRoute";
5
+ import { ITypedMcpRoute } from "./ITypedMcpRoute";
5
6
  import { ITypedWebSocketRoute } from "./ITypedWebSocketRoute";
6
7
 
7
8
  export interface ITypedApplication {
8
9
  project: INestiaProject;
9
10
  collection: IMetadataDictionary;
10
- routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>;
11
+ routes: Array<ITypedHttpRoute | ITypedWebSocketRoute | ITypedMcpRoute>;
11
12
  }
@@ -0,0 +1,35 @@
1
+ import ts from "typescript";
2
+
3
+ import { IReflectController } from "./IReflectController";
4
+ import { IReflectImport } from "./IReflectImport";
5
+ import { IReflectMcpOperation } from "./IReflectMcpOperation";
6
+ import { IReflectMcpOperationParameter } from "./IReflectMcpOperationParameter";
7
+ import { IReflectType } from "./IReflectType";
8
+
9
+ /**
10
+ * Final typed representation of an MCP tool route.
11
+ *
12
+ * Carries everything the SDK generator needs to emit a typed client function:
13
+ * the controller reference, accessor path, typia-derived input schema, and
14
+ * input/output type info.
15
+ *
16
+ * @author wildduck - https://github.com/wildduck2
17
+ */
18
+ export interface ITypedMcpRoute {
19
+ protocol: "mcp";
20
+ controller: IReflectController;
21
+ name: string;
22
+ toolName: string;
23
+ title: string | null;
24
+ toolDescription: string | null;
25
+ accessor: string[];
26
+ function: Function;
27
+ input: IReflectMcpOperationParameter | null;
28
+ returnType: IReflectType | null;
29
+ inputSchema: object;
30
+ outputSchema: object | null;
31
+ annotations: IReflectMcpOperation.IAnnotations | null;
32
+ imports: IReflectImport[];
33
+ description: string | null;
34
+ jsDocTags: ts.JSDocTagInfo[];
35
+ }