loopback4-mcp 0.0.1

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 (87) hide show
  1. package/README.md +87 -0
  2. package/dist/component.d.ts +11 -0
  3. package/dist/component.js +22 -0
  4. package/dist/component.js.map +1 -0
  5. package/dist/constants/index.d.ts +1 -0
  6. package/dist/constants/index.js +5 -0
  7. package/dist/constants/index.js.map +1 -0
  8. package/dist/constants/mcp-tool.constant.d.ts +1 -0
  9. package/dist/constants/mcp-tool.constant.js +6 -0
  10. package/dist/constants/mcp-tool.constant.js.map +1 -0
  11. package/dist/controllers/index.d.ts +1 -0
  12. package/dist/controllers/index.js +5 -0
  13. package/dist/controllers/index.js.map +1 -0
  14. package/dist/controllers/mcp.controller.d.ts +10 -0
  15. package/dist/controllers/mcp.controller.js +121 -0
  16. package/dist/controllers/mcp.controller.js.map +1 -0
  17. package/dist/decorators/index.d.ts +1 -0
  18. package/dist/decorators/index.js +5 -0
  19. package/dist/decorators/index.js.map +1 -0
  20. package/dist/decorators/mcp-tool.decorator.d.ts +2 -0
  21. package/dist/decorators/mcp-tool.decorator.js +45 -0
  22. package/dist/decorators/mcp-tool.decorator.js.map +1 -0
  23. package/dist/index.d.ts +5 -0
  24. package/dist/index.js +9 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/interfaces/index.d.ts +1 -0
  27. package/dist/interfaces/index.js +5 -0
  28. package/dist/interfaces/index.js.map +1 -0
  29. package/dist/interfaces/mcp-hook-provider.interface.d.ts +12 -0
  30. package/dist/interfaces/mcp-hook-provider.interface.js +3 -0
  31. package/dist/interfaces/mcp-hook-provider.interface.js.map +1 -0
  32. package/dist/keys.d.ts +1 -0
  33. package/dist/keys.js +3 -0
  34. package/dist/keys.js.map +1 -0
  35. package/dist/observers/index.d.ts +1 -0
  36. package/dist/observers/index.js +5 -0
  37. package/dist/observers/index.js.map +1 -0
  38. package/dist/observers/mcp-tool-registry-boot.observer.d.ts +19 -0
  39. package/dist/observers/mcp-tool-registry-boot.observer.js +42 -0
  40. package/dist/observers/mcp-tool-registry-boot.observer.js.map +1 -0
  41. package/dist/services/index.d.ts +3 -0
  42. package/dist/services/index.js +7 -0
  43. package/dist/services/index.js.map +1 -0
  44. package/dist/services/mcp-schema-generator-service.service.d.ts +20 -0
  45. package/dist/services/mcp-schema-generator-service.service.js +73 -0
  46. package/dist/services/mcp-schema-generator-service.service.js.map +1 -0
  47. package/dist/services/mcp-server-factory.service.d.ts +13 -0
  48. package/dist/services/mcp-server-factory.service.js +51 -0
  49. package/dist/services/mcp-server-factory.service.js.map +1 -0
  50. package/dist/services/mcp-tool-registry.service.d.ts +49 -0
  51. package/dist/services/mcp-tool-registry.service.js +245 -0
  52. package/dist/services/mcp-tool-registry.service.js.map +1 -0
  53. package/dist/types.d.ts +46 -0
  54. package/dist/types.js +17 -0
  55. package/dist/types.js.map +1 -0
  56. package/dist/utils/index.d.ts +1 -0
  57. package/dist/utils/index.js +5 -0
  58. package/dist/utils/index.js.map +1 -0
  59. package/dist/utils/mcp-parameter-extractor.d.ts +9 -0
  60. package/dist/utils/mcp-parameter-extractor.js +51 -0
  61. package/dist/utils/mcp-parameter-extractor.js.map +1 -0
  62. package/package.json +139 -0
  63. package/src/component.ts +18 -0
  64. package/src/constants/index.ts +1 -0
  65. package/src/constants/mcp-tool.constant.ts +2 -0
  66. package/src/controllers/README.md +6 -0
  67. package/src/controllers/index.ts +1 -0
  68. package/src/controllers/mcp.controller.ts +112 -0
  69. package/src/decorators/README.md +34 -0
  70. package/src/decorators/index.ts +1 -0
  71. package/src/decorators/mcp-tool.decorator.ts +68 -0
  72. package/src/index.ts +5 -0
  73. package/src/interfaces/index.ts +1 -0
  74. package/src/interfaces/mcp-hook-provider.interface.ts +11 -0
  75. package/src/keys.ts +1 -0
  76. package/src/mixins/README.md +216 -0
  77. package/src/observers/index.ts +1 -0
  78. package/src/observers/mcp-tool-registry-boot.observer.ts +40 -0
  79. package/src/providers/README.md +129 -0
  80. package/src/repositories/README.md +5 -0
  81. package/src/services/index.ts +3 -0
  82. package/src/services/mcp-schema-generator-service.service.ts +80 -0
  83. package/src/services/mcp-server-factory.service.ts +71 -0
  84. package/src/services/mcp-tool-registry.service.ts +368 -0
  85. package/src/types.ts +59 -0
  86. package/src/utils/index.ts +1 -0
  87. package/src/utils/mcp-parameter-extractor.ts +67 -0
package/src/types.ts ADDED
@@ -0,0 +1,59 @@
1
+ import {BindingKey, Context} from '@loopback/core';
2
+ import {RequestHandlerExtra} from '@modelcontextprotocol/sdk/shared/protocol';
3
+ import {
4
+ CallToolResult,
5
+ ServerNotification,
6
+ ServerRequest,
7
+ } from '@modelcontextprotocol/sdk/types';
8
+ import * as z from 'zod';
9
+ import {McpHookFunction} from './interfaces';
10
+ const objectSchema = z.object({
11
+ content: z.array(
12
+ z.object({
13
+ type: z.literal('text'),
14
+ text: z.string(),
15
+ }),
16
+ ),
17
+ isError: z.boolean().optional(),
18
+ });
19
+ export type McpToolHandler = (
20
+ ctx: Context,
21
+ args: {[key: string]: unknown},
22
+ extras: RequestHandlerExtra<ServerRequest, ServerNotification>,
23
+ ) => CallToolResult | Promise<CallToolResult>;
24
+
25
+ export interface McpTool {
26
+ name: string;
27
+ description: string;
28
+ schema: z.ZodRawShape;
29
+ handler: McpToolHandler;
30
+ }
31
+
32
+ export interface McpHookConfig {
33
+ binding: BindingKey<McpHookFunction> | string;
34
+ config?: {[key: string]: unknown};
35
+ }
36
+
37
+ export interface McpToolMetadata {
38
+ name: string;
39
+ description: string;
40
+ schema: z.ZodRawShape;
41
+ controllerFunction: Function;
42
+ preHook?: McpHookConfig;
43
+ postHook?: McpHookConfig;
44
+ parameterNames?: string[]; // Populated from LoopBack metadata
45
+ controllerBinding?: BindingKey<object>;
46
+ }
47
+
48
+ export interface McpToolDecoratorOptions {
49
+ name: string;
50
+ description: string;
51
+ schema?: z.ZodRawShape;
52
+ preHook?: McpHookConfig;
53
+ postHook?: McpHookConfig;
54
+ }
55
+ export function isTextMessage(
56
+ message: unknown,
57
+ ): message is z.infer<typeof objectSchema> {
58
+ return objectSchema.safeParse(message).success;
59
+ }
@@ -0,0 +1 @@
1
+ export * from './mcp-parameter-extractor';
@@ -0,0 +1,67 @@
1
+ import {MetadataInspector} from '@loopback/core';
2
+ import {SchemaObject} from '@loopback/openapi-v3';
3
+ import {OAI3Keys} from '@loopback/openapi-v3/dist/keys';
4
+ import {ParameterObject} from '@loopback/rest';
5
+
6
+ /**
7
+ * Extract parameter information using LoopBack's parameter metadata system
8
+ * Developers creating MCP tools must use @param decorators
9
+ */
10
+ export function extractParameterInfo(target: Object, propertyKey: string) {
11
+ const paramMetadata = MetadataInspector.getMethodMetadata(
12
+ OAI3Keys.PARAMETERS_KEY, // LoopBack parameter metadata key
13
+ target,
14
+ propertyKey,
15
+ );
16
+
17
+ if (
18
+ !paramMetadata ||
19
+ !Array.isArray(paramMetadata) ||
20
+ paramMetadata.length === 0
21
+ ) {
22
+ throw new Error(
23
+ `No LoopBack parameter metadata found for ${propertyKey}. ` +
24
+ `MCP tools must use @param decorators (e.g., @param.query.string('paramName'))`,
25
+ );
26
+ }
27
+
28
+ const parameterNames = paramMetadata.map(
29
+ (param: ParameterObject, index: number) => {
30
+ if (!param.name) {
31
+ throw new Error(
32
+ `Parameter ${index} in ${propertyKey} is missing name. Use @param.query.string('name')`,
33
+ );
34
+ }
35
+ return param.name;
36
+ },
37
+ );
38
+
39
+ const parameterOptional = paramMetadata.map(
40
+ (param: ParameterObject) => param.required === false,
41
+ );
42
+
43
+ const parameterTypes = paramMetadata.map((param: ParameterObject) => {
44
+ // Extract type information from LoopBack parameter schema
45
+ const schema = param.schema as SchemaObject;
46
+ if (schema?.type) {
47
+ switch (schema.type) {
48
+ case 'string':
49
+ return 'string';
50
+ case 'number':
51
+ case 'integer':
52
+ return 'number';
53
+ case 'boolean':
54
+ return 'boolean';
55
+ case 'object':
56
+ return 'object';
57
+ case 'array':
58
+ return 'array';
59
+ default:
60
+ return 'any';
61
+ }
62
+ }
63
+ return 'any';
64
+ });
65
+
66
+ return {parameterNames, parameterOptional, parameterTypes};
67
+ }