mcp-from-openapi 2.2.0 → 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/esm/index.mjs CHANGED
@@ -2,7 +2,6 @@
2
2
  import * as yaml from "yaml";
3
3
  import * as path from "path";
4
4
  import * as fs from "fs/promises";
5
- import $RefParser from "@apidevtools/json-schema-ref-parser";
6
5
 
7
6
  // src/types.ts
8
7
  function isReferenceObject(obj) {
@@ -686,6 +685,115 @@ var SchemaError = class extends OpenAPIToolError {
686
685
  }
687
686
  };
688
687
 
688
+ // src/format-resolver.ts
689
+ var BUILTIN_FORMAT_RESOLVERS = {
690
+ // String formats
691
+ uuid: (schema) => ({
692
+ ...schema,
693
+ 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}$",
694
+ description: schema.description || "UUID string (RFC 4122)"
695
+ }),
696
+ "date-time": (schema) => ({
697
+ ...schema,
698
+ description: schema.description || "ISO 8601 date-time (e.g., 2024-01-15T09:30:00Z)"
699
+ }),
700
+ date: (schema) => ({
701
+ ...schema,
702
+ pattern: schema.pattern ?? "^\\d{4}-\\d{2}-\\d{2}$",
703
+ description: schema.description || "ISO 8601 date (e.g., 2024-01-15)"
704
+ }),
705
+ time: (schema) => ({
706
+ ...schema,
707
+ pattern: schema.pattern ?? "^\\d{2}:\\d{2}:\\d{2}",
708
+ description: schema.description || "ISO 8601 time (e.g., 09:30:00)"
709
+ }),
710
+ email: (schema) => ({
711
+ ...schema,
712
+ description: schema.description || "Email address (RFC 5322)"
713
+ }),
714
+ uri: (schema) => ({
715
+ ...schema,
716
+ description: schema.description || "URI (RFC 3986)"
717
+ }),
718
+ "uri-reference": (schema) => ({
719
+ ...schema,
720
+ description: schema.description || "URI reference (RFC 3986)"
721
+ }),
722
+ hostname: (schema) => ({
723
+ ...schema,
724
+ description: schema.description || "Internet hostname (RFC 1123)"
725
+ }),
726
+ ipv4: (schema) => ({
727
+ ...schema,
728
+ pattern: schema.pattern ?? "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$",
729
+ description: schema.description || "IPv4 address"
730
+ }),
731
+ ipv6: (schema) => ({
732
+ ...schema,
733
+ description: schema.description || "IPv6 address (RFC 4291)"
734
+ }),
735
+ // Integer formats
736
+ int32: (schema) => ({
737
+ ...schema,
738
+ minimum: schema.minimum ?? -2147483648,
739
+ maximum: schema.maximum ?? 2147483647
740
+ }),
741
+ int64: (schema) => ({
742
+ ...schema,
743
+ minimum: schema.minimum ?? Number.MIN_SAFE_INTEGER,
744
+ maximum: schema.maximum ?? Number.MAX_SAFE_INTEGER
745
+ }),
746
+ // Binary/encoding formats
747
+ byte: (schema) => ({
748
+ ...schema,
749
+ pattern: schema.pattern ?? "^[A-Za-z0-9+/]*={0,2}$",
750
+ description: schema.description || "Base64-encoded string (RFC 4648)"
751
+ }),
752
+ binary: (schema) => ({
753
+ ...schema,
754
+ description: schema.description || "Binary data"
755
+ }),
756
+ // Sensitive data formats
757
+ password: (schema) => ({
758
+ ...schema,
759
+ description: schema.description || "Password (sensitive, UI should mask input)"
760
+ })
761
+ };
762
+ function resolveSchemaFormats(schema, resolvers) {
763
+ if (!schema || typeof schema !== "object") return schema;
764
+ let result = { ...schema };
765
+ const format = result["format"];
766
+ if (format && resolvers[format]) {
767
+ result = { ...resolvers[format](result) };
768
+ }
769
+ if (result["properties"] && typeof result["properties"] === "object") {
770
+ const props = {};
771
+ for (const [key, value] of Object.entries(result["properties"])) {
772
+ props[key] = resolveSchemaFormats(value, resolvers);
773
+ }
774
+ result["properties"] = props;
775
+ }
776
+ if (result["items"]) {
777
+ if (Array.isArray(result["items"])) {
778
+ result["items"] = result["items"].map((item) => resolveSchemaFormats(item, resolvers));
779
+ } else {
780
+ result["items"] = resolveSchemaFormats(result["items"], resolvers);
781
+ }
782
+ }
783
+ if (result["additionalProperties"] && typeof result["additionalProperties"] === "object") {
784
+ result["additionalProperties"] = resolveSchemaFormats(result["additionalProperties"], resolvers);
785
+ }
786
+ for (const key of ["allOf", "anyOf", "oneOf"]) {
787
+ if (result[key] && Array.isArray(result[key])) {
788
+ result[key] = result[key].map((s) => resolveSchemaFormats(s, resolvers));
789
+ }
790
+ }
791
+ if (result["not"] && typeof result["not"] === "object") {
792
+ result["not"] = resolveSchemaFormats(result["not"], resolvers);
793
+ }
794
+ return result;
795
+ }
796
+
689
797
  // src/generator.ts
690
798
  var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
691
799
  document;
@@ -909,17 +1017,12 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
909
1017
  return { resolve: resolveConfig };
910
1018
  }
911
1019
  /**
912
- * Initialize the generator (dereference if needed)
1020
+ * Initialize the generator (dereference if needed, then validate)
913
1021
  */
914
1022
  async initialize() {
915
- if (this.options.validate) {
916
- const result = await this.validate();
917
- if (!result.valid) {
918
- throw new ParseError("Invalid OpenAPI document", { errors: result.errors });
919
- }
920
- }
921
1023
  if (this.options.dereference && !this.dereferencedDocument) {
922
1024
  try {
1025
+ const { default: $RefParser } = await import("@apidevtools/json-schema-ref-parser");
923
1026
  const refParserOptions = this.buildRefParserOptions();
924
1027
  this.dereferencedDocument = await $RefParser.dereference(
925
1028
  JSON.parse(JSON.stringify(this.document)),
@@ -932,6 +1035,14 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
932
1035
  });
933
1036
  }
934
1037
  }
1038
+ if (this.options.validate) {
1039
+ const validator = new Validator();
1040
+ const documentToValidate = this.dereferencedDocument ?? this.document;
1041
+ const result = await validator.validate(documentToValidate);
1042
+ if (!result.valid) {
1043
+ throw new ParseError("Invalid OpenAPI document", { errors: result.errors });
1044
+ }
1045
+ }
935
1046
  }
936
1047
  /**
937
1048
  * Generate all tools from the OpenAPI specification
@@ -1000,11 +1111,18 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
1000
1111
  const name = this.generateToolName(pathStr, method, operation.operationId, options);
1001
1112
  const description = operation.summary || operation.description || `${method.toUpperCase()} ${pathStr}`;
1002
1113
  const metadata = this.extractMetadata(pathStr, method, operation, document, outputSchema);
1114
+ const formatResolvers = {
1115
+ ...options.resolveFormats ? BUILTIN_FORMAT_RESOLVERS : {},
1116
+ ...options.formatResolvers
1117
+ };
1118
+ const hasFormatResolvers = Object.keys(formatResolvers).length > 0;
1119
+ const resolvedInputSchema = hasFormatResolvers ? resolveSchemaFormats(inputSchema, formatResolvers) : inputSchema;
1120
+ const resolvedOutputSchema = hasFormatResolvers && outputSchema ? resolveSchemaFormats(outputSchema, formatResolvers) : outputSchema;
1003
1121
  return {
1004
1122
  name,
1005
1123
  description,
1006
- inputSchema,
1007
- outputSchema,
1124
+ inputSchema: resolvedInputSchema,
1125
+ outputSchema: resolvedOutputSchema,
1008
1126
  mapper,
1009
1127
  metadata
1010
1128
  };
@@ -1454,6 +1572,7 @@ var SecurityResolver = class {
1454
1572
  if (requiresSignature) {
1455
1573
  resolved.requiresSignature = true;
1456
1574
  resolved.signatureInfo = {
1575
+ /* c8 ignore next -- signatureScheme is always set from security.scheme */
1457
1576
  scheme: signatureScheme || "unknown"
1458
1577
  };
1459
1578
  }
@@ -1499,6 +1618,7 @@ var SecurityResolver = class {
1499
1618
  return this.resolveBasicAuth(context);
1500
1619
  case "digest":
1501
1620
  return this.resolveDigestAuth(context);
1621
+ /* c8 ignore next -- hoba is part of the same fall-through as mutual/negotiate/vapid/scram */
1502
1622
  case "hoba":
1503
1623
  case "mutual":
1504
1624
  case "negotiate":
@@ -1646,6 +1766,7 @@ function createSecurityContext(auth) {
1646
1766
  };
1647
1767
  }
1648
1768
  export {
1769
+ BUILTIN_FORMAT_RESOLVERS,
1649
1770
  GenerationError,
1650
1771
  LoadError,
1651
1772
  OpenAPIToolError,
@@ -1660,5 +1781,6 @@ export {
1660
1781
  Validator,
1661
1782
  createSecurityContext,
1662
1783
  isReferenceObject,
1784
+ resolveSchemaFormats,
1663
1785
  toJsonSchema
1664
1786
  };
package/esm/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-from-openapi",
3
- "version": "2.2.0",
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",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "homepage": "https://github.com/agentfront/mcp-from-openapi#readme",
29
29
  "engines": {
30
- "node": ">=18.0.0"
30
+ "node": ">=20.0.0"
31
31
  },
32
32
  "type": "module",
33
33
  "main": "../index.js",
@@ -48,7 +48,7 @@
48
48
  }
49
49
  },
50
50
  "dependencies": {
51
- "@apidevtools/json-schema-ref-parser": "^11.9.3",
51
+ "@apidevtools/json-schema-ref-parser": "^15.3.5",
52
52
  "openapi-types": "^12.1.3",
53
53
  "yaml": "^2.8.3"
54
54
  },
@@ -60,6 +60,7 @@
60
60
  "@swc/helpers": "^0.5.18",
61
61
  "@swc/jest": "~0.2.38",
62
62
  "@types/jest": "^29.5.0",
63
+ "@types/json-schema": "^7.0.15",
63
64
  "@types/node": "^24.0.0",
64
65
  "esbuild": "^0.27.2",
65
66
  "jest": "^29.7.0",
@@ -0,0 +1,12 @@
1
+ import type { JsonSchema, FormatResolver } from './types';
2
+ /**
3
+ * Built-in format resolvers that enrich JSON Schema with concrete constraints.
4
+ * Each resolver only adds constraints if not already present on the schema.
5
+ */
6
+ export declare const BUILTIN_FORMAT_RESOLVERS: Record<string, FormatResolver>;
7
+ /**
8
+ * Recursively resolve format fields in a JSON Schema tree.
9
+ * For each schema node with a `format` field, the matching resolver
10
+ * is applied to enrich the schema with concrete constraints.
11
+ */
12
+ export declare function resolveSchemaFormats(schema: JsonSchema, resolvers: Record<string, FormatResolver>): JsonSchema;
package/generator.d.ts CHANGED
@@ -49,7 +49,7 @@ export declare class OpenAPIToolGenerator {
49
49
  */
50
50
  private buildRefParserOptions;
51
51
  /**
52
- * Initialize the generator (dereference if needed)
52
+ * Initialize the generator (dereference if needed, then validate)
53
53
  */
54
54
  private initialize;
55
55
  /**
package/index.d.ts CHANGED
@@ -4,7 +4,8 @@ export { ParameterResolver } from './parameter-resolver';
4
4
  export { ResponseBuilder } from './response-builder';
5
5
  export { Validator } from './validator';
6
6
  export { SecurityResolver, createSecurityContext } from './security-resolver';
7
+ export { BUILTIN_FORMAT_RESOLVERS, resolveSchemaFormats } from './format-resolver';
7
8
  export { OpenAPIToolError, LoadError, ParseError, ValidationError, GenerationError, SchemaError } from './errors';
8
- export type { McpOpenAPITool, ParameterMapper, ToolMetadata, FrontMcpExtensionData, SerializationInfo, SecurityRequirement, SecurityParameterInfo, ServerInfo, RefResolutionOptions, LoadOptions, GenerateOptions, NamingStrategy, OperationWithContext, OpenAPIDocument, OpenAPIVersion, HTTPMethod, ParameterLocation, AuthType, OperationObject, ParameterObject, RequestBodyObject, ResponseObject, ResponsesObject, MediaTypeObject, HeaderObject, ExampleObject, PathItemObject, PathsObject, ServerObject, SecuritySchemeObject, ReferenceObject, TagObject, ExternalDocumentationObject, ServerVariableObject, EncodingObject, SecurityRequirementObject, SchemaObject, ValidationResult, ValidationErrorDetail, ValidationWarning, } from './types';
9
+ export type { McpOpenAPITool, ParameterMapper, ToolMetadata, FrontMcpExtensionData, SerializationInfo, SecurityRequirement, SecurityParameterInfo, ServerInfo, RefResolutionOptions, LoadOptions, GenerateOptions, FormatResolver, JsonSchema, NamingStrategy, OperationWithContext, OpenAPIDocument, OpenAPIVersion, HTTPMethod, ParameterLocation, AuthType, OperationObject, ParameterObject, RequestBodyObject, ResponseObject, ResponsesObject, MediaTypeObject, HeaderObject, ExampleObject, PathItemObject, PathsObject, ServerObject, SecuritySchemeObject, ReferenceObject, TagObject, ExternalDocumentationObject, ServerVariableObject, EncodingObject, SecurityRequirementObject, SchemaObject, ValidationResult, ValidationErrorDetail, ValidationWarning, } from './types';
9
10
  export type { SecurityContext, ResolvedSecurity, DigestAuthCredentials, ClientCertificate, AWSCredentials, SignatureData, } from './security-resolver';
10
11
  export { isReferenceObject, toJsonSchema } from './types';
package/index.js CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
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,6 +45,7 @@ __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);
@@ -52,7 +54,6 @@ module.exports = __toCommonJS(index_exports);
52
54
  var yaml = __toESM(require("yaml"));
53
55
  var path = __toESM(require("path"));
54
56
  var fs = __toESM(require("fs/promises"));
55
- var import_json_schema_ref_parser = __toESM(require("@apidevtools/json-schema-ref-parser"));
56
57
 
57
58
  // src/types.ts
58
59
  function isReferenceObject(obj) {
@@ -736,6 +737,115 @@ var SchemaError = class extends OpenAPIToolError {
736
737
  }
737
738
  };
738
739
 
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
+
739
849
  // src/generator.ts
740
850
  var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
741
851
  document;
@@ -959,19 +1069,14 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
959
1069
  return { resolve: resolveConfig };
960
1070
  }
961
1071
  /**
962
- * Initialize the generator (dereference if needed)
1072
+ * Initialize the generator (dereference if needed, then validate)
963
1073
  */
964
1074
  async initialize() {
965
- if (this.options.validate) {
966
- const result = await this.validate();
967
- if (!result.valid) {
968
- throw new ParseError("Invalid OpenAPI document", { errors: result.errors });
969
- }
970
- }
971
1075
  if (this.options.dereference && !this.dereferencedDocument) {
972
1076
  try {
1077
+ const { default: $RefParser } = await import("@apidevtools/json-schema-ref-parser");
973
1078
  const refParserOptions = this.buildRefParserOptions();
974
- this.dereferencedDocument = await import_json_schema_ref_parser.default.dereference(
1079
+ this.dereferencedDocument = await $RefParser.dereference(
975
1080
  JSON.parse(JSON.stringify(this.document)),
976
1081
  refParserOptions
977
1082
  );
@@ -982,6 +1087,14 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
982
1087
  });
983
1088
  }
984
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
+ }
985
1098
  }
986
1099
  /**
987
1100
  * Generate all tools from the OpenAPI specification
@@ -1050,11 +1163,18 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
1050
1163
  const name = this.generateToolName(pathStr, method, operation.operationId, options);
1051
1164
  const description = operation.summary || operation.description || `${method.toUpperCase()} ${pathStr}`;
1052
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;
1053
1173
  return {
1054
1174
  name,
1055
1175
  description,
1056
- inputSchema,
1057
- outputSchema,
1176
+ inputSchema: resolvedInputSchema,
1177
+ outputSchema: resolvedOutputSchema,
1058
1178
  mapper,
1059
1179
  metadata
1060
1180
  };
@@ -1504,6 +1624,7 @@ var SecurityResolver = class {
1504
1624
  if (requiresSignature) {
1505
1625
  resolved.requiresSignature = true;
1506
1626
  resolved.signatureInfo = {
1627
+ /* c8 ignore next -- signatureScheme is always set from security.scheme */
1507
1628
  scheme: signatureScheme || "unknown"
1508
1629
  };
1509
1630
  }
@@ -1549,6 +1670,7 @@ var SecurityResolver = class {
1549
1670
  return this.resolveBasicAuth(context);
1550
1671
  case "digest":
1551
1672
  return this.resolveDigestAuth(context);
1673
+ /* c8 ignore next -- hoba is part of the same fall-through as mutual/negotiate/vapid/scram */
1552
1674
  case "hoba":
1553
1675
  case "mutual":
1554
1676
  case "negotiate":
@@ -1697,6 +1819,7 @@ function createSecurityContext(auth) {
1697
1819
  }
1698
1820
  // Annotate the CommonJS export names for ESM import in node:
1699
1821
  0 && (module.exports = {
1822
+ BUILTIN_FORMAT_RESOLVERS,
1700
1823
  GenerationError,
1701
1824
  LoadError,
1702
1825
  OpenAPIToolError,
@@ -1711,5 +1834,6 @@ function createSecurityContext(auth) {
1711
1834
  Validator,
1712
1835
  createSecurityContext,
1713
1836
  isReferenceObject,
1837
+ resolveSchemaFormats,
1714
1838
  toJsonSchema
1715
1839
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-from-openapi",
3
- "version": "2.2.0",
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",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "homepage": "https://github.com/agentfront/mcp-from-openapi#readme",
29
29
  "engines": {
30
- "node": ">=18.0.0"
30
+ "node": ">=20.0.0"
31
31
  },
32
32
  "type": "commonjs",
33
33
  "main": "./index.js",
@@ -48,7 +48,7 @@
48
48
  }
49
49
  },
50
50
  "dependencies": {
51
- "@apidevtools/json-schema-ref-parser": "^11.9.3",
51
+ "@apidevtools/json-schema-ref-parser": "^15.3.5",
52
52
  "openapi-types": "^12.1.3",
53
53
  "yaml": "^2.8.3"
54
54
  },
@@ -60,6 +60,7 @@
60
60
  "@swc/helpers": "^0.5.18",
61
61
  "@swc/jest": "~0.2.38",
62
62
  "@types/jest": "^29.5.0",
63
+ "@types/json-schema": "^7.0.15",
63
64
  "@types/node": "^24.0.0",
64
65
  "esbuild": "^0.27.2",
65
66
  "jest": "^29.7.0",
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
@@ -457,7 +457,28 @@ export interface GenerateOptions {
457
457
  * @default false
458
458
  */
459
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>;
460
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;
461
482
  /**
462
483
  * Naming strategy for resolving parameter conflicts
463
484
  */
@@ -530,4 +551,3 @@ export interface ValidationWarning {
530
551
  */
531
552
  code?: string;
532
553
  }
533
- export {};
package/CHANGELOG.md DELETED
@@ -1,83 +0,0 @@
1
- ## [2.2.0] - 2026-04-07
2
-
3
- ## [2.1.2] - 2025-12-27
4
-
5
- ### Changed
6
-
7
- - Added `publish-alpha` Nx target to enable alpha publishing flow using common script.
8
-
9
- ## [2.1.1] - 2025-12-24
10
-
11
- ### Fixed
12
-
13
- - Revised build setup to emit CJS and ESM bundles with corrected export map and sideEffects flag to improve tree shaking.
14
- - Synced package entry points and type outputs with the new build artifacts while preserving the public API surface.
15
-
16
- ## [2.1.0] - 2025-12-19
17
-
18
- ### Added
19
-
20
- - Introduced logger support within the OpenAPI adapter to improve observability.
21
- - Expanded security handling with automatic auth type routing and enhanced documentation.
22
-
23
- ### Changed
24
-
25
- - Refined security resolver examples and guidance for broader authentication scheme coverage.
26
-
27
- ## [2.0.0] - 2025-12-11
28
-
29
- ### Breaking
30
-
31
- - Migrated to Zod v4 (now a peer dependency) and aligned JSON schema types with Zod’s v4 JSONSchema
32
- - Renamed utility export `toJSONSchema7` to `toJsonSchema`, affecting consumers of the types/helpers
33
-
34
- ### Changed
35
-
36
- - Updated SWC/Jest config to inline ES2022 settings and modernized tooling versions
37
- - Adjusted exports formatting and minor parameter resolver refactors for consistency
38
-
39
- # Changelog
40
-
41
- ## [1.0.0] - 2025-11-21
42
-
43
- ### Features
44
-
45
- - Production-ready library for converting OpenAPI specifications into MCP tool definitions
46
- - OpenAPI 3.0+ and Swagger 2.0 support
47
- - Comprehensive operation parsing:
48
- - RESTful endpoint detection (GET, POST, PUT, PATCH, DELETE, etc.)
49
- - Path parameter extraction and validation
50
- - Query parameter handling
51
- - Request body schema conversion
52
- - Response schema parsing
53
- - Advanced OpenAPI features:
54
- - Reference resolution ($ref) across the entire specification
55
- - Security scheme detection and configuration
56
- - Parameter conflict resolution
57
- - Operation naming controls and customization
58
- - Request mapper generation:
59
- - Automatic parameter mapping from MCP tool inputs to HTTP requests
60
- - Type-safe parameter handling
61
- - Support for different parameter locations (path, query, header, cookie)
62
- - Request body transformation
63
- - Tool metadata generation:
64
- - Descriptive tool names from operation IDs
65
- - Documentation from OpenAPI descriptions
66
- - Schema validation rules
67
- - Multiple input formats:
68
- - JSON OpenAPI specifications
69
- - YAML OpenAPI specifications
70
- - Inline specification objects
71
- - URL references to remote specifications
72
- - Type-safe TypeScript implementation
73
- - Node.js 18+ compatibility
74
-
75
- ### Documentation
76
-
77
- - Complete API reference
78
- - OpenAPI conversion examples
79
- - Integration guides for MCP servers
80
- - Best practices for tool generation
81
-
82
- This is the first official release of `mcp-from-openapi`, extracted from the FrontMCP framework to be published as a
83
- standalone, reusable library for the community.