mcp-from-openapi 2.1.2 → 2.2.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/CHANGELOG.md CHANGED
@@ -1,3 +1,5 @@
1
+ ## [2.2.0] - 2026-04-07
2
+
1
3
  ## [2.1.2] - 2025-12-27
2
4
 
3
5
  ### Changed
package/esm/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
- // libs/mcp-from-openapi/src/generator.ts
1
+ // src/generator.ts
2
2
  import * as yaml from "yaml";
3
- import * as fs from "fs/promises";
4
3
  import * as path from "path";
4
+ import * as fs from "fs/promises";
5
5
  import $RefParser from "@apidevtools/json-schema-ref-parser";
6
6
 
7
- // libs/mcp-from-openapi/src/types.ts
7
+ // src/types.ts
8
8
  function isReferenceObject(obj) {
9
9
  return obj && typeof obj === "object" && "$ref" in obj;
10
10
  }
@@ -70,7 +70,7 @@ function toJsonSchema(schema) {
70
70
  return result;
71
71
  }
72
72
 
73
- // libs/mcp-from-openapi/src/parameter-resolver.ts
73
+ // src/parameter-resolver.ts
74
74
  var ParameterResolver = class {
75
75
  namingStrategy;
76
76
  constructor(namingStrategy) {
@@ -335,7 +335,7 @@ var ParameterResolver = class {
335
335
  }
336
336
  };
337
337
 
338
- // libs/mcp-from-openapi/src/response-builder.ts
338
+ // src/response-builder.ts
339
339
  var ResponseBuilder = class {
340
340
  preferredStatusCodes;
341
341
  includeAllResponses;
@@ -455,7 +455,7 @@ var ResponseBuilder = class {
455
455
  }
456
456
  };
457
457
 
458
- // libs/mcp-from-openapi/src/validator.ts
458
+ // src/validator.ts
459
459
  var Validator = class {
460
460
  /**
461
461
  * Validate an OpenAPI document
@@ -646,7 +646,7 @@ var Validator = class {
646
646
  }
647
647
  };
648
648
 
649
- // libs/mcp-from-openapi/src/errors.ts
649
+ // src/errors.ts
650
650
  var OpenAPIToolError = class extends Error {
651
651
  context;
652
652
  constructor(message, context) {
@@ -686,7 +686,7 @@ var SchemaError = class extends OpenAPIToolError {
686
686
  }
687
687
  };
688
688
 
689
- // libs/mcp-from-openapi/src/generator.ts
689
+ // src/generator.ts
690
690
  var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
691
691
  document;
692
692
  dereferencedDocument;
@@ -702,7 +702,8 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
702
702
  headers: options.headers ?? {},
703
703
  timeout: options.timeout ?? 3e4,
704
704
  validate: options.validate ?? true,
705
- followRedirects: options.followRedirects ?? true
705
+ followRedirects: options.followRedirects ?? true,
706
+ refResolution: options.refResolution ?? {}
706
707
  };
707
708
  }
708
709
  /**
@@ -807,6 +808,106 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
807
808
  const validator = new Validator();
808
809
  return validator.validate(this.document);
809
810
  }
811
+ /**
812
+ * Hostnames and IP patterns that are blocked by default to prevent SSRF.
813
+ * Covers RFC 1918/6598 private ranges, link-local, loopback, and cloud metadata endpoints.
814
+ */
815
+ static BLOCKED_HOSTNAME_PATTERNS = [
816
+ "localhost",
817
+ "metadata.google.internal",
818
+ /^127\.\d+\.\d+\.\d+$/,
819
+ // 127.0.0.0/8 loopback
820
+ /^10\.\d+\.\d+\.\d+$/,
821
+ // 10.0.0.0/8 private
822
+ /^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/,
823
+ // 172.16.0.0/12 private
824
+ /^192\.168\.\d+\.\d+$/,
825
+ // 192.168.0.0/16 private
826
+ /^169\.254\.\d+\.\d+$/,
827
+ // 169.254.0.0/16 link-local / cloud metadata
828
+ /^0\.0\.0\.0$/,
829
+ // unspecified
830
+ "::1",
831
+ // IPv6 loopback
832
+ /^fd[0-9a-f]{2}:/i,
833
+ // fd00::/8 IPv6 ULA
834
+ /^fe80:/i,
835
+ // fe80::/10 IPv6 link-local
836
+ /^\[::1\]$/,
837
+ // bracketed IPv6 loopback
838
+ /^\[fd[0-9a-f]{2}:/i,
839
+ // bracketed IPv6 ULA
840
+ /^\[fe80:/i
841
+ // bracketed IPv6 link-local
842
+ ];
843
+ /**
844
+ * Check whether a hostname is blocked (internal/private IP or explicit blocklist).
845
+ */
846
+ isBlockedHost(hostname, refOpts) {
847
+ if (refOpts.allowInternalIPs) {
848
+ return refOpts.blockedHosts.includes(hostname);
849
+ }
850
+ if (refOpts.blockedHosts.includes(hostname)) {
851
+ return true;
852
+ }
853
+ for (const pattern of _OpenAPIToolGenerator.BLOCKED_HOSTNAME_PATTERNS) {
854
+ if (typeof pattern === "string") {
855
+ if (hostname === pattern) return true;
856
+ } else {
857
+ if (pattern.test(hostname)) return true;
858
+ }
859
+ }
860
+ return false;
861
+ }
862
+ /**
863
+ * Build $RefParser options based on refResolution configuration.
864
+ * Defaults: allow http/https, block file://, block internal IPs.
865
+ */
866
+ buildRefParserOptions() {
867
+ const raw = this.options.refResolution;
868
+ const refOpts = {
869
+ allowedProtocols: raw.allowedProtocols ?? ["http", "https"],
870
+ allowedHosts: raw.allowedHosts ?? [],
871
+ blockedHosts: raw.blockedHosts ?? [],
872
+ allowInternalIPs: raw.allowInternalIPs ?? false
873
+ };
874
+ const allowedProtocols = new Set(refOpts.allowedProtocols);
875
+ const hasNetworkProtocol = allowedProtocols.size > 0 && !([...allowedProtocols].length === 1 && allowedProtocols.has("file"));
876
+ if (allowedProtocols.size === 0) {
877
+ return { resolve: { external: false } };
878
+ }
879
+ const resolveConfig = {
880
+ external: true,
881
+ file: allowedProtocols.has("file") ? void 0 : false
882
+ };
883
+ if (hasNetworkProtocol) {
884
+ const hasHostAllowlist = refOpts.allowedHosts.length > 0;
885
+ const hostAllowSet = new Set(refOpts.allowedHosts);
886
+ resolveConfig["http"] = {
887
+ canRead: (file) => {
888
+ try {
889
+ const parsed = new URL(file.url);
890
+ const protocol = parsed.protocol.replace(":", "");
891
+ if (!allowedProtocols.has(protocol)) {
892
+ return false;
893
+ }
894
+ if (hasHostAllowlist && !hostAllowSet.has(parsed.hostname)) {
895
+ return false;
896
+ }
897
+ if (this.isBlockedHost(parsed.hostname, refOpts)) {
898
+ return false;
899
+ }
900
+ return true;
901
+ } catch {
902
+ return false;
903
+ }
904
+ }
905
+ };
906
+ } else {
907
+ resolveConfig["http"] = false;
908
+ }
909
+ return { resolve: resolveConfig };
910
+ }
810
911
  /**
811
912
  * Initialize the generator (dereference if needed)
812
913
  */
@@ -819,8 +920,10 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
819
920
  }
820
921
  if (this.options.dereference && !this.dereferencedDocument) {
821
922
  try {
923
+ const refParserOptions = this.buildRefParserOptions();
822
924
  this.dereferencedDocument = await $RefParser.dereference(
823
- JSON.parse(JSON.stringify(this.document))
925
+ JSON.parse(JSON.stringify(this.document)),
926
+ refParserOptions
824
927
  );
825
928
  } catch (error) {
826
929
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1024,7 +1127,7 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
1024
1127
  }
1025
1128
  };
1026
1129
 
1027
- // libs/mcp-from-openapi/src/schema-builder.ts
1130
+ // src/schema-builder.ts
1028
1131
  var SchemaBuilder = class {
1029
1132
  /**
1030
1133
  * Merge multiple schemas into one
@@ -1303,7 +1406,7 @@ var SchemaBuilder = class {
1303
1406
  }
1304
1407
  };
1305
1408
 
1306
- // libs/mcp-from-openapi/src/security-resolver.ts
1409
+ // src/security-resolver.ts
1307
1410
  var SecurityResolver = class {
1308
1411
  /**
1309
1412
  * Resolve security parameters from mapper entries
package/esm/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-from-openapi",
3
- "version": "2.1.2",
3
+ "version": "2.2.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,13 +20,12 @@
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
30
  "node": ">=18.0.0"
32
31
  },
@@ -46,19 +45,25 @@
46
45
  "types": "../index.d.ts",
47
46
  "default": "./index.mjs"
48
47
  }
49
- },
50
- "./esm": null
48
+ }
51
49
  },
52
50
  "dependencies": {
53
51
  "@apidevtools/json-schema-ref-parser": "^11.9.3",
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",
61
63
  "@types/node": "^24.0.0",
64
+ "esbuild": "^0.27.2",
65
+ "jest": "^29.7.0",
66
+ "tslib": "^2.8.1",
62
67
  "typescript": "^5.0.0",
63
68
  "zod": "^4.0.0"
64
69
  }
package/generator.d.ts CHANGED
@@ -34,6 +34,20 @@ export declare class OpenAPIToolGenerator {
34
34
  * Validate the OpenAPI document
35
35
  */
36
36
  validate(): Promise<ValidationResult>;
37
+ /**
38
+ * Hostnames and IP patterns that are blocked by default to prevent SSRF.
39
+ * Covers RFC 1918/6598 private ranges, link-local, loopback, and cloud metadata endpoints.
40
+ */
41
+ private static readonly BLOCKED_HOSTNAME_PATTERNS;
42
+ /**
43
+ * Check whether a hostname is blocked (internal/private IP or explicit blocklist).
44
+ */
45
+ private isBlockedHost;
46
+ /**
47
+ * Build $RefParser options based on refResolution configuration.
48
+ * Defaults: allow http/https, block file://, block internal IPs.
49
+ */
50
+ private buildRefParserOptions;
37
51
  /**
38
52
  * Initialize the generator (dereference if needed)
39
53
  */
package/index.d.ts CHANGED
@@ -5,6 +5,6 @@ export { ResponseBuilder } from './response-builder';
5
5
  export { Validator } from './validator';
6
6
  export { SecurityResolver, createSecurityContext } from './security-resolver';
7
7
  export { OpenAPIToolError, LoadError, ParseError, ValidationError, GenerationError, SchemaError } from './errors';
8
- export type { McpOpenAPITool, ParameterMapper, ToolMetadata, FrontMcpExtensionData, SerializationInfo, SecurityRequirement, SecurityParameterInfo, ServerInfo, 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';
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
9
  export type { SecurityContext, ResolvedSecurity, DigestAuthCredentials, ClientCertificate, AWSCredentials, SignatureData, } from './security-resolver';
10
10
  export { isReferenceObject, toJsonSchema } from './types';
package/index.js CHANGED
@@ -27,7 +27,7 @@ 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
33
  GenerationError: () => GenerationError,
@@ -48,13 +48,13 @@ __export(index_exports, {
48
48
  });
49
49
  module.exports = __toCommonJS(index_exports);
50
50
 
51
- // libs/mcp-from-openapi/src/generator.ts
51
+ // src/generator.ts
52
52
  var yaml = __toESM(require("yaml"));
53
- var fs = __toESM(require("fs/promises"));
54
53
  var path = __toESM(require("path"));
54
+ var fs = __toESM(require("fs/promises"));
55
55
  var import_json_schema_ref_parser = __toESM(require("@apidevtools/json-schema-ref-parser"));
56
56
 
57
- // libs/mcp-from-openapi/src/types.ts
57
+ // src/types.ts
58
58
  function isReferenceObject(obj) {
59
59
  return obj && typeof obj === "object" && "$ref" in obj;
60
60
  }
@@ -120,7 +120,7 @@ function toJsonSchema(schema) {
120
120
  return result;
121
121
  }
122
122
 
123
- // libs/mcp-from-openapi/src/parameter-resolver.ts
123
+ // src/parameter-resolver.ts
124
124
  var ParameterResolver = class {
125
125
  namingStrategy;
126
126
  constructor(namingStrategy) {
@@ -385,7 +385,7 @@ var ParameterResolver = class {
385
385
  }
386
386
  };
387
387
 
388
- // libs/mcp-from-openapi/src/response-builder.ts
388
+ // src/response-builder.ts
389
389
  var ResponseBuilder = class {
390
390
  preferredStatusCodes;
391
391
  includeAllResponses;
@@ -505,7 +505,7 @@ var ResponseBuilder = class {
505
505
  }
506
506
  };
507
507
 
508
- // libs/mcp-from-openapi/src/validator.ts
508
+ // src/validator.ts
509
509
  var Validator = class {
510
510
  /**
511
511
  * Validate an OpenAPI document
@@ -696,7 +696,7 @@ var Validator = class {
696
696
  }
697
697
  };
698
698
 
699
- // libs/mcp-from-openapi/src/errors.ts
699
+ // src/errors.ts
700
700
  var OpenAPIToolError = class extends Error {
701
701
  context;
702
702
  constructor(message, context) {
@@ -736,7 +736,7 @@ var SchemaError = class extends OpenAPIToolError {
736
736
  }
737
737
  };
738
738
 
739
- // libs/mcp-from-openapi/src/generator.ts
739
+ // src/generator.ts
740
740
  var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
741
741
  document;
742
742
  dereferencedDocument;
@@ -752,7 +752,8 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
752
752
  headers: options.headers ?? {},
753
753
  timeout: options.timeout ?? 3e4,
754
754
  validate: options.validate ?? true,
755
- followRedirects: options.followRedirects ?? true
755
+ followRedirects: options.followRedirects ?? true,
756
+ refResolution: options.refResolution ?? {}
756
757
  };
757
758
  }
758
759
  /**
@@ -857,6 +858,106 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
857
858
  const validator = new Validator();
858
859
  return validator.validate(this.document);
859
860
  }
861
+ /**
862
+ * Hostnames and IP patterns that are blocked by default to prevent SSRF.
863
+ * Covers RFC 1918/6598 private ranges, link-local, loopback, and cloud metadata endpoints.
864
+ */
865
+ static BLOCKED_HOSTNAME_PATTERNS = [
866
+ "localhost",
867
+ "metadata.google.internal",
868
+ /^127\.\d+\.\d+\.\d+$/,
869
+ // 127.0.0.0/8 loopback
870
+ /^10\.\d+\.\d+\.\d+$/,
871
+ // 10.0.0.0/8 private
872
+ /^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/,
873
+ // 172.16.0.0/12 private
874
+ /^192\.168\.\d+\.\d+$/,
875
+ // 192.168.0.0/16 private
876
+ /^169\.254\.\d+\.\d+$/,
877
+ // 169.254.0.0/16 link-local / cloud metadata
878
+ /^0\.0\.0\.0$/,
879
+ // unspecified
880
+ "::1",
881
+ // IPv6 loopback
882
+ /^fd[0-9a-f]{2}:/i,
883
+ // fd00::/8 IPv6 ULA
884
+ /^fe80:/i,
885
+ // fe80::/10 IPv6 link-local
886
+ /^\[::1\]$/,
887
+ // bracketed IPv6 loopback
888
+ /^\[fd[0-9a-f]{2}:/i,
889
+ // bracketed IPv6 ULA
890
+ /^\[fe80:/i
891
+ // bracketed IPv6 link-local
892
+ ];
893
+ /**
894
+ * Check whether a hostname is blocked (internal/private IP or explicit blocklist).
895
+ */
896
+ isBlockedHost(hostname, refOpts) {
897
+ if (refOpts.allowInternalIPs) {
898
+ return refOpts.blockedHosts.includes(hostname);
899
+ }
900
+ if (refOpts.blockedHosts.includes(hostname)) {
901
+ return true;
902
+ }
903
+ for (const pattern of _OpenAPIToolGenerator.BLOCKED_HOSTNAME_PATTERNS) {
904
+ if (typeof pattern === "string") {
905
+ if (hostname === pattern) return true;
906
+ } else {
907
+ if (pattern.test(hostname)) return true;
908
+ }
909
+ }
910
+ return false;
911
+ }
912
+ /**
913
+ * Build $RefParser options based on refResolution configuration.
914
+ * Defaults: allow http/https, block file://, block internal IPs.
915
+ */
916
+ buildRefParserOptions() {
917
+ const raw = this.options.refResolution;
918
+ const refOpts = {
919
+ allowedProtocols: raw.allowedProtocols ?? ["http", "https"],
920
+ allowedHosts: raw.allowedHosts ?? [],
921
+ blockedHosts: raw.blockedHosts ?? [],
922
+ allowInternalIPs: raw.allowInternalIPs ?? false
923
+ };
924
+ const allowedProtocols = new Set(refOpts.allowedProtocols);
925
+ const hasNetworkProtocol = allowedProtocols.size > 0 && !([...allowedProtocols].length === 1 && allowedProtocols.has("file"));
926
+ if (allowedProtocols.size === 0) {
927
+ return { resolve: { external: false } };
928
+ }
929
+ const resolveConfig = {
930
+ external: true,
931
+ file: allowedProtocols.has("file") ? void 0 : false
932
+ };
933
+ if (hasNetworkProtocol) {
934
+ const hasHostAllowlist = refOpts.allowedHosts.length > 0;
935
+ const hostAllowSet = new Set(refOpts.allowedHosts);
936
+ resolveConfig["http"] = {
937
+ canRead: (file) => {
938
+ try {
939
+ const parsed = new URL(file.url);
940
+ const protocol = parsed.protocol.replace(":", "");
941
+ if (!allowedProtocols.has(protocol)) {
942
+ return false;
943
+ }
944
+ if (hasHostAllowlist && !hostAllowSet.has(parsed.hostname)) {
945
+ return false;
946
+ }
947
+ if (this.isBlockedHost(parsed.hostname, refOpts)) {
948
+ return false;
949
+ }
950
+ return true;
951
+ } catch {
952
+ return false;
953
+ }
954
+ }
955
+ };
956
+ } else {
957
+ resolveConfig["http"] = false;
958
+ }
959
+ return { resolve: resolveConfig };
960
+ }
860
961
  /**
861
962
  * Initialize the generator (dereference if needed)
862
963
  */
@@ -869,8 +970,10 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
869
970
  }
870
971
  if (this.options.dereference && !this.dereferencedDocument) {
871
972
  try {
973
+ const refParserOptions = this.buildRefParserOptions();
872
974
  this.dereferencedDocument = await import_json_schema_ref_parser.default.dereference(
873
- JSON.parse(JSON.stringify(this.document))
975
+ JSON.parse(JSON.stringify(this.document)),
976
+ refParserOptions
874
977
  );
875
978
  } catch (error) {
876
979
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1074,7 +1177,7 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
1074
1177
  }
1075
1178
  };
1076
1179
 
1077
- // libs/mcp-from-openapi/src/schema-builder.ts
1180
+ // src/schema-builder.ts
1078
1181
  var SchemaBuilder = class {
1079
1182
  /**
1080
1183
  * Merge multiple schemas into one
@@ -1353,7 +1456,7 @@ var SchemaBuilder = class {
1353
1456
  }
1354
1457
  };
1355
1458
 
1356
- // libs/mcp-from-openapi/src/security-resolver.ts
1459
+ // src/security-resolver.ts
1357
1460
  var SecurityResolver = class {
1358
1461
  /**
1359
1462
  * Resolve security parameters from mapper entries
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-from-openapi",
3
- "version": "2.1.2",
3
+ "version": "2.2.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,13 +20,12 @@
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
30
  "node": ">=18.0.0"
32
31
  },
@@ -46,19 +45,25 @@
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
51
  "@apidevtools/json-schema-ref-parser": "^11.9.3",
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",
61
63
  "@types/node": "^24.0.0",
64
+ "esbuild": "^0.27.2",
65
+ "jest": "^29.7.0",
66
+ "tslib": "^2.8.1",
62
67
  "typescript": "^5.0.0",
63
68
  "zod": "^4.0.0"
64
69
  }
package/types.d.ts CHANGED
@@ -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