@malek0512/loopback4-mcp 1.0.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.
- package/README.md +124 -0
- package/dist/component.d.ts +8 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/component.js +67 -0
- package/dist/component.js.map +1 -0
- package/dist/controllers/index.d.ts +2 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/index.js +18 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/controllers/mcp.controller.d.ts +16 -0
- package/dist/controllers/mcp.controller.d.ts.map +1 -0
- package/dist/controllers/mcp.controller.js +66 -0
- package/dist/controllers/mcp.controller.js.map +1 -0
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +18 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/mcp-tool.decorator.d.ts +21 -0
- package/dist/decorators/mcp-tool.decorator.d.ts.map +1 -0
- package/dist/decorators/mcp-tool.decorator.js +30 -0
- package/dist/decorators/mcp-tool.decorator.js.map +1 -0
- package/dist/execution/context-manager.d.ts +14 -0
- package/dist/execution/context-manager.d.ts.map +1 -0
- package/dist/execution/context-manager.js +41 -0
- package/dist/execution/context-manager.js.map +1 -0
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +20 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/result-formatter.d.ts +16 -0
- package/dist/execution/result-formatter.d.ts.map +1 -0
- package/dist/execution/result-formatter.js +102 -0
- package/dist/execution/result-formatter.js.map +1 -0
- package/dist/execution/tool-executor.d.ts +12 -0
- package/dist/execution/tool-executor.d.ts.map +1 -0
- package/dist/execution/tool-executor.js +72 -0
- package/dist/execution/tool-executor.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/observers/index.d.ts +2 -0
- package/dist/observers/index.d.ts.map +1 -0
- package/dist/observers/index.js +18 -0
- package/dist/observers/index.js.map +1 -0
- package/dist/observers/mcp-boot.observer.d.ts +9 -0
- package/dist/observers/mcp-boot.observer.d.ts.map +1 -0
- package/dist/observers/mcp-boot.observer.js +36 -0
- package/dist/observers/mcp-boot.observer.js.map +1 -0
- package/dist/protocol/index.d.ts +4 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +20 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/json-rpc.handler.d.ts +10 -0
- package/dist/protocol/json-rpc.handler.d.ts.map +1 -0
- package/dist/protocol/json-rpc.handler.js +63 -0
- package/dist/protocol/json-rpc.handler.js.map +1 -0
- package/dist/protocol/message-router.d.ts +18 -0
- package/dist/protocol/message-router.d.ts.map +1 -0
- package/dist/protocol/message-router.js +106 -0
- package/dist/protocol/message-router.js.map +1 -0
- package/dist/protocol/types.d.ts +227 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +56 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/registry/index.d.ts +4 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +20 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/metadata-scanner.d.ts +13 -0
- package/dist/registry/metadata-scanner.d.ts.map +1 -0
- package/dist/registry/metadata-scanner.js +101 -0
- package/dist/registry/metadata-scanner.js.map +1 -0
- package/dist/registry/schema-generator.d.ts +19 -0
- package/dist/registry/schema-generator.d.ts.map +1 -0
- package/dist/registry/schema-generator.js +90 -0
- package/dist/registry/schema-generator.js.map +1 -0
- package/dist/registry/tool-registry.d.ts +23 -0
- package/dist/registry/tool-registry.d.ts.map +1 -0
- package/dist/registry/tool-registry.js +58 -0
- package/dist/registry/tool-registry.js.map +1 -0
- package/dist/transport/index.d.ts +2 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +18 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/sse.transport.d.ts +9 -0
- package/dist/transport/sse.transport.d.ts.map +1 -0
- package/dist/transport/sse.transport.js +67 -0
- package/dist/transport/sse.transport.js.map +1 -0
- package/package.json +26 -0
- package/src/component.ts +58 -0
- package/src/controllers/index.ts +1 -0
- package/src/controllers/mcp.controller.ts +42 -0
- package/src/decorators/index.ts +1 -0
- package/src/decorators/mcp-tool.decorator.ts +57 -0
- package/src/execution/context-manager.ts +44 -0
- package/src/execution/index.ts +3 -0
- package/src/execution/result-formatter.ts +104 -0
- package/src/execution/tool-executor.ts +61 -0
- package/src/index.ts +5 -0
- package/src/observers/index.ts +1 -0
- package/src/observers/mcp-boot.observer.ts +19 -0
- package/src/protocol/index.ts +3 -0
- package/src/protocol/json-rpc.handler.ts +77 -0
- package/src/protocol/message-router.ts +125 -0
- package/src/protocol/types.ts +309 -0
- package/src/registry/index.ts +3 -0
- package/src/registry/metadata-scanner.ts +105 -0
- package/src/registry/schema-generator.ts +82 -0
- package/src/registry/tool-registry.ts +57 -0
- package/src/transport/index.ts +1 -0
- package/src/transport/sse.transport.ts +56 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {bind, BindingScope, inject} from '@loopback/core';
|
|
2
|
+
import {Tool, JsonSchema} from '../protocol/types';
|
|
3
|
+
import {SchemaGenerator} from './schema-generator';
|
|
4
|
+
|
|
5
|
+
export interface ToolDescriptor {
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
inputSchema: JsonSchema;
|
|
9
|
+
controller: Object;
|
|
10
|
+
methodName: string;
|
|
11
|
+
handler: Function;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@bind({scope: BindingScope.SINGLETON})
|
|
15
|
+
export class ToolRegistry {
|
|
16
|
+
private tools = new Map<string, ToolDescriptor>();
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
@inject('mcp.schemaGenerator')
|
|
20
|
+
private schemaGenerator: SchemaGenerator,
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
register(descriptor: ToolDescriptor): void {
|
|
24
|
+
if (this.tools.has(descriptor.name)) {
|
|
25
|
+
throw new Error(`Tool '${descriptor.name}' is already registered`);
|
|
26
|
+
}
|
|
27
|
+
this.tools.set(descriptor.name, descriptor);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
unregister(name: string): boolean {
|
|
31
|
+
return this.tools.delete(name);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get(name: string): ToolDescriptor | undefined {
|
|
35
|
+
return this.tools.get(name);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
list(): Tool[] {
|
|
39
|
+
return Array.from(this.tools.values()).map(descriptor => ({
|
|
40
|
+
name: descriptor.name,
|
|
41
|
+
description: descriptor.description,
|
|
42
|
+
inputSchema: descriptor.inputSchema as any,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
has(name: string): boolean {
|
|
47
|
+
return this.tools.has(name);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
clear(): void {
|
|
51
|
+
this.tools.clear();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get size(): number {
|
|
55
|
+
return this.tools.size;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './sse.transport';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {bind, BindingScope, inject} from '@loopback/core';
|
|
2
|
+
import {Request, Response} from '@loopback/rest';
|
|
3
|
+
import {MessageRouter} from '../protocol/message-router';
|
|
4
|
+
import {JsonRpcRequest} from '../protocol/types';
|
|
5
|
+
|
|
6
|
+
@bind({scope: BindingScope.SINGLETON})
|
|
7
|
+
export class SseTransport {
|
|
8
|
+
constructor(
|
|
9
|
+
@inject('mcp.messageRouter')
|
|
10
|
+
private messageRouter: MessageRouter,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
async handleConnection(req: Request, res: Response): Promise<void> {
|
|
14
|
+
// Set SSE headers
|
|
15
|
+
res.setHeader('Content-Type', 'text/event-stream');
|
|
16
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
17
|
+
res.setHeader('Connection', 'keep-alive');
|
|
18
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
19
|
+
|
|
20
|
+
// Send initial connection event
|
|
21
|
+
this.sendEvent(res, 'connected', {message: 'MCP Server connected'});
|
|
22
|
+
|
|
23
|
+
// Handle incoming messages
|
|
24
|
+
req.on('data', async (chunk: Buffer) => {
|
|
25
|
+
try {
|
|
26
|
+
const message = JSON.parse(chunk.toString()) as JsonRpcRequest;
|
|
27
|
+
const response = await this.messageRouter.route(message);
|
|
28
|
+
this.sendEvent(res, 'message', response);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
this.sendEvent(res, 'error', {
|
|
31
|
+
message: 'Failed to process message',
|
|
32
|
+
error: error instanceof Error ? error.message : String(error),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Handle connection close
|
|
38
|
+
req.on('close', () => {
|
|
39
|
+
console.log('SSE connection closed');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Keep connection alive
|
|
43
|
+
const keepAliveInterval = setInterval(() => {
|
|
44
|
+
this.sendEvent(res, 'ping', {timestamp: Date.now()});
|
|
45
|
+
}, 30000);
|
|
46
|
+
|
|
47
|
+
req.on('close', () => {
|
|
48
|
+
clearInterval(keepAliveInterval);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private sendEvent(res: Response, event: string, data: unknown): void {
|
|
53
|
+
res.write(`event: ${event}\n`);
|
|
54
|
+
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
55
|
+
}
|
|
56
|
+
}
|