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/README.md +61 -554
- package/esm/index.mjs +246 -21
- package/esm/package.json +16 -10
- package/format-resolver.d.ts +12 -0
- package/generator.d.ts +15 -1
- package/index.d.ts +2 -1
- package/index.js +250 -23
- package/package.json +16 -10
- package/types.d.ts +59 -2
- package/CHANGELOG.md +0 -81
package/esm/index.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
//
|
|
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";
|
|
5
|
-
import
|
|
4
|
+
import * as fs from "fs/promises";
|
|
6
5
|
|
|
7
|
-
//
|
|
6
|
+
// src/types.ts
|
|
8
7
|
function isReferenceObject(obj) {
|
|
9
8
|
return obj && typeof obj === "object" && "$ref" in obj;
|
|
10
9
|
}
|
|
@@ -70,7 +69,7 @@ function toJsonSchema(schema) {
|
|
|
70
69
|
return result;
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
//
|
|
72
|
+
// src/parameter-resolver.ts
|
|
74
73
|
var ParameterResolver = class {
|
|
75
74
|
namingStrategy;
|
|
76
75
|
constructor(namingStrategy) {
|
|
@@ -335,7 +334,7 @@ var ParameterResolver = class {
|
|
|
335
334
|
}
|
|
336
335
|
};
|
|
337
336
|
|
|
338
|
-
//
|
|
337
|
+
// src/response-builder.ts
|
|
339
338
|
var ResponseBuilder = class {
|
|
340
339
|
preferredStatusCodes;
|
|
341
340
|
includeAllResponses;
|
|
@@ -455,7 +454,7 @@ var ResponseBuilder = class {
|
|
|
455
454
|
}
|
|
456
455
|
};
|
|
457
456
|
|
|
458
|
-
//
|
|
457
|
+
// src/validator.ts
|
|
459
458
|
var Validator = class {
|
|
460
459
|
/**
|
|
461
460
|
* Validate an OpenAPI document
|
|
@@ -646,7 +645,7 @@ var Validator = class {
|
|
|
646
645
|
}
|
|
647
646
|
};
|
|
648
647
|
|
|
649
|
-
//
|
|
648
|
+
// src/errors.ts
|
|
650
649
|
var OpenAPIToolError = class extends Error {
|
|
651
650
|
context;
|
|
652
651
|
constructor(message, context) {
|
|
@@ -686,7 +685,116 @@ var SchemaError = class extends OpenAPIToolError {
|
|
|
686
685
|
}
|
|
687
686
|
};
|
|
688
687
|
|
|
689
|
-
//
|
|
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
|
+
|
|
797
|
+
// src/generator.ts
|
|
690
798
|
var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
|
|
691
799
|
document;
|
|
692
800
|
dereferencedDocument;
|
|
@@ -702,7 +810,8 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
|
|
|
702
810
|
headers: options.headers ?? {},
|
|
703
811
|
timeout: options.timeout ?? 3e4,
|
|
704
812
|
validate: options.validate ?? true,
|
|
705
|
-
followRedirects: options.followRedirects ?? true
|
|
813
|
+
followRedirects: options.followRedirects ?? true,
|
|
814
|
+
refResolution: options.refResolution ?? {}
|
|
706
815
|
};
|
|
707
816
|
}
|
|
708
817
|
/**
|
|
@@ -808,19 +917,116 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
|
|
|
808
917
|
return validator.validate(this.document);
|
|
809
918
|
}
|
|
810
919
|
/**
|
|
811
|
-
*
|
|
920
|
+
* Hostnames and IP patterns that are blocked by default to prevent SSRF.
|
|
921
|
+
* Covers RFC 1918/6598 private ranges, link-local, loopback, and cloud metadata endpoints.
|
|
812
922
|
*/
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
923
|
+
static BLOCKED_HOSTNAME_PATTERNS = [
|
|
924
|
+
"localhost",
|
|
925
|
+
"metadata.google.internal",
|
|
926
|
+
/^127\.\d+\.\d+\.\d+$/,
|
|
927
|
+
// 127.0.0.0/8 loopback
|
|
928
|
+
/^10\.\d+\.\d+\.\d+$/,
|
|
929
|
+
// 10.0.0.0/8 private
|
|
930
|
+
/^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/,
|
|
931
|
+
// 172.16.0.0/12 private
|
|
932
|
+
/^192\.168\.\d+\.\d+$/,
|
|
933
|
+
// 192.168.0.0/16 private
|
|
934
|
+
/^169\.254\.\d+\.\d+$/,
|
|
935
|
+
// 169.254.0.0/16 link-local / cloud metadata
|
|
936
|
+
/^0\.0\.0\.0$/,
|
|
937
|
+
// unspecified
|
|
938
|
+
"::1",
|
|
939
|
+
// IPv6 loopback
|
|
940
|
+
/^fd[0-9a-f]{2}:/i,
|
|
941
|
+
// fd00::/8 IPv6 ULA
|
|
942
|
+
/^fe80:/i,
|
|
943
|
+
// fe80::/10 IPv6 link-local
|
|
944
|
+
/^\[::1\]$/,
|
|
945
|
+
// bracketed IPv6 loopback
|
|
946
|
+
/^\[fd[0-9a-f]{2}:/i,
|
|
947
|
+
// bracketed IPv6 ULA
|
|
948
|
+
/^\[fe80:/i
|
|
949
|
+
// bracketed IPv6 link-local
|
|
950
|
+
];
|
|
951
|
+
/**
|
|
952
|
+
* Check whether a hostname is blocked (internal/private IP or explicit blocklist).
|
|
953
|
+
*/
|
|
954
|
+
isBlockedHost(hostname, refOpts) {
|
|
955
|
+
if (refOpts.allowInternalIPs) {
|
|
956
|
+
return refOpts.blockedHosts.includes(hostname);
|
|
957
|
+
}
|
|
958
|
+
if (refOpts.blockedHosts.includes(hostname)) {
|
|
959
|
+
return true;
|
|
960
|
+
}
|
|
961
|
+
for (const pattern of _OpenAPIToolGenerator.BLOCKED_HOSTNAME_PATTERNS) {
|
|
962
|
+
if (typeof pattern === "string") {
|
|
963
|
+
if (hostname === pattern) return true;
|
|
964
|
+
} else {
|
|
965
|
+
if (pattern.test(hostname)) return true;
|
|
818
966
|
}
|
|
819
967
|
}
|
|
968
|
+
return false;
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* Build $RefParser options based on refResolution configuration.
|
|
972
|
+
* Defaults: allow http/https, block file://, block internal IPs.
|
|
973
|
+
*/
|
|
974
|
+
buildRefParserOptions() {
|
|
975
|
+
const raw = this.options.refResolution;
|
|
976
|
+
const refOpts = {
|
|
977
|
+
allowedProtocols: raw.allowedProtocols ?? ["http", "https"],
|
|
978
|
+
allowedHosts: raw.allowedHosts ?? [],
|
|
979
|
+
blockedHosts: raw.blockedHosts ?? [],
|
|
980
|
+
allowInternalIPs: raw.allowInternalIPs ?? false
|
|
981
|
+
};
|
|
982
|
+
const allowedProtocols = new Set(refOpts.allowedProtocols);
|
|
983
|
+
const hasNetworkProtocol = allowedProtocols.size > 0 && !([...allowedProtocols].length === 1 && allowedProtocols.has("file"));
|
|
984
|
+
if (allowedProtocols.size === 0) {
|
|
985
|
+
return { resolve: { external: false } };
|
|
986
|
+
}
|
|
987
|
+
const resolveConfig = {
|
|
988
|
+
external: true,
|
|
989
|
+
file: allowedProtocols.has("file") ? void 0 : false
|
|
990
|
+
};
|
|
991
|
+
if (hasNetworkProtocol) {
|
|
992
|
+
const hasHostAllowlist = refOpts.allowedHosts.length > 0;
|
|
993
|
+
const hostAllowSet = new Set(refOpts.allowedHosts);
|
|
994
|
+
resolveConfig["http"] = {
|
|
995
|
+
canRead: (file) => {
|
|
996
|
+
try {
|
|
997
|
+
const parsed = new URL(file.url);
|
|
998
|
+
const protocol = parsed.protocol.replace(":", "");
|
|
999
|
+
if (!allowedProtocols.has(protocol)) {
|
|
1000
|
+
return false;
|
|
1001
|
+
}
|
|
1002
|
+
if (hasHostAllowlist && !hostAllowSet.has(parsed.hostname)) {
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
if (this.isBlockedHost(parsed.hostname, refOpts)) {
|
|
1006
|
+
return false;
|
|
1007
|
+
}
|
|
1008
|
+
return true;
|
|
1009
|
+
} catch {
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
} else {
|
|
1015
|
+
resolveConfig["http"] = false;
|
|
1016
|
+
}
|
|
1017
|
+
return { resolve: resolveConfig };
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Initialize the generator (dereference if needed, then validate)
|
|
1021
|
+
*/
|
|
1022
|
+
async initialize() {
|
|
820
1023
|
if (this.options.dereference && !this.dereferencedDocument) {
|
|
821
1024
|
try {
|
|
1025
|
+
const { default: $RefParser } = await import("@apidevtools/json-schema-ref-parser");
|
|
1026
|
+
const refParserOptions = this.buildRefParserOptions();
|
|
822
1027
|
this.dereferencedDocument = await $RefParser.dereference(
|
|
823
|
-
JSON.parse(JSON.stringify(this.document))
|
|
1028
|
+
JSON.parse(JSON.stringify(this.document)),
|
|
1029
|
+
refParserOptions
|
|
824
1030
|
);
|
|
825
1031
|
} catch (error) {
|
|
826
1032
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -829,6 +1035,14 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
|
|
|
829
1035
|
});
|
|
830
1036
|
}
|
|
831
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
|
+
}
|
|
832
1046
|
}
|
|
833
1047
|
/**
|
|
834
1048
|
* Generate all tools from the OpenAPI specification
|
|
@@ -897,11 +1111,18 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
|
|
|
897
1111
|
const name = this.generateToolName(pathStr, method, operation.operationId, options);
|
|
898
1112
|
const description = operation.summary || operation.description || `${method.toUpperCase()} ${pathStr}`;
|
|
899
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;
|
|
900
1121
|
return {
|
|
901
1122
|
name,
|
|
902
1123
|
description,
|
|
903
|
-
inputSchema,
|
|
904
|
-
outputSchema,
|
|
1124
|
+
inputSchema: resolvedInputSchema,
|
|
1125
|
+
outputSchema: resolvedOutputSchema,
|
|
905
1126
|
mapper,
|
|
906
1127
|
metadata
|
|
907
1128
|
};
|
|
@@ -1024,7 +1245,7 @@ var OpenAPIToolGenerator = class _OpenAPIToolGenerator {
|
|
|
1024
1245
|
}
|
|
1025
1246
|
};
|
|
1026
1247
|
|
|
1027
|
-
//
|
|
1248
|
+
// src/schema-builder.ts
|
|
1028
1249
|
var SchemaBuilder = class {
|
|
1029
1250
|
/**
|
|
1030
1251
|
* Merge multiple schemas into one
|
|
@@ -1303,7 +1524,7 @@ var SchemaBuilder = class {
|
|
|
1303
1524
|
}
|
|
1304
1525
|
};
|
|
1305
1526
|
|
|
1306
|
-
//
|
|
1527
|
+
// src/security-resolver.ts
|
|
1307
1528
|
var SecurityResolver = class {
|
|
1308
1529
|
/**
|
|
1309
1530
|
* Resolve security parameters from mapper entries
|
|
@@ -1351,6 +1572,7 @@ var SecurityResolver = class {
|
|
|
1351
1572
|
if (requiresSignature) {
|
|
1352
1573
|
resolved.requiresSignature = true;
|
|
1353
1574
|
resolved.signatureInfo = {
|
|
1575
|
+
/* c8 ignore next -- signatureScheme is always set from security.scheme */
|
|
1354
1576
|
scheme: signatureScheme || "unknown"
|
|
1355
1577
|
};
|
|
1356
1578
|
}
|
|
@@ -1396,6 +1618,7 @@ var SecurityResolver = class {
|
|
|
1396
1618
|
return this.resolveBasicAuth(context);
|
|
1397
1619
|
case "digest":
|
|
1398
1620
|
return this.resolveDigestAuth(context);
|
|
1621
|
+
/* c8 ignore next -- hoba is part of the same fall-through as mutual/negotiate/vapid/scram */
|
|
1399
1622
|
case "hoba":
|
|
1400
1623
|
case "mutual":
|
|
1401
1624
|
case "negotiate":
|
|
@@ -1543,6 +1766,7 @@ function createSecurityContext(auth) {
|
|
|
1543
1766
|
};
|
|
1544
1767
|
}
|
|
1545
1768
|
export {
|
|
1769
|
+
BUILTIN_FORMAT_RESOLVERS,
|
|
1546
1770
|
GenerationError,
|
|
1547
1771
|
LoadError,
|
|
1548
1772
|
OpenAPIToolError,
|
|
@@ -1557,5 +1781,6 @@ export {
|
|
|
1557
1781
|
Validator,
|
|
1558
1782
|
createSecurityContext,
|
|
1559
1783
|
isReferenceObject,
|
|
1784
|
+
resolveSchemaFormats,
|
|
1560
1785
|
toJsonSchema
|
|
1561
1786
|
};
|
package/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-from-openapi",
|
|
3
|
-
"version": "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/
|
|
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/
|
|
26
|
+
"url": "https://github.com/agentfront/mcp-from-openapi/issues"
|
|
28
27
|
},
|
|
29
|
-
"homepage": "https://github.com/agentfront/
|
|
28
|
+
"homepage": "https://github.com/agentfront/mcp-from-openapi#readme",
|
|
30
29
|
"engines": {
|
|
31
|
-
"node": ">=
|
|
30
|
+
"node": ">=20.0.0"
|
|
32
31
|
},
|
|
33
32
|
"type": "module",
|
|
34
33
|
"main": "../index.js",
|
|
@@ -46,19 +45,26 @@
|
|
|
46
45
|
"types": "../index.d.ts",
|
|
47
46
|
"default": "./index.mjs"
|
|
48
47
|
}
|
|
49
|
-
}
|
|
50
|
-
"./esm": null
|
|
48
|
+
}
|
|
51
49
|
},
|
|
52
50
|
"dependencies": {
|
|
53
|
-
"@apidevtools/json-schema-ref-parser": "^
|
|
51
|
+
"@apidevtools/json-schema-ref-parser": "^15.3.5",
|
|
54
52
|
"openapi-types": "^12.1.3",
|
|
55
|
-
"yaml": "^2.8.
|
|
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
|
}
|
|
@@ -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
|
@@ -35,7 +35,21 @@ export declare class OpenAPIToolGenerator {
|
|
|
35
35
|
*/
|
|
36
36
|
validate(): Promise<ValidationResult>;
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
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;
|
|
51
|
+
/**
|
|
52
|
+
* Initialize the generator (dereference if needed, then validate)
|
|
39
53
|
*/
|
|
40
54
|
private initialize;
|
|
41
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, 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';
|