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.
- package/README.md +87 -0
- package/dist/component.d.ts +11 -0
- package/dist/component.js +22 -0
- package/dist/component.js.map +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +5 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/constants/mcp-tool.constant.d.ts +1 -0
- package/dist/constants/mcp-tool.constant.js +6 -0
- package/dist/constants/mcp-tool.constant.js.map +1 -0
- package/dist/controllers/index.d.ts +1 -0
- package/dist/controllers/index.js +5 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/controllers/mcp.controller.d.ts +10 -0
- package/dist/controllers/mcp.controller.js +121 -0
- package/dist/controllers/mcp.controller.js.map +1 -0
- package/dist/decorators/index.d.ts +1 -0
- package/dist/decorators/index.js +5 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/mcp-tool.decorator.d.ts +2 -0
- package/dist/decorators/mcp-tool.decorator.js +45 -0
- package/dist/decorators/mcp-tool.decorator.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/index.js +5 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/interfaces/mcp-hook-provider.interface.d.ts +12 -0
- package/dist/interfaces/mcp-hook-provider.interface.js +3 -0
- package/dist/interfaces/mcp-hook-provider.interface.js.map +1 -0
- package/dist/keys.d.ts +1 -0
- package/dist/keys.js +3 -0
- package/dist/keys.js.map +1 -0
- package/dist/observers/index.d.ts +1 -0
- package/dist/observers/index.js +5 -0
- package/dist/observers/index.js.map +1 -0
- package/dist/observers/mcp-tool-registry-boot.observer.d.ts +19 -0
- package/dist/observers/mcp-tool-registry-boot.observer.js +42 -0
- package/dist/observers/mcp-tool-registry-boot.observer.js.map +1 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +7 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/mcp-schema-generator-service.service.d.ts +20 -0
- package/dist/services/mcp-schema-generator-service.service.js +73 -0
- package/dist/services/mcp-schema-generator-service.service.js.map +1 -0
- package/dist/services/mcp-server-factory.service.d.ts +13 -0
- package/dist/services/mcp-server-factory.service.js +51 -0
- package/dist/services/mcp-server-factory.service.js.map +1 -0
- package/dist/services/mcp-tool-registry.service.d.ts +49 -0
- package/dist/services/mcp-tool-registry.service.js +245 -0
- package/dist/services/mcp-tool-registry.service.js.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/mcp-parameter-extractor.d.ts +9 -0
- package/dist/utils/mcp-parameter-extractor.js +51 -0
- package/dist/utils/mcp-parameter-extractor.js.map +1 -0
- package/package.json +139 -0
- package/src/component.ts +18 -0
- package/src/constants/index.ts +1 -0
- package/src/constants/mcp-tool.constant.ts +2 -0
- package/src/controllers/README.md +6 -0
- package/src/controllers/index.ts +1 -0
- package/src/controllers/mcp.controller.ts +112 -0
- package/src/decorators/README.md +34 -0
- package/src/decorators/index.ts +1 -0
- package/src/decorators/mcp-tool.decorator.ts +68 -0
- package/src/index.ts +5 -0
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/mcp-hook-provider.interface.ts +11 -0
- package/src/keys.ts +1 -0
- package/src/mixins/README.md +216 -0
- package/src/observers/index.ts +1 -0
- package/src/observers/mcp-tool-registry-boot.observer.ts +40 -0
- package/src/providers/README.md +129 -0
- package/src/repositories/README.md +5 -0
- package/src/services/index.ts +3 -0
- package/src/services/mcp-schema-generator-service.service.ts +80 -0
- package/src/services/mcp-server-factory.service.ts +71 -0
- package/src/services/mcp-tool-registry.service.ts +368 -0
- package/src/types.ts +59 -0
- package/src/utils/index.ts +1 -0
- 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
|
+
}
|