@forestadmin/ai-proxy 0.0.1 → 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/dist/errors.d.ts +42 -0
- package/dist/errors.js +86 -0
- package/dist/examples/run-mcp-calculator-server.d.ts +2 -0
- package/dist/examples/run-mcp-calculator-server.js +21 -0
- package/dist/examples/run-mcp-zendesk-server.d.ts +2 -0
- package/dist/examples/run-mcp-zendesk-server.js +29 -0
- package/dist/examples/simple-mcp-server.d.ts +4 -0
- package/dist/examples/simple-mcp-server.js +80 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +30 -0
- package/dist/mcp-client.d.ts +16 -0
- package/dist/mcp-client.js +83 -0
- package/dist/mcp-config-checker.d.ts +5 -0
- package/dist/mcp-config-checker.js +13 -0
- package/dist/provider-dispatcher.d.ts +19 -0
- package/dist/provider-dispatcher.js +56 -0
- package/dist/remote-tool.d.ts +15 -0
- package/dist/remote-tool.js +19 -0
- package/dist/remote-tools.d.ts +22 -0
- package/dist/remote-tools.js +49 -0
- package/dist/router.d.ts +43 -0
- package/dist/router.js +65 -0
- package/package.json +1 -1
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* -------------------------------------
|
|
3
|
+
* -------------------------------------
|
|
4
|
+
* -------------------------------------
|
|
5
|
+
* All custom errors must extend the AIError class.
|
|
6
|
+
* This inheritance is crucial for proper error translation
|
|
7
|
+
* and consistent handling throughout the system.
|
|
8
|
+
* -------------------------------------
|
|
9
|
+
* -------------------------------------
|
|
10
|
+
* -------------------------------------
|
|
11
|
+
*/
|
|
12
|
+
export declare class AIError extends Error {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class AIUnprocessableError extends AIError {
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
export declare class AINotConfiguredError extends AIError {
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
21
|
+
export declare class OpenAIUnprocessableError extends AIUnprocessableError {
|
|
22
|
+
constructor(message: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class AIToolUnprocessableError extends AIUnprocessableError {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
export declare class AIToolNotFoundError extends AIError {
|
|
28
|
+
constructor(message: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class McpError extends AIError {
|
|
31
|
+
constructor(message: string);
|
|
32
|
+
}
|
|
33
|
+
export declare class McpConnectionError extends McpError {
|
|
34
|
+
constructor(message: string);
|
|
35
|
+
}
|
|
36
|
+
export declare class McpConflictError extends McpError {
|
|
37
|
+
constructor(entityName: string);
|
|
38
|
+
}
|
|
39
|
+
export declare class McpConfigError extends McpError {
|
|
40
|
+
constructor(message: string);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* -------------------------------------
|
|
4
|
+
* -------------------------------------
|
|
5
|
+
* -------------------------------------
|
|
6
|
+
* All custom errors must extend the AIError class.
|
|
7
|
+
* This inheritance is crucial for proper error translation
|
|
8
|
+
* and consistent handling throughout the system.
|
|
9
|
+
* -------------------------------------
|
|
10
|
+
* -------------------------------------
|
|
11
|
+
* -------------------------------------
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.McpConfigError = exports.McpConflictError = exports.McpConnectionError = exports.McpError = exports.AIToolNotFoundError = exports.AIToolUnprocessableError = exports.OpenAIUnprocessableError = exports.AINotConfiguredError = exports.AIUnprocessableError = exports.AIError = void 0;
|
|
15
|
+
// eslint-disable-next-line max-classes-per-file
|
|
16
|
+
class AIError extends Error {
|
|
17
|
+
constructor(message) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = 'AIError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.AIError = AIError;
|
|
23
|
+
class AIUnprocessableError extends AIError {
|
|
24
|
+
constructor(message) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = 'AIUnprocessableError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.AIUnprocessableError = AIUnprocessableError;
|
|
30
|
+
class AINotConfiguredError extends AIError {
|
|
31
|
+
constructor() {
|
|
32
|
+
super('AI is not configured. Please call addAI() on your agent.');
|
|
33
|
+
this.name = 'AINotConfiguredError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.AINotConfiguredError = AINotConfiguredError;
|
|
37
|
+
class OpenAIUnprocessableError extends AIUnprocessableError {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = 'OpenAIError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.OpenAIUnprocessableError = OpenAIUnprocessableError;
|
|
44
|
+
class AIToolUnprocessableError extends AIUnprocessableError {
|
|
45
|
+
constructor(message) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = 'AIToolError';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.AIToolUnprocessableError = AIToolUnprocessableError;
|
|
51
|
+
class AIToolNotFoundError extends AIError {
|
|
52
|
+
constructor(message) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.name = 'AIToolNotFoundError';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.AIToolNotFoundError = AIToolNotFoundError;
|
|
58
|
+
class McpError extends AIError {
|
|
59
|
+
constructor(message) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = 'McpError';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.McpError = McpError;
|
|
65
|
+
class McpConnectionError extends McpError {
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.name = 'McpConnectionError';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.McpConnectionError = McpConnectionError;
|
|
72
|
+
class McpConflictError extends McpError {
|
|
73
|
+
constructor(entityName) {
|
|
74
|
+
super(`"${entityName}" already exists for your project`);
|
|
75
|
+
this.name = 'McpConflictError';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.McpConflictError = McpConflictError;
|
|
79
|
+
class McpConfigError extends McpError {
|
|
80
|
+
constructor(message) {
|
|
81
|
+
super(message);
|
|
82
|
+
this.name = 'McpConfigError';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.McpConfigError = McpConfigError;
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Vycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7R0FVRzs7O0FBRUgsZ0RBQWdEO0FBQ2hELE1BQWEsT0FBUSxTQUFRLEtBQUs7SUFDaEMsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFDO0lBQ3hCLENBQUM7Q0FDRjtBQUxELDBCQUtDO0FBRUQsTUFBYSxvQkFBcUIsU0FBUSxPQUFPO0lBQy9DLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLHNCQUFzQixDQUFDO0lBQ3JDLENBQUM7Q0FDRjtBQUxELG9EQUtDO0FBRUQsTUFBYSxvQkFBcUIsU0FBUSxPQUFPO0lBQy9DO1FBQ0UsS0FBSyxDQUFDLDBEQUEwRCxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLElBQUksR0FBRyxzQkFBc0IsQ0FBQztJQUNyQyxDQUFDO0NBQ0Y7QUFMRCxvREFLQztBQUVELE1BQWEsd0JBQXlCLFNBQVEsb0JBQW9CO0lBQ2hFLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLGFBQWEsQ0FBQztJQUM1QixDQUFDO0NBQ0Y7QUFMRCw0REFLQztBQUVELE1BQWEsd0JBQXlCLFNBQVEsb0JBQW9CO0lBQ2hFLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLGFBQWEsQ0FBQztJQUM1QixDQUFDO0NBQ0Y7QUFMRCw0REFLQztBQUVELE1BQWEsbUJBQW9CLFNBQVEsT0FBTztJQUM5QyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxxQkFBcUIsQ0FBQztJQUNwQyxDQUFDO0NBQ0Y7QUFMRCxrREFLQztBQUVELE1BQWEsUUFBUyxTQUFRLE9BQU87SUFDbkMsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDO0lBQ3pCLENBQUM7Q0FDRjtBQUxELDRCQUtDO0FBRUQsTUFBYSxrQkFBbUIsU0FBUSxRQUFRO0lBQzlDLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLG9CQUFvQixDQUFDO0lBQ25DLENBQUM7Q0FDRjtBQUxELGdEQUtDO0FBRUQsTUFBYSxnQkFBaUIsU0FBUSxRQUFRO0lBQzVDLFlBQVksVUFBa0I7UUFDNUIsS0FBSyxDQUFDLElBQUksVUFBVSxtQ0FBbUMsQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBTEQsNENBS0M7QUFFRCxNQUFhLGNBQWUsU0FBUSxRQUFRO0lBQzFDLFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLGdCQUFnQixDQUFDO0lBQy9CLENBQUM7Q0FDRjtBQUxELHdDQUtDIn0=
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable import/no-extraneous-dependencies, import/extensions */
|
|
7
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
8
|
+
const zod_1 = require("zod");
|
|
9
|
+
/* eslint-enable import/no-extraneous-dependencies, import/extensions */
|
|
10
|
+
const simple_mcp_server_1 = __importDefault(require("./simple-mcp-server"));
|
|
11
|
+
const server = new mcp_js_1.McpServer({
|
|
12
|
+
name: 'calculator',
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
});
|
|
15
|
+
server.tool('add', { a: zod_1.z.number(), b: zod_1.z.number() }, async ({ a, b }) => {
|
|
16
|
+
// eslint-disable-next-line no-console
|
|
17
|
+
console.log('Received add request:', a, b);
|
|
18
|
+
return { content: [{ type: 'text', text: String(a + b) }] };
|
|
19
|
+
});
|
|
20
|
+
(0, simple_mcp_server_1.default)(server, 3123);
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLW1jcC1jYWxjdWxhdG9yLXNlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leGFtcGxlcy9ydW4tbWNwLWNhbGN1bGF0b3Itc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUVBQXlFO0FBQ3pFLG9FQUFvRTtBQUNwRSw2QkFBd0I7QUFDeEIsd0VBQXdFO0FBRXhFLDRFQUErQztBQUUvQyxNQUFNLE1BQU0sR0FBRyxJQUFJLGtCQUFTLENBQUM7SUFDM0IsSUFBSSxFQUFFLFlBQVk7SUFDbEIsT0FBTyxFQUFFLE9BQU87Q0FDakIsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRTtJQUN0RSxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFM0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztBQUM5RCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUEsMkJBQVksRUFBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMifQ==
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable import/no-extraneous-dependencies, import/extensions */
|
|
7
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
8
|
+
const node_zendesk_1 = __importDefault(require("node-zendesk"));
|
|
9
|
+
/* eslint-enable import/no-extraneous-dependencies, import/extensions */
|
|
10
|
+
const simple_mcp_server_1 = __importDefault(require("./simple-mcp-server"));
|
|
11
|
+
const client = node_zendesk_1.default.createClient({
|
|
12
|
+
username: 'your-email@example.com',
|
|
13
|
+
token: 'YOUR_ZENDESK_API_TOKEN',
|
|
14
|
+
subdomain: 'your-subdomain',
|
|
15
|
+
});
|
|
16
|
+
const server = new mcp_js_1.McpServer({
|
|
17
|
+
name: 'zendesk',
|
|
18
|
+
version: '1.0.0',
|
|
19
|
+
});
|
|
20
|
+
server.tool('listUsers', {}, async () => {
|
|
21
|
+
const users = await client.users.list();
|
|
22
|
+
return { content: [{ type: 'text', text: JSON.stringify(users.map(u => u.name)) }] };
|
|
23
|
+
});
|
|
24
|
+
server.tool('listArticles', {}, async () => {
|
|
25
|
+
const articles = await client.helpcenter.articles.list();
|
|
26
|
+
return { content: [{ type: 'text', text: JSON.stringify(articles) }] };
|
|
27
|
+
});
|
|
28
|
+
(0, simple_mcp_server_1.default)(server, 3124);
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLW1jcC16ZW5kZXNrLXNlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leGFtcGxlcy9ydW4tbWNwLXplbmRlc2stc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUVBQXlFO0FBQ3pFLG9FQUFvRTtBQUNwRSxnRUFBbUM7QUFDbkMsd0VBQXdFO0FBRXhFLDRFQUErQztBQUUvQyxNQUFNLE1BQU0sR0FBRyxzQkFBTyxDQUFDLFlBQVksQ0FBQztJQUNsQyxRQUFRLEVBQUUsd0JBQXdCO0lBQ2xDLEtBQUssRUFBRSx3QkFBd0I7SUFDL0IsU0FBUyxFQUFFLGdCQUFnQjtDQUM1QixDQUFDLENBQUM7QUFFSCxNQUFNLE1BQU0sR0FBRyxJQUFJLGtCQUFTLENBQUM7SUFDM0IsSUFBSSxFQUFFLFNBQVM7SUFDZixPQUFPLEVBQUUsT0FBTztDQUNqQixDQUFDLENBQUM7QUFFSCxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDdEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0lBRXhDLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0FBQ3ZGLENBQUMsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsRUFBRSxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3pDLE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFekQsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztBQUN6RSxDQUFDLENBQUMsQ0FBQztBQUVILElBQUEsMkJBQVksRUFBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMifQ==
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
declare const _default: (server: McpServer, port: number, secureToken?: string) => import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
|
|
3
|
+
export default _default;
|
|
4
|
+
//# sourceMappingURL=simple-mcp-server.d.ts.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
/* eslint-enable import/no-extraneous-dependencies, import/extensions */
|
|
9
|
+
const BEARER_TOKEN = 'your-secure-token-here';
|
|
10
|
+
exports.default = (server, port, secureToken = BEARER_TOKEN) => {
|
|
11
|
+
const app = (0, express_1.default)();
|
|
12
|
+
app.use(express_1.default.json());
|
|
13
|
+
// Bearer Token Middleware
|
|
14
|
+
app.use('/mcp', (req, res, next) => {
|
|
15
|
+
const authHeader = req.headers.authorization || '';
|
|
16
|
+
const token = authHeader.replace(/^Bearer\s+/i, '');
|
|
17
|
+
if (token !== secureToken) {
|
|
18
|
+
res.status(401).json({
|
|
19
|
+
jsonrpc: '2.0',
|
|
20
|
+
error: {
|
|
21
|
+
code: -32001,
|
|
22
|
+
message: 'Unauthorized: Invalid or missing Bearer token',
|
|
23
|
+
},
|
|
24
|
+
id: null,
|
|
25
|
+
});
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
next();
|
|
29
|
+
});
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
31
|
+
app.post('/mcp', async (req, res) => {
|
|
32
|
+
try {
|
|
33
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
34
|
+
sessionIdGenerator: undefined,
|
|
35
|
+
});
|
|
36
|
+
res.on('close', () => {
|
|
37
|
+
// eslint-disable-next-line no-console
|
|
38
|
+
console.log('Request closed');
|
|
39
|
+
void transport.close();
|
|
40
|
+
void server.close();
|
|
41
|
+
});
|
|
42
|
+
await server.connect(transport);
|
|
43
|
+
await transport.handleRequest(req, res, req.body);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error('Error handling MCP request:', error);
|
|
47
|
+
if (!res.headersSent) {
|
|
48
|
+
res.status(500).json({
|
|
49
|
+
jsonrpc: '2.0',
|
|
50
|
+
error: {
|
|
51
|
+
code: -32603,
|
|
52
|
+
message: 'Internal server error',
|
|
53
|
+
},
|
|
54
|
+
id: null,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
60
|
+
app.get('/mcp', async (req, res) => {
|
|
61
|
+
res.writeHead(405).end(JSON.stringify({
|
|
62
|
+
jsonrpc: '2.0',
|
|
63
|
+
error: { code: -32000, message: 'Method not allowed.' },
|
|
64
|
+
id: null,
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
68
|
+
app.delete('/mcp', async (req, res) => {
|
|
69
|
+
res.writeHead(405).end(JSON.stringify({
|
|
70
|
+
jsonrpc: '2.0',
|
|
71
|
+
error: { code: -32000, message: 'Method not allowed.' },
|
|
72
|
+
id: null,
|
|
73
|
+
}));
|
|
74
|
+
});
|
|
75
|
+
return app.listen(port, () => {
|
|
76
|
+
// eslint-disable-next-line no-console
|
|
77
|
+
console.log(`MCP Stateless Streamable HTTP Server listening on port ${port}`);
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlLW1jcC1zZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZXhhbXBsZXMvc2ltcGxlLW1jcC1zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFHQSwwRkFBbUc7QUFDbkcsc0RBQThCO0FBQzlCLHdFQUF3RTtBQUV4RSxNQUFNLFlBQVksR0FBRyx3QkFBd0IsQ0FBQztBQUU5QyxrQkFBZSxDQUFDLE1BQWlCLEVBQUUsSUFBWSxFQUFFLGNBQXNCLFlBQVksRUFBRSxFQUFFO0lBQ3JGLE1BQU0sR0FBRyxHQUFHLElBQUEsaUJBQU8sR0FBRSxDQUFDO0lBQ3RCLEdBQUcsQ0FBQyxHQUFHLENBQUMsaUJBQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRXhCLDBCQUEwQjtJQUMxQixHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDakMsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksRUFBRSxDQUFDO1FBQ25ELE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRXBELElBQUksS0FBSyxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQzFCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNuQixPQUFPLEVBQUUsS0FBSztnQkFDZCxLQUFLLEVBQUU7b0JBQ0wsSUFBSSxFQUFFLENBQUMsS0FBSztvQkFDWixPQUFPLEVBQUUsK0NBQStDO2lCQUN6RDtnQkFDRCxFQUFFLEVBQUUsSUFBSTthQUNULENBQUMsQ0FBQztZQUVILE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxFQUFFLENBQUM7SUFDVCxDQUFDLENBQUMsQ0FBQztJQUVILGtFQUFrRTtJQUNsRSxHQUFHLENBQUMsSUFBSSxDQUFD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
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { McpConfiguration } from './mcp-client';
|
|
2
|
+
export * from './provider-dispatcher';
|
|
3
|
+
export * from './remote-tools';
|
|
4
|
+
export * from './router';
|
|
5
|
+
export * from './mcp-client';
|
|
6
|
+
export * from './errors';
|
|
7
|
+
export declare function validMcpConfigurationOrThrow(mcpConfig: McpConfiguration): Promise<true>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.validMcpConfigurationOrThrow = validMcpConfigurationOrThrow;
|
|
21
|
+
const mcp_config_checker_1 = __importDefault(require("./mcp-config-checker"));
|
|
22
|
+
__exportStar(require("./provider-dispatcher"), exports);
|
|
23
|
+
__exportStar(require("./remote-tools"), exports);
|
|
24
|
+
__exportStar(require("./router"), exports);
|
|
25
|
+
__exportStar(require("./mcp-client"), exports);
|
|
26
|
+
__exportStar(require("./errors"), exports);
|
|
27
|
+
function validMcpConfigurationOrThrow(mcpConfig) {
|
|
28
|
+
return mcp_config_checker_1.default.check(mcpConfig);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVdBLG9FQUVDO0FBWEQsOEVBQW9EO0FBRXBELHdEQUFzQztBQUN0QyxpREFBK0I7QUFDL0IsMkNBQXlCO0FBQ3pCLCtDQUE2QjtBQUU3QiwyQ0FBeUI7QUFFekIsU0FBZ0IsNEJBQTRCLENBQUMsU0FBMkI7SUFDdEUsT0FBTyw0QkFBZ0IsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDM0MsQ0FBQyJ9
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Logger } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
|
|
3
|
+
import RemoteTool from './remote-tool';
|
|
4
|
+
export type McpConfiguration = {
|
|
5
|
+
configs: MultiServerMCPClient['config']['mcpServers'];
|
|
6
|
+
} & Omit<MultiServerMCPClient['config'], 'mcpServers'>;
|
|
7
|
+
export default class McpClient {
|
|
8
|
+
private readonly mcpClients;
|
|
9
|
+
private readonly logger?;
|
|
10
|
+
readonly tools: RemoteTool[];
|
|
11
|
+
constructor(config: McpConfiguration, logger?: Logger);
|
|
12
|
+
loadTools(): Promise<RemoteTool[]>;
|
|
13
|
+
testConnections(): Promise<true>;
|
|
14
|
+
closeConnections(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=mcp-client.d.ts.map
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const mcp_adapters_1 = require("@langchain/mcp-adapters");
|
|
7
|
+
const errors_1 = require("./errors");
|
|
8
|
+
const remote_tool_1 = __importDefault(require("./remote-tool"));
|
|
9
|
+
class McpClient {
|
|
10
|
+
constructor(config, logger) {
|
|
11
|
+
this.mcpClients = {};
|
|
12
|
+
this.tools = [];
|
|
13
|
+
this.logger = logger;
|
|
14
|
+
// split the config into several clients to be more resilient
|
|
15
|
+
// if a mcp server is down, the others will still work
|
|
16
|
+
Object.entries(config.configs).forEach(([name, serverConfig]) => {
|
|
17
|
+
this.mcpClients[name] = new mcp_adapters_1.MultiServerMCPClient({
|
|
18
|
+
mcpServers: { [name]: serverConfig },
|
|
19
|
+
...config,
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async loadTools() {
|
|
24
|
+
const errors = [];
|
|
25
|
+
await Promise.all(Object.entries(this.mcpClients).map(async ([name, client]) => {
|
|
26
|
+
try {
|
|
27
|
+
const tools = (await client.getTools()) ?? [];
|
|
28
|
+
const extendedTools = tools.map(tool => new remote_tool_1.default({
|
|
29
|
+
tool,
|
|
30
|
+
sourceId: name,
|
|
31
|
+
sourceType: 'mcp-server',
|
|
32
|
+
}));
|
|
33
|
+
this.tools.push(...extendedTools);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
this.logger?.('Error', `Error loading tools for ${name}`, error);
|
|
37
|
+
errors.push({ server: name, error: error });
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
// Surface partial failures to provide better feedback
|
|
41
|
+
if (errors.length > 0) {
|
|
42
|
+
const errorMessage = errors.map(e => `${e.server}: ${e.error.message}`).join('; ');
|
|
43
|
+
this.logger?.('Error', `Failed to load tools from ${errors.length}/${Object.keys(this.mcpClients).length} ` +
|
|
44
|
+
`MCP server(s): ${errorMessage}`);
|
|
45
|
+
}
|
|
46
|
+
return this.tools;
|
|
47
|
+
}
|
|
48
|
+
async testConnections() {
|
|
49
|
+
try {
|
|
50
|
+
await Promise.all(Object.values(this.mcpClients).map(client => client.initializeConnections()));
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new errors_1.McpConnectionError(error.message);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
try {
|
|
58
|
+
await this.closeConnections();
|
|
59
|
+
}
|
|
60
|
+
catch (cleanupError) {
|
|
61
|
+
// Log but don't throw - we don't want to mask the original connection error
|
|
62
|
+
this.logger?.('Error', 'Error during test connection cleanup', cleanupError);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async closeConnections() {
|
|
67
|
+
const entries = Object.entries(this.mcpClients);
|
|
68
|
+
const results = await Promise.allSettled(entries.map(([, client]) => client.close()));
|
|
69
|
+
// Check for failures but don't throw - cleanup should be best-effort
|
|
70
|
+
const failures = results
|
|
71
|
+
.map((result, index) => ({ result, name: entries[index][0] }))
|
|
72
|
+
.filter(({ result }) => result.status === 'rejected');
|
|
73
|
+
if (failures.length > 0) {
|
|
74
|
+
failures.forEach(({ name, result }) => {
|
|
75
|
+
this.logger?.('Error', `Failed to close MCP connection for ${name}`, result.reason);
|
|
76
|
+
});
|
|
77
|
+
this.logger?.('Error', `Failed to close ${failures.length}/${results.length} MCP connections. ` +
|
|
78
|
+
`This may result in resource leaks.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.default = McpClient;
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWNwLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tY3AtY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBRUEsMERBQStEO0FBRS9ELHFDQUE4QztBQUM5QyxnRUFBdUM7QUFNdkMsTUFBcUIsU0FBUztJQU01QixZQUFZLE1BQXdCLEVBQUUsTUFBZTtRQUxwQyxlQUFVLEdBQXlDLEVBQUUsQ0FBQztRQUc5RCxVQUFLLEdBQWlCLEVBQUUsQ0FBQztRQUdoQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQiw2REFBNkQ7UUFDN0Qsc0RBQXNEO1FBQ3RELE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxFQUFFLEVBQUU7WUFDOUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLG1DQUFvQixDQUFDO2dCQUMvQyxVQUFVLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLFlBQVksRUFBRTtnQkFDcEMsR0FBRyxNQUFNO2FBQ1YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLFNBQVM7UUFDYixNQUFNLE1BQU0sR0FBNEMsRUFBRSxDQUFDO1FBRTNELE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEVBQUU7WUFDM0QsSUFBSSxDQUFDO2dCQUNILE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBTSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzlDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQzdCLElB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
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const mcp_client_1 = __importDefault(require("./mcp-client"));
|
|
7
|
+
class McpConfigChecker {
|
|
8
|
+
static check(mcpConfig) {
|
|
9
|
+
return new mcp_client_1.default(mcpConfig).testConnections();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.default = McpConfigChecker;
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWNwLWNvbmZpZy1jaGVja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21jcC1jb25maWctY2hlY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUVBLDhEQUFxQztBQUVyQyxNQUFxQixnQkFBZ0I7SUFDbkMsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUEyQjtRQUN0QyxPQUFPLElBQUksb0JBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUNwRCxDQUFDO0NBQ0Y7QUFKRCxtQ0FJQyJ9
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RemoteTools } from './remote-tools';
|
|
2
|
+
import type { ClientOptions } from 'openai';
|
|
3
|
+
import type { ChatCompletionCreateParamsNonStreaming } from 'openai/resources/chat/completions';
|
|
4
|
+
export type OpenAiConfiguration = ClientOptions & {
|
|
5
|
+
provider: 'openai';
|
|
6
|
+
model: ChatCompletionCreateParamsNonStreaming['model'];
|
|
7
|
+
};
|
|
8
|
+
export type AiConfiguration = OpenAiConfiguration;
|
|
9
|
+
export type AiProvider = AiConfiguration['provider'];
|
|
10
|
+
export type OpenAIBody = Pick<ChatCompletionCreateParamsNonStreaming, 'tools' | 'messages' | 'tool_choice'>;
|
|
11
|
+
export type DispatchBody = OpenAIBody;
|
|
12
|
+
export declare class ProviderDispatcher {
|
|
13
|
+
private readonly aiClient;
|
|
14
|
+
private readonly remoteTools;
|
|
15
|
+
constructor(configuration: AiConfiguration | null, remoteTools: RemoteTools);
|
|
16
|
+
dispatch(body: DispatchBody): Promise<unknown>;
|
|
17
|
+
private enhanceOpenAIRemoteTools;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=provider-dispatcher.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ProviderDispatcher = void 0;
|
|
7
|
+
const function_calling_1 = require("@langchain/core/utils/function_calling");
|
|
8
|
+
const openai_1 = __importDefault(require("openai"));
|
|
9
|
+
const errors_1 = require("./errors");
|
|
10
|
+
class ProviderDispatcher {
|
|
11
|
+
constructor(configuration, remoteTools) {
|
|
12
|
+
this.aiClient = null;
|
|
13
|
+
this.remoteTools = remoteTools;
|
|
14
|
+
if (configuration?.provider === 'openai' && configuration.apiKey) {
|
|
15
|
+
const { provider, model, ...clientOptions } = configuration;
|
|
16
|
+
this.aiClient = {
|
|
17
|
+
client: new openai_1.default(clientOptions),
|
|
18
|
+
model,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async dispatch(body) {
|
|
23
|
+
if (!this.aiClient) {
|
|
24
|
+
throw new errors_1.AINotConfiguredError();
|
|
25
|
+
}
|
|
26
|
+
// tools, messages and tool_choice must be extracted from the body and passed as options
|
|
27
|
+
// because we don't want to let users to pass any other option
|
|
28
|
+
const { tools, messages, tool_choice: toolChoice } = body;
|
|
29
|
+
const options = {
|
|
30
|
+
model: this.aiClient.model,
|
|
31
|
+
// Add the remote tools to the tools to be used by the AI
|
|
32
|
+
tools: this.enhanceOpenAIRemoteTools(tools),
|
|
33
|
+
messages,
|
|
34
|
+
tool_choice: toolChoice,
|
|
35
|
+
};
|
|
36
|
+
try {
|
|
37
|
+
return await this.aiClient.client.chat.completions.create(options);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new errors_1.OpenAIUnprocessableError(`Error while calling OpenAI: ${error.message}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
enhanceOpenAIRemoteTools(tools) {
|
|
44
|
+
if (!tools || !Array.isArray(tools))
|
|
45
|
+
return tools;
|
|
46
|
+
const remoteToolFunctions = this.remoteTools.tools.map(extendedTools => (0, function_calling_1.convertToOpenAIFunction)(extendedTools.base));
|
|
47
|
+
return tools.map(tool => {
|
|
48
|
+
const remoteFunction = remoteToolFunctions.find(functionDefinition => functionDefinition.name === tool.function.name);
|
|
49
|
+
if (remoteFunction)
|
|
50
|
+
return { ...tool, function: remoteFunction };
|
|
51
|
+
return tool;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.ProviderDispatcher = ProviderDispatcher;
|
|
56
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXItZGlzcGF0Y2hlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm92aWRlci1kaXNwYXRjaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUlBLDZFQUFpRjtBQUNqRixvREFBNEI7QUFFNUIscUNBQTBFO0FBb0IxRSxNQUFhLGtCQUFrQjtJQUs3QixZQUFZLGFBQXFDLEVBQUUsV0FBd0I7UUFKMUQsYUFBUSxHQUF3QixJQUFJLENBQUM7UUFLcEQsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFFL0IsSUFBSSxhQUFhLEVBQUUsUUFBUSxLQUFLLFFBQVEsSUFBSSxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakUsTUFBTSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsR0FBRyxhQUFhLEVBQUUsR0FBRyxhQUFhLENBQUM7WUFDNUQsSUFBSSxDQUFDLFFBQVEsR0FBRztnQkFDZCxNQUFNLEVBQUUsSUFBSSxnQkFBTSxDQUFDLGFBQWEsQ0FBQztnQkFDakMsS0FBSzthQUNOLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBa0I7UUFDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNuQixNQUFNLElBQUksNkJBQW9CLEVBQUUsQ0FBQztRQUNuQyxDQUFDO1FBRUQsd0ZBQXdGO1FBQ3hGLDhEQUE4RDtRQUM5RCxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBRTFELE1BQU0sT0FBTyxHQUFHO1lBQ2QsS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSztZQUMxQix5REFBeUQ7WUFDekQsS0FBSyxFQUFFLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUM7WUFDM0MsUUFBUTtZQUNSLFdBQVcsRUFBRSxVQUFVO1NBQ2tCLENBQUM7UUFFNUMsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3JFLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLGlDQUF3QixDQUFDLCtCQUFnQyxLQUFlLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNoRyxDQUFDO0lBQ0gsQ0FBQztJQUVPLHdCQUF3QixDQUFDLEtBQXVEO1FBQ3RGLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sS0FBSyxDQUFDO1FBRWxELE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQ3JFLElBQUEsMENBQXVCLEVBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUM1QyxDQUFDO1FBRUYsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3RCLE1BQU0sY0FBYyxHQUFHLG1CQUFtQixDQUFDLElBQUksQ0FDN0Msa0JBQWtCLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FDckUsQ0FBQztZQUNGLElBQUksY0FBYztnQkFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxDQUFDO1lBRWpFLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUF6REQsZ0RBeURDIn0=
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
2
|
+
export type SourceType = 'server' | 'mcp-server';
|
|
3
|
+
export default class RemoteTool<ToolType = unknown> {
|
|
4
|
+
base: StructuredToolInterface<ToolType>;
|
|
5
|
+
sourceId: string;
|
|
6
|
+
sourceType: SourceType;
|
|
7
|
+
constructor(options: {
|
|
8
|
+
tool: StructuredToolInterface<ToolType>;
|
|
9
|
+
sourceId?: string;
|
|
10
|
+
sourceType?: SourceType;
|
|
11
|
+
});
|
|
12
|
+
get sanitizedName(): string;
|
|
13
|
+
private sanitizeName;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=remote-tool.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class RemoteTool {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.base = options.tool;
|
|
6
|
+
this.sourceId = options.sourceId;
|
|
7
|
+
this.sourceType = options.sourceType;
|
|
8
|
+
}
|
|
9
|
+
get sanitizedName() {
|
|
10
|
+
return this.sanitizeName(this.base.name);
|
|
11
|
+
}
|
|
12
|
+
sanitizeName(name) {
|
|
13
|
+
// OpenAI function names must be alphanumeric and can contain underscores
|
|
14
|
+
// This function replaces non-alphanumeric characters with underscores
|
|
15
|
+
return name.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.default = RemoteTool;
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlLXRvb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcmVtb3RlLXRvb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFJQSxNQUFxQixVQUFVO0lBSzdCLFlBQVksT0FJWDtRQUNDLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztRQUN6QixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDakMsSUFBSSxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxJQUFJLGFBQWE7UUFDZixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRU8sWUFBWSxDQUFDLElBQVk7UUFDL0IseUVBQXlFO1FBQ3pFLHNFQUFzRTtRQUN0RSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDOUMsQ0FBQztDQUNGO0FBeEJELDZCQXdCQyJ9
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ResponseFormat } from '@langchain/core/tools';
|
|
2
|
+
import type { ChatCompletionCreateParamsNonStreaming } from 'openai/resources/chat/completions';
|
|
3
|
+
import RemoteTool from './remote-tool';
|
|
4
|
+
export type Messages = ChatCompletionCreateParamsNonStreaming['messages'];
|
|
5
|
+
export type RemoteToolsApiKeys = {
|
|
6
|
+
['AI_REMOTE_TOOL_BRAVE_SEARCH_API_KEY']: string;
|
|
7
|
+
} | Record<string, string>;
|
|
8
|
+
export declare class RemoteTools {
|
|
9
|
+
private readonly apiKeys?;
|
|
10
|
+
readonly tools: RemoteTool[];
|
|
11
|
+
constructor(apiKeys: RemoteToolsApiKeys, tools?: RemoteTool[]);
|
|
12
|
+
get toolDefinitionsForFrontend(): {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
responseFormat: ResponseFormat;
|
|
16
|
+
schema: import("@langchain/core/utils/json_schema").JSONSchema;
|
|
17
|
+
sourceId: string;
|
|
18
|
+
sourceType: import("./remote-tool").SourceType;
|
|
19
|
+
}[];
|
|
20
|
+
invokeTool(toolName: string, messages: ChatCompletionCreateParamsNonStreaming['messages']): Promise<unknown>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=remote-tools.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RemoteTools = void 0;
|
|
7
|
+
const brave_search_1 = require("@langchain/community/tools/brave_search");
|
|
8
|
+
const json_schema_1 = require("@langchain/core/utils/json_schema");
|
|
9
|
+
const errors_1 = require("./errors");
|
|
10
|
+
const remote_tool_1 = __importDefault(require("./remote-tool"));
|
|
11
|
+
class RemoteTools {
|
|
12
|
+
constructor(apiKeys, tools) {
|
|
13
|
+
this.tools = [];
|
|
14
|
+
this.apiKeys = apiKeys;
|
|
15
|
+
this.tools.push(...(tools ?? []));
|
|
16
|
+
if (this.apiKeys?.AI_REMOTE_TOOL_BRAVE_SEARCH_API_KEY) {
|
|
17
|
+
this.tools.push(new remote_tool_1.default({
|
|
18
|
+
sourceId: 'brave_search',
|
|
19
|
+
sourceType: 'server',
|
|
20
|
+
tool: new brave_search_1.BraveSearch({ apiKey: this.apiKeys.AI_REMOTE_TOOL_BRAVE_SEARCH_API_KEY }),
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
get toolDefinitionsForFrontend() {
|
|
25
|
+
return this.tools.map(extendedTool => {
|
|
26
|
+
return {
|
|
27
|
+
name: extendedTool.sanitizedName,
|
|
28
|
+
description: extendedTool.base.description,
|
|
29
|
+
responseFormat: 'content',
|
|
30
|
+
schema: (0, json_schema_1.toJsonSchema)(extendedTool.base.schema),
|
|
31
|
+
sourceId: extendedTool.sourceId,
|
|
32
|
+
sourceType: extendedTool.sourceType,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async invokeTool(toolName, messages) {
|
|
37
|
+
const extendedTool = this.tools.find(exTool => exTool.sanitizedName === toolName);
|
|
38
|
+
if (!extendedTool)
|
|
39
|
+
throw new errors_1.AIToolNotFoundError(`Tool ${toolName} not found`);
|
|
40
|
+
try {
|
|
41
|
+
return (await extendedTool.base.invoke(messages));
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new errors_1.AIToolUnprocessableError(`Error while calling tool ${toolName}: ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.RemoteTools = RemoteTools;
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlLXRvb2xzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JlbW90ZS10b29scy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFHQSwwRUFBc0U7QUFDdEUsbUVBQWlFO0FBRWpFLHFDQUF5RTtBQUN6RSxnRUFBdUM7QUFRdkMsTUFBYSxXQUFXO0lBSXRCLFlBQVksT0FBMkIsRUFBRSxLQUFvQjtRQUZwRCxVQUFLLEdBQWlCLEVBQUUsQ0FBQztRQUdoQyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFbEMsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLG1DQUFtQyxFQUFFLENBQUM7WUFDdEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQ2IsSUFBSSxxQkFBVSxDQUFDO2dCQUNiLFFBQVEsRUFBRSxjQUFjO2dCQUN4QixVQUFVLEVBQUUsUUFBUTtnQkFDcEIsSUFBSSxFQUFFLElBQUksMEJBQVcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLG1DQUFtQyxFQUFFLENBQUM7YUFDcEYsQ0FBQyxDQUNILENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksMEJBQTBCO1FBQzVCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFDbkMsT0FBTztnQkFDTCxJQUFJLEVBQUUsWUFBWSxDQUFDLGFBQWE7Z0JBQ2hDLFdBQVcsRUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLFdBQVc7Z0JBQzFDLGNBQWMsRUFBRSxTQUEyQjtnQkFDM0MsTUFBTSxFQUFFLElBQUEsMEJBQVksRUFBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztnQkFDOUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxRQUFRO2dCQUMvQixVQUFVLEVBQUUsWUFBWSxDQUFDLFVBQVU7YUFDcEMsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBZ0IsRUFBRSxRQUE0RDtRQUM3RixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEtBQUssUUFBUSxDQUFDLENBQUM7UUFFbEYsSUFBSSxDQUFDLFlBQVk7WUFBRSxNQUFNLElBQUksNEJBQW1CLENBQUMsUUFBUSxRQUFRLFlBQVksQ0FBQyxDQUFDO1FBRS9FLElBQUksQ0FBQztZQUNILE9BQU8sQ0FBQyxNQUFNLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFZLENBQUM7UUFDL0QsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLElBQUksaUNBQXdCLENBQ2hDLDRCQUE0QixRQUFRLEtBQU0sS0FBZSxDQUFDLE9BQU8sRUFBRSxDQUNwRSxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7Q0FDRjtBQTdDRCxrQ0E2Q0MifQ==
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { McpConfiguration } from './mcp-client';
|
|
2
|
+
import type { AiConfiguration, DispatchBody } from './provider-dispatcher';
|
|
3
|
+
import type { Messages, RemoteToolsApiKeys } from './remote-tools';
|
|
4
|
+
import type { Logger } from '@forestadmin/datasource-toolkit';
|
|
5
|
+
export type InvokeRemoteToolBody = {
|
|
6
|
+
inputs: Messages;
|
|
7
|
+
};
|
|
8
|
+
export type Body = DispatchBody | InvokeRemoteToolBody | undefined;
|
|
9
|
+
export type Route = 'ai-query' | 'remote-tools' | 'invoke-remote-tool';
|
|
10
|
+
export type Query = {
|
|
11
|
+
'tool-name'?: string;
|
|
12
|
+
};
|
|
13
|
+
export type ApiKeys = RemoteToolsApiKeys;
|
|
14
|
+
export declare class Router {
|
|
15
|
+
private readonly localToolsApiKeys?;
|
|
16
|
+
private readonly aiConfiguration;
|
|
17
|
+
private readonly logger?;
|
|
18
|
+
constructor(params?: {
|
|
19
|
+
aiConfiguration?: AiConfiguration;
|
|
20
|
+
localToolsApiKeys?: ApiKeys;
|
|
21
|
+
logger?: Logger;
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Route the request to the appropriate handler
|
|
25
|
+
*
|
|
26
|
+
* List of routes:
|
|
27
|
+
* // dispatch the query to the AI
|
|
28
|
+
* - /ai-query
|
|
29
|
+
*
|
|
30
|
+
* // invoke a remote tool by name
|
|
31
|
+
* - /invoke-remote-tool?tool-name=:toolName
|
|
32
|
+
*
|
|
33
|
+
* // get the list of available remote tools
|
|
34
|
+
* - /remote-tools
|
|
35
|
+
*/
|
|
36
|
+
route(args: {
|
|
37
|
+
body?: Body;
|
|
38
|
+
route: Route;
|
|
39
|
+
query?: Query;
|
|
40
|
+
mcpConfigs?: McpConfiguration;
|
|
41
|
+
}): Promise<unknown>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=router.d.ts.map
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Router = void 0;
|
|
7
|
+
const index_1 = require("./index");
|
|
8
|
+
const mcp_client_1 = __importDefault(require("./mcp-client"));
|
|
9
|
+
const remote_tools_1 = require("./remote-tools");
|
|
10
|
+
class Router {
|
|
11
|
+
constructor(params) {
|
|
12
|
+
this.aiConfiguration = params?.aiConfiguration ?? null;
|
|
13
|
+
this.localToolsApiKeys = params?.localToolsApiKeys;
|
|
14
|
+
this.logger = params?.logger;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Route the request to the appropriate handler
|
|
18
|
+
*
|
|
19
|
+
* List of routes:
|
|
20
|
+
* // dispatch the query to the AI
|
|
21
|
+
* - /ai-query
|
|
22
|
+
*
|
|
23
|
+
* // invoke a remote tool by name
|
|
24
|
+
* - /invoke-remote-tool?tool-name=:toolName
|
|
25
|
+
*
|
|
26
|
+
* // get the list of available remote tools
|
|
27
|
+
* - /remote-tools
|
|
28
|
+
*/
|
|
29
|
+
async route(args) {
|
|
30
|
+
let mcpClient;
|
|
31
|
+
try {
|
|
32
|
+
if (args.mcpConfigs) {
|
|
33
|
+
mcpClient = new mcp_client_1.default(args.mcpConfigs, this.logger);
|
|
34
|
+
}
|
|
35
|
+
const remoteTools = new remote_tools_1.RemoteTools(this.localToolsApiKeys, await mcpClient?.loadTools());
|
|
36
|
+
if (args.route === 'ai-query') {
|
|
37
|
+
return await new index_1.ProviderDispatcher(this.aiConfiguration, remoteTools).dispatch(args.body);
|
|
38
|
+
}
|
|
39
|
+
if (args.route === 'invoke-remote-tool') {
|
|
40
|
+
return await remoteTools.invokeTool(args.query['tool-name'], args.body.inputs);
|
|
41
|
+
}
|
|
42
|
+
if (args.route === 'remote-tools') {
|
|
43
|
+
return remoteTools.toolDefinitionsForFrontend;
|
|
44
|
+
}
|
|
45
|
+
// don't add mcpConfigs to the error message, as it may contain sensitive information
|
|
46
|
+
throw new index_1.AIUnprocessableError(`No action to perform: ${JSON.stringify({
|
|
47
|
+
body: args.body,
|
|
48
|
+
route: args.route,
|
|
49
|
+
query: args.query,
|
|
50
|
+
})}`);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
if (mcpClient) {
|
|
54
|
+
try {
|
|
55
|
+
await mcpClient.closeConnections();
|
|
56
|
+
}
|
|
57
|
+
catch (cleanupError) {
|
|
58
|
+
this.logger?.('Error', 'Error during MCP connection cleanup', cleanupError);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.Router = Router;
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFLQSxtQ0FBbUU7QUFDbkUsOERBQXFDO0FBQ3JDLGlEQUE2QztBQVU3QyxNQUFhLE1BQU07SUFLakIsWUFBWSxNQUlYO1FBQ0MsSUFBSSxDQUFDLGVBQWUsR0FBRyxNQUFNLEVBQUUsZUFBZSxJQUFJLElBQUksQ0FBQztRQUN2RCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsTUFBTSxFQUFFLGlCQUFpQixDQUFDO1FBQ25ELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUMvQixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFpRjtRQUMzRixJQUFJLFNBQWdDLENBQUM7UUFFckMsSUFBSSxDQUFDO1lBQ0gsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ3BCLFNBQVMsR0FBRyxJQUFJLG9CQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDMUQsQ0FBQztZQUVELE1BQU0sV0FBVyxHQUFHLElBQUksMEJBQVcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsTUFBTSxTQUFTLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztZQUUxRixJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQzlCLE9BQU8sTUFBTSxJQUFJLDBCQUFrQixDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUM3RSxJQUFJLENBQUMsSUFBb0IsQ0FDMUIsQ0FBQztZQUNKLENBQUM7WUFFRCxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssb0JBQW9CLEVBQUUsQ0FBQztnQkFDeEMsT0FBTyxNQUFNLFdBQVcsQ0FBQyxVQUFVLENBQ2pDLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQ3RCLElBQUksQ0FBQyxJQUE2QixDQUFDLE1BQU0sQ0FDM0MsQ0FBQztZQUNKLENBQUM7WUFFRCxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssY0FBYyxFQUFFLENBQUM7Z0JBQ2xDLE9BQU8sV0FBVyxDQUFDLDBCQUEwQixDQUFDO1lBQ2hELENBQUM7WUFFRCxxRkFBcUY7WUFDckYsTUFBTSxJQUFJLDRCQUFvQixDQUM1Qix5QkFBeUIsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDdEMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNmLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztnQkFDakIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO2FBQ2xCLENBQUMsRUFBRSxDQUNMLENBQUM7UUFDSixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNkLElBQUksQ0FBQztvQkFDSCxNQUFNLFNBQVMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNyQyxDQUFDO2dCQUFDLE9BQU8sWUFBWSxFQUFFLENBQUM7b0JBQ3RCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLEVBQUUscUNBQXFDLEVBQUUsWUFBcUIsQ0FBQyxDQUFDO2dCQUN2RixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUF6RUQsd0JBeUVDIn0=
|