@frontmcp/adapters 0.6.1 → 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 +29 -11
- 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
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Zod schemas for x-frontmcp OpenAPI extension validation.
|
|
4
|
-
*
|
|
5
|
-
* The x-frontmcp extension allows embedding FrontMCP-specific configuration
|
|
6
|
-
* directly in OpenAPI specs. This module provides versioned schema validation
|
|
7
|
-
* to ensure only valid data is used and invalid fields are warned about.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.FrontMcpExampleSchema = exports.FrontMcpCodeCallSchema = exports.FrontMcpCacheSchema = exports.FrontMcpAnnotationsSchema = exports.SUPPORTED_VERSIONS = exports.FRONTMCP_SCHEMA_VERSION = void 0;
|
|
11
|
-
exports.validateFrontMcpExtension = validateFrontMcpExtension;
|
|
12
|
-
const zod_1 = require("zod");
|
|
13
|
-
/**
|
|
14
|
-
* Current schema version for x-frontmcp extension.
|
|
15
|
-
* Increment when making breaking changes to the schema.
|
|
16
|
-
*/
|
|
17
|
-
exports.FRONTMCP_SCHEMA_VERSION = '1.0';
|
|
18
|
-
/**
|
|
19
|
-
* Supported schema versions.
|
|
20
|
-
*/
|
|
21
|
-
exports.SUPPORTED_VERSIONS = ['1.0'];
|
|
22
|
-
// ============================================================================
|
|
23
|
-
// Annotations Schema (v1.0)
|
|
24
|
-
// ============================================================================
|
|
25
|
-
/**
|
|
26
|
-
* Tool annotations schema - hints about tool behavior for AI clients.
|
|
27
|
-
*/
|
|
28
|
-
exports.FrontMcpAnnotationsSchema = zod_1.z.object({
|
|
29
|
-
/** Human-readable title for the tool */
|
|
30
|
-
title: zod_1.z.string().optional(),
|
|
31
|
-
/** If true, the tool does not modify its environment */
|
|
32
|
-
readOnlyHint: zod_1.z.boolean().optional(),
|
|
33
|
-
/** If true, the tool may perform destructive updates */
|
|
34
|
-
destructiveHint: zod_1.z.boolean().optional(),
|
|
35
|
-
/** If true, calling repeatedly with same args has no additional effect */
|
|
36
|
-
idempotentHint: zod_1.z.boolean().optional(),
|
|
37
|
-
/** If true, tool may interact with external entities */
|
|
38
|
-
openWorldHint: zod_1.z.boolean().optional(),
|
|
39
|
-
});
|
|
40
|
-
// ============================================================================
|
|
41
|
-
// Cache Schema (v1.0)
|
|
42
|
-
// ============================================================================
|
|
43
|
-
/**
|
|
44
|
-
* Cache configuration schema.
|
|
45
|
-
*/
|
|
46
|
-
exports.FrontMcpCacheSchema = zod_1.z.object({
|
|
47
|
-
/** Time-to-live in seconds for cached responses */
|
|
48
|
-
ttl: zod_1.z.number().int().positive().optional(),
|
|
49
|
-
/** If true, cache window slides on each access */
|
|
50
|
-
slideWindow: zod_1.z.boolean().optional(),
|
|
51
|
-
});
|
|
52
|
-
// ============================================================================
|
|
53
|
-
// CodeCall Schema (v1.0)
|
|
54
|
-
// ============================================================================
|
|
55
|
-
/**
|
|
56
|
-
* CodeCall plugin configuration schema.
|
|
57
|
-
*/
|
|
58
|
-
exports.FrontMcpCodeCallSchema = zod_1.z.object({
|
|
59
|
-
/** Whether this tool can be used via CodeCall */
|
|
60
|
-
enabledInCodeCall: zod_1.z.boolean().optional(),
|
|
61
|
-
/** If true, stays visible in list_tools when CodeCall is active */
|
|
62
|
-
visibleInListTools: zod_1.z.boolean().optional(),
|
|
63
|
-
});
|
|
64
|
-
// ============================================================================
|
|
65
|
-
// Example Schema (v1.0)
|
|
66
|
-
// ============================================================================
|
|
67
|
-
/**
|
|
68
|
-
* Tool usage example schema.
|
|
69
|
-
*/
|
|
70
|
-
exports.FrontMcpExampleSchema = zod_1.z.object({
|
|
71
|
-
/** Description of the example */
|
|
72
|
-
description: zod_1.z.string(),
|
|
73
|
-
/** Example input values */
|
|
74
|
-
input: zod_1.z.record(zod_1.z.string(), zod_1.z.any()),
|
|
75
|
-
/** Expected output (optional) */
|
|
76
|
-
output: zod_1.z.any().optional(),
|
|
77
|
-
});
|
|
78
|
-
// ============================================================================
|
|
79
|
-
// Known Fields for Validation
|
|
80
|
-
// ============================================================================
|
|
81
|
-
/** Known field names for validation */
|
|
82
|
-
const KNOWN_EXTENSION_FIELDS = new Set([
|
|
83
|
-
'version',
|
|
84
|
-
'annotations',
|
|
85
|
-
'cache',
|
|
86
|
-
'codecall',
|
|
87
|
-
'tags',
|
|
88
|
-
'hideFromDiscovery',
|
|
89
|
-
'examples',
|
|
90
|
-
]);
|
|
91
|
-
const KNOWN_ANNOTATION_FIELDS = new Set([
|
|
92
|
-
'title',
|
|
93
|
-
'readOnlyHint',
|
|
94
|
-
'destructiveHint',
|
|
95
|
-
'idempotentHint',
|
|
96
|
-
'openWorldHint',
|
|
97
|
-
]);
|
|
98
|
-
const KNOWN_CACHE_FIELDS = new Set(['ttl', 'slideWindow']);
|
|
99
|
-
const KNOWN_CODECALL_FIELDS = new Set(['enabledInCodeCall', 'visibleInListTools']);
|
|
100
|
-
// ============================================================================
|
|
101
|
-
// Schema Validation Functions
|
|
102
|
-
// ============================================================================
|
|
103
|
-
/**
|
|
104
|
-
* Validate and parse x-frontmcp extension data.
|
|
105
|
-
*
|
|
106
|
-
* This function:
|
|
107
|
-
* 1. Detects the schema version (defaults to current)
|
|
108
|
-
* 2. Validates each field against the appropriate schema
|
|
109
|
-
* 3. Returns only valid fields, ignoring invalid ones
|
|
110
|
-
* 4. Collects warnings for invalid/unknown fields
|
|
111
|
-
*
|
|
112
|
-
* @param rawData - Raw x-frontmcp data from OpenAPI spec
|
|
113
|
-
* @param toolName - Tool name for error context
|
|
114
|
-
* @param logger - Logger for warnings
|
|
115
|
-
* @returns Validation result with valid data and warnings
|
|
116
|
-
*/
|
|
117
|
-
function validateFrontMcpExtension(rawData, toolName, logger) {
|
|
118
|
-
const warnings = [];
|
|
119
|
-
// Handle null/undefined
|
|
120
|
-
if (rawData === null || rawData === undefined) {
|
|
121
|
-
return { success: true, data: null, warnings: [] };
|
|
122
|
-
}
|
|
123
|
-
// Must be an object
|
|
124
|
-
if (typeof rawData !== 'object' || Array.isArray(rawData)) {
|
|
125
|
-
warnings.push(`x-frontmcp must be an object, got ${Array.isArray(rawData) ? 'array' : typeof rawData}`);
|
|
126
|
-
logger.warn(`[${toolName}] Invalid x-frontmcp extension: ${warnings[0]}`);
|
|
127
|
-
return { success: false, data: null, warnings };
|
|
128
|
-
}
|
|
129
|
-
const data = rawData;
|
|
130
|
-
// Detect version
|
|
131
|
-
const version = typeof data['version'] === 'string' ? data['version'] : exports.FRONTMCP_SCHEMA_VERSION;
|
|
132
|
-
// Check if version is supported
|
|
133
|
-
if (!exports.SUPPORTED_VERSIONS.includes(version)) {
|
|
134
|
-
warnings.push(`Unsupported x-frontmcp version '${version}'. Supported versions: ${exports.SUPPORTED_VERSIONS.join(', ')}`);
|
|
135
|
-
logger.warn(`[${toolName}] ${warnings[0]}`);
|
|
136
|
-
return { success: false, data: null, warnings };
|
|
137
|
-
}
|
|
138
|
-
// Extract valid fields and collect warnings
|
|
139
|
-
const validData = extractValidFields(data, version, warnings);
|
|
140
|
-
if (warnings.length > 0) {
|
|
141
|
-
logger.warn(`[${toolName}] x-frontmcp extension has invalid fields that were ignored:`);
|
|
142
|
-
warnings.forEach((w) => logger.warn(` - ${w}`));
|
|
143
|
-
}
|
|
144
|
-
return {
|
|
145
|
-
success: true,
|
|
146
|
-
data: validData,
|
|
147
|
-
warnings,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Extract valid fields from x-frontmcp data, collecting warnings for invalid fields.
|
|
152
|
-
*/
|
|
153
|
-
function extractValidFields(data, version, warnings) {
|
|
154
|
-
const result = {
|
|
155
|
-
version: version,
|
|
156
|
-
};
|
|
157
|
-
// Warn about unknown top-level fields
|
|
158
|
-
for (const key of Object.keys(data)) {
|
|
159
|
-
if (!KNOWN_EXTENSION_FIELDS.has(key)) {
|
|
160
|
-
warnings.push(`Unknown field '${key}' in x-frontmcp (will be ignored)`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
// Validate annotations
|
|
164
|
-
if (data['annotations'] !== undefined) {
|
|
165
|
-
const annotationsResult = exports.FrontMcpAnnotationsSchema.safeParse(data['annotations']);
|
|
166
|
-
if (annotationsResult.success) {
|
|
167
|
-
result.annotations = annotationsResult.data;
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
const issues = formatZodIssues(annotationsResult.error.issues, 'annotations');
|
|
171
|
-
warnings.push(...issues);
|
|
172
|
-
// Try to extract valid annotation fields
|
|
173
|
-
result.annotations = extractValidAnnotations(data['annotations'], warnings);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// Validate cache
|
|
177
|
-
if (data['cache'] !== undefined) {
|
|
178
|
-
const cacheResult = exports.FrontMcpCacheSchema.safeParse(data['cache']);
|
|
179
|
-
if (cacheResult.success) {
|
|
180
|
-
result.cache = cacheResult.data;
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
const issues = formatZodIssues(cacheResult.error.issues, 'cache');
|
|
184
|
-
warnings.push(...issues);
|
|
185
|
-
// Try to extract valid cache fields
|
|
186
|
-
result.cache = extractValidCache(data['cache'], warnings);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
// Validate codecall
|
|
190
|
-
if (data['codecall'] !== undefined) {
|
|
191
|
-
const codecallResult = exports.FrontMcpCodeCallSchema.safeParse(data['codecall']);
|
|
192
|
-
if (codecallResult.success) {
|
|
193
|
-
result.codecall = codecallResult.data;
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
const issues = formatZodIssues(codecallResult.error.issues, 'codecall');
|
|
197
|
-
warnings.push(...issues);
|
|
198
|
-
// Try to extract valid codecall fields
|
|
199
|
-
result.codecall = extractValidCodeCall(data['codecall'], warnings);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
// Validate tags
|
|
203
|
-
if (data['tags'] !== undefined) {
|
|
204
|
-
const tagsSchema = zod_1.z.array(zod_1.z.string());
|
|
205
|
-
const tagsResult = tagsSchema.safeParse(data['tags']);
|
|
206
|
-
if (tagsResult.success) {
|
|
207
|
-
result.tags = tagsResult.data;
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
warnings.push(`Invalid 'tags': expected array of strings`);
|
|
211
|
-
// Try to extract valid tags
|
|
212
|
-
result.tags = extractValidTags(data['tags']);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
// Validate hideFromDiscovery
|
|
216
|
-
if (data['hideFromDiscovery'] !== undefined) {
|
|
217
|
-
if (typeof data['hideFromDiscovery'] === 'boolean') {
|
|
218
|
-
result.hideFromDiscovery = data['hideFromDiscovery'];
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
warnings.push(`Invalid 'hideFromDiscovery': expected boolean, got ${typeof data['hideFromDiscovery']}`);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
// Validate examples
|
|
225
|
-
if (data['examples'] !== undefined) {
|
|
226
|
-
const examplesSchema = zod_1.z.array(exports.FrontMcpExampleSchema);
|
|
227
|
-
const examplesResult = examplesSchema.safeParse(data['examples']);
|
|
228
|
-
if (examplesResult.success) {
|
|
229
|
-
result.examples = examplesResult.data;
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
warnings.push(`Invalid 'examples': some examples have invalid format`);
|
|
233
|
-
// Try to extract valid examples
|
|
234
|
-
result.examples = extractValidExamples(data['examples'], warnings);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
return result;
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Extract valid annotation fields.
|
|
241
|
-
*/
|
|
242
|
-
function extractValidAnnotations(data, warnings) {
|
|
243
|
-
if (typeof data !== 'object' || data === null)
|
|
244
|
-
return undefined;
|
|
245
|
-
const obj = data;
|
|
246
|
-
const result = {};
|
|
247
|
-
for (const field of KNOWN_ANNOTATION_FIELDS) {
|
|
248
|
-
if (obj[field] !== undefined) {
|
|
249
|
-
if (field === 'title' && typeof obj[field] === 'string') {
|
|
250
|
-
result.title = obj[field];
|
|
251
|
-
}
|
|
252
|
-
else if (field !== 'title' && typeof obj[field] === 'boolean') {
|
|
253
|
-
result[field] = obj[field];
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
// Warn about unknown annotation fields
|
|
258
|
-
for (const key of Object.keys(obj)) {
|
|
259
|
-
if (!KNOWN_ANNOTATION_FIELDS.has(key)) {
|
|
260
|
-
warnings.push(`Unknown field 'annotations.${key}' (will be ignored)`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return Object.keys(result).length > 0 ? result : undefined;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Extract valid cache fields.
|
|
267
|
-
*/
|
|
268
|
-
function extractValidCache(data, warnings) {
|
|
269
|
-
if (typeof data !== 'object' || data === null)
|
|
270
|
-
return undefined;
|
|
271
|
-
const obj = data;
|
|
272
|
-
const result = {};
|
|
273
|
-
if (typeof obj['ttl'] === 'number' && Number.isInteger(obj['ttl']) && obj['ttl'] > 0) {
|
|
274
|
-
result.ttl = obj['ttl'];
|
|
275
|
-
}
|
|
276
|
-
else if (obj['ttl'] !== undefined) {
|
|
277
|
-
warnings.push(`Invalid 'cache.ttl': expected positive integer`);
|
|
278
|
-
}
|
|
279
|
-
if (typeof obj['slideWindow'] === 'boolean') {
|
|
280
|
-
result.slideWindow = obj['slideWindow'];
|
|
281
|
-
}
|
|
282
|
-
else if (obj['slideWindow'] !== undefined) {
|
|
283
|
-
warnings.push(`Invalid 'cache.slideWindow': expected boolean`);
|
|
284
|
-
}
|
|
285
|
-
// Warn about unknown cache fields
|
|
286
|
-
for (const key of Object.keys(obj)) {
|
|
287
|
-
if (!KNOWN_CACHE_FIELDS.has(key)) {
|
|
288
|
-
warnings.push(`Unknown field 'cache.${key}' (will be ignored)`);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
return Object.keys(result).length > 0 ? result : undefined;
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Extract valid codecall fields.
|
|
295
|
-
*/
|
|
296
|
-
function extractValidCodeCall(data, warnings) {
|
|
297
|
-
if (typeof data !== 'object' || data === null)
|
|
298
|
-
return undefined;
|
|
299
|
-
const obj = data;
|
|
300
|
-
const result = {};
|
|
301
|
-
if (typeof obj['enabledInCodeCall'] === 'boolean') {
|
|
302
|
-
result.enabledInCodeCall = obj['enabledInCodeCall'];
|
|
303
|
-
}
|
|
304
|
-
else if (obj['enabledInCodeCall'] !== undefined) {
|
|
305
|
-
warnings.push(`Invalid 'codecall.enabledInCodeCall': expected boolean`);
|
|
306
|
-
}
|
|
307
|
-
if (typeof obj['visibleInListTools'] === 'boolean') {
|
|
308
|
-
result.visibleInListTools = obj['visibleInListTools'];
|
|
309
|
-
}
|
|
310
|
-
else if (obj['visibleInListTools'] !== undefined) {
|
|
311
|
-
warnings.push(`Invalid 'codecall.visibleInListTools': expected boolean`);
|
|
312
|
-
}
|
|
313
|
-
// Warn about unknown codecall fields
|
|
314
|
-
for (const key of Object.keys(obj)) {
|
|
315
|
-
if (!KNOWN_CODECALL_FIELDS.has(key)) {
|
|
316
|
-
warnings.push(`Unknown field 'codecall.${key}' (will be ignored)`);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return Object.keys(result).length > 0 ? result : undefined;
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Extract valid tags from array.
|
|
323
|
-
*/
|
|
324
|
-
function extractValidTags(data) {
|
|
325
|
-
if (!Array.isArray(data))
|
|
326
|
-
return undefined;
|
|
327
|
-
const validTags = data.filter((item) => typeof item === 'string');
|
|
328
|
-
return validTags.length > 0 ? validTags : undefined;
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Extract valid examples from array.
|
|
332
|
-
*/
|
|
333
|
-
function extractValidExamples(data, warnings) {
|
|
334
|
-
if (!Array.isArray(data))
|
|
335
|
-
return undefined;
|
|
336
|
-
const validExamples = [];
|
|
337
|
-
for (let i = 0; i < data.length; i++) {
|
|
338
|
-
const item = data[i];
|
|
339
|
-
const result = exports.FrontMcpExampleSchema.safeParse(item);
|
|
340
|
-
if (result.success) {
|
|
341
|
-
validExamples.push(result.data);
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
warnings.push(`Invalid example at index ${i}: ${formatZodIssues(result.error.issues, `examples[${i}]`).join(', ')}`);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return validExamples.length > 0 ? validExamples : undefined;
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* Format Zod validation issues into readable messages.
|
|
351
|
-
*/
|
|
352
|
-
function formatZodIssues(issues, prefix) {
|
|
353
|
-
return issues.map((issue) => {
|
|
354
|
-
const path = issue.path.length > 0 ? `${prefix}.${issue.path.join('.')}` : prefix;
|
|
355
|
-
return `Invalid '${path}': ${issue.message}`;
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
//# sourceMappingURL=openapi.frontmcp-schema.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.frontmcp-schema.js","sourceRoot":"","sources":["../../../src/openapi/openapi.frontmcp-schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Zod schemas for x-frontmcp OpenAPI extension validation.\n *\n * The x-frontmcp extension allows embedding FrontMCP-specific configuration\n * directly in OpenAPI specs. This module provides versioned schema validation\n * to ensure only valid data is used and invalid fields are warned about.\n */\n\nimport { z } from 'zod';\nimport type { FrontMcpLogger } from '@frontmcp/sdk';\n\n/**\n * Current schema version for x-frontmcp extension.\n * Increment when making breaking changes to the schema.\n */\nexport const FRONTMCP_SCHEMA_VERSION = '1.0' as const;\n\n/**\n * Supported schema versions.\n */\nexport const SUPPORTED_VERSIONS = ['1.0'] as const;\nexport type FrontMcpSchemaVersion = (typeof SUPPORTED_VERSIONS)[number];\n\n// ============================================================================\n// Annotations Schema (v1.0)\n// ============================================================================\n\n/**\n * Tool annotations schema - hints about tool behavior for AI clients.\n */\nexport const FrontMcpAnnotationsSchema = z.object({\n /** Human-readable title for the tool */\n title: z.string().optional(),\n /** If true, the tool does not modify its environment */\n readOnlyHint: z.boolean().optional(),\n /** If true, the tool may perform destructive updates */\n destructiveHint: z.boolean().optional(),\n /** If true, calling repeatedly with same args has no additional effect */\n idempotentHint: z.boolean().optional(),\n /** If true, tool may interact with external entities */\n openWorldHint: z.boolean().optional(),\n});\n\nexport type FrontMcpAnnotations = z.infer<typeof FrontMcpAnnotationsSchema>;\n\n// ============================================================================\n// Cache Schema (v1.0)\n// ============================================================================\n\n/**\n * Cache configuration schema.\n */\nexport const FrontMcpCacheSchema = z.object({\n /** Time-to-live in seconds for cached responses */\n ttl: z.number().int().positive().optional(),\n /** If true, cache window slides on each access */\n slideWindow: z.boolean().optional(),\n});\n\nexport type FrontMcpCache = z.infer<typeof FrontMcpCacheSchema>;\n\n// ============================================================================\n// CodeCall Schema (v1.0)\n// ============================================================================\n\n/**\n * CodeCall plugin configuration schema.\n */\nexport const FrontMcpCodeCallSchema = z.object({\n /** Whether this tool can be used via CodeCall */\n enabledInCodeCall: z.boolean().optional(),\n /** If true, stays visible in list_tools when CodeCall is active */\n visibleInListTools: z.boolean().optional(),\n});\n\nexport type FrontMcpCodeCall = z.infer<typeof FrontMcpCodeCallSchema>;\n\n// ============================================================================\n// Example Schema (v1.0)\n// ============================================================================\n\n/**\n * Tool usage example schema.\n */\nexport const FrontMcpExampleSchema = z.object({\n /** Description of the example */\n description: z.string(),\n /** Example input values */\n input: z.record(z.string(), z.any()),\n /** Expected output (optional) */\n output: z.any().optional(),\n});\n\nexport type FrontMcpExample = z.infer<typeof FrontMcpExampleSchema>;\n\n// ============================================================================\n// Known Fields for Validation\n// ============================================================================\n\n/** Known field names for validation */\nconst KNOWN_EXTENSION_FIELDS = new Set([\n 'version',\n 'annotations',\n 'cache',\n 'codecall',\n 'tags',\n 'hideFromDiscovery',\n 'examples',\n]);\n\nconst KNOWN_ANNOTATION_FIELDS = new Set([\n 'title',\n 'readOnlyHint',\n 'destructiveHint',\n 'idempotentHint',\n 'openWorldHint',\n]);\n\nconst KNOWN_CACHE_FIELDS = new Set(['ttl', 'slideWindow']);\nconst KNOWN_CODECALL_FIELDS = new Set(['enabledInCodeCall', 'visibleInListTools']);\n\n// ============================================================================\n// Validated Extension Type (after parsing)\n// ============================================================================\n\n/**\n * Validated x-frontmcp extension data.\n * This is the output after schema validation.\n */\nexport interface ValidatedFrontMcpExtension {\n version: FrontMcpSchemaVersion;\n annotations?: FrontMcpAnnotations;\n cache?: FrontMcpCache;\n codecall?: FrontMcpCodeCall;\n tags?: string[];\n hideFromDiscovery?: boolean;\n examples?: FrontMcpExample[];\n}\n\n// ============================================================================\n// Validation Result\n// ============================================================================\n\nexport interface FrontMcpValidationResult {\n /** Whether validation succeeded (may still have warnings) */\n success: boolean;\n /** Validated data (only valid fields) */\n data: ValidatedFrontMcpExtension | null;\n /** Validation warnings (invalid fields that were ignored) */\n warnings: string[];\n}\n\n// ============================================================================\n// Schema Validation Functions\n// ============================================================================\n\n/**\n * Validate and parse x-frontmcp extension data.\n *\n * This function:\n * 1. Detects the schema version (defaults to current)\n * 2. Validates each field against the appropriate schema\n * 3. Returns only valid fields, ignoring invalid ones\n * 4. Collects warnings for invalid/unknown fields\n *\n * @param rawData - Raw x-frontmcp data from OpenAPI spec\n * @param toolName - Tool name for error context\n * @param logger - Logger for warnings\n * @returns Validation result with valid data and warnings\n */\nexport function validateFrontMcpExtension(\n rawData: unknown,\n toolName: string,\n logger: FrontMcpLogger,\n): FrontMcpValidationResult {\n const warnings: string[] = [];\n\n // Handle null/undefined\n if (rawData === null || rawData === undefined) {\n return { success: true, data: null, warnings: [] };\n }\n\n // Must be an object\n if (typeof rawData !== 'object' || Array.isArray(rawData)) {\n warnings.push(`x-frontmcp must be an object, got ${Array.isArray(rawData) ? 'array' : typeof rawData}`);\n logger.warn(`[${toolName}] Invalid x-frontmcp extension: ${warnings[0]}`);\n return { success: false, data: null, warnings };\n }\n\n const data = rawData as Record<string, unknown>;\n\n // Detect version\n const version = typeof data['version'] === 'string' ? data['version'] : FRONTMCP_SCHEMA_VERSION;\n\n // Check if version is supported\n if (!SUPPORTED_VERSIONS.includes(version as FrontMcpSchemaVersion)) {\n warnings.push(`Unsupported x-frontmcp version '${version}'. Supported versions: ${SUPPORTED_VERSIONS.join(', ')}`);\n logger.warn(`[${toolName}] ${warnings[0]}`);\n return { success: false, data: null, warnings };\n }\n\n // Extract valid fields and collect warnings\n const validData = extractValidFields(data, version, warnings);\n\n if (warnings.length > 0) {\n logger.warn(`[${toolName}] x-frontmcp extension has invalid fields that were ignored:`);\n warnings.forEach((w) => logger.warn(` - ${w}`));\n }\n\n return {\n success: true,\n data: validData,\n warnings,\n };\n}\n\n/**\n * Extract valid fields from x-frontmcp data, collecting warnings for invalid fields.\n */\nfunction extractValidFields(\n data: Record<string, unknown>,\n version: string,\n warnings: string[],\n): ValidatedFrontMcpExtension {\n const result: ValidatedFrontMcpExtension = {\n version: version as FrontMcpSchemaVersion,\n };\n\n // Warn about unknown top-level fields\n for (const key of Object.keys(data)) {\n if (!KNOWN_EXTENSION_FIELDS.has(key)) {\n warnings.push(`Unknown field '${key}' in x-frontmcp (will be ignored)`);\n }\n }\n\n // Validate annotations\n if (data['annotations'] !== undefined) {\n const annotationsResult = FrontMcpAnnotationsSchema.safeParse(data['annotations']);\n if (annotationsResult.success) {\n result.annotations = annotationsResult.data;\n } else {\n const issues = formatZodIssues(annotationsResult.error.issues, 'annotations');\n warnings.push(...issues);\n // Try to extract valid annotation fields\n result.annotations = extractValidAnnotations(data['annotations'], warnings);\n }\n }\n\n // Validate cache\n if (data['cache'] !== undefined) {\n const cacheResult = FrontMcpCacheSchema.safeParse(data['cache']);\n if (cacheResult.success) {\n result.cache = cacheResult.data;\n } else {\n const issues = formatZodIssues(cacheResult.error.issues, 'cache');\n warnings.push(...issues);\n // Try to extract valid cache fields\n result.cache = extractValidCache(data['cache'], warnings);\n }\n }\n\n // Validate codecall\n if (data['codecall'] !== undefined) {\n const codecallResult = FrontMcpCodeCallSchema.safeParse(data['codecall']);\n if (codecallResult.success) {\n result.codecall = codecallResult.data;\n } else {\n const issues = formatZodIssues(codecallResult.error.issues, 'codecall');\n warnings.push(...issues);\n // Try to extract valid codecall fields\n result.codecall = extractValidCodeCall(data['codecall'], warnings);\n }\n }\n\n // Validate tags\n if (data['tags'] !== undefined) {\n const tagsSchema = z.array(z.string());\n const tagsResult = tagsSchema.safeParse(data['tags']);\n if (tagsResult.success) {\n result.tags = tagsResult.data;\n } else {\n warnings.push(`Invalid 'tags': expected array of strings`);\n // Try to extract valid tags\n result.tags = extractValidTags(data['tags']);\n }\n }\n\n // Validate hideFromDiscovery\n if (data['hideFromDiscovery'] !== undefined) {\n if (typeof data['hideFromDiscovery'] === 'boolean') {\n result.hideFromDiscovery = data['hideFromDiscovery'];\n } else {\n warnings.push(`Invalid 'hideFromDiscovery': expected boolean, got ${typeof data['hideFromDiscovery']}`);\n }\n }\n\n // Validate examples\n if (data['examples'] !== undefined) {\n const examplesSchema = z.array(FrontMcpExampleSchema);\n const examplesResult = examplesSchema.safeParse(data['examples']);\n if (examplesResult.success) {\n result.examples = examplesResult.data;\n } else {\n warnings.push(`Invalid 'examples': some examples have invalid format`);\n // Try to extract valid examples\n result.examples = extractValidExamples(data['examples'], warnings);\n }\n }\n\n return result;\n}\n\n/**\n * Extract valid annotation fields.\n */\nfunction extractValidAnnotations(data: unknown, warnings: string[]): FrontMcpAnnotations | undefined {\n if (typeof data !== 'object' || data === null) return undefined;\n\n const obj = data as Record<string, unknown>;\n const result: FrontMcpAnnotations = {};\n\n for (const field of KNOWN_ANNOTATION_FIELDS) {\n if (obj[field] !== undefined) {\n if (field === 'title' && typeof obj[field] === 'string') {\n result.title = obj[field] as string;\n } else if (field !== 'title' && typeof obj[field] === 'boolean') {\n (result as Record<string, unknown>)[field] = obj[field];\n }\n }\n }\n\n // Warn about unknown annotation fields\n for (const key of Object.keys(obj)) {\n if (!KNOWN_ANNOTATION_FIELDS.has(key)) {\n warnings.push(`Unknown field 'annotations.${key}' (will be ignored)`);\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/**\n * Extract valid cache fields.\n */\nfunction extractValidCache(data: unknown, warnings: string[]): FrontMcpCache | undefined {\n if (typeof data !== 'object' || data === null) return undefined;\n\n const obj = data as Record<string, unknown>;\n const result: FrontMcpCache = {};\n\n if (typeof obj['ttl'] === 'number' && Number.isInteger(obj['ttl']) && obj['ttl'] > 0) {\n result.ttl = obj['ttl'];\n } else if (obj['ttl'] !== undefined) {\n warnings.push(`Invalid 'cache.ttl': expected positive integer`);\n }\n\n if (typeof obj['slideWindow'] === 'boolean') {\n result.slideWindow = obj['slideWindow'];\n } else if (obj['slideWindow'] !== undefined) {\n warnings.push(`Invalid 'cache.slideWindow': expected boolean`);\n }\n\n // Warn about unknown cache fields\n for (const key of Object.keys(obj)) {\n if (!KNOWN_CACHE_FIELDS.has(key)) {\n warnings.push(`Unknown field 'cache.${key}' (will be ignored)`);\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/**\n * Extract valid codecall fields.\n */\nfunction extractValidCodeCall(data: unknown, warnings: string[]): FrontMcpCodeCall | undefined {\n if (typeof data !== 'object' || data === null) return undefined;\n\n const obj = data as Record<string, unknown>;\n const result: FrontMcpCodeCall = {};\n\n if (typeof obj['enabledInCodeCall'] === 'boolean') {\n result.enabledInCodeCall = obj['enabledInCodeCall'];\n } else if (obj['enabledInCodeCall'] !== undefined) {\n warnings.push(`Invalid 'codecall.enabledInCodeCall': expected boolean`);\n }\n\n if (typeof obj['visibleInListTools'] === 'boolean') {\n result.visibleInListTools = obj['visibleInListTools'];\n } else if (obj['visibleInListTools'] !== undefined) {\n warnings.push(`Invalid 'codecall.visibleInListTools': expected boolean`);\n }\n\n // Warn about unknown codecall fields\n for (const key of Object.keys(obj)) {\n if (!KNOWN_CODECALL_FIELDS.has(key)) {\n warnings.push(`Unknown field 'codecall.${key}' (will be ignored)`);\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/**\n * Extract valid tags from array.\n */\nfunction extractValidTags(data: unknown): string[] | undefined {\n if (!Array.isArray(data)) return undefined;\n\n const validTags = data.filter((item): item is string => typeof item === 'string');\n return validTags.length > 0 ? validTags : undefined;\n}\n\n/**\n * Extract valid examples from array.\n */\nfunction extractValidExamples(data: unknown, warnings: string[]): FrontMcpExample[] | undefined {\n if (!Array.isArray(data)) return undefined;\n\n const validExamples: FrontMcpExample[] = [];\n\n for (let i = 0; i < data.length; i++) {\n const item = data[i];\n const result = FrontMcpExampleSchema.safeParse(item);\n if (result.success) {\n validExamples.push(result.data);\n } else {\n warnings.push(\n `Invalid example at index ${i}: ${formatZodIssues(result.error.issues, `examples[${i}]`).join(', ')}`,\n );\n }\n }\n\n return validExamples.length > 0 ? validExamples : undefined;\n}\n\n/** Zod issue shape for formatting */\ninterface ZodIssue {\n path: PropertyKey[];\n message: string;\n}\n\n/**\n * Format Zod validation issues into readable messages.\n */\nfunction formatZodIssues(issues: ZodIssue[], prefix: string): string[] {\n return issues.map((issue) => {\n const path = issue.path.length > 0 ? `${prefix}.${issue.path.join('.')}` : prefix;\n return `Invalid '${path}': ${issue.message}`;\n });\n}\n"]}
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createSecurityContextFromAuth = createSecurityContextFromAuth;
|
|
4
|
-
exports.extractSecuritySchemes = extractSecuritySchemes;
|
|
5
|
-
exports.validateSecurityConfiguration = validateSecurityConfiguration;
|
|
6
|
-
exports.resolveToolSecurity = resolveToolSecurity;
|
|
7
|
-
const mcp_from_openapi_1 = require("mcp-from-openapi");
|
|
8
|
-
/**
|
|
9
|
-
* Resolve security context from FrontMCP context with support for multiple auth providers
|
|
10
|
-
*
|
|
11
|
-
* @param tool - OpenAPI tool to resolve security for
|
|
12
|
-
* @param ctx - FrontMCP request context with authInfo, sessionId, traceId, etc.
|
|
13
|
-
* @param options - Adapter options with auth configuration
|
|
14
|
-
* @returns Security context for resolver
|
|
15
|
-
*/
|
|
16
|
-
async function createSecurityContextFromAuth(tool, ctx, options) {
|
|
17
|
-
// 1. Use custom security resolver if provided (highest priority)
|
|
18
|
-
if (options.securityResolver) {
|
|
19
|
-
return await options.securityResolver(tool, ctx);
|
|
20
|
-
}
|
|
21
|
-
// 2. Use auth provider mapper if provided
|
|
22
|
-
if (options.authProviderMapper) {
|
|
23
|
-
const context = (0, mcp_from_openapi_1.createSecurityContext)({});
|
|
24
|
-
// Find all security schemes used by this tool
|
|
25
|
-
const securitySchemes = new Set();
|
|
26
|
-
for (const mapper of tool.mapper) {
|
|
27
|
-
if (mapper.security?.scheme) {
|
|
28
|
-
securitySchemes.add(mapper.security.scheme);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
// Map each security scheme to its auth provider
|
|
32
|
-
// Process all schemes - first matching token for each auth type (jwt, apiKey, basic, oauth2Token)
|
|
33
|
-
for (const scheme of securitySchemes) {
|
|
34
|
-
const authExtractor = options.authProviderMapper[scheme];
|
|
35
|
-
if (authExtractor) {
|
|
36
|
-
try {
|
|
37
|
-
const token = authExtractor(ctx);
|
|
38
|
-
// Validate return type - must be string or undefined/null
|
|
39
|
-
if (token !== undefined && token !== null && typeof token !== 'string') {
|
|
40
|
-
throw new Error(`authProviderMapper['${scheme}'] must return a string or undefined, ` + `but returned: ${typeof token}`);
|
|
41
|
-
}
|
|
42
|
-
// Reject empty string tokens explicitly - indicates misconfiguration
|
|
43
|
-
if (token === '') {
|
|
44
|
-
throw new Error(`authProviderMapper['${scheme}'] returned empty string. ` +
|
|
45
|
-
`Return undefined/null if no token is available, or provide a valid token.`);
|
|
46
|
-
}
|
|
47
|
-
if (token) {
|
|
48
|
-
// Route token to correct context field based on scheme type
|
|
49
|
-
// Look up the scheme info from the mapper to determine type
|
|
50
|
-
const schemeMapper = tool.mapper.find((m) => m.security?.scheme === scheme);
|
|
51
|
-
const schemeType = schemeMapper?.security?.type?.toLowerCase();
|
|
52
|
-
const httpScheme = schemeMapper?.security?.httpScheme?.toLowerCase();
|
|
53
|
-
// Route based on security scheme type (first token for each type wins)
|
|
54
|
-
if (schemeType === 'apikey') {
|
|
55
|
-
if (!context.apiKey) {
|
|
56
|
-
context.apiKey = token;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
else if (schemeType === 'http' && httpScheme === 'basic') {
|
|
60
|
-
if (!context.basic) {
|
|
61
|
-
context.basic = token;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
else if (schemeType === 'oauth2') {
|
|
65
|
-
if (!context.oauth2Token) {
|
|
66
|
-
context.oauth2Token = token;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
// Default to jwt for http bearer and unknown types
|
|
71
|
-
if (!context.jwt) {
|
|
72
|
-
context.jwt = token;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// Continue checking other schemes - don't break
|
|
76
|
-
// This allows validation to see all configured providers
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
// Re-throw validation errors as-is
|
|
81
|
-
if (err instanceof Error && err.message.includes('authProviderMapper')) {
|
|
82
|
-
throw err;
|
|
83
|
-
}
|
|
84
|
-
// Wrap other errors with context
|
|
85
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
86
|
-
throw new Error(`authProviderMapper['${scheme}'] threw an error: ${errorMessage}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// If no auth was set from providers, fall back to ctx.authInfo.token
|
|
91
|
-
// Only fall back if ALL auth fields are empty (not just jwt)
|
|
92
|
-
const hasAnyAuth = context.jwt || context.apiKey || context.basic || context.oauth2Token;
|
|
93
|
-
const authToken = ctx.authInfo?.token;
|
|
94
|
-
if (!hasAnyAuth && authToken) {
|
|
95
|
-
// Validate type before assignment to prevent non-string values
|
|
96
|
-
if (typeof authToken !== 'string') {
|
|
97
|
-
throw new Error(`authInfo.token must be a string, but got: ${typeof authToken}`);
|
|
98
|
-
}
|
|
99
|
-
context.jwt = authToken;
|
|
100
|
-
}
|
|
101
|
-
return context;
|
|
102
|
-
}
|
|
103
|
-
// 3. Use static auth if provided
|
|
104
|
-
if (options.staticAuth) {
|
|
105
|
-
return (0, mcp_from_openapi_1.createSecurityContext)(options.staticAuth);
|
|
106
|
-
}
|
|
107
|
-
// 4. Default: use main JWT token from auth context
|
|
108
|
-
return (0, mcp_from_openapi_1.createSecurityContext)({
|
|
109
|
-
jwt: ctx.authInfo?.token,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Extract all security schemes used by a set of tools
|
|
114
|
-
*
|
|
115
|
-
* @param tools - OpenAPI tools
|
|
116
|
-
* @returns Set of security scheme names
|
|
117
|
-
*/
|
|
118
|
-
function extractSecuritySchemes(tools) {
|
|
119
|
-
const schemes = new Set();
|
|
120
|
-
for (const tool of tools) {
|
|
121
|
-
for (const mapper of tool.mapper) {
|
|
122
|
-
if (mapper.security?.scheme) {
|
|
123
|
-
schemes.add(mapper.security.scheme);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return schemes;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Validate security configuration against OpenAPI security requirements
|
|
131
|
-
*
|
|
132
|
-
* @param tools - OpenAPI tools
|
|
133
|
-
* @param options - Adapter options
|
|
134
|
-
* @returns Validation result with errors and warnings
|
|
135
|
-
*/
|
|
136
|
-
function validateSecurityConfiguration(tools, options) {
|
|
137
|
-
const result = {
|
|
138
|
-
valid: true,
|
|
139
|
-
missingMappings: [],
|
|
140
|
-
warnings: [],
|
|
141
|
-
securityRiskScore: 'low',
|
|
142
|
-
};
|
|
143
|
-
// Extract all security schemes used
|
|
144
|
-
const securitySchemes = extractSecuritySchemes(tools);
|
|
145
|
-
// If includeSecurityInInput is true, auth is provided by user (high security risk)
|
|
146
|
-
const includeSecurityInInput = options.generateOptions?.includeSecurityInInput ?? false;
|
|
147
|
-
if (includeSecurityInInput) {
|
|
148
|
-
result.securityRiskScore = 'high';
|
|
149
|
-
result.warnings.push('SECURITY WARNING: includeSecurityInInput is enabled. Users will provide authentication directly in tool inputs. This increases security risk as credentials may be logged or exposed.');
|
|
150
|
-
// Don't validate mappings if security is in input
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
// Check if we have custom security resolver (most flexible, low risk)
|
|
154
|
-
if (options.securityResolver) {
|
|
155
|
-
result.securityRiskScore = 'low';
|
|
156
|
-
result.warnings.push('INFO: Using custom securityResolver. Ensure your resolver properly validates and secures credentials from context.');
|
|
157
|
-
return result;
|
|
158
|
-
}
|
|
159
|
-
// Check if we have static auth (medium risk - static credentials)
|
|
160
|
-
if (options.staticAuth && Object.keys(options.staticAuth).length > 0) {
|
|
161
|
-
result.securityRiskScore = 'medium';
|
|
162
|
-
result.warnings.push('SECURITY INFO: Using staticAuth with hardcoded credentials. Ensure credentials are stored securely (environment variables, secrets manager).');
|
|
163
|
-
// If static auth is provided, assume it covers all schemes
|
|
164
|
-
return result;
|
|
165
|
-
}
|
|
166
|
-
// Get schemes that will be provided via input (don't need mapping)
|
|
167
|
-
const schemesInInput = new Set(options.securitySchemesInInput || []);
|
|
168
|
-
// Check authProviderMapper (low risk - context-based auth)
|
|
169
|
-
if (options.authProviderMapper || schemesInInput.size > 0) {
|
|
170
|
-
result.securityRiskScore = schemesInInput.size > 0 ? 'medium' : 'low';
|
|
171
|
-
// Log info about per-scheme control
|
|
172
|
-
if (schemesInInput.size > 0) {
|
|
173
|
-
result.warnings.push(`INFO: Per-scheme security control enabled. Schemes in input: ${Array.from(schemesInInput).join(', ')}`);
|
|
174
|
-
}
|
|
175
|
-
// Validate that all schemes have mappings (except those in input)
|
|
176
|
-
for (const scheme of securitySchemes) {
|
|
177
|
-
// Skip schemes that will be provided via input
|
|
178
|
-
if (schemesInInput.has(scheme)) {
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
// Check if there's a mapping for this scheme
|
|
182
|
-
if (!options.authProviderMapper?.[scheme]) {
|
|
183
|
-
result.valid = false;
|
|
184
|
-
result.missingMappings.push(scheme);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
if (!result.valid) {
|
|
188
|
-
result.warnings.push(`ERROR: Missing auth provider mappings for security schemes: ${result.missingMappings.join(', ')}`);
|
|
189
|
-
}
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
// No auth configuration provided - will use default ctx.authInfo.token
|
|
193
|
-
// This only works if there's a single Bearer auth scheme
|
|
194
|
-
if (securitySchemes.size > 0) {
|
|
195
|
-
result.securityRiskScore = 'medium';
|
|
196
|
-
result.warnings.push(`INFO: No auth configuration provided. Using default ctx.authInfo.token for all security schemes: ${Array.from(securitySchemes).join(', ')}`);
|
|
197
|
-
result.warnings.push('RECOMMENDATION: For multiple auth providers, use authProviderMapper or securityResolver to map each security scheme to the correct auth provider.');
|
|
198
|
-
}
|
|
199
|
-
return result;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Resolve security for an OpenAPI tool with validation
|
|
203
|
-
*
|
|
204
|
-
* @param tool - OpenAPI tool with mapper
|
|
205
|
-
* @param ctx - FrontMCP request context with authInfo, sessionId, traceId, etc.
|
|
206
|
-
* @param options - Adapter options with auth configuration
|
|
207
|
-
* @returns Resolved security (headers, query params, etc.)
|
|
208
|
-
* @throws Error if security cannot be resolved
|
|
209
|
-
*/
|
|
210
|
-
async function resolveToolSecurity(tool, ctx, options) {
|
|
211
|
-
const securityResolver = new mcp_from_openapi_1.SecurityResolver();
|
|
212
|
-
const securityContext = await createSecurityContextFromAuth(tool, ctx, options);
|
|
213
|
-
// Validate that we have auth for this tool
|
|
214
|
-
const hasAuth = securityContext.jwt ||
|
|
215
|
-
securityContext.apiKey ||
|
|
216
|
-
securityContext.basic ||
|
|
217
|
-
securityContext.oauth2Token ||
|
|
218
|
-
(securityContext.apiKeys && Object.keys(securityContext.apiKeys).length > 0) ||
|
|
219
|
-
(securityContext.customHeaders && Object.keys(securityContext.customHeaders).length > 0);
|
|
220
|
-
// Check if this tool requires security
|
|
221
|
-
// A tool requires security ONLY if a mapper has security with required=true
|
|
222
|
-
// Optional security schemes (required=false or undefined) should not block requests
|
|
223
|
-
const requiresSecurity = tool.mapper.some((m) => m.security && m.required === true);
|
|
224
|
-
if (requiresSecurity && !hasAuth) {
|
|
225
|
-
// Extract required security scheme names for error message
|
|
226
|
-
const requiredSchemes = tool.mapper
|
|
227
|
-
.filter((m) => m.security && m.required === true)
|
|
228
|
-
.map((m) => m.security?.scheme ?? 'unknown');
|
|
229
|
-
const uniqueSchemes = [...new Set(requiredSchemes)];
|
|
230
|
-
const schemesStr = uniqueSchemes.join(', ') || 'unknown';
|
|
231
|
-
const firstScheme = uniqueSchemes[0] || 'BearerAuth';
|
|
232
|
-
throw new Error(`Authentication required for tool '${tool.name}' but no auth configuration found.\n` +
|
|
233
|
-
`Required security schemes: ${schemesStr}\n` +
|
|
234
|
-
`Solutions:\n` +
|
|
235
|
-
` 1. Add authProviderMapper: { '${firstScheme}': (ctx) => ctx.authInfo.user?.token }\n` +
|
|
236
|
-
` 2. Add securityResolver: (tool, ctx) => ({ jwt: ctx.authInfo.token })\n` +
|
|
237
|
-
` 3. Add staticAuth: { jwt: process.env.API_TOKEN }\n` +
|
|
238
|
-
` 4. Set generateOptions.includeSecurityInInput: true (not recommended for production)`);
|
|
239
|
-
}
|
|
240
|
-
return await securityResolver.resolve(tool.mapper, securityContext);
|
|
241
|
-
}
|
|
242
|
-
//# sourceMappingURL=openapi.security.js.map
|