@frontmcp/adapters 0.6.0 → 0.6.2
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/esm/index.mjs +1168 -0
- package/esm/openapi/index.mjs +1168 -0
- package/esm/package.json +63 -0
- package/index.js +1193 -0
- package/openapi/index.js +1192 -0
- package/package.json +30 -12
- package/src/index.js +0 -8
- package/src/index.js.map +0 -1
- package/src/openapi/README.md +0 -1215
- package/src/openapi/index.js +0 -8
- package/src/openapi/index.js.map +0 -1
- package/src/openapi/openapi.adapter.js +0 -434
- package/src/openapi/openapi.adapter.js.map +0 -1
- package/src/openapi/openapi.frontmcp-schema.js +0 -358
- package/src/openapi/openapi.frontmcp-schema.js.map +0 -1
- package/src/openapi/openapi.security.js +0 -242
- package/src/openapi/openapi.security.js.map +0 -1
- package/src/openapi/openapi.tool.js +0 -267
- package/src/openapi/openapi.tool.js.map +0 -1
- package/src/openapi/openapi.types.js +0 -29
- package/src/openapi/openapi.types.js.map +0 -1
- package/src/openapi/openapi.utils.js +0 -229
- package/src/openapi/openapi.utils.js.map +0 -1
- /package/{src/index.d.ts → index.d.ts} +0 -0
- /package/{src/openapi → openapi}/index.d.ts +0 -0
- /package/{src/openapi → openapi}/openapi.adapter.d.ts +0 -0
- /package/{src/openapi → openapi}/openapi.frontmcp-schema.d.ts +0 -0
- /package/{src/openapi → openapi}/openapi.security.d.ts +0 -0
- /package/{src/openapi → openapi}/openapi.tool.d.ts +0 -0
- /package/{src/openapi → openapi}/openapi.types.d.ts +0 -0
- /package/{src/openapi → openapi}/openapi.utils.d.ts +0 -0
package/src/openapi/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
var openapi_adapter_1 = require("./openapi.adapter");
|
|
6
|
-
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return tslib_1.__importDefault(openapi_adapter_1).default; } });
|
|
7
|
-
tslib_1.__exportStar(require("./openapi.types"), exports);
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
package/src/openapi/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/openapi/index.ts"],"names":[],"mappings":";;;;AAAA,qDAA4C;AAAnC,mIAAA,OAAO,OAAA;AAChB,0DAAgC","sourcesContent":["export { default } from './openapi.adapter';\nexport * from './openapi.types';\n"]}
|
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
|
-
const sdk_1 = require("@frontmcp/sdk");
|
|
5
|
-
const mcp_from_openapi_1 = require("mcp-from-openapi");
|
|
6
|
-
const openapi_tool_1 = require("./openapi.tool");
|
|
7
|
-
const openapi_security_1 = require("./openapi.security");
|
|
8
|
-
/** Reserved keys that cannot be used as inputKey (prototype pollution protection) */
|
|
9
|
-
const RESERVED_KEYS = ['__proto__', 'constructor', 'prototype'];
|
|
10
|
-
/**
|
|
11
|
-
* Creates a simple console-based logger for use outside the SDK context.
|
|
12
|
-
*/
|
|
13
|
-
function createConsoleLogger(prefix) {
|
|
14
|
-
const formatMessage = (level, msg) => `[${prefix}] ${level}: ${msg}`;
|
|
15
|
-
return {
|
|
16
|
-
verbose: (msg, ...args) => console.debug(formatMessage('VERBOSE', msg), ...args),
|
|
17
|
-
debug: (msg, ...args) => console.debug(formatMessage('DEBUG', msg), ...args),
|
|
18
|
-
info: (msg, ...args) => console.info(formatMessage('INFO', msg), ...args),
|
|
19
|
-
warn: (msg, ...args) => console.warn(formatMessage('WARN', msg), ...args),
|
|
20
|
-
error: (msg, ...args) => console.error(formatMessage('ERROR', msg), ...args),
|
|
21
|
-
child: (childPrefix) => createConsoleLogger(`${prefix}:${childPrefix}`),
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
let OpenapiAdapter = class OpenapiAdapter extends sdk_1.DynamicAdapter {
|
|
25
|
-
generator;
|
|
26
|
-
logger;
|
|
27
|
-
options;
|
|
28
|
-
constructor(options) {
|
|
29
|
-
super();
|
|
30
|
-
this.options = options;
|
|
31
|
-
// Use provided logger or create console fallback
|
|
32
|
-
this.logger = options.logger ?? createConsoleLogger(`openapi:${options.name}`);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Receive the SDK logger. Called by the SDK before fetch().
|
|
36
|
-
*/
|
|
37
|
-
setLogger(logger) {
|
|
38
|
-
this.logger = logger;
|
|
39
|
-
}
|
|
40
|
-
async fetch() {
|
|
41
|
-
// Lazy load: Initialize generator on first fetch if not already initialized
|
|
42
|
-
if (!this.generator) {
|
|
43
|
-
this.generator = await this.initializeGenerator();
|
|
44
|
-
}
|
|
45
|
-
// Determine if we need security in input
|
|
46
|
-
// If securitySchemesInInput is set, we need all security in input first, then filter
|
|
47
|
-
const hasPerSchemeControl = this.options.securitySchemesInInput && this.options.securitySchemesInInput.length > 0;
|
|
48
|
-
const includeSecurityInInput = hasPerSchemeControl || (this.options.generateOptions?.includeSecurityInInput ?? false);
|
|
49
|
-
// Generate tools from OpenAPI spec
|
|
50
|
-
let openapiTools = await this.generator.generateTools({
|
|
51
|
-
includeOperations: this.options.generateOptions?.includeOperations,
|
|
52
|
-
excludeOperations: this.options.generateOptions?.excludeOperations,
|
|
53
|
-
filterFn: this.options.generateOptions?.filterFn,
|
|
54
|
-
namingStrategy: this.options.generateOptions?.namingStrategy,
|
|
55
|
-
preferredStatusCodes: this.options.generateOptions?.preferredStatusCodes ?? [200, 201, 202, 204],
|
|
56
|
-
includeDeprecated: this.options.generateOptions?.includeDeprecated ?? false,
|
|
57
|
-
includeAllResponses: this.options.generateOptions?.includeAllResponses ?? true,
|
|
58
|
-
includeSecurityInInput: includeSecurityInInput,
|
|
59
|
-
maxSchemaDepth: this.options.generateOptions?.maxSchemaDepth,
|
|
60
|
-
includeExamples: this.options.generateOptions?.includeExamples,
|
|
61
|
-
});
|
|
62
|
-
// If per-scheme control is enabled, filter security inputs
|
|
63
|
-
if (hasPerSchemeControl) {
|
|
64
|
-
openapiTools = openapiTools.map((tool) => this.filterSecuritySchemes(tool));
|
|
65
|
-
}
|
|
66
|
-
// Validate security configuration
|
|
67
|
-
const validation = (0, openapi_security_1.validateSecurityConfiguration)(openapiTools, this.options);
|
|
68
|
-
// Log security information
|
|
69
|
-
this.logger.info('Security Analysis:');
|
|
70
|
-
this.logger.info(` Security Risk Score: ${validation.securityRiskScore.toUpperCase()}`);
|
|
71
|
-
this.logger.info(` Valid Configuration: ${validation.valid ? 'YES' : 'NO'}`);
|
|
72
|
-
if (validation.warnings.length > 0) {
|
|
73
|
-
this.logger.info('Messages:');
|
|
74
|
-
validation.warnings.forEach((warning) => {
|
|
75
|
-
if (warning.startsWith('ERROR:')) {
|
|
76
|
-
this.logger.error(` - ${warning}`);
|
|
77
|
-
}
|
|
78
|
-
else if (warning.startsWith('SECURITY WARNING:')) {
|
|
79
|
-
this.logger.warn(` - ${warning}`);
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
this.logger.info(` - ${warning}`);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
// Fail if configuration is invalid and security is required
|
|
87
|
-
if (!validation.valid) {
|
|
88
|
-
throw new Error(`[OpenAPI Adapter: ${this.options.name}] Invalid security configuration.\n` +
|
|
89
|
-
`Missing auth provider mappings for security schemes: ${validation.missingMappings.join(', ')}\n\n` +
|
|
90
|
-
`Your OpenAPI spec requires these security schemes, but no auth configuration was provided.\n\n` +
|
|
91
|
-
`Add one of the following to your adapter configuration:\n\n` +
|
|
92
|
-
`1. authProviderMapper (recommended):\n` +
|
|
93
|
-
` authProviderMapper: {\n` +
|
|
94
|
-
validation.missingMappings
|
|
95
|
-
.map((s) => ` '${s}': (authInfo) => authInfo.user?.${s.toLowerCase()}Token,`)
|
|
96
|
-
.join('\n') +
|
|
97
|
-
`\n }\n\n` +
|
|
98
|
-
`2. securityResolver:\n` +
|
|
99
|
-
` securityResolver: (tool, authInfo) => ({ jwt: authInfo.token })\n\n` +
|
|
100
|
-
`3. staticAuth:\n` +
|
|
101
|
-
` staticAuth: { jwt: process.env.API_TOKEN }\n\n` +
|
|
102
|
-
`4. Include security in input (NOT recommended for production):\n` +
|
|
103
|
-
` generateOptions: { includeSecurityInInput: true }`);
|
|
104
|
-
}
|
|
105
|
-
// Apply all transforms to tools
|
|
106
|
-
let transformedTools = openapiTools;
|
|
107
|
-
// 1. Apply description mode (generates description from summary/description)
|
|
108
|
-
if (this.options.descriptionMode && this.options.descriptionMode !== 'summaryOnly') {
|
|
109
|
-
transformedTools = transformedTools.map((tool) => this.applyDescriptionMode(tool));
|
|
110
|
-
}
|
|
111
|
-
// 2. Apply tool transforms (annotations, name, description overrides, etc.)
|
|
112
|
-
if (this.options.toolTransforms) {
|
|
113
|
-
transformedTools = transformedTools.map((tool) => this.applyToolTransforms(tool));
|
|
114
|
-
}
|
|
115
|
-
// 3. Apply input transforms (hide inputs, inject values at runtime)
|
|
116
|
-
if (this.options.inputTransforms) {
|
|
117
|
-
transformedTools = transformedTools.map((tool) => this.applyInputTransforms(tool));
|
|
118
|
-
}
|
|
119
|
-
// Convert OpenAPI tools to FrontMCP tools
|
|
120
|
-
const tools = transformedTools.map((openapiTool) => (0, openapi_tool_1.createOpenApiTool)(openapiTool, this.options, this.logger));
|
|
121
|
-
return { tools };
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Initialize the OpenAPI tool generator from URL or spec
|
|
125
|
-
* @private
|
|
126
|
-
*/
|
|
127
|
-
async initializeGenerator() {
|
|
128
|
-
if ('url' in this.options) {
|
|
129
|
-
return await mcp_from_openapi_1.OpenAPIToolGenerator.fromURL(this.options.url, {
|
|
130
|
-
baseUrl: this.options.baseUrl,
|
|
131
|
-
validate: this.options.loadOptions?.validate ?? true,
|
|
132
|
-
dereference: this.options.loadOptions?.dereference ?? true,
|
|
133
|
-
headers: this.options.loadOptions?.headers,
|
|
134
|
-
timeout: this.options.loadOptions?.timeout,
|
|
135
|
-
followRedirects: this.options.loadOptions?.followRedirects,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
else if ('spec' in this.options) {
|
|
139
|
-
return await mcp_from_openapi_1.OpenAPIToolGenerator.fromJSON(this.options.spec, {
|
|
140
|
-
baseUrl: this.options.baseUrl,
|
|
141
|
-
validate: this.options.loadOptions?.validate ?? true,
|
|
142
|
-
dereference: this.options.loadOptions?.dereference ?? true,
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
throw new Error('Either url or spec must be provided in OpenApiAdapterOptions');
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Apply description mode to generate description from summary/description
|
|
151
|
-
* @private
|
|
152
|
-
*/
|
|
153
|
-
applyDescriptionMode(tool) {
|
|
154
|
-
const mode = this.options.descriptionMode || 'summaryOnly';
|
|
155
|
-
const metadata = tool.metadata;
|
|
156
|
-
const summary = metadata['operationSummary'];
|
|
157
|
-
const opDescription = metadata['operationDescription'];
|
|
158
|
-
const operationId = metadata['operationId'];
|
|
159
|
-
const method = metadata['method'];
|
|
160
|
-
const path = metadata['path'];
|
|
161
|
-
let description;
|
|
162
|
-
switch (mode) {
|
|
163
|
-
case 'descriptionOnly':
|
|
164
|
-
description = opDescription || summary || `${method.toUpperCase()} ${path}`;
|
|
165
|
-
break;
|
|
166
|
-
case 'combined':
|
|
167
|
-
if (summary && opDescription) {
|
|
168
|
-
description = `${summary}\n\n${opDescription}`;
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
description = summary || opDescription || `${method.toUpperCase()} ${path}`;
|
|
172
|
-
}
|
|
173
|
-
break;
|
|
174
|
-
case 'full': {
|
|
175
|
-
const parts = [];
|
|
176
|
-
if (summary)
|
|
177
|
-
parts.push(summary);
|
|
178
|
-
if (opDescription && opDescription !== summary)
|
|
179
|
-
parts.push(opDescription);
|
|
180
|
-
if (operationId)
|
|
181
|
-
parts.push(`Operation: ${operationId}`);
|
|
182
|
-
parts.push(`${method.toUpperCase()} ${path}`);
|
|
183
|
-
description = parts.join('\n\n');
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
default:
|
|
187
|
-
// 'summaryOnly' - use existing description
|
|
188
|
-
return tool;
|
|
189
|
-
}
|
|
190
|
-
return {
|
|
191
|
-
...tool,
|
|
192
|
-
description,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Collect tool transforms for a specific tool
|
|
197
|
-
* @private
|
|
198
|
-
*/
|
|
199
|
-
collectToolTransforms(tool) {
|
|
200
|
-
const result = {};
|
|
201
|
-
const opts = this.options.toolTransforms;
|
|
202
|
-
if (!opts)
|
|
203
|
-
return result;
|
|
204
|
-
// 1. Apply global transforms
|
|
205
|
-
if (opts.global) {
|
|
206
|
-
Object.assign(result, opts.global);
|
|
207
|
-
if (opts.global.annotations) {
|
|
208
|
-
result.annotations = { ...opts.global.annotations };
|
|
209
|
-
}
|
|
210
|
-
if (opts.global.tags) {
|
|
211
|
-
result.tags = [...opts.global.tags];
|
|
212
|
-
}
|
|
213
|
-
if (opts.global.examples) {
|
|
214
|
-
result.examples = [...opts.global.examples];
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// 2. Apply per-tool transforms (override global)
|
|
218
|
-
if (opts.perTool?.[tool.name]) {
|
|
219
|
-
const perTool = opts.perTool[tool.name];
|
|
220
|
-
if (perTool.name)
|
|
221
|
-
result.name = perTool.name;
|
|
222
|
-
if (perTool.description)
|
|
223
|
-
result.description = perTool.description;
|
|
224
|
-
if (perTool.hideFromDiscovery !== undefined)
|
|
225
|
-
result.hideFromDiscovery = perTool.hideFromDiscovery;
|
|
226
|
-
if (perTool.ui)
|
|
227
|
-
result.ui = perTool.ui;
|
|
228
|
-
if (perTool.annotations) {
|
|
229
|
-
result.annotations = { ...result.annotations, ...perTool.annotations };
|
|
230
|
-
}
|
|
231
|
-
if (perTool.tags) {
|
|
232
|
-
result.tags = [...(result.tags || []), ...perTool.tags];
|
|
233
|
-
}
|
|
234
|
-
if (perTool.examples) {
|
|
235
|
-
result.examples = [...(result.examples || []), ...perTool.examples];
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
// 3. Apply generator-produced transforms (override per-tool)
|
|
239
|
-
if (opts.generator) {
|
|
240
|
-
const generated = opts.generator(tool);
|
|
241
|
-
if (generated) {
|
|
242
|
-
if (generated.name)
|
|
243
|
-
result.name = generated.name;
|
|
244
|
-
if (generated.description)
|
|
245
|
-
result.description = generated.description;
|
|
246
|
-
if (generated.hideFromDiscovery !== undefined)
|
|
247
|
-
result.hideFromDiscovery = generated.hideFromDiscovery;
|
|
248
|
-
if (generated.ui)
|
|
249
|
-
result.ui = generated.ui;
|
|
250
|
-
if (generated.annotations) {
|
|
251
|
-
result.annotations = { ...result.annotations, ...generated.annotations };
|
|
252
|
-
}
|
|
253
|
-
if (generated.tags) {
|
|
254
|
-
result.tags = [...(result.tags || []), ...generated.tags];
|
|
255
|
-
}
|
|
256
|
-
if (generated.examples) {
|
|
257
|
-
result.examples = [...(result.examples || []), ...generated.examples];
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return result;
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Apply tool transforms to an OpenAPI tool
|
|
265
|
-
* @private
|
|
266
|
-
*/
|
|
267
|
-
applyToolTransforms(tool) {
|
|
268
|
-
const transforms = this.collectToolTransforms(tool);
|
|
269
|
-
if (Object.keys(transforms).length === 0)
|
|
270
|
-
return tool;
|
|
271
|
-
let newName = tool.name;
|
|
272
|
-
let newDescription = tool.description;
|
|
273
|
-
// Apply name transform
|
|
274
|
-
if (transforms.name) {
|
|
275
|
-
newName = typeof transforms.name === 'function' ? transforms.name(tool.name, tool) : transforms.name;
|
|
276
|
-
}
|
|
277
|
-
// Apply description transform
|
|
278
|
-
if (transforms.description) {
|
|
279
|
-
newDescription =
|
|
280
|
-
typeof transforms.description === 'function'
|
|
281
|
-
? transforms.description(tool.description, tool)
|
|
282
|
-
: transforms.description;
|
|
283
|
-
}
|
|
284
|
-
this.logger.debug(`Applied tool transforms to '${tool.name}'`);
|
|
285
|
-
const metadataRecord = tool.metadata;
|
|
286
|
-
const existingAdapter = metadataRecord['adapter'];
|
|
287
|
-
return {
|
|
288
|
-
...tool,
|
|
289
|
-
name: newName,
|
|
290
|
-
description: newDescription,
|
|
291
|
-
metadata: {
|
|
292
|
-
...tool.metadata,
|
|
293
|
-
adapter: {
|
|
294
|
-
...(existingAdapter || {}),
|
|
295
|
-
toolTransform: transforms,
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Collect all input transforms for a specific tool
|
|
302
|
-
* @private
|
|
303
|
-
*/
|
|
304
|
-
collectTransformsForTool(tool) {
|
|
305
|
-
const transforms = [];
|
|
306
|
-
const opts = this.options.inputTransforms;
|
|
307
|
-
if (!opts)
|
|
308
|
-
return transforms;
|
|
309
|
-
// 1. Add global transforms
|
|
310
|
-
if (opts.global) {
|
|
311
|
-
transforms.push(...opts.global);
|
|
312
|
-
}
|
|
313
|
-
// 2. Add per-tool transforms
|
|
314
|
-
if (opts.perTool?.[tool.name]) {
|
|
315
|
-
transforms.push(...opts.perTool[tool.name]);
|
|
316
|
-
}
|
|
317
|
-
// 3. Add generator-produced transforms
|
|
318
|
-
if (opts.generator) {
|
|
319
|
-
transforms.push(...opts.generator(tool));
|
|
320
|
-
}
|
|
321
|
-
return transforms;
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Apply input transforms to an OpenAPI tool
|
|
325
|
-
* - Removes transformed inputKeys from the inputSchema
|
|
326
|
-
* - Stores transform metadata for runtime injection
|
|
327
|
-
* @private
|
|
328
|
-
*/
|
|
329
|
-
applyInputTransforms(tool) {
|
|
330
|
-
const transforms = this.collectTransformsForTool(tool);
|
|
331
|
-
if (transforms.length === 0)
|
|
332
|
-
return tool;
|
|
333
|
-
// Validate input keys against reserved keys (prototype pollution protection)
|
|
334
|
-
for (const transform of transforms) {
|
|
335
|
-
if (RESERVED_KEYS.includes(transform.inputKey)) {
|
|
336
|
-
throw new Error(`Invalid inputKey '${transform.inputKey}' in tool '${tool.name}': ` +
|
|
337
|
-
`reserved keys (${RESERVED_KEYS.join(', ')}) cannot be used`);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
const transformedInputKeys = new Set(transforms.map((t) => t.inputKey));
|
|
341
|
-
// Clone and modify inputSchema to remove transformed keys
|
|
342
|
-
const inputSchema = tool.inputSchema;
|
|
343
|
-
const properties = inputSchema?.['properties'] || {};
|
|
344
|
-
const required = inputSchema?.['required'] || [];
|
|
345
|
-
// Remove transformed keys from properties
|
|
346
|
-
const newProperties = { ...properties };
|
|
347
|
-
for (const key of transformedInputKeys) {
|
|
348
|
-
delete newProperties[key];
|
|
349
|
-
}
|
|
350
|
-
// Update required array to exclude transformed keys
|
|
351
|
-
const newRequired = required.filter((key) => !transformedInputKeys.has(key));
|
|
352
|
-
this.logger.debug(`Applied ${transforms.length} input transforms to tool '${tool.name}'`);
|
|
353
|
-
const metadataRecord = tool.metadata;
|
|
354
|
-
const existingAdapter = metadataRecord['adapter'];
|
|
355
|
-
return {
|
|
356
|
-
...tool,
|
|
357
|
-
inputSchema: {
|
|
358
|
-
...inputSchema,
|
|
359
|
-
properties: newProperties,
|
|
360
|
-
...(newRequired.length > 0 ? { required: newRequired } : {}),
|
|
361
|
-
},
|
|
362
|
-
// Store transforms in metadata for runtime use
|
|
363
|
-
metadata: {
|
|
364
|
-
...tool.metadata,
|
|
365
|
-
adapter: {
|
|
366
|
-
...(existingAdapter || {}),
|
|
367
|
-
inputTransforms: transforms,
|
|
368
|
-
},
|
|
369
|
-
},
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Filter security schemes in tool input based on securitySchemesInInput option.
|
|
374
|
-
* Removes security inputs that should be resolved from context instead of user input.
|
|
375
|
-
* @private
|
|
376
|
-
*/
|
|
377
|
-
filterSecuritySchemes(tool) {
|
|
378
|
-
const allowedSchemes = new Set(this.options.securitySchemesInInput || []);
|
|
379
|
-
if (allowedSchemes.size === 0)
|
|
380
|
-
return tool;
|
|
381
|
-
// Find security mappers that should NOT be in input (resolved from context)
|
|
382
|
-
const schemesToRemove = new Set();
|
|
383
|
-
const inputKeysToRemove = new Set();
|
|
384
|
-
for (const mapper of tool.mapper) {
|
|
385
|
-
if (mapper.security?.scheme && !allowedSchemes.has(mapper.security.scheme)) {
|
|
386
|
-
schemesToRemove.add(mapper.security.scheme);
|
|
387
|
-
inputKeysToRemove.add(mapper.inputKey);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (inputKeysToRemove.size === 0)
|
|
391
|
-
return tool;
|
|
392
|
-
// Remove security inputs from inputSchema
|
|
393
|
-
const inputSchema = tool.inputSchema;
|
|
394
|
-
const properties = inputSchema?.['properties'] || {};
|
|
395
|
-
const required = inputSchema?.['required'] || [];
|
|
396
|
-
const newProperties = { ...properties };
|
|
397
|
-
for (const key of inputKeysToRemove) {
|
|
398
|
-
delete newProperties[key];
|
|
399
|
-
}
|
|
400
|
-
const newRequired = required.filter((key) => !inputKeysToRemove.has(key));
|
|
401
|
-
this.logger.debug(`[${tool.name}] Filtered security schemes from input: ${Array.from(schemesToRemove).join(', ')}. ` +
|
|
402
|
-
`Kept in input: ${Array.from(allowedSchemes)
|
|
403
|
-
.filter((s) => !schemesToRemove.has(s))
|
|
404
|
-
.join(', ') || 'none'}`);
|
|
405
|
-
const metadataRecord = tool.metadata;
|
|
406
|
-
const existingAdapter = metadataRecord['adapter'];
|
|
407
|
-
return {
|
|
408
|
-
...tool,
|
|
409
|
-
inputSchema: {
|
|
410
|
-
...inputSchema,
|
|
411
|
-
properties: newProperties,
|
|
412
|
-
...(newRequired.length > 0 ? { required: newRequired } : {}),
|
|
413
|
-
},
|
|
414
|
-
// Store which security schemes are in input vs context for later resolution
|
|
415
|
-
metadata: {
|
|
416
|
-
...tool.metadata,
|
|
417
|
-
adapter: {
|
|
418
|
-
...(existingAdapter || {}),
|
|
419
|
-
securitySchemesInInput: Array.from(allowedSchemes),
|
|
420
|
-
securitySchemesFromContext: Array.from(schemesToRemove),
|
|
421
|
-
},
|
|
422
|
-
},
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
};
|
|
426
|
-
OpenapiAdapter = tslib_1.__decorate([
|
|
427
|
-
(0, sdk_1.Adapter)({
|
|
428
|
-
name: 'openapi',
|
|
429
|
-
description: 'OpenAPI adapter for FrontMCP - Automatically generates MCP tools from OpenAPI specifications',
|
|
430
|
-
}),
|
|
431
|
-
tslib_1.__metadata("design:paramtypes", [Object])
|
|
432
|
-
], OpenapiAdapter);
|
|
433
|
-
exports.default = OpenapiAdapter;
|
|
434
|
-
//# sourceMappingURL=openapi.adapter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.adapter.js","sourceRoot":"","sources":["../../../src/openapi/openapi.adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Adapter, DynamicAdapter, FrontMcpAdapterResponse, FrontMcpLogger } from '@frontmcp/sdk';\nimport { OpenApiAdapterOptions, InputTransform, ToolTransform, ExtendedMcpOpenAPITool } from './openapi.types';\nimport { OpenAPIToolGenerator, McpOpenAPITool } from 'mcp-from-openapi';\nimport { createOpenApiTool } from './openapi.tool';\nimport { validateSecurityConfiguration } from './openapi.security';\n\n/** Reserved keys that cannot be used as inputKey (prototype pollution protection) */\nconst RESERVED_KEYS = ['__proto__', 'constructor', 'prototype'];\n\n/**\n * Creates a simple console-based logger for use outside the SDK context.\n */\nfunction createConsoleLogger(prefix: string): FrontMcpLogger {\n const formatMessage = (level: string, msg: string) => `[${prefix}] ${level}: ${msg}`;\n return {\n verbose: (msg: string, ...args: unknown[]) => console.debug(formatMessage('VERBOSE', msg), ...args),\n debug: (msg: string, ...args: unknown[]) => console.debug(formatMessage('DEBUG', msg), ...args),\n info: (msg: string, ...args: unknown[]) => console.info(formatMessage('INFO', msg), ...args),\n warn: (msg: string, ...args: unknown[]) => console.warn(formatMessage('WARN', msg), ...args),\n error: (msg: string, ...args: unknown[]) => console.error(formatMessage('ERROR', msg), ...args),\n child: (childPrefix: string) => createConsoleLogger(`${prefix}:${childPrefix}`),\n };\n}\n\n@Adapter({\n name: 'openapi',\n description: 'OpenAPI adapter for FrontMCP - Automatically generates MCP tools from OpenAPI specifications',\n})\nexport default class OpenapiAdapter extends DynamicAdapter<OpenApiAdapterOptions> {\n private generator?: OpenAPIToolGenerator;\n private logger: FrontMcpLogger;\n public options: OpenApiAdapterOptions;\n\n constructor(options: OpenApiAdapterOptions) {\n super();\n this.options = options;\n // Use provided logger or create console fallback\n this.logger = options.logger ?? createConsoleLogger(`openapi:${options.name}`);\n }\n\n /**\n * Receive the SDK logger. Called by the SDK before fetch().\n */\n setLogger(logger: FrontMcpLogger): void {\n this.logger = logger;\n }\n\n async fetch(): Promise<FrontMcpAdapterResponse> {\n // Lazy load: Initialize generator on first fetch if not already initialized\n if (!this.generator) {\n this.generator = await this.initializeGenerator();\n }\n\n // Determine if we need security in input\n // If securitySchemesInInput is set, we need all security in input first, then filter\n const hasPerSchemeControl = this.options.securitySchemesInInput && this.options.securitySchemesInInput.length > 0;\n const includeSecurityInInput =\n hasPerSchemeControl || (this.options.generateOptions?.includeSecurityInInput ?? false);\n\n // Generate tools from OpenAPI spec\n let openapiTools = await this.generator.generateTools({\n includeOperations: this.options.generateOptions?.includeOperations,\n excludeOperations: this.options.generateOptions?.excludeOperations,\n filterFn: this.options.generateOptions?.filterFn,\n namingStrategy: this.options.generateOptions?.namingStrategy,\n preferredStatusCodes: this.options.generateOptions?.preferredStatusCodes ?? [200, 201, 202, 204],\n includeDeprecated: this.options.generateOptions?.includeDeprecated ?? false,\n includeAllResponses: this.options.generateOptions?.includeAllResponses ?? true,\n includeSecurityInInput: includeSecurityInInput,\n maxSchemaDepth: this.options.generateOptions?.maxSchemaDepth,\n includeExamples: this.options.generateOptions?.includeExamples,\n });\n\n // If per-scheme control is enabled, filter security inputs\n if (hasPerSchemeControl) {\n openapiTools = openapiTools.map((tool) => this.filterSecuritySchemes(tool));\n }\n\n // Validate security configuration\n const validation = validateSecurityConfiguration(openapiTools, this.options);\n\n // Log security information\n this.logger.info('Security Analysis:');\n this.logger.info(` Security Risk Score: ${validation.securityRiskScore.toUpperCase()}`);\n this.logger.info(` Valid Configuration: ${validation.valid ? 'YES' : 'NO'}`);\n\n if (validation.warnings.length > 0) {\n this.logger.info('Messages:');\n validation.warnings.forEach((warning) => {\n if (warning.startsWith('ERROR:')) {\n this.logger.error(` - ${warning}`);\n } else if (warning.startsWith('SECURITY WARNING:')) {\n this.logger.warn(` - ${warning}`);\n } else {\n this.logger.info(` - ${warning}`);\n }\n });\n }\n\n // Fail if configuration is invalid and security is required\n if (!validation.valid) {\n throw new Error(\n `[OpenAPI Adapter: ${this.options.name}] Invalid security configuration.\\n` +\n `Missing auth provider mappings for security schemes: ${validation.missingMappings.join(', ')}\\n\\n` +\n `Your OpenAPI spec requires these security schemes, but no auth configuration was provided.\\n\\n` +\n `Add one of the following to your adapter configuration:\\n\\n` +\n `1. authProviderMapper (recommended):\\n` +\n ` authProviderMapper: {\\n` +\n validation.missingMappings\n .map((s) => ` '${s}': (authInfo) => authInfo.user?.${s.toLowerCase()}Token,`)\n .join('\\n') +\n `\\n }\\n\\n` +\n `2. securityResolver:\\n` +\n ` securityResolver: (tool, authInfo) => ({ jwt: authInfo.token })\\n\\n` +\n `3. staticAuth:\\n` +\n ` staticAuth: { jwt: process.env.API_TOKEN }\\n\\n` +\n `4. Include security in input (NOT recommended for production):\\n` +\n ` generateOptions: { includeSecurityInInput: true }`,\n );\n }\n\n // Apply all transforms to tools\n let transformedTools = openapiTools;\n\n // 1. Apply description mode (generates description from summary/description)\n if (this.options.descriptionMode && this.options.descriptionMode !== 'summaryOnly') {\n transformedTools = transformedTools.map((tool) => this.applyDescriptionMode(tool));\n }\n\n // 2. Apply tool transforms (annotations, name, description overrides, etc.)\n if (this.options.toolTransforms) {\n transformedTools = transformedTools.map((tool) => this.applyToolTransforms(tool));\n }\n\n // 3. Apply input transforms (hide inputs, inject values at runtime)\n if (this.options.inputTransforms) {\n transformedTools = transformedTools.map((tool) => this.applyInputTransforms(tool));\n }\n\n // Convert OpenAPI tools to FrontMCP tools\n const tools = transformedTools.map((openapiTool) => createOpenApiTool(openapiTool, this.options, this.logger));\n\n return { tools };\n }\n\n /**\n * Initialize the OpenAPI tool generator from URL or spec\n * @private\n */\n private async initializeGenerator(): Promise<OpenAPIToolGenerator> {\n if ('url' in this.options) {\n return await OpenAPIToolGenerator.fromURL(this.options.url, {\n baseUrl: this.options.baseUrl,\n validate: this.options.loadOptions?.validate ?? true,\n dereference: this.options.loadOptions?.dereference ?? true,\n headers: this.options.loadOptions?.headers,\n timeout: this.options.loadOptions?.timeout,\n followRedirects: this.options.loadOptions?.followRedirects,\n });\n } else if ('spec' in this.options) {\n return await OpenAPIToolGenerator.fromJSON(this.options.spec, {\n baseUrl: this.options.baseUrl,\n validate: this.options.loadOptions?.validate ?? true,\n dereference: this.options.loadOptions?.dereference ?? true,\n });\n } else {\n throw new Error('Either url or spec must be provided in OpenApiAdapterOptions');\n }\n }\n\n /**\n * Apply description mode to generate description from summary/description\n * @private\n */\n private applyDescriptionMode(tool: McpOpenAPITool): McpOpenAPITool {\n const mode = this.options.descriptionMode || 'summaryOnly';\n const metadata = tool.metadata as unknown as Record<string, unknown>;\n const summary = metadata['operationSummary'] as string | undefined;\n const opDescription = metadata['operationDescription'] as string | undefined;\n const operationId = metadata['operationId'] as string | undefined;\n const method = metadata['method'] as string;\n const path = metadata['path'] as string;\n\n let description: string;\n\n switch (mode) {\n case 'descriptionOnly':\n description = opDescription || summary || `${method.toUpperCase()} ${path}`;\n break;\n case 'combined':\n if (summary && opDescription) {\n description = `${summary}\\n\\n${opDescription}`;\n } else {\n description = summary || opDescription || `${method.toUpperCase()} ${path}`;\n }\n break;\n case 'full': {\n const parts: string[] = [];\n if (summary) parts.push(summary);\n if (opDescription && opDescription !== summary) parts.push(opDescription);\n if (operationId) parts.push(`Operation: ${operationId}`);\n parts.push(`${method.toUpperCase()} ${path}`);\n description = parts.join('\\n\\n');\n break;\n }\n default:\n // 'summaryOnly' - use existing description\n return tool;\n }\n\n return {\n ...tool,\n description,\n };\n }\n\n /**\n * Collect tool transforms for a specific tool\n * @private\n */\n private collectToolTransforms(tool: McpOpenAPITool): ToolTransform {\n const result: ToolTransform = {};\n const opts = this.options.toolTransforms;\n if (!opts) return result;\n\n // 1. Apply global transforms\n if (opts.global) {\n Object.assign(result, opts.global);\n if (opts.global.annotations) {\n result.annotations = { ...opts.global.annotations };\n }\n if (opts.global.tags) {\n result.tags = [...opts.global.tags];\n }\n if (opts.global.examples) {\n result.examples = [...opts.global.examples];\n }\n }\n\n // 2. Apply per-tool transforms (override global)\n if (opts.perTool?.[tool.name]) {\n const perTool = opts.perTool[tool.name];\n if (perTool.name) result.name = perTool.name;\n if (perTool.description) result.description = perTool.description;\n if (perTool.hideFromDiscovery !== undefined) result.hideFromDiscovery = perTool.hideFromDiscovery;\n if (perTool.ui) result.ui = perTool.ui;\n if (perTool.annotations) {\n result.annotations = { ...result.annotations, ...perTool.annotations };\n }\n if (perTool.tags) {\n result.tags = [...(result.tags || []), ...perTool.tags];\n }\n if (perTool.examples) {\n result.examples = [...(result.examples || []), ...perTool.examples];\n }\n }\n\n // 3. Apply generator-produced transforms (override per-tool)\n if (opts.generator) {\n const generated = opts.generator(tool);\n if (generated) {\n if (generated.name) result.name = generated.name;\n if (generated.description) result.description = generated.description;\n if (generated.hideFromDiscovery !== undefined) result.hideFromDiscovery = generated.hideFromDiscovery;\n if (generated.ui) result.ui = generated.ui;\n if (generated.annotations) {\n result.annotations = { ...result.annotations, ...generated.annotations };\n }\n if (generated.tags) {\n result.tags = [...(result.tags || []), ...generated.tags];\n }\n if (generated.examples) {\n result.examples = [...(result.examples || []), ...generated.examples];\n }\n }\n }\n\n return result;\n }\n\n /**\n * Apply tool transforms to an OpenAPI tool\n * @private\n */\n private applyToolTransforms(tool: McpOpenAPITool): McpOpenAPITool {\n const transforms = this.collectToolTransforms(tool);\n if (Object.keys(transforms).length === 0) return tool;\n\n let newName = tool.name;\n let newDescription = tool.description;\n\n // Apply name transform\n if (transforms.name) {\n newName = typeof transforms.name === 'function' ? transforms.name(tool.name, tool) : transforms.name;\n }\n\n // Apply description transform\n if (transforms.description) {\n newDescription =\n typeof transforms.description === 'function'\n ? transforms.description(tool.description, tool)\n : transforms.description;\n }\n\n this.logger.debug(`Applied tool transforms to '${tool.name}'`);\n\n const metadataRecord = tool.metadata as unknown as Record<string, unknown>;\n const existingAdapter = metadataRecord['adapter'] as Record<string, unknown> | undefined;\n return {\n ...tool,\n name: newName,\n description: newDescription,\n metadata: {\n ...tool.metadata,\n adapter: {\n ...(existingAdapter || {}),\n toolTransform: transforms,\n },\n },\n } as ExtendedMcpOpenAPITool;\n }\n\n /**\n * Collect all input transforms for a specific tool\n * @private\n */\n private collectTransformsForTool(tool: McpOpenAPITool): InputTransform[] {\n const transforms: InputTransform[] = [];\n const opts = this.options.inputTransforms;\n if (!opts) return transforms;\n\n // 1. Add global transforms\n if (opts.global) {\n transforms.push(...opts.global);\n }\n\n // 2. Add per-tool transforms\n if (opts.perTool?.[tool.name]) {\n transforms.push(...opts.perTool[tool.name]);\n }\n\n // 3. Add generator-produced transforms\n if (opts.generator) {\n transforms.push(...opts.generator(tool));\n }\n\n return transforms;\n }\n\n /**\n * Apply input transforms to an OpenAPI tool\n * - Removes transformed inputKeys from the inputSchema\n * - Stores transform metadata for runtime injection\n * @private\n */\n private applyInputTransforms(tool: McpOpenAPITool): McpOpenAPITool {\n const transforms = this.collectTransformsForTool(tool);\n if (transforms.length === 0) return tool;\n\n // Validate input keys against reserved keys (prototype pollution protection)\n for (const transform of transforms) {\n if (RESERVED_KEYS.includes(transform.inputKey)) {\n throw new Error(\n `Invalid inputKey '${transform.inputKey}' in tool '${tool.name}': ` +\n `reserved keys (${RESERVED_KEYS.join(', ')}) cannot be used`,\n );\n }\n }\n\n const transformedInputKeys = new Set(transforms.map((t) => t.inputKey));\n\n // Clone and modify inputSchema to remove transformed keys\n const inputSchema = tool.inputSchema as Record<string, unknown>;\n const properties = (inputSchema?.['properties'] as Record<string, unknown>) || {};\n const required = (inputSchema?.['required'] as string[]) || [];\n\n // Remove transformed keys from properties\n const newProperties = { ...properties };\n for (const key of transformedInputKeys) {\n delete newProperties[key];\n }\n\n // Update required array to exclude transformed keys\n const newRequired = required.filter((key) => !transformedInputKeys.has(key));\n\n this.logger.debug(`Applied ${transforms.length} input transforms to tool '${tool.name}'`);\n\n const metadataRecord = tool.metadata as unknown as Record<string, unknown>;\n const existingAdapter = metadataRecord['adapter'] as Record<string, unknown> | undefined;\n return {\n ...tool,\n inputSchema: {\n ...inputSchema,\n properties: newProperties,\n ...(newRequired.length > 0 ? { required: newRequired } : {}),\n },\n // Store transforms in metadata for runtime use\n metadata: {\n ...tool.metadata,\n adapter: {\n ...(existingAdapter || {}),\n inputTransforms: transforms,\n },\n },\n } as ExtendedMcpOpenAPITool;\n }\n\n /**\n * Filter security schemes in tool input based on securitySchemesInInput option.\n * Removes security inputs that should be resolved from context instead of user input.\n * @private\n */\n private filterSecuritySchemes(tool: McpOpenAPITool): McpOpenAPITool {\n const allowedSchemes = new Set(this.options.securitySchemesInInput || []);\n if (allowedSchemes.size === 0) return tool;\n\n // Find security mappers that should NOT be in input (resolved from context)\n const schemesToRemove = new Set<string>();\n const inputKeysToRemove = new Set<string>();\n\n for (const mapper of tool.mapper) {\n if (mapper.security?.scheme && !allowedSchemes.has(mapper.security.scheme)) {\n schemesToRemove.add(mapper.security.scheme);\n inputKeysToRemove.add(mapper.inputKey);\n }\n }\n\n if (inputKeysToRemove.size === 0) return tool;\n\n // Remove security inputs from inputSchema\n const inputSchema = tool.inputSchema as Record<string, unknown>;\n const properties = (inputSchema?.['properties'] as Record<string, unknown>) || {};\n const required = (inputSchema?.['required'] as string[]) || [];\n\n const newProperties = { ...properties };\n for (const key of inputKeysToRemove) {\n delete newProperties[key];\n }\n\n const newRequired = required.filter((key) => !inputKeysToRemove.has(key));\n\n this.logger.debug(\n `[${tool.name}] Filtered security schemes from input: ${Array.from(schemesToRemove).join(', ')}. ` +\n `Kept in input: ${\n Array.from(allowedSchemes)\n .filter((s) => !schemesToRemove.has(s))\n .join(', ') || 'none'\n }`,\n );\n\n const metadataRecord = tool.metadata as unknown as Record<string, unknown>;\n const existingAdapter = metadataRecord['adapter'] as Record<string, unknown> | undefined;\n return {\n ...tool,\n inputSchema: {\n ...inputSchema,\n properties: newProperties,\n ...(newRequired.length > 0 ? { required: newRequired } : {}),\n },\n // Store which security schemes are in input vs context for later resolution\n metadata: {\n ...tool.metadata,\n adapter: {\n ...(existingAdapter || {}),\n securitySchemesInInput: Array.from(allowedSchemes),\n securitySchemesFromContext: Array.from(schemesToRemove),\n },\n },\n } as ExtendedMcpOpenAPITool;\n }\n}\n"]}
|