mcp-from-openapi 2.1.0 → 2.1.1

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/index.js ADDED
@@ -0,0 +1,1612 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // libs/mcp-from-openapi/src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ GenerationError: () => GenerationError,
34
+ LoadError: () => LoadError,
35
+ OpenAPIToolError: () => OpenAPIToolError,
36
+ OpenAPIToolGenerator: () => OpenAPIToolGenerator,
37
+ ParameterResolver: () => ParameterResolver,
38
+ ParseError: () => ParseError,
39
+ ResponseBuilder: () => ResponseBuilder,
40
+ SchemaBuilder: () => SchemaBuilder,
41
+ SchemaError: () => SchemaError,
42
+ SecurityResolver: () => SecurityResolver,
43
+ ValidationError: () => ValidationError,
44
+ Validator: () => Validator,
45
+ createSecurityContext: () => createSecurityContext,
46
+ isReferenceObject: () => isReferenceObject,
47
+ toJsonSchema: () => toJsonSchema
48
+ });
49
+ module.exports = __toCommonJS(index_exports);
50
+
51
+ // libs/mcp-from-openapi/src/generator.ts
52
+ var yaml = __toESM(require("yaml"));
53
+ var fs = __toESM(require("fs/promises"));
54
+ var path = __toESM(require("path"));
55
+ var import_json_schema_ref_parser = __toESM(require("@apidevtools/json-schema-ref-parser"));
56
+
57
+ // libs/mcp-from-openapi/src/types.ts
58
+ function isReferenceObject(obj) {
59
+ return obj && typeof obj === "object" && "$ref" in obj;
60
+ }
61
+ function toJsonSchema(schema) {
62
+ if (isReferenceObject(schema)) {
63
+ return { $ref: schema.$ref };
64
+ }
65
+ const { exclusiveMaximum, exclusiveMinimum, maximum, minimum, ...rest } = schema;
66
+ const result = { ...rest };
67
+ if (typeof exclusiveMaximum === "boolean") {
68
+ if (exclusiveMaximum && maximum !== void 0) {
69
+ result["exclusiveMaximum"] = maximum;
70
+ } else if (maximum !== void 0) {
71
+ result["maximum"] = maximum;
72
+ }
73
+ } else if (exclusiveMaximum !== void 0) {
74
+ result["exclusiveMaximum"] = exclusiveMaximum;
75
+ if (maximum !== void 0) {
76
+ result["maximum"] = maximum;
77
+ }
78
+ } else if (maximum !== void 0) {
79
+ result["maximum"] = maximum;
80
+ }
81
+ if (typeof exclusiveMinimum === "boolean") {
82
+ if (exclusiveMinimum && minimum !== void 0) {
83
+ result["exclusiveMinimum"] = minimum;
84
+ } else if (minimum !== void 0) {
85
+ result["minimum"] = minimum;
86
+ }
87
+ } else if (exclusiveMinimum !== void 0) {
88
+ result["exclusiveMinimum"] = exclusiveMinimum;
89
+ if (minimum !== void 0) {
90
+ result["minimum"] = minimum;
91
+ }
92
+ } else if (minimum !== void 0) {
93
+ result["minimum"] = minimum;
94
+ }
95
+ if (result["properties"] && typeof result["properties"] === "object") {
96
+ const props = {};
97
+ for (const [key, value] of Object.entries(result["properties"])) {
98
+ props[key] = toJsonSchema(value);
99
+ }
100
+ result["properties"] = props;
101
+ }
102
+ if (result["items"]) {
103
+ if (Array.isArray(result["items"])) {
104
+ result["items"] = result["items"].map(toJsonSchema);
105
+ } else {
106
+ result["items"] = toJsonSchema(result["items"]);
107
+ }
108
+ }
109
+ if (result["additionalProperties"] && typeof result["additionalProperties"] === "object") {
110
+ result["additionalProperties"] = toJsonSchema(result["additionalProperties"]);
111
+ }
112
+ for (const key of ["allOf", "anyOf", "oneOf"]) {
113
+ if (result[key] && Array.isArray(result[key])) {
114
+ result[key] = result[key].map(toJsonSchema);
115
+ }
116
+ }
117
+ if (result["not"]) {
118
+ result["not"] = toJsonSchema(result["not"]);
119
+ }
120
+ return result;
121
+ }
122
+
123
+ // libs/mcp-from-openapi/src/parameter-resolver.ts
124
+ var ParameterResolver = class {
125
+ namingStrategy;
126
+ constructor(namingStrategy) {
127
+ this.namingStrategy = namingStrategy ?? {
128
+ conflictResolver: this.defaultConflictResolver
129
+ };
130
+ }
131
+ /**
132
+ * Default conflict resolver: prefix with location
133
+ */
134
+ defaultConflictResolver(paramName, location, index) {
135
+ const locationPrefix = {
136
+ path: "path",
137
+ query: "query",
138
+ header: "header",
139
+ cookie: "cookie",
140
+ body: "body"
141
+ }[location];
142
+ return `${locationPrefix}${paramName.charAt(0).toUpperCase()}${paramName.slice(1)}`;
143
+ }
144
+ /**
145
+ * Resolve all parameters for an operation
146
+ */
147
+ resolve(operation, pathParameters, securityRequirements, includeSecurityInInput) {
148
+ const allParameters = [...pathParameters ?? [], ...operation.parameters ?? []];
149
+ const requestBody = operation.requestBody;
150
+ const parametersByName = /* @__PURE__ */ new Map();
151
+ allParameters.forEach((param) => {
152
+ const info = {
153
+ name: param.name,
154
+ location: param.in,
155
+ required: param.required ?? param.in === "path",
156
+ schema: param.schema ?? { type: "string" },
157
+ description: param.description,
158
+ style: param.style,
159
+ explode: param.explode,
160
+ allowReserved: param.allowReserved,
161
+ deprecated: param.deprecated
162
+ };
163
+ if (!parametersByName.has(param.name)) {
164
+ parametersByName.set(param.name, []);
165
+ }
166
+ parametersByName.get(param.name).push(info);
167
+ });
168
+ if (requestBody?.content) {
169
+ const contentType = this.selectContentType(requestBody.content);
170
+ const mediaType = requestBody.content[contentType];
171
+ if (mediaType?.schema) {
172
+ this.extractBodyParameters(mediaType.schema, parametersByName, requestBody.required ?? false, contentType);
173
+ }
174
+ }
175
+ const properties = {};
176
+ const required = [];
177
+ const mapper = [];
178
+ for (const [originalName, params] of parametersByName.entries()) {
179
+ if (params.length === 1) {
180
+ const param = params[0];
181
+ const inputKey = originalName;
182
+ properties[inputKey] = this.buildParameterSchema(param);
183
+ if (param.required) {
184
+ required.push(inputKey);
185
+ }
186
+ mapper.push({
187
+ inputKey,
188
+ type: param.location,
189
+ key: originalName,
190
+ required: param.required,
191
+ style: param.style,
192
+ explode: param.explode,
193
+ serialization: param.serialization
194
+ });
195
+ } else {
196
+ params.forEach((param, index) => {
197
+ const inputKey = this.namingStrategy.conflictResolver(originalName, param.location, index);
198
+ properties[inputKey] = this.buildParameterSchema(param);
199
+ if (param.required) {
200
+ required.push(inputKey);
201
+ }
202
+ mapper.push({
203
+ inputKey,
204
+ type: param.location,
205
+ key: originalName,
206
+ required: param.required,
207
+ style: param.style,
208
+ explode: param.explode,
209
+ serialization: param.serialization
210
+ });
211
+ });
212
+ }
213
+ }
214
+ if (securityRequirements && securityRequirements.length > 0) {
215
+ this.processSecurityRequirements(
216
+ securityRequirements,
217
+ properties,
218
+ required,
219
+ mapper,
220
+ includeSecurityInInput ?? false
221
+ );
222
+ }
223
+ const inputSchema = {
224
+ type: "object",
225
+ properties,
226
+ ...required.length > 0 && { required },
227
+ additionalProperties: false
228
+ };
229
+ return { inputSchema, mapper };
230
+ }
231
+ /**
232
+ * Extract parameters from request body schema
233
+ */
234
+ extractBodyParameters(schema, parametersByName, required, contentType, prefix = "") {
235
+ if (!schema || typeof schema !== "object") return;
236
+ const jsonSchema = toJsonSchema(schema);
237
+ if (jsonSchema.type === "object" && jsonSchema.properties) {
238
+ const requiredFields = new Set(jsonSchema.required ?? []);
239
+ for (const [propName, propSchema] of Object.entries(jsonSchema.properties)) {
240
+ const fullName = prefix ? `${prefix}.${propName}` : propName;
241
+ const isRequired = required && requiredFields.has(propName);
242
+ if (typeof propSchema === "object") {
243
+ const info = {
244
+ name: fullName,
245
+ location: "body",
246
+ required: isRequired,
247
+ schema: propSchema,
248
+ description: propSchema.description,
249
+ serialization: {
250
+ contentType
251
+ }
252
+ };
253
+ if (!parametersByName.has(fullName)) {
254
+ parametersByName.set(fullName, []);
255
+ }
256
+ parametersByName.get(fullName).push(info);
257
+ }
258
+ }
259
+ } else {
260
+ const bodyParamName = prefix || "body";
261
+ const info = {
262
+ name: bodyParamName,
263
+ location: "body",
264
+ required,
265
+ schema,
266
+ serialization: {
267
+ contentType
268
+ }
269
+ };
270
+ if (!parametersByName.has(bodyParamName)) {
271
+ parametersByName.set(bodyParamName, []);
272
+ }
273
+ parametersByName.get(bodyParamName).push(info);
274
+ }
275
+ }
276
+ /**
277
+ * Build JSON Schema for a parameter
278
+ */
279
+ buildParameterSchema(param) {
280
+ const schema = toJsonSchema(param.schema);
281
+ if (param.description) {
282
+ schema.description = param.description;
283
+ }
284
+ if (param.deprecated) {
285
+ schema["deprecated"] = true;
286
+ }
287
+ schema["x-parameter-location"] = param.location;
288
+ if (param.style) {
289
+ schema["x-parameter-style"] = param.style;
290
+ }
291
+ if (param.explode !== void 0) {
292
+ schema["x-parameter-explode"] = param.explode;
293
+ }
294
+ return schema;
295
+ }
296
+ /**
297
+ * Select the most appropriate content type
298
+ */
299
+ selectContentType(content) {
300
+ const preferences = [
301
+ "application/json",
302
+ "application/x-www-form-urlencoded",
303
+ "multipart/form-data",
304
+ "application/xml",
305
+ "text/plain"
306
+ ];
307
+ for (const pref of preferences) {
308
+ if (content[pref]) return pref;
309
+ }
310
+ const firstKey = Object.keys(content)[0];
311
+ if (!firstKey) {
312
+ throw new Error("No content type available in request body");
313
+ }
314
+ return firstKey;
315
+ }
316
+ /**
317
+ * Process security requirements and add to mapper/inputSchema
318
+ */
319
+ processSecurityRequirements(securityRequirements, properties, required, mapper, includeInInput) {
320
+ for (const secReq of securityRequirements) {
321
+ const { scheme, type, name: apiKeyName, in: apiKeyIn, scopes } = secReq;
322
+ const securityInfo = {
323
+ scheme,
324
+ type,
325
+ scopes
326
+ };
327
+ let inputKey;
328
+ let headerKey;
329
+ let paramLocation;
330
+ let description;
331
+ let schema;
332
+ if (type === "http") {
333
+ inputKey = scheme;
334
+ headerKey = "Authorization";
335
+ paramLocation = "header";
336
+ const httpScheme = "httpScheme" in secReq && secReq.httpScheme ? secReq.httpScheme : "bearer";
337
+ const bearerFormat = "bearerFormat" in secReq ? secReq.bearerFormat : void 0;
338
+ securityInfo.httpScheme = httpScheme;
339
+ if (bearerFormat) {
340
+ securityInfo.bearerFormat = bearerFormat;
341
+ }
342
+ description = `${httpScheme.charAt(0).toUpperCase()}${httpScheme.slice(1)} authentication token`;
343
+ if (bearerFormat) {
344
+ description += ` (${bearerFormat})`;
345
+ }
346
+ schema = {
347
+ type: "string",
348
+ description
349
+ };
350
+ } else if (type === "apiKey") {
351
+ inputKey = scheme;
352
+ headerKey = apiKeyName || "X-API-Key";
353
+ paramLocation = apiKeyIn || "header";
354
+ securityInfo.apiKeyName = apiKeyName;
355
+ securityInfo.apiKeyIn = apiKeyIn;
356
+ description = `API key for ${scheme}`;
357
+ schema = {
358
+ type: "string",
359
+ description
360
+ };
361
+ } else if (type === "oauth2" || type === "openIdConnect") {
362
+ inputKey = scheme;
363
+ headerKey = "Authorization";
364
+ paramLocation = "header";
365
+ description = `OAuth2 access token${scopes && scopes.length > 0 ? ` (scopes: ${scopes.join(", ")})` : ""}`;
366
+ schema = {
367
+ type: "string",
368
+ description
369
+ };
370
+ } else {
371
+ continue;
372
+ }
373
+ mapper.push({
374
+ inputKey,
375
+ type: paramLocation,
376
+ key: headerKey,
377
+ required: true,
378
+ security: securityInfo
379
+ });
380
+ if (includeInInput) {
381
+ properties[inputKey] = schema;
382
+ required.push(inputKey);
383
+ }
384
+ }
385
+ }
386
+ };
387
+
388
+ // libs/mcp-from-openapi/src/response-builder.ts
389
+ var ResponseBuilder = class {
390
+ preferredStatusCodes;
391
+ includeAllResponses;
392
+ constructor(options = {}) {
393
+ this.preferredStatusCodes = options.preferredStatusCodes ?? [200, 201, 204, 202, 203, 206];
394
+ this.includeAllResponses = options.includeAllResponses ?? true;
395
+ }
396
+ /**
397
+ * Build output schema from responses
398
+ */
399
+ build(responses) {
400
+ if (!responses || Object.keys(responses).length === 0) {
401
+ return void 0;
402
+ }
403
+ const schemas = this.extractResponseSchemas(responses);
404
+ if (schemas.length === 0) {
405
+ return void 0;
406
+ }
407
+ if (schemas.length === 1) {
408
+ return schemas[0].schema;
409
+ }
410
+ if (this.includeAllResponses) {
411
+ return {
412
+ oneOf: schemas.map((s) => s.schema),
413
+ description: "Response can be one of multiple status codes"
414
+ };
415
+ } else {
416
+ const preferred = this.selectPreferredSchema(schemas);
417
+ return preferred.schema;
418
+ }
419
+ }
420
+ /**
421
+ * Extract schemas from all responses
422
+ */
423
+ extractResponseSchemas(responses) {
424
+ const schemas = [];
425
+ for (const [statusCode, response] of Object.entries(responses)) {
426
+ if (isReferenceObject(response)) continue;
427
+ if (statusCode === "default") continue;
428
+ const code = parseInt(statusCode, 10);
429
+ if (isNaN(code)) continue;
430
+ const schema = this.extractResponseSchema(response, code);
431
+ if (schema) {
432
+ schemas.push(schema);
433
+ }
434
+ }
435
+ if (schemas.length === 0 && responses["default"]) {
436
+ const defaultResponse = responses["default"];
437
+ if (!isReferenceObject(defaultResponse)) {
438
+ const schema = this.extractResponseSchema(defaultResponse, 0);
439
+ if (schema) {
440
+ schemas.push(schema);
441
+ }
442
+ }
443
+ }
444
+ return schemas;
445
+ }
446
+ /**
447
+ * Extract schema from a single response
448
+ */
449
+ extractResponseSchema(response, statusCode) {
450
+ if (!response.content) {
451
+ return {
452
+ statusCode,
453
+ schema: {
454
+ type: "null",
455
+ description: response.description,
456
+ "x-status-code": statusCode
457
+ }
458
+ };
459
+ }
460
+ const contentType = this.selectContentType(response.content);
461
+ const mediaType = response.content[contentType];
462
+ if (!mediaType?.schema) {
463
+ return null;
464
+ }
465
+ const schema = {
466
+ ...toJsonSchema(mediaType.schema),
467
+ "x-status-code": statusCode
468
+ };
469
+ if (!schema.description && response.description) {
470
+ schema.description = response.description;
471
+ }
472
+ schema["x-content-type"] = contentType;
473
+ return { statusCode, schema };
474
+ }
475
+ /**
476
+ * Select the most appropriate content type
477
+ */
478
+ selectContentType(content) {
479
+ const preferences = [
480
+ "application/json",
481
+ "application/hal+json",
482
+ "application/problem+json",
483
+ "application/xml",
484
+ "text/plain",
485
+ "text/html"
486
+ ];
487
+ for (const pref of preferences) {
488
+ if (content[pref]) return pref;
489
+ }
490
+ return Object.keys(content)[0];
491
+ }
492
+ /**
493
+ * Select the preferred schema based on status code preferences
494
+ */
495
+ selectPreferredSchema(schemas) {
496
+ for (const preferredCode of this.preferredStatusCodes) {
497
+ const found = schemas.find((s) => s.statusCode === preferredCode);
498
+ if (found) return found;
499
+ }
500
+ const success = schemas.find((s) => s.statusCode >= 200 && s.statusCode < 300);
501
+ if (success) return success;
502
+ const redirect = schemas.find((s) => s.statusCode >= 300 && s.statusCode < 400);
503
+ if (redirect) return redirect;
504
+ return schemas[0];
505
+ }
506
+ };
507
+
508
+ // libs/mcp-from-openapi/src/validator.ts
509
+ var Validator = class {
510
+ /**
511
+ * Validate an OpenAPI document
512
+ */
513
+ async validate(document) {
514
+ const errors = [];
515
+ const warnings = [];
516
+ if (!document.openapi) {
517
+ errors.push({
518
+ message: "Missing required field: openapi",
519
+ path: "/openapi",
520
+ code: "MISSING_OPENAPI_VERSION"
521
+ });
522
+ } else if (!this.isValidOpenAPIVersion(document.openapi)) {
523
+ errors.push({
524
+ message: `Unsupported OpenAPI version: ${document.openapi}. Expected 3.0.x or 3.1.x`,
525
+ path: "/openapi",
526
+ code: "INVALID_OPENAPI_VERSION"
527
+ });
528
+ }
529
+ if (!document.info) {
530
+ errors.push({
531
+ message: "Missing required field: info",
532
+ path: "/info",
533
+ code: "MISSING_INFO"
534
+ });
535
+ } else {
536
+ if (!document.info.title) {
537
+ errors.push({
538
+ message: "Missing required field: info.title",
539
+ path: "/info/title",
540
+ code: "MISSING_TITLE"
541
+ });
542
+ }
543
+ if (!document.info.version) {
544
+ errors.push({
545
+ message: "Missing required field: info.version",
546
+ path: "/info/version",
547
+ code: "MISSING_VERSION"
548
+ });
549
+ }
550
+ }
551
+ if (!document.paths || Object.keys(document.paths).length === 0) {
552
+ warnings.push({
553
+ message: "No paths defined in OpenAPI document",
554
+ path: "/paths",
555
+ code: "NO_PATHS"
556
+ });
557
+ } else {
558
+ this.validatePaths(document.paths, errors, warnings);
559
+ }
560
+ if (!document.servers || document.servers.length === 0) {
561
+ warnings.push({
562
+ message: "No servers defined. You may need to provide a baseUrl option.",
563
+ path: "/servers",
564
+ code: "NO_SERVERS"
565
+ });
566
+ }
567
+ if (document.security && !document.components?.securitySchemes) {
568
+ warnings.push({
569
+ message: "Security requirements defined but no security schemes found",
570
+ path: "/security",
571
+ code: "NO_SECURITY_SCHEMES"
572
+ });
573
+ }
574
+ return {
575
+ valid: errors.length === 0,
576
+ errors: errors.length > 0 ? errors : void 0,
577
+ warnings: warnings.length > 0 ? warnings : void 0
578
+ };
579
+ }
580
+ /**
581
+ * Check if OpenAPI version is valid
582
+ */
583
+ isValidOpenAPIVersion(version) {
584
+ return /^3\.[01]\.\d+$/.test(version);
585
+ }
586
+ /**
587
+ * Validate paths
588
+ */
589
+ validatePaths(paths, errors, warnings) {
590
+ for (const [path2, pathItem] of Object.entries(paths)) {
591
+ if (!pathItem) continue;
592
+ if (!path2.startsWith("/")) {
593
+ errors.push({
594
+ message: `Path must start with '/': ${path2}`,
595
+ path: `/paths/${path2}`,
596
+ code: "INVALID_PATH_FORMAT"
597
+ });
598
+ }
599
+ const methods = ["get", "post", "put", "patch", "delete", "head", "options", "trace"];
600
+ let hasOperations = false;
601
+ for (const method of methods) {
602
+ const operation = pathItem[method];
603
+ if (operation) {
604
+ hasOperations = true;
605
+ this.validateOperation(operation, path2, method, errors, warnings);
606
+ }
607
+ }
608
+ if (!hasOperations && !pathItem.$ref) {
609
+ warnings.push({
610
+ message: `Path has no operations: ${path2}`,
611
+ path: `/paths/${path2}`,
612
+ code: "NO_OPERATIONS"
613
+ });
614
+ }
615
+ }
616
+ }
617
+ /**
618
+ * Validate an operation
619
+ */
620
+ validateOperation(operation, path2, method, errors, warnings) {
621
+ const basePath = `/paths/${path2}/${method}`;
622
+ if (!operation.operationId) {
623
+ warnings.push({
624
+ message: `Operation missing operationId: ${method.toUpperCase()} ${path2}`,
625
+ path: `${basePath}/operationId`,
626
+ code: "NO_OPERATION_ID"
627
+ });
628
+ }
629
+ if (!operation.responses || Object.keys(operation.responses).length === 0) {
630
+ errors.push({
631
+ message: `Operation missing responses: ${method.toUpperCase()} ${path2}`,
632
+ path: `${basePath}/responses`,
633
+ code: "NO_RESPONSES"
634
+ });
635
+ }
636
+ if (operation.parameters) {
637
+ this.validateParameters(operation.parameters, path2, method, errors, warnings);
638
+ }
639
+ const pathParams = path2.match(/\{([^}]+)\}/g)?.map((p) => p.slice(1, -1)) ?? [];
640
+ const definedPathParams = new Set(
641
+ operation.parameters?.filter((p) => p.in === "path").map((p) => p.name) ?? []
642
+ );
643
+ for (const param of pathParams) {
644
+ if (!definedPathParams.has(param)) {
645
+ errors.push({
646
+ message: `Path parameter '${param}' not defined in parameters: ${method.toUpperCase()} ${path2}`,
647
+ path: `${basePath}/parameters`,
648
+ code: "MISSING_PATH_PARAMETER"
649
+ });
650
+ }
651
+ }
652
+ }
653
+ /**
654
+ * Validate parameters
655
+ */
656
+ validateParameters(parameters, path2, method, errors, warnings) {
657
+ const basePath = `/paths/${path2}/${method}/parameters`;
658
+ for (let i = 0; i < parameters.length; i++) {
659
+ const param = parameters[i];
660
+ const paramPath = `${basePath}/${i}`;
661
+ if (!param.name) {
662
+ errors.push({
663
+ message: "Parameter missing name",
664
+ path: `${paramPath}/name`,
665
+ code: "MISSING_PARAMETER_NAME"
666
+ });
667
+ }
668
+ if (!param.in) {
669
+ errors.push({
670
+ message: 'Parameter missing "in" field',
671
+ path: `${paramPath}/in`,
672
+ code: "MISSING_PARAMETER_IN"
673
+ });
674
+ } else if (!["path", "query", "header", "cookie"].includes(param.in)) {
675
+ errors.push({
676
+ message: `Invalid parameter location: ${param.in}`,
677
+ path: `${paramPath}/in`,
678
+ code: "INVALID_PARAMETER_IN"
679
+ });
680
+ }
681
+ if (param.in === "path" && !param.required) {
682
+ errors.push({
683
+ message: `Path parameter '${param.name}' must be required`,
684
+ path: `${paramPath}/required`,
685
+ code: "PATH_PARAMETER_NOT_REQUIRED"
686
+ });
687
+ }
688
+ if (!param.schema && !param.content) {
689
+ errors.push({
690
+ message: `Parameter '${param.name}' missing schema or content`,
691
+ path: `${paramPath}`,
692
+ code: "MISSING_PARAMETER_SCHEMA"
693
+ });
694
+ }
695
+ }
696
+ }
697
+ };
698
+
699
+ // libs/mcp-from-openapi/src/errors.ts
700
+ var OpenAPIToolError = class extends Error {
701
+ context;
702
+ constructor(message, context) {
703
+ super(message);
704
+ this.name = this.constructor.name;
705
+ this.context = context;
706
+ if (Error.captureStackTrace) {
707
+ Error.captureStackTrace(this, this.constructor);
708
+ }
709
+ }
710
+ };
711
+ var LoadError = class extends OpenAPIToolError {
712
+ constructor(message, context) {
713
+ super(message, context);
714
+ }
715
+ };
716
+ var ParseError = class extends OpenAPIToolError {
717
+ constructor(message, context) {
718
+ super(message, context);
719
+ }
720
+ };
721
+ var ValidationError = class extends OpenAPIToolError {
722
+ errors;
723
+ constructor(message, context) {
724
+ super(message, context);
725
+ this.errors = context?.["errors"];
726
+ }
727
+ };
728
+ var GenerationError = class extends OpenAPIToolError {
729
+ constructor(message, context) {
730
+ super(message, context);
731
+ }
732
+ };
733
+ var SchemaError = class extends OpenAPIToolError {
734
+ constructor(message, context) {
735
+ super(message, context);
736
+ }
737
+ };
738
+
739
+ // libs/mcp-from-openapi/src/generator.ts
740
+ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
741
+ document;
742
+ dereferencedDocument;
743
+ options;
744
+ /**
745
+ * Private constructor - use static factory methods to create instances
746
+ */
747
+ constructor(document, options = {}) {
748
+ this.document = document;
749
+ this.options = {
750
+ dereference: options.dereference ?? true,
751
+ baseUrl: options.baseUrl ?? "",
752
+ headers: options.headers ?? {},
753
+ timeout: options.timeout ?? 3e4,
754
+ validate: options.validate ?? true,
755
+ followRedirects: options.followRedirects ?? true
756
+ };
757
+ }
758
+ /**
759
+ * Create generator from a URL
760
+ */
761
+ static async fromURL(url, options = {}) {
762
+ try {
763
+ const controller = new AbortController();
764
+ const timeout = setTimeout(() => controller.abort(), options.timeout ?? 3e4);
765
+ const response = await fetch(url, {
766
+ headers: options.headers,
767
+ signal: controller.signal,
768
+ redirect: options.followRedirects ?? true ? "follow" : "manual"
769
+ });
770
+ clearTimeout(timeout);
771
+ if (!response.ok) {
772
+ throw new LoadError(`Failed to fetch OpenAPI spec from URL: ${response.status} ${response.statusText}`, {
773
+ url,
774
+ status: response.status
775
+ });
776
+ }
777
+ const contentType = response.headers.get("content-type") || "";
778
+ const text = await response.text();
779
+ let document;
780
+ if (contentType.includes("yaml") || contentType.includes("yml") || url.match(/\.ya?ml$/i)) {
781
+ document = yaml.parse(text);
782
+ } else {
783
+ document = JSON.parse(text);
784
+ }
785
+ return new _OpenAPIToolGenerator(document, options);
786
+ } catch (error) {
787
+ if (error instanceof LoadError) {
788
+ throw error;
789
+ }
790
+ const errorMessage = error instanceof Error ? error.message : String(error);
791
+ throw new LoadError(`Failed to load OpenAPI spec from URL: ${errorMessage}`, {
792
+ url,
793
+ originalError: error
794
+ });
795
+ }
796
+ }
797
+ /**
798
+ * Create generator from a file path
799
+ */
800
+ static async fromFile(filePath, options = {}) {
801
+ try {
802
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
803
+ const content = await fs.readFile(absolutePath, "utf-8");
804
+ const ext = path.extname(filePath).toLowerCase();
805
+ let document;
806
+ if (ext === ".yaml" || ext === ".yml") {
807
+ document = yaml.parse(content);
808
+ } else if (ext === ".json") {
809
+ document = JSON.parse(content);
810
+ } else {
811
+ try {
812
+ document = JSON.parse(content);
813
+ } catch {
814
+ document = yaml.parse(content);
815
+ }
816
+ }
817
+ return new _OpenAPIToolGenerator(document, options);
818
+ } catch (error) {
819
+ const errorMessage = error instanceof Error ? error.message : String(error);
820
+ throw new LoadError(`Failed to load OpenAPI spec from file: ${errorMessage}`, {
821
+ filePath,
822
+ originalError: error
823
+ });
824
+ }
825
+ }
826
+ /**
827
+ * Create generator from a YAML string
828
+ */
829
+ static async fromYAML(yamlString, options = {}) {
830
+ try {
831
+ const document = yaml.parse(yamlString);
832
+ return new _OpenAPIToolGenerator(document, options);
833
+ } catch (error) {
834
+ const errorMessage = error instanceof Error ? error.message : String(error);
835
+ throw new ParseError(`Failed to parse YAML: ${errorMessage}`, {
836
+ originalError: error
837
+ });
838
+ }
839
+ }
840
+ /**
841
+ * Create generator from a JSON object
842
+ */
843
+ static async fromJSON(json, options = {}) {
844
+ const document = JSON.parse(JSON.stringify(json));
845
+ return new _OpenAPIToolGenerator(document, options);
846
+ }
847
+ /**
848
+ * Get the OpenAPI document
849
+ */
850
+ getDocument() {
851
+ return this.dereferencedDocument ?? this.document;
852
+ }
853
+ /**
854
+ * Validate the OpenAPI document
855
+ */
856
+ async validate() {
857
+ const validator = new Validator();
858
+ return validator.validate(this.document);
859
+ }
860
+ /**
861
+ * Initialize the generator (dereference if needed)
862
+ */
863
+ async initialize() {
864
+ if (this.options.validate) {
865
+ const result = await this.validate();
866
+ if (!result.valid) {
867
+ throw new ParseError("Invalid OpenAPI document", { errors: result.errors });
868
+ }
869
+ }
870
+ if (this.options.dereference && !this.dereferencedDocument) {
871
+ try {
872
+ this.dereferencedDocument = await import_json_schema_ref_parser.default.dereference(
873
+ JSON.parse(JSON.stringify(this.document))
874
+ );
875
+ } catch (error) {
876
+ const errorMessage = error instanceof Error ? error.message : String(error);
877
+ throw new ParseError(`Failed to dereference OpenAPI document: ${errorMessage}`, {
878
+ originalError: error
879
+ });
880
+ }
881
+ }
882
+ }
883
+ /**
884
+ * Generate all tools from the OpenAPI specification
885
+ */
886
+ async generateTools(options = {}) {
887
+ await this.initialize();
888
+ const document = this.getDocument();
889
+ const tools = [];
890
+ if (!document.paths) {
891
+ return tools;
892
+ }
893
+ for (const [pathStr, pathItem] of Object.entries(document.paths)) {
894
+ if (!pathItem || "$ref" in pathItem) continue;
895
+ const methods = ["get", "post", "put", "patch", "delete", "head", "options", "trace"];
896
+ for (const method of methods) {
897
+ const operation = pathItem[method];
898
+ if (!operation) continue;
899
+ if (!this.shouldIncludeOperation(operation, pathStr, method, options)) {
900
+ continue;
901
+ }
902
+ try {
903
+ const tool = await this.generateTool(pathStr, method, options);
904
+ tools.push(tool);
905
+ } catch (error) {
906
+ const errorMessage = error instanceof Error ? error.message : String(error);
907
+ console.warn(`Failed to generate tool for ${method.toUpperCase()} ${pathStr}:`, errorMessage);
908
+ }
909
+ }
910
+ }
911
+ return tools;
912
+ }
913
+ /**
914
+ * Generate a specific tool for a path and method
915
+ */
916
+ async generateTool(pathStr, method, options = {}) {
917
+ await this.initialize();
918
+ const document = this.getDocument();
919
+ if (!document.paths) {
920
+ throw new Error("No paths defined in OpenAPI document");
921
+ }
922
+ const pathItem = document.paths[pathStr];
923
+ const operation = pathItem?.[method.toLowerCase()];
924
+ if (!operation) {
925
+ throw new Error(`Operation not found: ${method.toUpperCase()} ${pathStr}`);
926
+ }
927
+ const parameterResolver = new ParameterResolver(options.namingStrategy);
928
+ let pathParameters = void 0;
929
+ if (pathItem.parameters) {
930
+ pathParameters = pathItem.parameters.filter(
931
+ (p) => !isReferenceObject(p)
932
+ );
933
+ }
934
+ let securityRequirements = void 0;
935
+ const securitySpec = operation.security ?? document.security;
936
+ if (securitySpec) {
937
+ securityRequirements = this.extractSecurityRequirements(securitySpec, document);
938
+ }
939
+ const { inputSchema, mapper } = parameterResolver.resolve(
940
+ operation,
941
+ pathParameters,
942
+ securityRequirements,
943
+ options.includeSecurityInInput
944
+ );
945
+ const responseBuilder = new ResponseBuilder(options);
946
+ const outputSchema = responseBuilder.build(operation.responses);
947
+ const name = this.generateToolName(pathStr, method, operation.operationId, options);
948
+ const description = operation.summary || operation.description || `${method.toUpperCase()} ${pathStr}`;
949
+ const metadata = this.extractMetadata(pathStr, method, operation, document, outputSchema);
950
+ return {
951
+ name,
952
+ description,
953
+ inputSchema,
954
+ outputSchema,
955
+ mapper,
956
+ metadata
957
+ };
958
+ }
959
+ /**
960
+ * Check if an operation should be included
961
+ */
962
+ shouldIncludeOperation(operation, path2, method, options) {
963
+ if (operation.deprecated && !options.includeDeprecated) {
964
+ return false;
965
+ }
966
+ if (options.includeOperations && operation.operationId) {
967
+ if (!options.includeOperations.includes(operation.operationId)) {
968
+ return false;
969
+ }
970
+ }
971
+ if (options.excludeOperations && operation.operationId) {
972
+ if (options.excludeOperations.includes(operation.operationId)) {
973
+ return false;
974
+ }
975
+ }
976
+ if (options.filterFn) {
977
+ return options.filterFn({
978
+ ...operation,
979
+ path: path2,
980
+ method
981
+ });
982
+ }
983
+ return true;
984
+ }
985
+ /**
986
+ * Generate a tool name
987
+ */
988
+ generateToolName(path2, method, operationId, options = {}) {
989
+ if (options.namingStrategy?.toolNameGenerator) {
990
+ return options.namingStrategy.toolNameGenerator(path2, method, operationId);
991
+ }
992
+ if (operationId) {
993
+ return operationId;
994
+ }
995
+ const sanitized = path2.replace(/\{([^}]+)\}/g, "By_$1").replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
996
+ return `${method}_${sanitized}`;
997
+ }
998
+ /**
999
+ * Extract metadata from operation
1000
+ */
1001
+ extractMetadata(path2, method, operation, document, outputSchema) {
1002
+ const metadata = {
1003
+ path: path2,
1004
+ method,
1005
+ operationId: operation.operationId,
1006
+ operationSummary: operation.summary,
1007
+ operationDescription: operation.description,
1008
+ tags: operation.tags,
1009
+ deprecated: operation.deprecated
1010
+ };
1011
+ if (operation.security || document.security) {
1012
+ metadata.security = this.extractSecurityRequirements(
1013
+ operation.security ?? document.security,
1014
+ document
1015
+ );
1016
+ }
1017
+ const servers = operation.servers ?? document.servers;
1018
+ if (servers) {
1019
+ metadata.servers = servers.map((server) => ({
1020
+ url: this.options.baseUrl || server.url,
1021
+ description: server.description,
1022
+ variables: server.variables
1023
+ }));
1024
+ } else if (this.options.baseUrl) {
1025
+ metadata.servers = [{ url: this.options.baseUrl }];
1026
+ }
1027
+ const schemaObj = outputSchema;
1028
+ if (schemaObj && Array.isArray(schemaObj["oneOf"])) {
1029
+ const codes = schemaObj["oneOf"].map((schema) => schema["x-status-code"]).filter((code) => code !== void 0 && code !== null);
1030
+ if (codes.length > 0) {
1031
+ metadata.responseStatusCodes = codes;
1032
+ }
1033
+ } else if (schemaObj && schemaObj["x-status-code"] !== void 0 && schemaObj["x-status-code"] !== null) {
1034
+ metadata.responseStatusCodes = [schemaObj["x-status-code"]];
1035
+ }
1036
+ if (operation.externalDocs) {
1037
+ metadata.externalDocs = operation.externalDocs;
1038
+ }
1039
+ const operationWithExt = operation;
1040
+ if (operationWithExt["x-frontmcp"]) {
1041
+ metadata.frontmcp = operationWithExt["x-frontmcp"];
1042
+ }
1043
+ return metadata;
1044
+ }
1045
+ /**
1046
+ * Extract security requirements
1047
+ */
1048
+ extractSecurityRequirements(security, document) {
1049
+ if (!security || !document.components?.securitySchemes) {
1050
+ return [];
1051
+ }
1052
+ return security.flatMap(
1053
+ (req) => Object.entries(req).map(([scheme, scopes]) => {
1054
+ const securityScheme = document.components.securitySchemes[scheme];
1055
+ if (isReferenceObject(securityScheme)) {
1056
+ return { scheme, type: "http", scopes };
1057
+ }
1058
+ const apiKeyIn = "in" in securityScheme ? securityScheme.in : void 0;
1059
+ const result = {
1060
+ scheme,
1061
+ type: securityScheme.type,
1062
+ scopes,
1063
+ name: "name" in securityScheme ? securityScheme.name : void 0,
1064
+ in: apiKeyIn && (apiKeyIn === "query" || apiKeyIn === "header" || apiKeyIn === "cookie") ? apiKeyIn : void 0
1065
+ };
1066
+ if (securityScheme.type === "http") {
1067
+ result.httpScheme = "scheme" in securityScheme ? securityScheme.scheme : void 0;
1068
+ result.bearerFormat = "bearerFormat" in securityScheme ? securityScheme.bearerFormat : void 0;
1069
+ }
1070
+ result.description = "description" in securityScheme ? securityScheme.description : void 0;
1071
+ return result;
1072
+ })
1073
+ );
1074
+ }
1075
+ };
1076
+
1077
+ // libs/mcp-from-openapi/src/schema-builder.ts
1078
+ var SchemaBuilder = class {
1079
+ /**
1080
+ * Merge multiple schemas into one
1081
+ */
1082
+ static merge(schemas) {
1083
+ if (schemas.length === 0) {
1084
+ return { type: "object" };
1085
+ }
1086
+ if (schemas.length === 1) {
1087
+ return schemas[0];
1088
+ }
1089
+ const merged = {
1090
+ type: "object",
1091
+ properties: {},
1092
+ required: []
1093
+ };
1094
+ const allRequired = /* @__PURE__ */ new Set();
1095
+ for (const schema of schemas) {
1096
+ if (schema.properties) {
1097
+ merged.properties = {
1098
+ ...merged.properties,
1099
+ ...schema.properties
1100
+ };
1101
+ }
1102
+ if (schema.required) {
1103
+ schema.required.forEach((field) => allRequired.add(field));
1104
+ }
1105
+ }
1106
+ if (allRequired.size > 0) {
1107
+ merged.required = Array.from(allRequired);
1108
+ }
1109
+ return merged;
1110
+ }
1111
+ /**
1112
+ * Create a union schema (oneOf)
1113
+ */
1114
+ static union(schemas) {
1115
+ if (schemas.length === 0) {
1116
+ return {};
1117
+ }
1118
+ if (schemas.length === 1) {
1119
+ return schemas[0];
1120
+ }
1121
+ return {
1122
+ oneOf: schemas
1123
+ };
1124
+ }
1125
+ /**
1126
+ * Deep clone a schema
1127
+ */
1128
+ static clone(schema) {
1129
+ return JSON.parse(JSON.stringify(schema));
1130
+ }
1131
+ /**
1132
+ * Remove $ref from schema (assumes already dereferenced)
1133
+ */
1134
+ static removeRefs(schema) {
1135
+ const cloned = this.clone(schema);
1136
+ this.removeRefsRecursive(cloned);
1137
+ return cloned;
1138
+ }
1139
+ static removeRefsRecursive(obj) {
1140
+ if (!obj || typeof obj !== "object") return;
1141
+ if (obj.$ref) {
1142
+ delete obj.$ref;
1143
+ }
1144
+ for (const key in obj) {
1145
+ if (key in obj) {
1146
+ const value = obj[key];
1147
+ if (value && typeof value === "object") {
1148
+ this.removeRefsRecursive(value);
1149
+ }
1150
+ }
1151
+ }
1152
+ }
1153
+ /**
1154
+ * Add description to schema
1155
+ */
1156
+ static withDescription(schema, description) {
1157
+ return {
1158
+ ...schema,
1159
+ description
1160
+ };
1161
+ }
1162
+ /**
1163
+ * Add example to schema
1164
+ */
1165
+ static withExample(schema, example) {
1166
+ const existingExamples = Array.isArray(schema.examples) ? schema.examples : [];
1167
+ return {
1168
+ ...schema,
1169
+ examples: [...existingExamples, example]
1170
+ };
1171
+ }
1172
+ /**
1173
+ * Add default value to schema
1174
+ */
1175
+ static withDefault(schema, defaultValue) {
1176
+ return {
1177
+ ...schema,
1178
+ default: defaultValue
1179
+ };
1180
+ }
1181
+ /**
1182
+ * Add format to schema
1183
+ */
1184
+ static withFormat(schema, format) {
1185
+ return {
1186
+ ...schema,
1187
+ format
1188
+ };
1189
+ }
1190
+ /**
1191
+ * Add pattern to schema
1192
+ */
1193
+ static withPattern(schema, pattern) {
1194
+ return {
1195
+ ...schema,
1196
+ pattern
1197
+ };
1198
+ }
1199
+ /**
1200
+ * Add enum to schema
1201
+ */
1202
+ static withEnum(schema, values) {
1203
+ return {
1204
+ ...schema,
1205
+ enum: values
1206
+ };
1207
+ }
1208
+ /**
1209
+ * Add minimum/maximum constraints
1210
+ */
1211
+ static withRange(schema, min, max, options = {}) {
1212
+ const result = { ...schema };
1213
+ if (min !== void 0) {
1214
+ if (options.exclusive) {
1215
+ result.exclusiveMinimum = min;
1216
+ } else {
1217
+ result.minimum = min;
1218
+ }
1219
+ }
1220
+ if (max !== void 0) {
1221
+ if (options.exclusive) {
1222
+ result.exclusiveMaximum = max;
1223
+ } else {
1224
+ result.maximum = max;
1225
+ }
1226
+ }
1227
+ return result;
1228
+ }
1229
+ /**
1230
+ * Add minLength/maxLength constraints
1231
+ */
1232
+ static withLength(schema, minLength, maxLength) {
1233
+ const result = { ...schema };
1234
+ if (minLength !== void 0) {
1235
+ result.minLength = minLength;
1236
+ }
1237
+ if (maxLength !== void 0) {
1238
+ result.maxLength = maxLength;
1239
+ }
1240
+ return result;
1241
+ }
1242
+ /**
1243
+ * Create object schema
1244
+ */
1245
+ static object(properties, required) {
1246
+ return {
1247
+ type: "object",
1248
+ properties,
1249
+ ...required && required.length > 0 && { required },
1250
+ additionalProperties: false
1251
+ };
1252
+ }
1253
+ /**
1254
+ * Create array schema
1255
+ */
1256
+ static array(items, constraints) {
1257
+ return {
1258
+ type: "array",
1259
+ items,
1260
+ ...constraints
1261
+ };
1262
+ }
1263
+ /**
1264
+ * Create string schema
1265
+ */
1266
+ static string(constraints) {
1267
+ return {
1268
+ type: "string",
1269
+ ...constraints
1270
+ };
1271
+ }
1272
+ /**
1273
+ * Create number schema
1274
+ */
1275
+ static number(constraints) {
1276
+ return {
1277
+ type: "number",
1278
+ ...constraints
1279
+ };
1280
+ }
1281
+ /**
1282
+ * Create integer schema
1283
+ */
1284
+ static integer(constraints) {
1285
+ return {
1286
+ type: "integer",
1287
+ ...constraints
1288
+ };
1289
+ }
1290
+ /**
1291
+ * Create boolean schema
1292
+ */
1293
+ static boolean() {
1294
+ return {
1295
+ type: "boolean"
1296
+ };
1297
+ }
1298
+ /**
1299
+ * Create null schema
1300
+ */
1301
+ static null() {
1302
+ return {
1303
+ type: "null"
1304
+ };
1305
+ }
1306
+ /**
1307
+ * Flatten nested oneOf/anyOf/allOf schemas
1308
+ */
1309
+ static flatten(schema, maxDepth = 10) {
1310
+ if (maxDepth <= 0) return schema;
1311
+ const cloned = this.clone(schema);
1312
+ if (cloned.oneOf) {
1313
+ const flattened = cloned.oneOf.flatMap((s) => {
1314
+ const sub = this.flatten(s, maxDepth - 1);
1315
+ return sub.oneOf ? sub.oneOf : [sub];
1316
+ });
1317
+ cloned.oneOf = flattened;
1318
+ }
1319
+ if (cloned.anyOf) {
1320
+ const flattened = cloned.anyOf.flatMap((s) => {
1321
+ const sub = this.flatten(s, maxDepth - 1);
1322
+ return sub.anyOf ? sub.anyOf : [sub];
1323
+ });
1324
+ cloned.anyOf = flattened;
1325
+ }
1326
+ if (cloned.allOf) {
1327
+ const flattened = cloned.allOf.flatMap((s) => {
1328
+ const sub = this.flatten(s, maxDepth - 1);
1329
+ return sub.allOf ? sub.allOf : [sub];
1330
+ });
1331
+ cloned.allOf = flattened;
1332
+ }
1333
+ return cloned;
1334
+ }
1335
+ /**
1336
+ * Simplify schema by removing unnecessary fields
1337
+ */
1338
+ static simplify(schema) {
1339
+ const cloned = this.clone(schema);
1340
+ if (Array.isArray(cloned.required) && cloned.required.length === 0) {
1341
+ delete cloned.required;
1342
+ }
1343
+ if (cloned.properties && Object.keys(cloned.properties).length === 0) {
1344
+ delete cloned.properties;
1345
+ }
1346
+ if (Array.isArray(cloned.examples) && cloned.examples.length === 0) {
1347
+ delete cloned.examples;
1348
+ }
1349
+ if (cloned.title && cloned.description && cloned.title === cloned.description) {
1350
+ delete cloned.title;
1351
+ }
1352
+ return cloned;
1353
+ }
1354
+ };
1355
+
1356
+ // libs/mcp-from-openapi/src/security-resolver.ts
1357
+ var SecurityResolver = class {
1358
+ /**
1359
+ * Resolve security parameters from mapper entries
1360
+ *
1361
+ * @param mappers - Parameter mappers from the tool definition
1362
+ * @param context - Security context with auth values or custom resolver
1363
+ * @returns Resolved headers, query params, and cookies with auth applied
1364
+ */
1365
+ async resolve(mappers, context) {
1366
+ const resolved = {
1367
+ headers: {},
1368
+ query: {},
1369
+ cookies: {}
1370
+ };
1371
+ if (context.clientCertificate) {
1372
+ resolved.clientCertificate = context.clientCertificate;
1373
+ }
1374
+ let requiresSignature = false;
1375
+ let signatureScheme;
1376
+ for (const mapper of mappers) {
1377
+ if (!mapper.security) {
1378
+ continue;
1379
+ }
1380
+ if (this.isSignatureBasedAuth(mapper.security)) {
1381
+ requiresSignature = true;
1382
+ signatureScheme = mapper.security.scheme;
1383
+ continue;
1384
+ }
1385
+ const authValue = await this.resolveAuthValue(mapper.security, context);
1386
+ if (!authValue) {
1387
+ continue;
1388
+ }
1389
+ const headerName = mapper.key;
1390
+ if (mapper.type === "header") {
1391
+ resolved.headers[headerName] = authValue;
1392
+ } else if (mapper.type === "query") {
1393
+ resolved.query[headerName] = authValue;
1394
+ } else if (mapper.type === "cookie") {
1395
+ resolved.cookies[headerName] = authValue;
1396
+ }
1397
+ }
1398
+ if (context.cookies) {
1399
+ resolved.cookies = { ...resolved.cookies, ...context.cookies };
1400
+ }
1401
+ if (requiresSignature) {
1402
+ resolved.requiresSignature = true;
1403
+ resolved.signatureInfo = {
1404
+ scheme: signatureScheme || "unknown"
1405
+ };
1406
+ }
1407
+ return resolved;
1408
+ }
1409
+ /**
1410
+ * Check if security scheme requires request signing
1411
+ */
1412
+ isSignatureBasedAuth(security) {
1413
+ const signatureSchemes = ["aws4", "hmac", "signature", "hawk", "custom-signature"];
1414
+ return signatureSchemes.some(
1415
+ (scheme) => security.scheme.toLowerCase().includes(scheme)
1416
+ );
1417
+ }
1418
+ /**
1419
+ * Resolve the actual auth value based on security type
1420
+ */
1421
+ async resolveAuthValue(security, context) {
1422
+ if (context.customResolver) {
1423
+ const customValue = await context.customResolver(security);
1424
+ if (customValue !== void 0) {
1425
+ return customValue;
1426
+ }
1427
+ }
1428
+ if (security.type === "http") {
1429
+ return this.resolveHttpAuth(security, context);
1430
+ } else if (security.type === "apiKey") {
1431
+ return this.resolveApiKey(security, context);
1432
+ } else if (security.type === "oauth2" || security.type === "openIdConnect") {
1433
+ return this.resolveOAuth2(security, context);
1434
+ }
1435
+ return void 0;
1436
+ }
1437
+ /**
1438
+ * Resolve HTTP authentication (bearer, basic, digest, etc.)
1439
+ */
1440
+ resolveHttpAuth(security, context) {
1441
+ const scheme = security.httpScheme?.toLowerCase() || "bearer";
1442
+ switch (scheme) {
1443
+ case "bearer":
1444
+ return this.resolveBearerAuth(context);
1445
+ case "basic":
1446
+ return this.resolveBasicAuth(context);
1447
+ case "digest":
1448
+ return this.resolveDigestAuth(context);
1449
+ case "hoba":
1450
+ case "mutual":
1451
+ case "negotiate":
1452
+ case "vapid":
1453
+ case "scram":
1454
+ return this.resolveCustomHttpScheme(scheme, security, context);
1455
+ default:
1456
+ return void 0;
1457
+ }
1458
+ }
1459
+ /**
1460
+ * Resolve Bearer token authentication
1461
+ */
1462
+ resolveBearerAuth(context) {
1463
+ const token = context.jwt;
1464
+ if (!token) return void 0;
1465
+ return `Bearer ${token}`;
1466
+ }
1467
+ /**
1468
+ * Resolve Basic authentication
1469
+ */
1470
+ resolveBasicAuth(context) {
1471
+ const credentials = context.basic;
1472
+ if (!credentials) return void 0;
1473
+ return `Basic ${credentials}`;
1474
+ }
1475
+ /**
1476
+ * Resolve Digest authentication
1477
+ */
1478
+ resolveDigestAuth(context) {
1479
+ const digest = context.digest;
1480
+ if (!digest) return void 0;
1481
+ const parts = [
1482
+ `username="${digest.username}"`,
1483
+ digest.realm ? `realm="${digest.realm}"` : "",
1484
+ digest.nonce ? `nonce="${digest.nonce}"` : "",
1485
+ digest.uri ? `uri="${digest.uri}"` : "",
1486
+ digest.response ? `response="${digest.response}"` : "",
1487
+ digest.opaque ? `opaque="${digest.opaque}"` : "",
1488
+ digest.qop ? `qop=${digest.qop}` : "",
1489
+ digest.nc ? `nc=${digest.nc}` : "",
1490
+ digest.cnonce ? `cnonce="${digest.cnonce}"` : ""
1491
+ ].filter(Boolean);
1492
+ return `Digest ${parts.join(", ")}`;
1493
+ }
1494
+ /**
1495
+ * Resolve custom HTTP authentication schemes
1496
+ */
1497
+ resolveCustomHttpScheme(scheme, security, context) {
1498
+ const headerKey = security.apiKeyName || `X-${scheme.toUpperCase()}`;
1499
+ if (context.customHeaders?.[headerKey]) {
1500
+ return context.customHeaders[headerKey];
1501
+ }
1502
+ return void 0;
1503
+ }
1504
+ /**
1505
+ * Resolve API key authentication
1506
+ */
1507
+ resolveApiKey(security, context) {
1508
+ if (context.apiKeys && security.apiKeyName) {
1509
+ const key = context.apiKeys[security.apiKeyName];
1510
+ if (key) return key;
1511
+ }
1512
+ if (context.customHeaders && security.apiKeyName) {
1513
+ const header = context.customHeaders[security.apiKeyName];
1514
+ if (header) return header;
1515
+ }
1516
+ return context.apiKey;
1517
+ }
1518
+ /**
1519
+ * Resolve OAuth2/OpenID Connect authentication
1520
+ */
1521
+ resolveOAuth2(security, context) {
1522
+ const token = context.oauth2Token;
1523
+ if (!token) return void 0;
1524
+ return `Bearer ${token}`;
1525
+ }
1526
+ /**
1527
+ * Check if any security requirements are missing from context
1528
+ *
1529
+ * @param mappers - Parameter mappers from the tool definition
1530
+ * @param context - Security context with auth values
1531
+ * @returns Array of missing security scheme names
1532
+ */
1533
+ async checkMissingSecurity(mappers, context) {
1534
+ const missing = [];
1535
+ for (const mapper of mappers) {
1536
+ if (!mapper.security) continue;
1537
+ const authValue = await this.resolveAuthValue(mapper.security, context);
1538
+ if (!authValue) {
1539
+ missing.push(mapper.security.scheme);
1540
+ }
1541
+ }
1542
+ return missing;
1543
+ }
1544
+ /**
1545
+ * Sign a request for signature-based authentication
1546
+ *
1547
+ * Use this when resolved.requiresSignature is true.
1548
+ * This method will call the signatureGenerator from context to sign the request.
1549
+ *
1550
+ * @param mappers - Parameter mappers from the tool definition
1551
+ * @param signatureData - Request data to sign
1552
+ * @param context - Security context with signature generator
1553
+ * @returns Headers with signature added
1554
+ *
1555
+ * @example
1556
+ * ```typescript
1557
+ * const resolved = resolver.resolve(tool.mapper, context);
1558
+ * if (resolved.requiresSignature) {
1559
+ * const signedHeaders = await resolver.signRequest(
1560
+ * tool.mapper,
1561
+ * { method: 'GET', url: 'https://api.example.com/data', headers: resolved.headers },
1562
+ * context
1563
+ * );
1564
+ * // Use signedHeaders in request
1565
+ * }
1566
+ * ```
1567
+ */
1568
+ async signRequest(mappers, signatureData, context) {
1569
+ const headers = { ...signatureData.headers };
1570
+ if (!context.signatureGenerator) {
1571
+ throw new Error("Signature-based auth required but no signatureGenerator provided");
1572
+ }
1573
+ for (const mapper of mappers) {
1574
+ if (!mapper.security || !this.isSignatureBasedAuth(mapper.security)) {
1575
+ continue;
1576
+ }
1577
+ const signature = await context.signatureGenerator(signatureData, mapper.security);
1578
+ if (mapper.type === "header") {
1579
+ headers[mapper.key] = signature;
1580
+ }
1581
+ }
1582
+ return headers;
1583
+ }
1584
+ };
1585
+ function createSecurityContext(auth) {
1586
+ return {
1587
+ ...auth,
1588
+ jwt: auth.jwt,
1589
+ basic: auth.basic,
1590
+ apiKey: auth.apiKey,
1591
+ oauth2Token: auth.oauth2Token,
1592
+ customResolver: auth.customResolver
1593
+ };
1594
+ }
1595
+ // Annotate the CommonJS export names for ESM import in node:
1596
+ 0 && (module.exports = {
1597
+ GenerationError,
1598
+ LoadError,
1599
+ OpenAPIToolError,
1600
+ OpenAPIToolGenerator,
1601
+ ParameterResolver,
1602
+ ParseError,
1603
+ ResponseBuilder,
1604
+ SchemaBuilder,
1605
+ SchemaError,
1606
+ SecurityResolver,
1607
+ ValidationError,
1608
+ Validator,
1609
+ createSecurityContext,
1610
+ isReferenceObject,
1611
+ toJsonSchema
1612
+ });