mcp-from-openapi 2.1.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -27,9 +27,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // libs/mcp-from-openapi/src/index.ts
30
+ // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ BUILTIN_FORMAT_RESOLVERS: () => BUILTIN_FORMAT_RESOLVERS,
33
34
  GenerationError: () => GenerationError,
34
35
  LoadError: () => LoadError,
35
36
  OpenAPIToolError: () => OpenAPIToolError,
@@ -44,17 +45,17 @@ __export(index_exports, {
44
45
  Validator: () => Validator,
45
46
  createSecurityContext: () => createSecurityContext,
46
47
  isReferenceObject: () => isReferenceObject,
48
+ resolveSchemaFormats: () => resolveSchemaFormats,
47
49
  toJsonSchema: () => toJsonSchema
48
50
  });
49
51
  module.exports = __toCommonJS(index_exports);
50
52
 
51
- // libs/mcp-from-openapi/src/generator.ts
53
+ // src/generator.ts
52
54
  var yaml = __toESM(require("yaml"));
53
- var fs = __toESM(require("fs/promises"));
54
55
  var path = __toESM(require("path"));
55
- var import_json_schema_ref_parser = __toESM(require("@apidevtools/json-schema-ref-parser"));
56
+ var fs = __toESM(require("fs/promises"));
56
57
 
57
- // libs/mcp-from-openapi/src/types.ts
58
+ // src/types.ts
58
59
  function isReferenceObject(obj) {
59
60
  return obj && typeof obj === "object" && "$ref" in obj;
60
61
  }
@@ -120,7 +121,7 @@ function toJsonSchema(schema) {
120
121
  return result;
121
122
  }
122
123
 
123
- // libs/mcp-from-openapi/src/parameter-resolver.ts
124
+ // src/parameter-resolver.ts
124
125
  var ParameterResolver = class {
125
126
  namingStrategy;
126
127
  constructor(namingStrategy) {
@@ -385,7 +386,7 @@ var ParameterResolver = class {
385
386
  }
386
387
  };
387
388
 
388
- // libs/mcp-from-openapi/src/response-builder.ts
389
+ // src/response-builder.ts
389
390
  var ResponseBuilder = class {
390
391
  preferredStatusCodes;
391
392
  includeAllResponses;
@@ -505,7 +506,7 @@ var ResponseBuilder = class {
505
506
  }
506
507
  };
507
508
 
508
- // libs/mcp-from-openapi/src/validator.ts
509
+ // src/validator.ts
509
510
  var Validator = class {
510
511
  /**
511
512
  * Validate an OpenAPI document
@@ -696,7 +697,7 @@ var Validator = class {
696
697
  }
697
698
  };
698
699
 
699
- // libs/mcp-from-openapi/src/errors.ts
700
+ // src/errors.ts
700
701
  var OpenAPIToolError = class extends Error {
701
702
  context;
702
703
  constructor(message, context) {
@@ -736,7 +737,116 @@ var SchemaError = class extends OpenAPIToolError {
736
737
  }
737
738
  };
738
739
 
739
- // libs/mcp-from-openapi/src/generator.ts
740
+ // src/format-resolver.ts
741
+ var BUILTIN_FORMAT_RESOLVERS = {
742
+ // String formats
743
+ uuid: (schema) => ({
744
+ ...schema,
745
+ pattern: schema.pattern ?? "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
746
+ description: schema.description || "UUID string (RFC 4122)"
747
+ }),
748
+ "date-time": (schema) => ({
749
+ ...schema,
750
+ description: schema.description || "ISO 8601 date-time (e.g., 2024-01-15T09:30:00Z)"
751
+ }),
752
+ date: (schema) => ({
753
+ ...schema,
754
+ pattern: schema.pattern ?? "^\\d{4}-\\d{2}-\\d{2}$",
755
+ description: schema.description || "ISO 8601 date (e.g., 2024-01-15)"
756
+ }),
757
+ time: (schema) => ({
758
+ ...schema,
759
+ pattern: schema.pattern ?? "^\\d{2}:\\d{2}:\\d{2}",
760
+ description: schema.description || "ISO 8601 time (e.g., 09:30:00)"
761
+ }),
762
+ email: (schema) => ({
763
+ ...schema,
764
+ description: schema.description || "Email address (RFC 5322)"
765
+ }),
766
+ uri: (schema) => ({
767
+ ...schema,
768
+ description: schema.description || "URI (RFC 3986)"
769
+ }),
770
+ "uri-reference": (schema) => ({
771
+ ...schema,
772
+ description: schema.description || "URI reference (RFC 3986)"
773
+ }),
774
+ hostname: (schema) => ({
775
+ ...schema,
776
+ description: schema.description || "Internet hostname (RFC 1123)"
777
+ }),
778
+ ipv4: (schema) => ({
779
+ ...schema,
780
+ pattern: schema.pattern ?? "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$",
781
+ description: schema.description || "IPv4 address"
782
+ }),
783
+ ipv6: (schema) => ({
784
+ ...schema,
785
+ description: schema.description || "IPv6 address (RFC 4291)"
786
+ }),
787
+ // Integer formats
788
+ int32: (schema) => ({
789
+ ...schema,
790
+ minimum: schema.minimum ?? -2147483648,
791
+ maximum: schema.maximum ?? 2147483647
792
+ }),
793
+ int64: (schema) => ({
794
+ ...schema,
795
+ minimum: schema.minimum ?? Number.MIN_SAFE_INTEGER,
796
+ maximum: schema.maximum ?? Number.MAX_SAFE_INTEGER
797
+ }),
798
+ // Binary/encoding formats
799
+ byte: (schema) => ({
800
+ ...schema,
801
+ pattern: schema.pattern ?? "^[A-Za-z0-9+/]*={0,2}$",
802
+ description: schema.description || "Base64-encoded string (RFC 4648)"
803
+ }),
804
+ binary: (schema) => ({
805
+ ...schema,
806
+ description: schema.description || "Binary data"
807
+ }),
808
+ // Sensitive data formats
809
+ password: (schema) => ({
810
+ ...schema,
811
+ description: schema.description || "Password (sensitive, UI should mask input)"
812
+ })
813
+ };
814
+ function resolveSchemaFormats(schema, resolvers) {
815
+ if (!schema || typeof schema !== "object") return schema;
816
+ let result = { ...schema };
817
+ const format = result["format"];
818
+ if (format && resolvers[format]) {
819
+ result = { ...resolvers[format](result) };
820
+ }
821
+ if (result["properties"] && typeof result["properties"] === "object") {
822
+ const props = {};
823
+ for (const [key, value] of Object.entries(result["properties"])) {
824
+ props[key] = resolveSchemaFormats(value, resolvers);
825
+ }
826
+ result["properties"] = props;
827
+ }
828
+ if (result["items"]) {
829
+ if (Array.isArray(result["items"])) {
830
+ result["items"] = result["items"].map((item) => resolveSchemaFormats(item, resolvers));
831
+ } else {
832
+ result["items"] = resolveSchemaFormats(result["items"], resolvers);
833
+ }
834
+ }
835
+ if (result["additionalProperties"] && typeof result["additionalProperties"] === "object") {
836
+ result["additionalProperties"] = resolveSchemaFormats(result["additionalProperties"], resolvers);
837
+ }
838
+ for (const key of ["allOf", "anyOf", "oneOf"]) {
839
+ if (result[key] && Array.isArray(result[key])) {
840
+ result[key] = result[key].map((s) => resolveSchemaFormats(s, resolvers));
841
+ }
842
+ }
843
+ if (result["not"] && typeof result["not"] === "object") {
844
+ result["not"] = resolveSchemaFormats(result["not"], resolvers);
845
+ }
846
+ return result;
847
+ }
848
+
849
+ // src/generator.ts
740
850
  var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
741
851
  document;
742
852
  dereferencedDocument;
@@ -752,7 +862,8 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
752
862
  headers: options.headers ?? {},
753
863
  timeout: options.timeout ?? 3e4,
754
864
  validate: options.validate ?? true,
755
- followRedirects: options.followRedirects ?? true
865
+ followRedirects: options.followRedirects ?? true,
866
+ refResolution: options.refResolution ?? {}
756
867
  };
757
868
  }
758
869
  /**
@@ -858,19 +969,116 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
858
969
  return validator.validate(this.document);
859
970
  }
860
971
  /**
861
- * Initialize the generator (dereference if needed)
972
+ * Hostnames and IP patterns that are blocked by default to prevent SSRF.
973
+ * Covers RFC 1918/6598 private ranges, link-local, loopback, and cloud metadata endpoints.
862
974
  */
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 });
975
+ static BLOCKED_HOSTNAME_PATTERNS = [
976
+ "localhost",
977
+ "metadata.google.internal",
978
+ /^127\.\d+\.\d+\.\d+$/,
979
+ // 127.0.0.0/8 loopback
980
+ /^10\.\d+\.\d+\.\d+$/,
981
+ // 10.0.0.0/8 private
982
+ /^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/,
983
+ // 172.16.0.0/12 private
984
+ /^192\.168\.\d+\.\d+$/,
985
+ // 192.168.0.0/16 private
986
+ /^169\.254\.\d+\.\d+$/,
987
+ // 169.254.0.0/16 link-local / cloud metadata
988
+ /^0\.0\.0\.0$/,
989
+ // unspecified
990
+ "::1",
991
+ // IPv6 loopback
992
+ /^fd[0-9a-f]{2}:/i,
993
+ // fd00::/8 IPv6 ULA
994
+ /^fe80:/i,
995
+ // fe80::/10 IPv6 link-local
996
+ /^\[::1\]$/,
997
+ // bracketed IPv6 loopback
998
+ /^\[fd[0-9a-f]{2}:/i,
999
+ // bracketed IPv6 ULA
1000
+ /^\[fe80:/i
1001
+ // bracketed IPv6 link-local
1002
+ ];
1003
+ /**
1004
+ * Check whether a hostname is blocked (internal/private IP or explicit blocklist).
1005
+ */
1006
+ isBlockedHost(hostname, refOpts) {
1007
+ if (refOpts.allowInternalIPs) {
1008
+ return refOpts.blockedHosts.includes(hostname);
1009
+ }
1010
+ if (refOpts.blockedHosts.includes(hostname)) {
1011
+ return true;
1012
+ }
1013
+ for (const pattern of _OpenAPIToolGenerator.BLOCKED_HOSTNAME_PATTERNS) {
1014
+ if (typeof pattern === "string") {
1015
+ if (hostname === pattern) return true;
1016
+ } else {
1017
+ if (pattern.test(hostname)) return true;
868
1018
  }
869
1019
  }
1020
+ return false;
1021
+ }
1022
+ /**
1023
+ * Build $RefParser options based on refResolution configuration.
1024
+ * Defaults: allow http/https, block file://, block internal IPs.
1025
+ */
1026
+ buildRefParserOptions() {
1027
+ const raw = this.options.refResolution;
1028
+ const refOpts = {
1029
+ allowedProtocols: raw.allowedProtocols ?? ["http", "https"],
1030
+ allowedHosts: raw.allowedHosts ?? [],
1031
+ blockedHosts: raw.blockedHosts ?? [],
1032
+ allowInternalIPs: raw.allowInternalIPs ?? false
1033
+ };
1034
+ const allowedProtocols = new Set(refOpts.allowedProtocols);
1035
+ const hasNetworkProtocol = allowedProtocols.size > 0 && !([...allowedProtocols].length === 1 && allowedProtocols.has("file"));
1036
+ if (allowedProtocols.size === 0) {
1037
+ return { resolve: { external: false } };
1038
+ }
1039
+ const resolveConfig = {
1040
+ external: true,
1041
+ file: allowedProtocols.has("file") ? void 0 : false
1042
+ };
1043
+ if (hasNetworkProtocol) {
1044
+ const hasHostAllowlist = refOpts.allowedHosts.length > 0;
1045
+ const hostAllowSet = new Set(refOpts.allowedHosts);
1046
+ resolveConfig["http"] = {
1047
+ canRead: (file) => {
1048
+ try {
1049
+ const parsed = new URL(file.url);
1050
+ const protocol = parsed.protocol.replace(":", "");
1051
+ if (!allowedProtocols.has(protocol)) {
1052
+ return false;
1053
+ }
1054
+ if (hasHostAllowlist && !hostAllowSet.has(parsed.hostname)) {
1055
+ return false;
1056
+ }
1057
+ if (this.isBlockedHost(parsed.hostname, refOpts)) {
1058
+ return false;
1059
+ }
1060
+ return true;
1061
+ } catch {
1062
+ return false;
1063
+ }
1064
+ }
1065
+ };
1066
+ } else {
1067
+ resolveConfig["http"] = false;
1068
+ }
1069
+ return { resolve: resolveConfig };
1070
+ }
1071
+ /**
1072
+ * Initialize the generator (dereference if needed, then validate)
1073
+ */
1074
+ async initialize() {
870
1075
  if (this.options.dereference && !this.dereferencedDocument) {
871
1076
  try {
872
- this.dereferencedDocument = await import_json_schema_ref_parser.default.dereference(
873
- JSON.parse(JSON.stringify(this.document))
1077
+ const { default: $RefParser } = await import("@apidevtools/json-schema-ref-parser");
1078
+ const refParserOptions = this.buildRefParserOptions();
1079
+ this.dereferencedDocument = await $RefParser.dereference(
1080
+ JSON.parse(JSON.stringify(this.document)),
1081
+ refParserOptions
874
1082
  );
875
1083
  } catch (error) {
876
1084
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -879,6 +1087,14 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
879
1087
  });
880
1088
  }
881
1089
  }
1090
+ if (this.options.validate) {
1091
+ const validator = new Validator();
1092
+ const documentToValidate = this.dereferencedDocument ?? this.document;
1093
+ const result = await validator.validate(documentToValidate);
1094
+ if (!result.valid) {
1095
+ throw new ParseError("Invalid OpenAPI document", { errors: result.errors });
1096
+ }
1097
+ }
882
1098
  }
883
1099
  /**
884
1100
  * Generate all tools from the OpenAPI specification
@@ -947,11 +1163,18 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
947
1163
  const name = this.generateToolName(pathStr, method, operation.operationId, options);
948
1164
  const description = operation.summary || operation.description || `${method.toUpperCase()} ${pathStr}`;
949
1165
  const metadata = this.extractMetadata(pathStr, method, operation, document, outputSchema);
1166
+ const formatResolvers = {
1167
+ ...options.resolveFormats ? BUILTIN_FORMAT_RESOLVERS : {},
1168
+ ...options.formatResolvers
1169
+ };
1170
+ const hasFormatResolvers = Object.keys(formatResolvers).length > 0;
1171
+ const resolvedInputSchema = hasFormatResolvers ? resolveSchemaFormats(inputSchema, formatResolvers) : inputSchema;
1172
+ const resolvedOutputSchema = hasFormatResolvers && outputSchema ? resolveSchemaFormats(outputSchema, formatResolvers) : outputSchema;
950
1173
  return {
951
1174
  name,
952
1175
  description,
953
- inputSchema,
954
- outputSchema,
1176
+ inputSchema: resolvedInputSchema,
1177
+ outputSchema: resolvedOutputSchema,
955
1178
  mapper,
956
1179
  metadata
957
1180
  };
@@ -1074,7 +1297,7 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
1074
1297
  }
1075
1298
  };
1076
1299
 
1077
- // libs/mcp-from-openapi/src/schema-builder.ts
1300
+ // src/schema-builder.ts
1078
1301
  var SchemaBuilder = class {
1079
1302
  /**
1080
1303
  * Merge multiple schemas into one
@@ -1353,7 +1576,7 @@ var SchemaBuilder = class {
1353
1576
  }
1354
1577
  };
1355
1578
 
1356
- // libs/mcp-from-openapi/src/security-resolver.ts
1579
+ // src/security-resolver.ts
1357
1580
  var SecurityResolver = class {
1358
1581
  /**
1359
1582
  * Resolve security parameters from mapper entries
@@ -1401,6 +1624,7 @@ var SecurityResolver = class {
1401
1624
  if (requiresSignature) {
1402
1625
  resolved.requiresSignature = true;
1403
1626
  resolved.signatureInfo = {
1627
+ /* c8 ignore next -- signatureScheme is always set from security.scheme */
1404
1628
  scheme: signatureScheme || "unknown"
1405
1629
  };
1406
1630
  }
@@ -1446,6 +1670,7 @@ var SecurityResolver = class {
1446
1670
  return this.resolveBasicAuth(context);
1447
1671
  case "digest":
1448
1672
  return this.resolveDigestAuth(context);
1673
+ /* c8 ignore next -- hoba is part of the same fall-through as mutual/negotiate/vapid/scram */
1449
1674
  case "hoba":
1450
1675
  case "mutual":
1451
1676
  case "negotiate":
@@ -1594,6 +1819,7 @@ function createSecurityContext(auth) {
1594
1819
  }
1595
1820
  // Annotate the CommonJS export names for ESM import in node:
1596
1821
  0 && (module.exports = {
1822
+ BUILTIN_FORMAT_RESOLVERS,
1597
1823
  GenerationError,
1598
1824
  LoadError,
1599
1825
  OpenAPIToolError,
@@ -1608,5 +1834,6 @@ function createSecurityContext(auth) {
1608
1834
  Validator,
1609
1835
  createSecurityContext,
1610
1836
  isReferenceObject,
1837
+ resolveSchemaFormats,
1611
1838
  toJsonSchema
1612
1839
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-from-openapi",
3
- "version": "2.1.2",
3
+ "version": "2.3.0",
4
4
  "description": "Production-ready library for converting OpenAPI specifications into MCP tool definitions",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -20,15 +20,14 @@
20
20
  ],
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "git+https://github.com/agentfront/frontmcp.git",
24
- "directory": "libs/mcp-from-openapi"
23
+ "url": "git+https://github.com/agentfront/mcp-from-openapi.git"
25
24
  },
26
25
  "bugs": {
27
- "url": "https://github.com/agentfront/frontmcp/issues"
26
+ "url": "https://github.com/agentfront/mcp-from-openapi/issues"
28
27
  },
29
- "homepage": "https://github.com/agentfront/frontmcp/blob/main/libs/mcp-from-openapi/README.md",
28
+ "homepage": "https://github.com/agentfront/mcp-from-openapi#readme",
30
29
  "engines": {
31
- "node": ">=18.0.0"
30
+ "node": ">=20.0.0"
32
31
  },
33
32
  "type": "commonjs",
34
33
  "main": "./index.js",
@@ -46,19 +45,26 @@
46
45
  "types": "./index.d.ts",
47
46
  "default": "./esm/index.mjs"
48
47
  }
49
- },
50
- "./esm": null
48
+ }
51
49
  },
52
50
  "dependencies": {
53
- "@apidevtools/json-schema-ref-parser": "^11.9.3",
51
+ "@apidevtools/json-schema-ref-parser": "^15.3.5",
54
52
  "openapi-types": "^12.1.3",
55
- "yaml": "^2.8.1"
53
+ "yaml": "^2.8.3"
56
54
  },
57
55
  "peerDependencies": {
58
56
  "zod": "^4.0.0"
59
57
  },
60
58
  "devDependencies": {
59
+ "@swc/core": "~1.5.7",
60
+ "@swc/helpers": "^0.5.18",
61
+ "@swc/jest": "~0.2.38",
62
+ "@types/jest": "^29.5.0",
63
+ "@types/json-schema": "^7.0.15",
61
64
  "@types/node": "^24.0.0",
65
+ "esbuild": "^0.27.2",
66
+ "jest": "^29.7.0",
67
+ "tslib": "^2.8.1",
62
68
  "typescript": "^5.0.0",
63
69
  "zod": "^4.0.0"
64
70
  }
package/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { JSONSchema } from 'zod/v4/core';
2
2
  /** JSON Schema type from Zod v4 */
3
- type JsonSchema = JSONSchema.JSONSchema;
3
+ export type JsonSchema = JSONSchema.JSONSchema;
4
4
  import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
5
5
  /**
6
6
  * OpenAPI specification version 3.0.x or 3.1.x
@@ -326,6 +326,37 @@ export interface ServerInfo {
326
326
  */
327
327
  variables?: Record<string, ServerVariableObject>;
328
328
  }
329
+ /**
330
+ * Controls how external $ref pointers are resolved during dereferencing.
331
+ * By default, only http/https protocols are allowed and internal/private
332
+ * IP addresses are blocked to prevent SSRF attacks.
333
+ */
334
+ export interface RefResolutionOptions {
335
+ /**
336
+ * Protocols allowed for external $ref resolution.
337
+ * Any protocol string is accepted (http, https, ftp, ws, wss, etc.).
338
+ * @default ['http', 'https']
339
+ */
340
+ allowedProtocols?: string[];
341
+ /**
342
+ * Hostnames allowed for external $ref resolution (network protocols only).
343
+ * When set, only refs pointing to these hosts are resolved.
344
+ * When not set, all hosts are allowed except blocked internal ranges.
345
+ */
346
+ allowedHosts?: string[];
347
+ /**
348
+ * Additional hostnames/IPs to block. Applied on top of the built-in
349
+ * internal IP block list (localhost, 169.254.x.x, 10.x.x.x, etc.).
350
+ */
351
+ blockedHosts?: string[];
352
+ /**
353
+ * Disable the built-in internal/private IP block list.
354
+ * WARNING: Enabling this may expose your application to SSRF attacks
355
+ * against cloud metadata endpoints and internal services.
356
+ * @default false
357
+ */
358
+ allowInternalIPs?: boolean;
359
+ }
329
360
  /**
330
361
  * Options for loading OpenAPI specifications
331
362
  */
@@ -359,6 +390,12 @@ export interface LoadOptions {
359
390
  * @default true
360
391
  */
361
392
  followRedirects?: boolean;
393
+ /**
394
+ * Controls external $ref resolution security.
395
+ * By default, file:// is blocked and internal IPs are blocked.
396
+ * @see RefResolutionOptions
397
+ */
398
+ refResolution?: RefResolutionOptions;
362
399
  }
363
400
  /**
364
401
  * Operation object with additional context for filtering
@@ -420,7 +457,28 @@ export interface GenerateOptions {
420
457
  * @default false
421
458
  */
422
459
  includeSecurityInInput?: boolean;
460
+ /**
461
+ * Enable built-in format-to-schema resolution.
462
+ * Enriches schemas with concrete constraints (patterns, descriptions, min/max)
463
+ * based on OpenAPI format values (uuid, date-time, email, int32, etc.).
464
+ * @default false
465
+ */
466
+ resolveFormats?: boolean;
467
+ /**
468
+ * Custom format resolvers. Keys are format names, values are functions
469
+ * that receive the original schema and return an enriched schema.
470
+ *
471
+ * When used with `resolveFormats: true`, custom resolvers are merged with
472
+ * built-in resolvers (custom takes precedence for the same format).
473
+ * When used without `resolveFormats`, only custom resolvers are applied.
474
+ */
475
+ formatResolvers?: Record<string, FormatResolver>;
423
476
  }
477
+ /**
478
+ * A function that enriches a JSON Schema based on its format field.
479
+ * Receives the schema and returns a new schema with additional constraints.
480
+ */
481
+ export type FormatResolver = (schema: JsonSchema) => JsonSchema;
424
482
  /**
425
483
  * Naming strategy for resolving parameter conflicts
426
484
  */
@@ -493,4 +551,3 @@ export interface ValidationWarning {
493
551
  */
494
552
  code?: string;
495
553
  }
496
- export {};
package/CHANGELOG.md DELETED
@@ -1,81 +0,0 @@
1
- ## [2.1.2] - 2025-12-27
2
-
3
- ### Changed
4
-
5
- - Added `publish-alpha` Nx target to enable alpha publishing flow using common script.
6
-
7
- ## [2.1.1] - 2025-12-24
8
-
9
- ### Fixed
10
-
11
- - Revised build setup to emit CJS and ESM bundles with corrected export map and sideEffects flag to improve tree shaking.
12
- - Synced package entry points and type outputs with the new build artifacts while preserving the public API surface.
13
-
14
- ## [2.1.0] - 2025-12-19
15
-
16
- ### Added
17
-
18
- - Introduced logger support within the OpenAPI adapter to improve observability.
19
- - Expanded security handling with automatic auth type routing and enhanced documentation.
20
-
21
- ### Changed
22
-
23
- - Refined security resolver examples and guidance for broader authentication scheme coverage.
24
-
25
- ## [2.0.0] - 2025-12-11
26
-
27
- ### Breaking
28
-
29
- - Migrated to Zod v4 (now a peer dependency) and aligned JSON schema types with Zod’s v4 JSONSchema
30
- - Renamed utility export `toJSONSchema7` to `toJsonSchema`, affecting consumers of the types/helpers
31
-
32
- ### Changed
33
-
34
- - Updated SWC/Jest config to inline ES2022 settings and modernized tooling versions
35
- - Adjusted exports formatting and minor parameter resolver refactors for consistency
36
-
37
- # Changelog
38
-
39
- ## [1.0.0] - 2025-11-21
40
-
41
- ### Features
42
-
43
- - Production-ready library for converting OpenAPI specifications into MCP tool definitions
44
- - OpenAPI 3.0+ and Swagger 2.0 support
45
- - Comprehensive operation parsing:
46
- - RESTful endpoint detection (GET, POST, PUT, PATCH, DELETE, etc.)
47
- - Path parameter extraction and validation
48
- - Query parameter handling
49
- - Request body schema conversion
50
- - Response schema parsing
51
- - Advanced OpenAPI features:
52
- - Reference resolution ($ref) across the entire specification
53
- - Security scheme detection and configuration
54
- - Parameter conflict resolution
55
- - Operation naming controls and customization
56
- - Request mapper generation:
57
- - Automatic parameter mapping from MCP tool inputs to HTTP requests
58
- - Type-safe parameter handling
59
- - Support for different parameter locations (path, query, header, cookie)
60
- - Request body transformation
61
- - Tool metadata generation:
62
- - Descriptive tool names from operation IDs
63
- - Documentation from OpenAPI descriptions
64
- - Schema validation rules
65
- - Multiple input formats:
66
- - JSON OpenAPI specifications
67
- - YAML OpenAPI specifications
68
- - Inline specification objects
69
- - URL references to remote specifications
70
- - Type-safe TypeScript implementation
71
- - Node.js 18+ compatibility
72
-
73
- ### Documentation
74
-
75
- - Complete API reference
76
- - OpenAPI conversion examples
77
- - Integration guides for MCP servers
78
- - Best practices for tool generation
79
-
80
- This is the first official release of `mcp-from-openapi`, extracted from the FrontMCP framework to be published as a
81
- standalone, reusable library for the community.