@forestadmin/agent 1.66.2 → 1.68.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/agent.d.ts +15 -0
- package/dist/agent.js +88 -8
- package/dist/fastify-adapter.d.ts +41 -0
- package/dist/fastify-adapter.js +118 -0
- package/dist/framework-mounter.d.ts +8 -3
- package/dist/framework-mounter.js +42 -48
- package/dist/index.js +3 -3
- package/dist/mcp-middleware.d.ts +29 -0
- package/dist/mcp-middleware.js +70 -0
- package/dist/routes/access/api-chart-collection.d.ts +0 -1
- package/dist/routes/access/api-chart-collection.js +1 -1
- package/dist/routes/access/api-chart-datasource.d.ts +0 -1
- package/dist/routes/access/api-chart-datasource.js +1 -1
- package/dist/routes/access/chart.d.ts +0 -1
- package/dist/routes/access/chart.js +2 -2
- package/dist/routes/access/count-related.d.ts +0 -1
- package/dist/routes/access/count-related.js +1 -1
- package/dist/routes/access/count.d.ts +0 -1
- package/dist/routes/access/count.js +1 -1
- package/dist/routes/access/csv-related.d.ts +0 -1
- package/dist/routes/access/csv.d.ts +0 -1
- package/dist/routes/access/get.d.ts +0 -1
- package/dist/routes/access/get.js +1 -1
- package/dist/routes/access/list-related.d.ts +0 -1
- package/dist/routes/access/list.d.ts +0 -1
- package/dist/routes/access/native-query-datasource.d.ts +0 -1
- package/dist/routes/access/native-query-datasource.js +1 -1
- package/dist/routes/base-route.d.ts +0 -1
- package/dist/routes/capabilities.d.ts +0 -1
- package/dist/routes/index.js +2 -2
- package/dist/routes/modification/action/action-authorization.js +1 -1
- package/dist/routes/modification/action/action.d.ts +0 -1
- package/dist/routes/modification/action/action.js +1 -1
- package/dist/routes/modification/associate-related.d.ts +0 -1
- package/dist/routes/modification/associate-related.js +1 -1
- package/dist/routes/modification/create.d.ts +0 -1
- package/dist/routes/modification/create.js +1 -1
- package/dist/routes/modification/delete.d.ts +0 -1
- package/dist/routes/modification/dissociate-delete-related.d.ts +0 -1
- package/dist/routes/modification/dissociate-delete-related.js +1 -1
- package/dist/routes/modification/update-field.d.ts +0 -1
- package/dist/routes/modification/update-field.js +1 -1
- package/dist/routes/modification/update-relation.d.ts +0 -1
- package/dist/routes/modification/update-relation.js +1 -1
- package/dist/routes/modification/update.d.ts +0 -1
- package/dist/routes/modification/update.js +1 -1
- package/dist/routes/security/authentication.d.ts +0 -1
- package/dist/routes/security/authentication.js +1 -1
- package/dist/routes/security/ip-whitelist.d.ts +0 -1
- package/dist/routes/security/ip-whitelist.js +1 -1
- package/dist/routes/security/scope-invalidation.d.ts +0 -1
- package/dist/routes/security/scope-invalidation.js +1 -1
- package/dist/routes/system/error-handling.d.ts +0 -1
- package/dist/routes/system/error-handling.js +1 -1
- package/dist/routes/system/healthcheck.d.ts +0 -1
- package/dist/routes/system/logger.d.ts +0 -1
- package/dist/routes/system/logger.js +1 -1
- package/dist/services/authorization/authorization.js +1 -1
- package/dist/services/authorization/index.js +2 -2
- package/dist/services/model-customizations/actions/get-actions.js +2 -2
- package/dist/services/model-customizations/actions/update-record/execute-update-record.js +2 -2
- package/dist/services/model-customizations/actions/update-record/update-record-plugin.js +2 -2
- package/dist/services/model-customizations/actions/webhook/execute-webhook.js +2 -2
- package/dist/services/model-customizations/actions/webhook/webhook-plugin.js +2 -2
- package/dist/services/model-customizations/customization.js +2 -2
- package/dist/services/segment-query-handler.js +1 -1
- package/dist/services/serializer.js +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js +3 -3
- package/dist/utils/condition-tree-parser.js +1 -1
- package/dist/utils/csv-generator.js +1 -1
- package/dist/utils/express-to-koa.d.ts +23 -0
- package/dist/utils/express-to-koa.js +49 -0
- package/dist/utils/forest-schema/action-values.js +1 -1
- package/dist/utils/forest-schema/column-schema-validator.js +1 -1
- package/dist/utils/forest-schema/generator-action-field-widget.js +2 -2
- package/dist/utils/forest-schema/generator-actions.js +3 -3
- package/dist/utils/forest-schema/generator-fields.js +2 -2
- package/dist/utils/forest-schema/validation.js +3 -3
- package/dist/utils/id.js +1 -1
- package/dist/utils/options-validator.js +3 -2
- package/dist/utils/query-string.js +2 -2
- package/package.json +8 -3
package/dist/agent.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export default class Agent<S extends TSchema = TSchema> extends FrameworkMounter
|
|
|
21
21
|
protected nocodeCustomizer: DataSourceCustomizer<S>;
|
|
22
22
|
protected customizationService: CustomizationService;
|
|
23
23
|
protected schemaGenerator: SchemaGenerator;
|
|
24
|
+
/** Whether MCP server should be mounted */
|
|
25
|
+
private mcpEnabled;
|
|
24
26
|
/**
|
|
25
27
|
* Create a new Agent Builder.
|
|
26
28
|
* If any options are missing, the default will be applied:
|
|
@@ -106,11 +108,24 @@ export default class Agent<S extends TSchema = TSchema> extends FrameworkMounter
|
|
|
106
108
|
* agent.use(advancedExportPlugin, { format: 'xlsx' });
|
|
107
109
|
*/
|
|
108
110
|
use<Options>(plugin: Plugin<Options>, options?: Options): this;
|
|
111
|
+
/**
|
|
112
|
+
* Enable MCP (Model Context Protocol) server support.
|
|
113
|
+
* This allows AI assistants to interact with your Forest Admin data.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* agent.mountAiMcpServer();
|
|
117
|
+
*/
|
|
118
|
+
mountAiMcpServer(): this;
|
|
109
119
|
protected getRoutes(dataSource: DataSource, services: ForestAdminHttpDriverServices): import("./routes/base-route").default[];
|
|
110
120
|
/**
|
|
111
121
|
* Create an http handler which can respond to all queries which are expected from an agent.
|
|
122
|
+
* Returns the main router and optional MCP HTTP callback.
|
|
112
123
|
*/
|
|
113
124
|
private getRouter;
|
|
125
|
+
/**
|
|
126
|
+
* Initialize the MCP server using dynamic import.
|
|
127
|
+
*/
|
|
128
|
+
private initializeMcpServer;
|
|
114
129
|
private buildRouterAndSendSchema;
|
|
115
130
|
/**
|
|
116
131
|
* Send the apimap to forest admin server
|
package/dist/agent.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -46,6 +79,8 @@ class Agent extends framework_mounter_1.default {
|
|
|
46
79
|
constructor(options) {
|
|
47
80
|
const allOptions = options_validator_1.default.validate(options_validator_1.default.withDefaults(options));
|
|
48
81
|
super(allOptions.prefix, allOptions.logger);
|
|
82
|
+
/** Whether MCP server should be mounted */
|
|
83
|
+
this.mcpEnabled = false;
|
|
49
84
|
this.options = allOptions;
|
|
50
85
|
this.customizer = new datasource_customizer_1.DataSourceCustomizer({
|
|
51
86
|
ignoreMissingSchemaElementErrors: options.ignoreMissingSchemaElementErrors || false,
|
|
@@ -57,9 +92,10 @@ class Agent extends framework_mounter_1.default {
|
|
|
57
92
|
* Start the agent.
|
|
58
93
|
*/
|
|
59
94
|
async start() {
|
|
60
|
-
const router = await this.buildRouterAndSendSchema();
|
|
95
|
+
const { router, mcpHttpCallback } = await this.buildRouterAndSendSchema();
|
|
61
96
|
await this.options.forestAdminClient.subscribeToServerEvents();
|
|
62
97
|
this.options.forestAdminClient.onRefreshCustomizations(this.restart.bind(this));
|
|
98
|
+
this.setMcpCallback(mcpHttpCallback ?? null);
|
|
63
99
|
await this.mount(router);
|
|
64
100
|
}
|
|
65
101
|
/**
|
|
@@ -76,8 +112,9 @@ class Agent extends framework_mounter_1.default {
|
|
|
76
112
|
*/
|
|
77
113
|
async restart() {
|
|
78
114
|
// We force sending schema when restarting
|
|
79
|
-
const
|
|
80
|
-
|
|
115
|
+
const { router, mcpHttpCallback } = await this.buildRouterAndSendSchema();
|
|
116
|
+
this.setMcpCallback(mcpHttpCallback ?? null);
|
|
117
|
+
await this.remount(router);
|
|
81
118
|
}
|
|
82
119
|
/**
|
|
83
120
|
* Add a datasource
|
|
@@ -154,18 +191,35 @@ class Agent extends framework_mounter_1.default {
|
|
|
154
191
|
this.customizer.use(plugin, options);
|
|
155
192
|
return this;
|
|
156
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Enable MCP (Model Context Protocol) server support.
|
|
196
|
+
* This allows AI assistants to interact with your Forest Admin data.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* agent.mountAiMcpServer();
|
|
200
|
+
*/
|
|
201
|
+
mountAiMcpServer() {
|
|
202
|
+
this.mcpEnabled = true;
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
157
205
|
getRoutes(dataSource, services) {
|
|
158
206
|
return (0, routes_1.default)(dataSource, this.options, services);
|
|
159
207
|
}
|
|
160
208
|
/**
|
|
161
209
|
* Create an http handler which can respond to all queries which are expected from an agent.
|
|
210
|
+
* Returns the main router and optional MCP HTTP callback.
|
|
162
211
|
*/
|
|
163
212
|
async getRouter(dataSource) {
|
|
164
213
|
// Bootstrap app
|
|
165
214
|
const services = (0, services_1.default)(this.options);
|
|
166
215
|
const routes = this.getRoutes(dataSource, services);
|
|
167
216
|
await Promise.all(routes.map(route => route.bootstrap()));
|
|
168
|
-
//
|
|
217
|
+
// Initialize MCP server if enabled via mountAiMcpServer()
|
|
218
|
+
let mcpHttpCallback;
|
|
219
|
+
if (this.mcpEnabled) {
|
|
220
|
+
mcpHttpCallback = await this.initializeMcpServer();
|
|
221
|
+
}
|
|
222
|
+
// Build main router
|
|
169
223
|
const router = new router_1.default();
|
|
170
224
|
router.all('(.*)', (0, cors_1.default)({ credentials: true, maxAge: 24 * 3600, privateNetworkAccess: true }));
|
|
171
225
|
router.use((0, bodyparser_1.default)({
|
|
@@ -175,7 +229,33 @@ class Agent extends framework_mounter_1.default {
|
|
|
175
229
|
...this.options.bodyParserOptions,
|
|
176
230
|
}));
|
|
177
231
|
routes.forEach(route => route.setupRoutes(router));
|
|
178
|
-
return router;
|
|
232
|
+
return { router, mcpHttpCallback };
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Initialize the MCP server using dynamic import.
|
|
236
|
+
*/
|
|
237
|
+
async initializeMcpServer() {
|
|
238
|
+
try {
|
|
239
|
+
// Dynamic import to defer loading until mountAiMcpServer() is actually used
|
|
240
|
+
// This avoids loading the transitive dependency @forestadmin/agent-client
|
|
241
|
+
// at startup for users who don't use MCP
|
|
242
|
+
const { ForestMCPServer } = await Promise.resolve().then(() => __importStar(require('@forestadmin/mcp-server')));
|
|
243
|
+
const mcpServer = new ForestMCPServer({
|
|
244
|
+
forestServerUrl: this.options.forestServerUrl,
|
|
245
|
+
forestAppUrl: this.options.forestAppUrl,
|
|
246
|
+
envSecret: this.options.envSecret,
|
|
247
|
+
authSecret: this.options.authSecret,
|
|
248
|
+
logger: this.options.logger,
|
|
249
|
+
});
|
|
250
|
+
const httpCallback = await mcpServer.getHttpCallback();
|
|
251
|
+
this.options.logger('Info', 'MCP server initialized successfully');
|
|
252
|
+
return httpCallback;
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
const { message } = error;
|
|
256
|
+
this.options.logger('Error', `Failed to initialize MCP server: ${message}`);
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
179
259
|
}
|
|
180
260
|
async buildRouterAndSendSchema() {
|
|
181
261
|
const { isProduction, logger, typingsPath, typingsMaxDepth } = this.options;
|
|
@@ -187,14 +267,14 @@ class Agent extends framework_mounter_1.default {
|
|
|
187
267
|
this.nocodeCustomizer.addDataSource(this.customizer.getFactory());
|
|
188
268
|
this.nocodeCustomizer.use(this.customizationService.addCustomizations);
|
|
189
269
|
const dataSource = await this.nocodeCustomizer.getDataSource(logger);
|
|
190
|
-
const [
|
|
270
|
+
const [routers] = await Promise.all([
|
|
191
271
|
this.getRouter(dataSource),
|
|
192
272
|
this.sendSchema(dataSource),
|
|
193
273
|
!isProduction && typingsPath
|
|
194
274
|
? this.customizer.updateTypesOnFileSystem(typingsPath, typingsMaxDepth, logger)
|
|
195
275
|
: Promise.resolve(),
|
|
196
276
|
]);
|
|
197
|
-
return
|
|
277
|
+
return routers;
|
|
198
278
|
}
|
|
199
279
|
/**
|
|
200
280
|
* Send the apimap to forest admin server
|
|
@@ -228,4 +308,4 @@ class Agent extends framework_mounter_1.default {
|
|
|
228
308
|
}
|
|
229
309
|
}
|
|
230
310
|
exports.default = Agent;
|
|
231
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
311
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx1REFBdUQ7QUFDdkQsOEVBUTRDO0FBRzVDLGlFQUF5QztBQUN6QyxxREFBNkI7QUFDN0IseURBQWlDO0FBQ2pDLDBDQUFrRDtBQUNsRCxrR0FBc0Q7QUFFdEQsNEVBQW1EO0FBQ25ELHNEQUFrQztBQUNsQywwREFBeUU7QUFDekUsa0dBQWlGO0FBRWpGLGdGQUE4RDtBQUM5RCxrRkFBeUQ7QUFFekQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBcUIsS0FBbUMsU0FBUSwyQkFBZ0I7SUFVOUU7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0gsWUFBWSxPQUFxQjtRQUMvQixNQUFNLFVBQVUsR0FBRywyQkFBZ0IsQ0FBQyxRQUFRLENBQUMsMkJBQWdCLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDckYsS0FBSyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBckI5QywyQ0FBMkM7UUFDbkMsZUFBVSxHQUFHLEtBQUssQ0FBQztRQXNCekIsSUFBSSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUM7UUFDMUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLDRDQUFvQixDQUFJO1lBQzVDLGdDQUFnQyxFQUFFLE9BQU8sQ0FBQyxnQ0FBZ0MsSUFBSSxLQUFLO1NBQ3BGLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLHVCQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2pFLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxtQkFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxLQUFLO1FBQ1QsTUFBTSxFQUFFLE1BQU0s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
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Logger } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { HttpCallback } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Handles mounting Express-style middleware on Fastify instances.
|
|
5
|
+
* Manages the complexity of different Fastify versions (v2, v3, v4) and
|
|
6
|
+
* automatic registration of @fastify/express when needed.
|
|
7
|
+
*
|
|
8
|
+
* Uses a WeakMap to track state per Fastify instance, allowing the same
|
|
9
|
+
* adapter to be used for multiple Fastify instances (v2, v3, v4).
|
|
10
|
+
*/
|
|
11
|
+
export default class FastifyAdapter {
|
|
12
|
+
private readonly logger;
|
|
13
|
+
private readonly fastifyStates;
|
|
14
|
+
constructor(logger: Logger);
|
|
15
|
+
/**
|
|
16
|
+
* Get or create state for a Fastify instance.
|
|
17
|
+
*/
|
|
18
|
+
private getState;
|
|
19
|
+
/**
|
|
20
|
+
* Mount an Express-style callback on a Fastify instance.
|
|
21
|
+
* Automatically handles @fastify/express registration if needed.
|
|
22
|
+
*/
|
|
23
|
+
useCallback(fastify: any, callback: HttpCallback, prefix: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Queue a callback and register @fastify/express if not already done for this Fastify instance.
|
|
26
|
+
*/
|
|
27
|
+
private queueAndRegister;
|
|
28
|
+
/**
|
|
29
|
+
* Register all pending callbacks with path-filtering wrappers.
|
|
30
|
+
* Uses a wrapper that handles path filtering because @fastify/express's
|
|
31
|
+
* path-based middleware has issues with kRoutePrefix in the after() context.
|
|
32
|
+
*/
|
|
33
|
+
private registerPendingCallbacks;
|
|
34
|
+
/**
|
|
35
|
+
* Create a wrapped callback that handles path filtering.
|
|
36
|
+
* For root prefix ('/'), passes through directly.
|
|
37
|
+
* For other prefixes, strips the prefix from URL before calling the callback.
|
|
38
|
+
*/
|
|
39
|
+
private createWrappedCallback;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=fastify-adapter.d.ts.map
|
|
@@ -0,0 +1,118 @@
|
|
|
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 express_1 = __importDefault(require("@fastify/express"));
|
|
7
|
+
/**
|
|
8
|
+
* Handles mounting Express-style middleware on Fastify instances.
|
|
9
|
+
* Manages the complexity of different Fastify versions (v2, v3, v4) and
|
|
10
|
+
* automatic registration of @fastify/express when needed.
|
|
11
|
+
*
|
|
12
|
+
* Uses a WeakMap to track state per Fastify instance, allowing the same
|
|
13
|
+
* adapter to be used for multiple Fastify instances (v2, v3, v4).
|
|
14
|
+
*/
|
|
15
|
+
class FastifyAdapter {
|
|
16
|
+
constructor(logger) {
|
|
17
|
+
this.fastifyStates = new WeakMap();
|
|
18
|
+
this.logger = logger;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get or create state for a Fastify instance.
|
|
22
|
+
*/
|
|
23
|
+
getState(fastify) {
|
|
24
|
+
let state = this.fastifyStates.get(fastify);
|
|
25
|
+
if (!state) {
|
|
26
|
+
state = { registered: null, pendingCallbacks: [] };
|
|
27
|
+
this.fastifyStates.set(fastify, state);
|
|
28
|
+
}
|
|
29
|
+
return state;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Mount an Express-style callback on a Fastify instance.
|
|
33
|
+
* Automatically handles @fastify/express registration if needed.
|
|
34
|
+
*/
|
|
35
|
+
useCallback(fastify, callback, prefix) {
|
|
36
|
+
// In Fastify v4+, fastify.use is undefined until @fastify/middie or @fastify/express is registered
|
|
37
|
+
// In Fastify v2/v3 with middie/express already registered, fastify.use exists
|
|
38
|
+
if (typeof fastify.use !== 'function') {
|
|
39
|
+
this.queueAndRegister(fastify, callback, prefix);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
fastify.use(prefix, callback);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
// Fastify 3 throws FST_ERR_MISSING_MIDDLEWARE if middleware support isn't loaded
|
|
47
|
+
if (e.code === 'FST_ERR_MISSING_MIDDLEWARE') {
|
|
48
|
+
this.queueAndRegister(fastify, callback, prefix);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Queue a callback and register @fastify/express if not already done for this Fastify instance.
|
|
57
|
+
*/
|
|
58
|
+
queueAndRegister(fastify, callback, prefix) {
|
|
59
|
+
const state = this.getState(fastify);
|
|
60
|
+
state.pendingCallbacks.push({ callback, prefix });
|
|
61
|
+
// Only register @fastify/express once per Fastify instance
|
|
62
|
+
if (state.registered) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Store reference to pendingCallbacks for use in after() callback
|
|
66
|
+
const { pendingCallbacks } = state;
|
|
67
|
+
state.registered = new Promise((resolve, reject) => {
|
|
68
|
+
fastify.register(express_1.default).after((err) => {
|
|
69
|
+
if (err) {
|
|
70
|
+
this.logger('Error', err.message);
|
|
71
|
+
reject(err);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Register all pending callbacks now that @fastify/express is loaded
|
|
75
|
+
this.registerPendingCallbacks(fastify, pendingCallbacks);
|
|
76
|
+
state.pendingCallbacks = [];
|
|
77
|
+
resolve();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Register all pending callbacks with path-filtering wrappers.
|
|
83
|
+
* Uses a wrapper that handles path filtering because @fastify/express's
|
|
84
|
+
* path-based middleware has issues with kRoutePrefix in the after() context.
|
|
85
|
+
*/
|
|
86
|
+
registerPendingCallbacks(fastify, callbacks) {
|
|
87
|
+
for (const pending of callbacks) {
|
|
88
|
+
const wrappedCallback = this.createWrappedCallback(pending.callback, pending.prefix);
|
|
89
|
+
fastify.use(wrappedCallback);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create a wrapped callback that handles path filtering.
|
|
94
|
+
* For root prefix ('/'), passes through directly.
|
|
95
|
+
* For other prefixes, strips the prefix from URL before calling the callback.
|
|
96
|
+
*/
|
|
97
|
+
createWrappedCallback(callback, prefix) {
|
|
98
|
+
return (req, res, next) => {
|
|
99
|
+
if (prefix === '/') {
|
|
100
|
+
callback(req, res, next);
|
|
101
|
+
}
|
|
102
|
+
else if (req.url.startsWith(prefix)) {
|
|
103
|
+
// Strip prefix from URL to simulate Express's prefix-based mounting behavior
|
|
104
|
+
const originalUrl = req.url;
|
|
105
|
+
req.url = req.url.slice(prefix.length) || '/';
|
|
106
|
+
callback(req, res, () => {
|
|
107
|
+
req.url = originalUrl;
|
|
108
|
+
next();
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
next();
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.default = FastifyAdapter;
|
|
118
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFzdGlmeS1hZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Zhc3RpZnktYWRhcHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUdBLCtEQUE4QztBQVM5Qzs7Ozs7OztHQU9HO0FBQ0gsTUFBcUIsY0FBYztJQUlqQyxZQUFZLE1BQWM7UUFGVCxrQkFBYSxHQUFHLElBQUksT0FBTyxFQUFxQixDQUFDO1FBR2hFLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7T0FFRztJQUNLLFFBQVEsQ0FBQyxPQUFZO1FBQzNCLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTVDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLEtBQUssR0FBRyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxFQUFFLENBQUM7WUFDbkQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3pDLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXLENBQUMsT0FBWSxFQUFFLFFBQXNCLEVBQUUsTUFBYztRQUM5RCxtR0FBbUc7UUFDbkcsOEVBQThFO1FBQzlFLElBQUksT0FBTyxPQUFPLENBQUMsR0FBRyxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBRWpELE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDO1lBQ0gsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDaEMsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxpRkFBaUY7WUFDakYs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
|
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
/// <reference types="koa__router" />
|
|
2
1
|
import type { Logger } from '@forestadmin/datasource-toolkit';
|
|
3
2
|
import Router from '@koa/router';
|
|
3
|
+
import { HttpCallback } from './types';
|
|
4
4
|
export default class FrameworkMounter {
|
|
5
5
|
standaloneServerPort: number;
|
|
6
6
|
private readonly onFirstStart;
|
|
7
7
|
private readonly onEachStart;
|
|
8
8
|
private readonly onStop;
|
|
9
|
-
|
|
9
|
+
protected readonly prefix: string;
|
|
10
10
|
private readonly logger;
|
|
11
|
+
private readonly fastifyAdapter;
|
|
12
|
+
private readonly mcpMiddleware;
|
|
11
13
|
/** Compute the prefix that the main router should be mounted at in the client's application */
|
|
12
14
|
private get completeMountPrefix();
|
|
13
15
|
constructor(prefix: string, logger: Logger);
|
|
16
|
+
/**
|
|
17
|
+
* Set the MCP HTTP callback. Call this before mount() or remount().
|
|
18
|
+
*/
|
|
19
|
+
protected setMcpCallback(callback: HttpCallback | null): void;
|
|
14
20
|
protected mount(router: Router): Promise<void>;
|
|
15
21
|
protected remount(router: Router): Promise<void>;
|
|
16
22
|
stop(): Promise<void>;
|
|
@@ -42,7 +48,6 @@ export default class FrameworkMounter {
|
|
|
42
48
|
* @param nestJs instance of a NestJS application
|
|
43
49
|
*/
|
|
44
50
|
mountOnNestJs(nestJs: any): this;
|
|
45
|
-
private useCallbackOnFastify;
|
|
46
51
|
private getConnectCallback;
|
|
47
52
|
}
|
|
48
53
|
//# sourceMappingURL=framework-mounter.d.ts.map
|
|
@@ -1,27 +1,4 @@
|
|
|
1
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
4
|
};
|
|
@@ -30,6 +7,8 @@ const router_1 = __importDefault(require("@koa/router"));
|
|
|
30
7
|
const http_1 = require("http");
|
|
31
8
|
const koa_1 = __importDefault(require("koa"));
|
|
32
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const fastify_adapter_1 = __importDefault(require("./fastify-adapter"));
|
|
11
|
+
const mcp_middleware_1 = __importDefault(require("./mcp-middleware"));
|
|
33
12
|
class FrameworkMounter {
|
|
34
13
|
/** Compute the prefix that the main router should be mounted at in the client's application */
|
|
35
14
|
get completeMountPrefix() {
|
|
@@ -41,6 +20,14 @@ class FrameworkMounter {
|
|
|
41
20
|
this.onStop = [];
|
|
42
21
|
this.prefix = prefix;
|
|
43
22
|
this.logger = logger;
|
|
23
|
+
this.fastifyAdapter = new fastify_adapter_1.default(logger);
|
|
24
|
+
this.mcpMiddleware = new mcp_middleware_1.default();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Set the MCP HTTP callback. Call this before mount() or remount().
|
|
28
|
+
*/
|
|
29
|
+
setMcpCallback(callback) {
|
|
30
|
+
this.mcpMiddleware.setCallback(callback);
|
|
44
31
|
}
|
|
45
32
|
async mount(router) {
|
|
46
33
|
for (const task of this.onFirstStart)
|
|
@@ -95,6 +82,9 @@ class FrameworkMounter {
|
|
|
95
82
|
* @param express instance of the express app or router.
|
|
96
83
|
*/
|
|
97
84
|
mountOnExpress(express) {
|
|
85
|
+
// MCP middleware - the callback handles its own path filtering and calls next() for non-MCP routes
|
|
86
|
+
express.use(this.mcpMiddleware.getExpressMiddleware());
|
|
87
|
+
// Mount main forest routes at /{prefix}/forest
|
|
98
88
|
express.use(this.completeMountPrefix, this.getConnectCallback(false));
|
|
99
89
|
this.logger('Info', `Successfully mounted on Express.js`);
|
|
100
90
|
return this;
|
|
@@ -104,8 +94,11 @@ class FrameworkMounter {
|
|
|
104
94
|
* @param fastify instance of the fastify app, or of a fastify context
|
|
105
95
|
*/
|
|
106
96
|
mountOnFastify(fastify) {
|
|
97
|
+
// MCP middleware at root - the callback handles its own path filtering
|
|
98
|
+
this.fastifyAdapter.useCallback(fastify, this.mcpMiddleware.getExpressMiddleware(), '/');
|
|
99
|
+
// Mount main forest routes
|
|
107
100
|
const callback = this.getConnectCallback(false);
|
|
108
|
-
this.
|
|
101
|
+
this.fastifyAdapter.useCallback(fastify, callback, this.completeMountPrefix);
|
|
109
102
|
this.logger('Info', `Successfully mounted on Fastify`);
|
|
110
103
|
return this;
|
|
111
104
|
}
|
|
@@ -126,6 +119,8 @@ class FrameworkMounter {
|
|
|
126
119
|
// Mounts new ones
|
|
127
120
|
parentRouter.use(driverRouter.routes());
|
|
128
121
|
});
|
|
122
|
+
// MCP middleware - intercepts MCP routes before they reach Koa's body parser
|
|
123
|
+
koa.use(this.mcpMiddleware.getKoaMiddleware());
|
|
129
124
|
koa.use(parentRouter.routes());
|
|
130
125
|
this.logger('Info', `Successfully mounted on Koa`);
|
|
131
126
|
return this;
|
|
@@ -138,36 +133,19 @@ class FrameworkMounter {
|
|
|
138
133
|
const adapter = nestJs.getHttpAdapter();
|
|
139
134
|
const callback = this.getConnectCallback(false);
|
|
140
135
|
if (adapter.constructor.name === 'ExpressAdapter') {
|
|
136
|
+
// MCP middleware at root - the callback handles its own path filtering
|
|
137
|
+
nestJs.use(this.mcpMiddleware.getExpressMiddleware());
|
|
138
|
+
// Mount main forest routes
|
|
141
139
|
nestJs.use(this.completeMountPrefix, callback);
|
|
142
140
|
}
|
|
143
141
|
else {
|
|
144
|
-
|
|
142
|
+
// Fastify adapter - MCP middleware at root
|
|
143
|
+
this.fastifyAdapter.useCallback(nestJs, this.mcpMiddleware.getExpressMiddleware(), '/');
|
|
144
|
+
this.fastifyAdapter.useCallback(nestJs, callback, this.completeMountPrefix);
|
|
145
145
|
}
|
|
146
146
|
this.logger('Info', `Successfully mounted on NestJS`);
|
|
147
147
|
return this;
|
|
148
148
|
}
|
|
149
|
-
useCallbackOnFastify(fastify, callback) {
|
|
150
|
-
try {
|
|
151
|
-
// 'fastify 2' or 'middie' or 'fastify-express'
|
|
152
|
-
fastify.use(this.completeMountPrefix, callback);
|
|
153
|
-
}
|
|
154
|
-
catch (e) {
|
|
155
|
-
// 'fastify 3'
|
|
156
|
-
if (e.code === 'FST_ERR_MISSING_MIDDLEWARE') {
|
|
157
|
-
fastify
|
|
158
|
-
.register(Promise.resolve().then(() => __importStar(require('@fastify/express'))))
|
|
159
|
-
.then(() => {
|
|
160
|
-
fastify.use(this.completeMountPrefix, callback);
|
|
161
|
-
})
|
|
162
|
-
.catch(err => {
|
|
163
|
-
this.logger('Error', err.message);
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
throw e;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
149
|
getConnectCallback(nested) {
|
|
172
150
|
let handler = null;
|
|
173
151
|
this.onEachStart.push(async (driverRouter) => {
|
|
@@ -178,6 +156,22 @@ class FrameworkMounter {
|
|
|
178
156
|
handler = new koa_1.default().use(router.routes()).callback();
|
|
179
157
|
});
|
|
180
158
|
return (req, res) => {
|
|
159
|
+
// For standalone server (nested), check MCP callback first
|
|
160
|
+
// The MCP callback handles its own path filtering
|
|
161
|
+
const mcpCallback = this.mcpMiddleware.getCallback();
|
|
162
|
+
if (nested && mcpCallback) {
|
|
163
|
+
mcpCallback(req, res, () => {
|
|
164
|
+
// next() called means not an MCP route - forward to main handler
|
|
165
|
+
if (handler) {
|
|
166
|
+
handler(req, res);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
170
|
+
res.end(JSON.stringify({ error: 'Agent is not started' }));
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
181
175
|
if (handler) {
|
|
182
176
|
handler(req, res);
|
|
183
177
|
}
|
|
@@ -189,4 +183,4 @@ class FrameworkMounter {
|
|
|
189
183
|
}
|
|
190
184
|
}
|
|
191
185
|
exports.default = FrameworkMounter;
|
|
192
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
186
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhbWV3b3JrLW1vdW50ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZnJhbWV3b3JrLW1vdW50ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFHQSx5REFBaUM7QUFDakMsK0JBQW9DO0FBQ3BDLDhDQUFzQjtBQUV0QixnREFBd0I7QUFFeEIsd0VBQStDO0FBQy9DLHNFQUE2QztBQUc3QyxNQUFxQixnQkFBZ0I7SUFhbkMsK0ZBQStGO0lBQy9GLElBQVksbUJBQW1CO1FBQzdCLE9BQU8sY0FBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELFlBQVksTUFBYyxFQUFFLE1BQWM7UUFmekIsaUJBQVksR0FBNEIsRUFBRSxDQUFDO1FBQzNDLGdCQUFXLEdBQTBDLEVBQUUsQ0FBQztRQUV4RCxXQUFNLEdBQTRCLEVBQUUsQ0FBQztRQWFwRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUkseUJBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksd0JBQWEsRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNPLGNBQWMsQ0FBQyxRQUE2QjtRQUNwRCxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRVMsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFjO1FBQ2xDLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLFlBQVk7WUFBRSxNQUFNLElBQUksRUFBRSxDQUFDLENBQUMsdUNBQXVDO1FBRTNGLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM3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
|
package/dist/index.js
CHANGED
|
@@ -17,15 +17,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.SchemaGenerator = exports.Agent =
|
|
20
|
+
exports.SchemaGenerator = exports.Agent = void 0;
|
|
21
|
+
exports.createAgent = createAgent;
|
|
21
22
|
const agent_1 = __importDefault(require("./agent"));
|
|
22
23
|
exports.Agent = agent_1.default;
|
|
23
24
|
function createAgent(options) {
|
|
24
25
|
return new agent_1.default(options);
|
|
25
26
|
}
|
|
26
|
-
exports.createAgent = createAgent;
|
|
27
27
|
__exportStar(require("@forestadmin/datasource-customizer"), exports);
|
|
28
28
|
// export is necessary for the agent-generator package
|
|
29
29
|
var generator_1 = require("./utils/forest-schema/generator");
|
|
30
30
|
Object.defineProperty(exports, "SchemaGenerator", { enumerable: true, get: function () { return __importDefault(generator_1).default; } });
|
|
31
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFLQSxrQ0FFQztBQUxELG9EQUE0QjtBQU9uQixnQkFQRixlQUFLLENBT0U7QUFKZCxTQUFnQixXQUFXLENBQThCLE9BQXFCO0lBQzVFLE9BQU8sSUFBSSxlQUFLLENBQUksT0FBTyxDQUFDLENBQUM7QUFDL0IsQ0FBQztBQUlELHFFQUFtRDtBQUVuRCxzREFBc0Q7QUFDdEQsNkRBQTZFO0FBQXBFLDZIQUFBLE9BQU8sT0FBbUIifQ==
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Koa from 'koa';
|
|
2
|
+
import { HttpCallback } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Factory functions for creating MCP middleware for different frameworks.
|
|
5
|
+
* MCP middleware intercepts MCP-specific routes (/.well-known/*, /oauth/*, /mcp)
|
|
6
|
+
* and forwards them to the MCP callback, while passing through other routes.
|
|
7
|
+
*/
|
|
8
|
+
export default class McpMiddleware {
|
|
9
|
+
private mcpHttpCallback;
|
|
10
|
+
/**
|
|
11
|
+
* Set the MCP HTTP callback. Call this before using the middleware.
|
|
12
|
+
*/
|
|
13
|
+
setCallback(callback: HttpCallback | null): void;
|
|
14
|
+
/**
|
|
15
|
+
* Get the current MCP HTTP callback.
|
|
16
|
+
*/
|
|
17
|
+
getCallback(): HttpCallback | null;
|
|
18
|
+
/**
|
|
19
|
+
* Get an Express/Connect-style middleware that forwards requests to the MCP callback.
|
|
20
|
+
* The MCP callback handles path filtering and calls next() for non-MCP routes.
|
|
21
|
+
*/
|
|
22
|
+
getExpressMiddleware(): HttpCallback;
|
|
23
|
+
/**
|
|
24
|
+
* Get a Koa middleware that forwards requests to the MCP callback.
|
|
25
|
+
* Uses expressToKoa wrapper for proper Koa integration.
|
|
26
|
+
*/
|
|
27
|
+
getKoaMiddleware(): Koa.Middleware;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=mcp-middleware.d.ts.map
|