fastmcp 4.24.3 → 4.24.5
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/dist/FastMCP.cjs +2 -2
- package/dist/FastMCP.js +1 -1
- package/dist/{chunk-XPGMRMMN.cjs → chunk-P56ABHAK.cjs} +10 -5
- package/dist/chunk-P56ABHAK.cjs.map +1 -0
- package/dist/{chunk-D2CVYAA5.js → chunk-UYV7MFKA.js} +10 -5
- package/dist/chunk-UYV7MFKA.js.map +1 -0
- package/dist/edge/index.cjs +12 -4
- package/dist/edge/index.cjs.map +1 -1
- package/dist/edge/index.js +12 -4
- package/dist/edge/index.js.map +1 -1
- package/dist/examples/custom-routes.cjs +2 -2
- package/dist/examples/custom-routes.js +1 -1
- package/dist/openapi/index.cjs +645 -545
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.js +629 -529
- package/dist/openapi/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-D2CVYAA5.js.map +0 -1
- package/dist/chunk-XPGMRMMN.cjs.map +0 -1
package/dist/openapi/index.cjs
CHANGED
|
@@ -2,21 +2,339 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkP56ABHAKcjs = require('../chunk-P56ABHAK.cjs');
|
|
6
6
|
require('../chunk-BV4PWTT6.cjs');
|
|
7
7
|
require('../chunk-6TDYSPLC.cjs');
|
|
8
8
|
|
|
9
9
|
// src/openapi/loadSpec.ts
|
|
10
10
|
var _swaggerparser = require('@apidevtools/swagger-parser'); var _swaggerparser2 = _interopRequireDefault(_swaggerparser);
|
|
11
|
+
|
|
12
|
+
// src/openapi/schemas.ts
|
|
13
|
+
var SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
14
|
+
"$defs",
|
|
15
|
+
"definitions",
|
|
16
|
+
"dependentSchemas",
|
|
17
|
+
"patternProperties",
|
|
18
|
+
"properties"
|
|
19
|
+
]);
|
|
20
|
+
var DATA_KEYS = /* @__PURE__ */ new Set([
|
|
21
|
+
"const",
|
|
22
|
+
"default",
|
|
23
|
+
"enum",
|
|
24
|
+
"example",
|
|
25
|
+
"examples"
|
|
26
|
+
]);
|
|
27
|
+
var STRIP_KEYS = /* @__PURE__ */ new Set(["example", "examples"]);
|
|
28
|
+
function buildFlatSchema(route, sharedDefs) {
|
|
29
|
+
const byName = /* @__PURE__ */ new Map();
|
|
30
|
+
for (const param of route.parameters) {
|
|
31
|
+
const list = _nullishCoalesce(byName.get(param.name), () => ( []));
|
|
32
|
+
list.push(param);
|
|
33
|
+
byName.set(param.name, list);
|
|
34
|
+
}
|
|
35
|
+
const {
|
|
36
|
+
bodyEncoding,
|
|
37
|
+
properties: bodyProperties,
|
|
38
|
+
unsupportedBodyContentType,
|
|
39
|
+
wholeBodyKey
|
|
40
|
+
} = extractBodyProperties(
|
|
41
|
+
route.method === "get" ? void 0 : route.requestBody,
|
|
42
|
+
sharedDefs
|
|
43
|
+
);
|
|
44
|
+
const properties = /* @__PURE__ */ Object.create(null);
|
|
45
|
+
const required = [];
|
|
46
|
+
const parameterMap = /* @__PURE__ */ Object.create(null);
|
|
47
|
+
const used = new Set(bodyProperties.keys());
|
|
48
|
+
for (const [name, occurrences] of byName) {
|
|
49
|
+
if (occurrences.length === 1 && !bodyProperties.has(name)) {
|
|
50
|
+
used.add(name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const allocateAlias = (base) => {
|
|
54
|
+
let key = base;
|
|
55
|
+
let suffix = 1;
|
|
56
|
+
while (used.has(key)) {
|
|
57
|
+
suffix += 1;
|
|
58
|
+
key = `${base}_${suffix}`;
|
|
59
|
+
}
|
|
60
|
+
used.add(key);
|
|
61
|
+
return key;
|
|
62
|
+
};
|
|
63
|
+
for (const [name, occurrences] of byName) {
|
|
64
|
+
const collides = name === "__proto__" || occurrences.length > 1 || bodyProperties.has(name);
|
|
65
|
+
for (const param of occurrences) {
|
|
66
|
+
const base = collides ? `${name}__${param.in}` : name;
|
|
67
|
+
const key = collides ? allocateAlias(base) : name;
|
|
68
|
+
properties[key] = rewriteComponentRefs(
|
|
69
|
+
_nullishCoalesce(param.schema, () => ( { type: "string" }))
|
|
70
|
+
);
|
|
71
|
+
parameterMap[key] = {
|
|
72
|
+
allowReserved: param.allowReserved,
|
|
73
|
+
explode: param.explode,
|
|
74
|
+
in: param.in,
|
|
75
|
+
name,
|
|
76
|
+
style: param.style
|
|
77
|
+
};
|
|
78
|
+
if (param.in === "path" || param.required) {
|
|
79
|
+
required.push(key);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const [name, { required: isRequired, schema }] of bodyProperties) {
|
|
84
|
+
const key = name === "__proto__" ? allocateAlias(`${name}__body`) : name;
|
|
85
|
+
properties[key] = rewriteComponentRefs(schema);
|
|
86
|
+
parameterMap[key] = { in: "body", name };
|
|
87
|
+
if (isRequired) {
|
|
88
|
+
required.push(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const flatSchema = {
|
|
92
|
+
additionalProperties: false,
|
|
93
|
+
properties,
|
|
94
|
+
type: "object",
|
|
95
|
+
...required.length > 0 ? { required } : {}
|
|
96
|
+
};
|
|
97
|
+
const usedDefs = sharedDefs && filterReferencedDefs(properties, sharedDefs);
|
|
98
|
+
if (usedDefs) {
|
|
99
|
+
flatSchema.$defs = usedDefs;
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
bodyEncoding,
|
|
103
|
+
flatSchema,
|
|
104
|
+
parameterMap,
|
|
105
|
+
unsupportedBodyContentType,
|
|
106
|
+
wholeBodyKey
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function buildSharedDefs(document) {
|
|
110
|
+
const schemas = _optionalChain([document, 'access', _ => _.components, 'optionalAccess', _2 => _2.schemas]);
|
|
111
|
+
if (!schemas || Object.keys(schemas).length === 0) {
|
|
112
|
+
return void 0;
|
|
113
|
+
}
|
|
114
|
+
return rewriteNode(schemas, "schemaMap");
|
|
115
|
+
}
|
|
116
|
+
var SUCCESS_STATUS_PATTERN = /^2\d\d$/;
|
|
117
|
+
var MAX_OUTPUT_SCHEMA_DEFS = 50;
|
|
118
|
+
function buildOutputSchema(route, sharedDefs) {
|
|
119
|
+
const successEntry = Object.entries(_nullishCoalesce(route.responses, () => ( {}))).find(
|
|
120
|
+
([code]) => SUCCESS_STATUS_PATTERN.test(code)
|
|
121
|
+
);
|
|
122
|
+
const declaredSchema = _optionalChain([findMediaType, 'call', _3 => _3(
|
|
123
|
+
_optionalChain([successEntry, 'optionalAccess', _4 => _4[1], 'access', _5 => _5.content]),
|
|
124
|
+
"application/json"
|
|
125
|
+
), 'optionalAccess', _6 => _6.schema]);
|
|
126
|
+
if (!declaredSchema) {
|
|
127
|
+
return void 0;
|
|
128
|
+
}
|
|
129
|
+
const schema = resolveComponentRef(declaredSchema, sharedDefs);
|
|
130
|
+
const rewritten = rewriteComponentRefs(schema, true);
|
|
131
|
+
const { type } = rewritten;
|
|
132
|
+
const isObjectShaped = type === "object" || Array.isArray(type) && type.includes("object");
|
|
133
|
+
if (!isObjectShaped) {
|
|
134
|
+
return void 0;
|
|
135
|
+
}
|
|
136
|
+
const normalized = { ...rewritten, type: "object" };
|
|
137
|
+
const usedDefs = sharedDefs && filterReferencedDefs(normalized, sharedDefs);
|
|
138
|
+
if (usedDefs && Object.keys(usedDefs).length > MAX_OUTPUT_SCHEMA_DEFS) {
|
|
139
|
+
return void 0;
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
...normalized,
|
|
143
|
+
...usedDefs ? {
|
|
144
|
+
$defs: rewriteNode(usedDefs, "schemaMap", true)
|
|
145
|
+
} : {}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function resolveComponentRef(schema, sharedDefs) {
|
|
149
|
+
const seen = /* @__PURE__ */ new Set();
|
|
150
|
+
let current = schema;
|
|
151
|
+
let ref = current.$ref;
|
|
152
|
+
while (typeof ref === "string") {
|
|
153
|
+
const name = componentSchemaName(ref);
|
|
154
|
+
const target = name === void 0 ? void 0 : _optionalChain([sharedDefs, 'optionalAccess', _7 => _7[name]]);
|
|
155
|
+
if (name === void 0 || target === void 0 || seen.has(name)) {
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
seen.add(name);
|
|
159
|
+
current = target;
|
|
160
|
+
ref = current.$ref;
|
|
161
|
+
}
|
|
162
|
+
return current;
|
|
163
|
+
}
|
|
164
|
+
function rewriteComponentRefs(value, stripExamples = false) {
|
|
165
|
+
return rewriteNode(value, "schema", stripExamples);
|
|
166
|
+
}
|
|
167
|
+
function childMode(key) {
|
|
168
|
+
if (DATA_KEYS.has(key)) {
|
|
169
|
+
return "data";
|
|
170
|
+
}
|
|
171
|
+
return SCHEMA_MAP_KEYS.has(key) ? "schemaMap" : "schema";
|
|
172
|
+
}
|
|
173
|
+
function componentSchemaName(ref) {
|
|
174
|
+
for (const prefix of ["#/components/schemas/", "#/$defs/"]) {
|
|
175
|
+
if (ref.startsWith(prefix)) {
|
|
176
|
+
return ref.slice(prefix.length).replaceAll("~1", "/").replaceAll("~0", "~");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return void 0;
|
|
180
|
+
}
|
|
181
|
+
function extractBodyProperties(requestBody, sharedDefs) {
|
|
182
|
+
const properties = /* @__PURE__ */ new Map();
|
|
183
|
+
const content = _optionalChain([requestBody, 'optionalAccess', _8 => _8.content]);
|
|
184
|
+
if (!content) {
|
|
185
|
+
return { properties };
|
|
186
|
+
}
|
|
187
|
+
const json = findMediaType(content, "application/json");
|
|
188
|
+
const form = findMediaType(content, "application/x-www-form-urlencoded");
|
|
189
|
+
if (json === void 0 && form === void 0) {
|
|
190
|
+
const contentTypes = Object.keys(content);
|
|
191
|
+
return contentTypes.length > 0 ? { properties, unsupportedBodyContentType: contentTypes[0] } : { properties };
|
|
192
|
+
}
|
|
193
|
+
const bodyEncoding = json === void 0 ? "form" : "json";
|
|
194
|
+
const declaredSchema = bodyEncoding === "json" ? _optionalChain([json, 'optionalAccess', _9 => _9.schema]) : _optionalChain([form, 'optionalAccess', _10 => _10.schema]);
|
|
195
|
+
if (!declaredSchema) {
|
|
196
|
+
return { bodyEncoding, properties };
|
|
197
|
+
}
|
|
198
|
+
const schema = bodyEncoding === "form" ? resolveComponentRef(declaredSchema, sharedDefs) : declaredSchema;
|
|
199
|
+
const schemaProperties = schema.properties;
|
|
200
|
+
if (schema.type === "object" && schemaProperties && (bodyEncoding === "form" || schema.additionalProperties === false || Object.keys(schemaProperties).length > 0)) {
|
|
201
|
+
const requiredNames = new Set(
|
|
202
|
+
_nullishCoalesce(schema.required, () => ( []))
|
|
203
|
+
);
|
|
204
|
+
for (const [name, propertySchema] of Object.entries(schemaProperties)) {
|
|
205
|
+
properties.set(name, {
|
|
206
|
+
required: requiredNames.has(name),
|
|
207
|
+
schema: propertySchema
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return { bodyEncoding, properties };
|
|
211
|
+
}
|
|
212
|
+
if (bodyEncoding === "form") {
|
|
213
|
+
return {
|
|
214
|
+
properties,
|
|
215
|
+
unsupportedBodyContentType: "application/x-www-form-urlencoded"
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
properties.set("body", {
|
|
219
|
+
required: _nullishCoalesce(_optionalChain([requestBody, 'optionalAccess', _11 => _11.required]), () => ( false)),
|
|
220
|
+
schema
|
|
221
|
+
});
|
|
222
|
+
return { bodyEncoding, properties, wholeBodyKey: "body" };
|
|
223
|
+
}
|
|
224
|
+
function filterReferencedDefs(node, allDefs) {
|
|
225
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
226
|
+
const stack = [node];
|
|
227
|
+
while (stack.length > 0) {
|
|
228
|
+
const current = stack.pop();
|
|
229
|
+
if (Array.isArray(current)) {
|
|
230
|
+
stack.push(...current);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (!current || typeof current !== "object") {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
for (const [key, value] of Object.entries(
|
|
237
|
+
current
|
|
238
|
+
)) {
|
|
239
|
+
if (key === "$ref" && typeof value === "string" && value.startsWith("#/$defs/")) {
|
|
240
|
+
const [first = ""] = value.slice("#/$defs/".length).split("/");
|
|
241
|
+
const name = first.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
242
|
+
if (allDefs[name] && !referenced.has(name)) {
|
|
243
|
+
referenced.add(name);
|
|
244
|
+
stack.push(allDefs[name]);
|
|
245
|
+
}
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
stack.push(value);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (referenced.size === 0) {
|
|
252
|
+
return void 0;
|
|
253
|
+
}
|
|
254
|
+
return Object.fromEntries(
|
|
255
|
+
[...referenced].map((name) => [name, allDefs[name]])
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
function findMediaType(content, mediaType) {
|
|
259
|
+
if (!content) {
|
|
260
|
+
return void 0;
|
|
261
|
+
}
|
|
262
|
+
const key = Object.hasOwn(content, mediaType) ? mediaType : Object.keys(content).find(
|
|
263
|
+
(candidate) => candidate.split(";")[0].trim().toLowerCase() === mediaType
|
|
264
|
+
);
|
|
265
|
+
return key === void 0 ? void 0 : content[key];
|
|
266
|
+
}
|
|
267
|
+
function normalizeExclusiveBound(schema, exclusiveKey, boundKey) {
|
|
268
|
+
const { [exclusiveKey]: exclusive, ...rest } = schema;
|
|
269
|
+
if (typeof exclusive !== "boolean") {
|
|
270
|
+
return schema;
|
|
271
|
+
}
|
|
272
|
+
if (!exclusive || typeof rest[boundKey] !== "number") {
|
|
273
|
+
return rest;
|
|
274
|
+
}
|
|
275
|
+
const { [boundKey]: bound, ...unbounded } = rest;
|
|
276
|
+
return { ...unbounded, [exclusiveKey]: bound };
|
|
277
|
+
}
|
|
278
|
+
function normalizeExclusiveBounds(schema) {
|
|
279
|
+
return normalizeExclusiveBound(
|
|
280
|
+
normalizeExclusiveBound(schema, "exclusiveMinimum", "minimum"),
|
|
281
|
+
"exclusiveMaximum",
|
|
282
|
+
"maximum"
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
function normalizeNullable(schema) {
|
|
286
|
+
if (!("nullable" in schema)) {
|
|
287
|
+
return schema;
|
|
288
|
+
}
|
|
289
|
+
const { nullable, ...rest } = schema;
|
|
290
|
+
if (nullable !== true) {
|
|
291
|
+
return rest;
|
|
292
|
+
}
|
|
293
|
+
const { type } = rest;
|
|
294
|
+
if (typeof type === "string") {
|
|
295
|
+
return { ...rest, type: [type, "null"] };
|
|
296
|
+
}
|
|
297
|
+
if (Array.isArray(type)) {
|
|
298
|
+
return { ...rest, type: [.../* @__PURE__ */ new Set(["null", ...type])] };
|
|
299
|
+
}
|
|
300
|
+
return rest;
|
|
301
|
+
}
|
|
302
|
+
function rewriteNode(value, mode, stripExamples = false) {
|
|
303
|
+
if (mode === "data") {
|
|
304
|
+
return value;
|
|
305
|
+
}
|
|
306
|
+
if (Array.isArray(value)) {
|
|
307
|
+
return value.map((item) => rewriteNode(item, "schema", stripExamples));
|
|
308
|
+
}
|
|
309
|
+
if (!value || typeof value !== "object") {
|
|
310
|
+
return value;
|
|
311
|
+
}
|
|
312
|
+
const entries = Object.entries(value).filter(
|
|
313
|
+
([key]) => !stripExamples || mode !== "schema" || !STRIP_KEYS.has(key)
|
|
314
|
+
).map(([key, entryValue]) => {
|
|
315
|
+
if (mode === "schemaMap") {
|
|
316
|
+
return [key, rewriteNode(entryValue, "schema", stripExamples)];
|
|
317
|
+
}
|
|
318
|
+
if (key === "$ref" && typeof entryValue === "string" && entryValue.startsWith("#/components/schemas/")) {
|
|
319
|
+
return [key, entryValue.replace("#/components/schemas/", "#/$defs/")];
|
|
320
|
+
}
|
|
321
|
+
return [key, rewriteNode(entryValue, childMode(key), stripExamples)];
|
|
322
|
+
});
|
|
323
|
+
const rewritten = Object.fromEntries(entries);
|
|
324
|
+
return mode === "schemaMap" ? rewritten : normalizeExclusiveBounds(normalizeNullable(rewritten));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/openapi/loadSpec.ts
|
|
11
328
|
async function loadSpec(spec) {
|
|
12
329
|
const document = await _swaggerparser2.default.bundle(
|
|
13
330
|
spec
|
|
14
331
|
);
|
|
15
|
-
if (!_optionalChain([document, 'access',
|
|
332
|
+
if (!_optionalChain([document, 'access', _12 => _12.openapi, 'optionalAccess', _13 => _13.startsWith, 'call', _14 => _14("3.")])) {
|
|
16
333
|
throw new Error(
|
|
17
334
|
`fromOpenAPI only supports OpenAPI 3.x documents (found ${_nullishCoalesce(_nullishCoalesce(document.openapi, () => ( document.swagger)), () => ( "an unrecognized version"))}). Swagger 2.0 is not supported.`
|
|
18
335
|
);
|
|
19
336
|
}
|
|
337
|
+
resolveBundledPointerRefs(document);
|
|
20
338
|
return {
|
|
21
339
|
document,
|
|
22
340
|
origin: typeof spec === "string" && isHttpUrl(spec) ? spec : void 0
|
|
@@ -25,605 +343,386 @@ async function loadSpec(spec) {
|
|
|
25
343
|
function isHttpUrl(value) {
|
|
26
344
|
return /^https?:\/\//i.test(value);
|
|
27
345
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
candidate = `${base}_${suffix}`;
|
|
42
|
-
}
|
|
43
|
-
used.add(candidate);
|
|
44
|
-
names.set(route, candidate);
|
|
45
|
-
}
|
|
46
|
-
return names;
|
|
47
|
-
}
|
|
48
|
-
function baseNameFor(route, mcpNames) {
|
|
49
|
-
if (route.operationId) {
|
|
50
|
-
const override = mcpNames && Object.hasOwn(mcpNames, route.operationId) ? mcpNames[route.operationId] : void 0;
|
|
51
|
-
return _nullishCoalesce(override, () => ( route.operationId.split("__")[0]));
|
|
52
|
-
}
|
|
53
|
-
return route.summary || `${route.method}_${route.path}`;
|
|
54
|
-
}
|
|
55
|
-
function slugify(value) {
|
|
56
|
-
const slug = value.replace(/[^a-zA-Z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").slice(0, MAX_BASE_LENGTH);
|
|
57
|
-
return slug || "operation";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// src/openapi/requestBuilder.ts
|
|
61
|
-
async function executeRequest(options) {
|
|
62
|
-
const baseUrl = resolveBaseUrl(
|
|
63
|
-
options.servers,
|
|
64
|
-
options.origin,
|
|
65
|
-
options.baseUrlOverride
|
|
66
|
-
);
|
|
67
|
-
const pathParams = /* @__PURE__ */ Object.create(null);
|
|
68
|
-
const queryParts = [];
|
|
69
|
-
const headers = new Headers(await resolveHeaders(options.headers));
|
|
70
|
-
const bodyProps = /* @__PURE__ */ Object.create(null);
|
|
71
|
-
for (const [key, value] of Object.entries(options.args)) {
|
|
72
|
-
const mapping = options.parameterMap[key];
|
|
73
|
-
if (!mapping || value === void 0) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
switch (mapping.in) {
|
|
77
|
-
case "body":
|
|
78
|
-
bodyProps[mapping.name] = value;
|
|
79
|
-
break;
|
|
80
|
-
case "cookie": {
|
|
81
|
-
const pair = `${mapping.name}=${encodeCookieValue(mapping, value)}`;
|
|
82
|
-
const existing = headers.get("cookie");
|
|
83
|
-
headers.set("cookie", existing ? `${existing}; ${pair}` : pair);
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
case "header":
|
|
87
|
-
headers.set(mapping.name, String(value));
|
|
88
|
-
break;
|
|
89
|
-
case "path":
|
|
90
|
-
pathParams[mapping.name] = encodePathValue(
|
|
91
|
-
value,
|
|
92
|
-
mapping.style,
|
|
93
|
-
mapping.explode
|
|
94
|
-
);
|
|
95
|
-
break;
|
|
96
|
-
case "query": {
|
|
97
|
-
const query = new URLSearchParams();
|
|
98
|
-
appendQueryValue(
|
|
99
|
-
query,
|
|
100
|
-
mapping.name,
|
|
101
|
-
mapping.style,
|
|
102
|
-
value,
|
|
103
|
-
mapping.explode
|
|
104
|
-
);
|
|
105
|
-
if (query.size > 0) {
|
|
106
|
-
queryParts.push(serializeQuery(query, mapping.allowReserved));
|
|
107
|
-
}
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
346
|
+
function resolveBundledPointerRefs(document) {
|
|
347
|
+
const hoisted = /* @__PURE__ */ new Map();
|
|
348
|
+
let counter = 0;
|
|
349
|
+
const resolvePointer = (pointer) => {
|
|
350
|
+
let segments;
|
|
351
|
+
try {
|
|
352
|
+
segments = pointer.slice(2).split("/").map(
|
|
353
|
+
(segment) => decodeURIComponent(
|
|
354
|
+
segment.replaceAll("~1", "/").replaceAll("~0", "~")
|
|
355
|
+
)
|
|
356
|
+
);
|
|
357
|
+
} catch (e) {
|
|
358
|
+
return void 0;
|
|
110
359
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
assertNoSubstitutedDotSegments(options.route, path);
|
|
117
|
-
const url = new URL(baseUrl.replace(/\/$/, "") + path);
|
|
118
|
-
url.search = queryParts.join("&");
|
|
119
|
-
let body;
|
|
120
|
-
const requiredJsonBody = options.bodyEncoding === "json" && _optionalChain([options, 'access', _4 => _4.route, 'access', _5 => _5.requestBody, 'optionalAccess', _6 => _6.required]) === true && !options.wholeBodyKey;
|
|
121
|
-
if (Object.keys(bodyProps).length > 0 || requiredJsonBody) {
|
|
122
|
-
const payload = options.wholeBodyKey ? bodyProps[options.wholeBodyKey] : bodyProps;
|
|
123
|
-
if (options.bodyEncoding === "form") {
|
|
124
|
-
if (!headers.has("content-type")) {
|
|
125
|
-
headers.set("content-type", "application/x-www-form-urlencoded");
|
|
126
|
-
}
|
|
127
|
-
body = encodeFormBody(payload);
|
|
128
|
-
} else {
|
|
129
|
-
if (!headers.has("content-type")) {
|
|
130
|
-
headers.set("content-type", "application/json");
|
|
360
|
+
let node = document;
|
|
361
|
+
for (const segment of segments) {
|
|
362
|
+
if (!node || typeof node !== "object" || !Object.hasOwn(node, segment)) {
|
|
363
|
+
return void 0;
|
|
131
364
|
}
|
|
132
|
-
|
|
365
|
+
node = node[segment];
|
|
133
366
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const text = await response.text();
|
|
141
|
-
if (!response.ok) {
|
|
142
|
-
throw new (0, _chunkXPGMRMMNcjs.UserError)(
|
|
143
|
-
`${options.route.method.toUpperCase()} ${path} failed with ${response.status}: ${text.slice(0, 2e3)}`
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
const mediaType = _optionalChain([response, 'access', _7 => _7.headers, 'access', _8 => _8.get, 'call', _9 => _9("content-type"), 'optionalAccess', _10 => _10.split, 'call', _11 => _11(";"), 'access', _12 => _12[0]]);
|
|
147
|
-
if (_optionalChain([mediaType, 'optionalAccess', _13 => _13.toLowerCase, 'call', _14 => _14(), 'access', _15 => _15.includes, 'call', _16 => _16("json")])) {
|
|
148
|
-
try {
|
|
149
|
-
const json = JSON.parse(text);
|
|
150
|
-
return { json, text: JSON.stringify(json, null, 2) };
|
|
151
|
-
} catch (e) {
|
|
152
|
-
return { text };
|
|
367
|
+
return node;
|
|
368
|
+
};
|
|
369
|
+
const hoist = (ref) => {
|
|
370
|
+
const existing = hoisted.get(ref);
|
|
371
|
+
if (existing !== void 0) {
|
|
372
|
+
return existing;
|
|
153
373
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
function resolveBaseUrl(servers, origin, overrideUrl) {
|
|
158
|
-
if (overrideUrl) {
|
|
159
|
-
return overrideUrl.replace(/\/$/, "");
|
|
160
|
-
}
|
|
161
|
-
const server = _optionalChain([servers, 'optionalAccess', _17 => _17[0]]);
|
|
162
|
-
if (!server) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
"The OpenAPI document has no `servers` entry. Pass `baseUrl` to fromOpenAPI() explicitly."
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
let url = server.url;
|
|
168
|
-
for (const [name, variable] of Object.entries(_nullishCoalesce(server.variables, () => ( {})))) {
|
|
169
|
-
url = url.replaceAll(`{${name}}`, () => variable.default);
|
|
170
|
-
}
|
|
171
|
-
try {
|
|
172
|
-
return new URL(url).toString().replace(/\/$/, "");
|
|
173
|
-
} catch (e2) {
|
|
174
|
-
if (!origin) {
|
|
175
|
-
throw new Error(
|
|
176
|
-
`The OpenAPI document's servers[0].url ("${url}") is relative, and the spec was not loaded from an http(s) URL, so it cannot be resolved to an absolute address. Pass \`baseUrl\` to fromOpenAPI() explicitly.`
|
|
177
|
-
);
|
|
374
|
+
const target = resolvePointer(ref);
|
|
375
|
+
if (!target || typeof target !== "object") {
|
|
376
|
+
return void 0;
|
|
178
377
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
378
|
+
const schemas = (document.components ??= {}).schemas ??= {};
|
|
379
|
+
let name;
|
|
380
|
+
do {
|
|
381
|
+
name = `__bundle_${counter++}`;
|
|
382
|
+
} while (Object.hasOwn(schemas, name));
|
|
383
|
+
hoisted.set(ref, name);
|
|
384
|
+
schemas[name] = target;
|
|
385
|
+
walk(target, "schema");
|
|
386
|
+
return name;
|
|
387
|
+
};
|
|
388
|
+
const rewriteRef = (record) => {
|
|
389
|
+
const ref = record.$ref;
|
|
390
|
+
if (typeof ref !== "string" || !ref.startsWith("#/") || ref.startsWith("#/components/schemas/") || ref.startsWith("#/$defs/")) {
|
|
391
|
+
return;
|
|
190
392
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
for (const [subKey, subValue] of Object.entries(
|
|
195
|
-
value
|
|
196
|
-
)) {
|
|
197
|
-
if (subValue !== void 0) {
|
|
198
|
-
appendBracketPairs(params, `${key}[${subKey}]`, subValue);
|
|
199
|
-
}
|
|
393
|
+
const name = hoist(ref);
|
|
394
|
+
if (name !== void 0) {
|
|
395
|
+
record.$ref = `#/components/schemas/${name}`;
|
|
200
396
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
function appendQueryValue(query, name, style, value, explode) {
|
|
206
|
-
if (style === "deepObject") {
|
|
207
|
-
appendBracketPairs(query, name, value);
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
if (style === "spaceDelimited" || style === "pipeDelimited") {
|
|
211
|
-
const items = Array.isArray(value) ? value : [value];
|
|
212
|
-
const separator = style === "spaceDelimited" ? " " : "|";
|
|
213
|
-
query.append(name, items.map(String).join(separator));
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if ((style === void 0 || style === "form") && value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
217
|
-
const entries = Object.entries(value);
|
|
218
|
-
if (explode === false) {
|
|
219
|
-
if (entries.length > 0) {
|
|
220
|
-
query.append(
|
|
221
|
-
name,
|
|
222
|
-
entries.flatMap(([key, item]) => [key, String(item)]).join(",")
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
} else {
|
|
226
|
-
for (const [key, item] of entries) {
|
|
227
|
-
query.append(key, String(item));
|
|
228
|
-
}
|
|
397
|
+
};
|
|
398
|
+
const childMode2 = (key, mode) => {
|
|
399
|
+
if (mode === "schemaMap") {
|
|
400
|
+
return "schema";
|
|
229
401
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if ((style === void 0 || style === "form") && explode === false && Array.isArray(value) && value.length > 0) {
|
|
233
|
-
query.append(name, value.map(String).join(","));
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
for (const item of Array.isArray(value) ? value : [value]) {
|
|
237
|
-
query.append(name, String(item));
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
function assertNoSubstitutedDotSegments(route, resolvedPath) {
|
|
241
|
-
const templateSegments = new Set(route.path.split("/"));
|
|
242
|
-
for (const segment of resolvedPath.split("/")) {
|
|
243
|
-
if ((segment === "." || segment === "..") && !templateSegments.has(segment)) {
|
|
244
|
-
throw new (0, _chunkXPGMRMMNcjs.UserError)(
|
|
245
|
-
`${route.method.toUpperCase()} ${route.path}: path parameter values must not produce a "${segment}" path segment.`
|
|
246
|
-
);
|
|
402
|
+
if (mode === "schema") {
|
|
403
|
+
return SCHEMA_MAP_KEYS.has(key) ? "schemaMap" : "schema";
|
|
247
404
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
function encodeCookieValue(mapping, value) {
|
|
251
|
-
return (Array.isArray(value) ? value : [value]).map((item) => {
|
|
252
|
-
const text = String(item);
|
|
253
|
-
if (mapping.style !== "cookie") {
|
|
254
|
-
return encodePathComponent(text);
|
|
405
|
+
if (key === "schema") {
|
|
406
|
+
return "schema";
|
|
255
407
|
}
|
|
256
|
-
if (
|
|
257
|
-
|
|
258
|
-
`Cookie parameter "${mapping.name}" uses style "cookie" and its value contains ";" or ","`
|
|
259
|
-
);
|
|
408
|
+
if (mode === "document" && key === "components") {
|
|
409
|
+
return "components";
|
|
260
410
|
}
|
|
261
|
-
return
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
for (const [key, value] of Object.entries(
|
|
268
|
-
payload
|
|
269
|
-
)) {
|
|
270
|
-
if (value === void 0) {
|
|
271
|
-
continue;
|
|
411
|
+
return mode === "components" && key === "schemas" ? "schemaMap" : "document";
|
|
412
|
+
};
|
|
413
|
+
const walk = (value, mode) => {
|
|
414
|
+
if (Array.isArray(value)) {
|
|
415
|
+
for (const item of value) {
|
|
416
|
+
walk(item, mode);
|
|
272
417
|
}
|
|
273
|
-
|
|
418
|
+
return;
|
|
274
419
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
function encodePathComponent(value) {
|
|
279
|
-
return encodeURIComponent(value).replace(
|
|
280
|
-
/[!'()*]/g,
|
|
281
|
-
(character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
function encodePathValue(value, style, explode) {
|
|
285
|
-
if ((style === void 0 || style === "simple") && Array.isArray(value) && value.every((item) => item === null || typeof item !== "object")) {
|
|
286
|
-
return value.map((item) => encodePathComponent(String(item))).join(",");
|
|
287
|
-
}
|
|
288
|
-
if ((style === void 0 || style === "simple") && value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
289
|
-
const entries = Object.entries(value);
|
|
290
|
-
if (entries.every(([, item]) => item === null || typeof item !== "object")) {
|
|
291
|
-
return entries.map(([key, item]) => {
|
|
292
|
-
const encodedKey = encodePathComponent(key);
|
|
293
|
-
const encodedValue = encodePathComponent(String(item));
|
|
294
|
-
return explode === true ? `${encodedKey}=${encodedValue}` : `${encodedKey},${encodedValue}`;
|
|
295
|
-
}).join(",");
|
|
420
|
+
if (!value || typeof value !== "object") {
|
|
421
|
+
return;
|
|
296
422
|
}
|
|
297
|
-
|
|
298
|
-
|
|
423
|
+
const record = value;
|
|
424
|
+
for (const [key, entryValue] of Object.entries(record)) {
|
|
425
|
+
if (mode === "schema" && key === "$ref") {
|
|
426
|
+
rewriteRef(record);
|
|
427
|
+
} else if (mode !== "schema" || !DATA_KEYS.has(key)) {
|
|
428
|
+
walk(entryValue, childMode2(key, mode));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
walk(document, "document");
|
|
299
433
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
434
|
+
|
|
435
|
+
// src/openapi/naming.ts
|
|
436
|
+
var MAX_NAME_LENGTH = 56;
|
|
437
|
+
var MAX_BASE_LENGTH = MAX_NAME_LENGTH - 5;
|
|
438
|
+
function generateNames(routes, mcpNames) {
|
|
439
|
+
const names = /* @__PURE__ */ new Map();
|
|
440
|
+
const used = /* @__PURE__ */ new Set();
|
|
441
|
+
for (const route of routes) {
|
|
442
|
+
const base = slugify(baseNameFor(route, mcpNames));
|
|
443
|
+
let candidate = base;
|
|
444
|
+
let suffix = 1;
|
|
445
|
+
while (used.has(candidate)) {
|
|
446
|
+
suffix += 1;
|
|
447
|
+
candidate = `${base}_${suffix}`;
|
|
448
|
+
}
|
|
449
|
+
used.add(candidate);
|
|
450
|
+
names.set(route, candidate);
|
|
303
451
|
}
|
|
304
|
-
return
|
|
452
|
+
return names;
|
|
305
453
|
}
|
|
306
|
-
function
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
return
|
|
454
|
+
function baseNameFor(route, mcpNames) {
|
|
455
|
+
if (route.operationId) {
|
|
456
|
+
const override = mcpNames && Object.hasOwn(mcpNames, route.operationId) ? mcpNames[route.operationId] : void 0;
|
|
457
|
+
return _nullishCoalesce(override, () => ( route.operationId.split("__")[0]));
|
|
310
458
|
}
|
|
311
|
-
return
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
);
|
|
317
|
-
return `${name}=${expanded}`;
|
|
318
|
-
}).join("&");
|
|
459
|
+
return route.summary || `${route.method}_${route.path}`;
|
|
460
|
+
}
|
|
461
|
+
function slugify(value) {
|
|
462
|
+
const slug = value.replace(/[^a-zA-Z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").slice(0, MAX_BASE_LENGTH);
|
|
463
|
+
return slug || "operation";
|
|
319
464
|
}
|
|
320
465
|
|
|
321
|
-
// src/openapi/
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
"properties"
|
|
328
|
-
]);
|
|
329
|
-
var DATA_KEYS = /* @__PURE__ */ new Set(["const", "default", "enum", "example", "examples"]);
|
|
330
|
-
var STRIP_KEYS = /* @__PURE__ */ new Set(["example", "examples"]);
|
|
331
|
-
function buildFlatSchema(route, sharedDefs) {
|
|
332
|
-
const byName = /* @__PURE__ */ new Map();
|
|
333
|
-
for (const param of route.parameters) {
|
|
334
|
-
const list = _nullishCoalesce(byName.get(param.name), () => ( []));
|
|
335
|
-
list.push(param);
|
|
336
|
-
byName.set(param.name, list);
|
|
337
|
-
}
|
|
338
|
-
const {
|
|
339
|
-
bodyEncoding,
|
|
340
|
-
properties: bodyProperties,
|
|
341
|
-
unsupportedBodyContentType,
|
|
342
|
-
wholeBodyKey
|
|
343
|
-
} = extractBodyProperties(
|
|
344
|
-
route.method === "get" ? void 0 : route.requestBody,
|
|
345
|
-
sharedDefs
|
|
466
|
+
// src/openapi/requestBuilder.ts
|
|
467
|
+
async function executeRequest(options) {
|
|
468
|
+
const baseUrl = resolveBaseUrl(
|
|
469
|
+
options.servers,
|
|
470
|
+
options.origin,
|
|
471
|
+
options.baseUrlOverride
|
|
346
472
|
);
|
|
347
|
-
const
|
|
348
|
-
const
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
for (const [
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
const allocateAlias = (base) => {
|
|
357
|
-
let key = base;
|
|
358
|
-
let suffix = 1;
|
|
359
|
-
while (used.has(key)) {
|
|
360
|
-
suffix += 1;
|
|
361
|
-
key = `${base}_${suffix}`;
|
|
473
|
+
const pathParams = /* @__PURE__ */ Object.create(null);
|
|
474
|
+
const queryParts = [];
|
|
475
|
+
const headers = new Headers(await resolveHeaders(options.headers));
|
|
476
|
+
const bodyProps = /* @__PURE__ */ Object.create(null);
|
|
477
|
+
for (const [key, value] of Object.entries(options.args)) {
|
|
478
|
+
const mapping = options.parameterMap[key];
|
|
479
|
+
if (!mapping || value === void 0) {
|
|
480
|
+
continue;
|
|
362
481
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
482
|
+
switch (mapping.in) {
|
|
483
|
+
case "body":
|
|
484
|
+
bodyProps[mapping.name] = value;
|
|
485
|
+
break;
|
|
486
|
+
case "cookie": {
|
|
487
|
+
const pair = `${mapping.name}=${encodeCookieValue(mapping, value)}`;
|
|
488
|
+
const existing = headers.get("cookie");
|
|
489
|
+
headers.set("cookie", existing ? `${existing}; ${pair}` : pair);
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
case "header":
|
|
493
|
+
headers.set(mapping.name, String(value));
|
|
494
|
+
break;
|
|
495
|
+
case "path":
|
|
496
|
+
pathParams[mapping.name] = encodePathValue(
|
|
497
|
+
value,
|
|
498
|
+
mapping.style,
|
|
499
|
+
mapping.explode
|
|
500
|
+
);
|
|
501
|
+
break;
|
|
502
|
+
case "query": {
|
|
503
|
+
const query = new URLSearchParams();
|
|
504
|
+
appendQueryValue(
|
|
505
|
+
query,
|
|
506
|
+
mapping.name,
|
|
507
|
+
mapping.style,
|
|
508
|
+
value,
|
|
509
|
+
mapping.explode
|
|
510
|
+
);
|
|
511
|
+
if (query.size > 0) {
|
|
512
|
+
queryParts.push(serializeQuery(query, mapping.allowReserved));
|
|
513
|
+
}
|
|
514
|
+
break;
|
|
383
515
|
}
|
|
384
516
|
}
|
|
385
517
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
518
|
+
let path = options.route.path;
|
|
519
|
+
for (const [name, value] of Object.entries(pathParams)) {
|
|
520
|
+
path = path.replaceAll(`{${name}}`, value);
|
|
521
|
+
}
|
|
522
|
+
assertNoSubstitutedDotSegments(options.route, path);
|
|
523
|
+
const url = new URL(baseUrl.replace(/\/$/, "") + path);
|
|
524
|
+
url.search = queryParts.join("&");
|
|
525
|
+
let body;
|
|
526
|
+
const requiredJsonBody = options.bodyEncoding === "json" && _optionalChain([options, 'access', _15 => _15.route, 'access', _16 => _16.requestBody, 'optionalAccess', _17 => _17.required]) === true && !options.wholeBodyKey;
|
|
527
|
+
if (Object.keys(bodyProps).length > 0 || requiredJsonBody) {
|
|
528
|
+
const payload = options.wholeBodyKey ? bodyProps[options.wholeBodyKey] : bodyProps;
|
|
529
|
+
if (options.bodyEncoding === "form") {
|
|
530
|
+
if (!headers.has("content-type")) {
|
|
531
|
+
headers.set("content-type", "application/x-www-form-urlencoded");
|
|
532
|
+
}
|
|
533
|
+
body = encodeFormBody(payload);
|
|
534
|
+
} else {
|
|
535
|
+
if (!headers.has("content-type")) {
|
|
536
|
+
headers.set("content-type", "application/json");
|
|
537
|
+
}
|
|
538
|
+
body = JSON.stringify(payload);
|
|
392
539
|
}
|
|
393
540
|
}
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
};
|
|
400
|
-
const
|
|
401
|
-
if (
|
|
402
|
-
|
|
541
|
+
const response = await options.fetchImpl(url.toString(), {
|
|
542
|
+
body,
|
|
543
|
+
headers,
|
|
544
|
+
method: options.route.method.toUpperCase(),
|
|
545
|
+
signal: options.signal
|
|
546
|
+
});
|
|
547
|
+
const text = await response.text();
|
|
548
|
+
if (!response.ok) {
|
|
549
|
+
throw new (0, _chunkP56ABHAKcjs.UserError)(
|
|
550
|
+
`${options.route.method.toUpperCase()} ${path} failed with ${response.status}: ${text.slice(0, 2e3)}`
|
|
551
|
+
);
|
|
403
552
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
function buildSharedDefs(document) {
|
|
413
|
-
const schemas = _optionalChain([document, 'access', _18 => _18.components, 'optionalAccess', _19 => _19.schemas]);
|
|
414
|
-
if (!schemas || Object.keys(schemas).length === 0) {
|
|
415
|
-
return void 0;
|
|
553
|
+
const mediaType = _optionalChain([response, 'access', _18 => _18.headers, 'access', _19 => _19.get, 'call', _20 => _20("content-type"), 'optionalAccess', _21 => _21.split, 'call', _22 => _22(";"), 'access', _23 => _23[0]]);
|
|
554
|
+
if (_optionalChain([mediaType, 'optionalAccess', _24 => _24.toLowerCase, 'call', _25 => _25(), 'access', _26 => _26.includes, 'call', _27 => _27("json")])) {
|
|
555
|
+
try {
|
|
556
|
+
const json = JSON.parse(text);
|
|
557
|
+
return { json, text: JSON.stringify(json, null, 2) };
|
|
558
|
+
} catch (e2) {
|
|
559
|
+
return { text };
|
|
560
|
+
}
|
|
416
561
|
}
|
|
417
|
-
return
|
|
562
|
+
return { text };
|
|
418
563
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const successEntry = Object.entries(_nullishCoalesce(route.responses, () => ( {}))).find(
|
|
423
|
-
([code]) => SUCCESS_STATUS_PATTERN.test(code)
|
|
424
|
-
);
|
|
425
|
-
const declaredSchema = _optionalChain([findMediaType, 'call', _20 => _20(
|
|
426
|
-
_optionalChain([successEntry, 'optionalAccess', _21 => _21[1], 'access', _22 => _22.content]),
|
|
427
|
-
"application/json"
|
|
428
|
-
), 'optionalAccess', _23 => _23.schema]);
|
|
429
|
-
if (!declaredSchema) {
|
|
430
|
-
return void 0;
|
|
431
|
-
}
|
|
432
|
-
const schema = resolveComponentRef(declaredSchema, sharedDefs);
|
|
433
|
-
const rewritten = rewriteComponentRefs(schema, true);
|
|
434
|
-
const { type } = rewritten;
|
|
435
|
-
const isObjectShaped = type === "object" || Array.isArray(type) && type.includes("object");
|
|
436
|
-
if (!isObjectShaped) {
|
|
437
|
-
return void 0;
|
|
438
|
-
}
|
|
439
|
-
const normalized = { ...rewritten, type: "object" };
|
|
440
|
-
const usedDefs = sharedDefs && filterReferencedDefs(normalized, sharedDefs);
|
|
441
|
-
if (usedDefs && Object.keys(usedDefs).length > MAX_OUTPUT_SCHEMA_DEFS) {
|
|
442
|
-
return void 0;
|
|
564
|
+
function resolveBaseUrl(servers, origin, overrideUrl) {
|
|
565
|
+
if (overrideUrl) {
|
|
566
|
+
return overrideUrl.replace(/\/$/, "");
|
|
443
567
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
568
|
+
const server = _optionalChain([servers, 'optionalAccess', _28 => _28[0]]);
|
|
569
|
+
if (!server) {
|
|
570
|
+
throw new Error(
|
|
571
|
+
"The OpenAPI document has no `servers` entry. Pass `baseUrl` to fromOpenAPI() explicitly."
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
let url = server.url;
|
|
575
|
+
for (const [name, variable] of Object.entries(_nullishCoalesce(server.variables, () => ( {})))) {
|
|
576
|
+
url = url.replaceAll(`{${name}}`, () => variable.default);
|
|
577
|
+
}
|
|
578
|
+
try {
|
|
579
|
+
return new URL(url).toString().replace(/\/$/, "");
|
|
580
|
+
} catch (e3) {
|
|
581
|
+
if (!origin) {
|
|
582
|
+
throw new Error(
|
|
583
|
+
`The OpenAPI document's servers[0].url ("${url}") is relative, and the spec was not loaded from an http(s) URL, so it cannot be resolved to an absolute address. Pass \`baseUrl\` to fromOpenAPI() explicitly.`
|
|
584
|
+
);
|
|
460
585
|
}
|
|
461
|
-
|
|
462
|
-
current = target;
|
|
463
|
-
ref = current.$ref;
|
|
586
|
+
return new URL(url, origin).toString().replace(/\/$/, "");
|
|
464
587
|
}
|
|
465
|
-
return current;
|
|
466
|
-
}
|
|
467
|
-
function rewriteComponentRefs(value, stripExamples = false) {
|
|
468
|
-
return rewriteNode(value, "schema", stripExamples);
|
|
469
588
|
}
|
|
470
|
-
function
|
|
471
|
-
if (
|
|
472
|
-
|
|
589
|
+
function appendBracketPairs(params, key, value) {
|
|
590
|
+
if (Array.isArray(value)) {
|
|
591
|
+
for (const item of value) {
|
|
592
|
+
if (item !== null && typeof item === "object") {
|
|
593
|
+
appendBracketPairs(params, `${key}[]`, item);
|
|
594
|
+
} else {
|
|
595
|
+
params.append(key, String(item));
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return;
|
|
473
599
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
600
|
+
if (value !== null && typeof value === "object") {
|
|
601
|
+
for (const [subKey, subValue] of Object.entries(
|
|
602
|
+
value
|
|
603
|
+
)) {
|
|
604
|
+
if (subValue !== void 0) {
|
|
605
|
+
appendBracketPairs(params, `${key}[${subKey}]`, subValue);
|
|
606
|
+
}
|
|
480
607
|
}
|
|
608
|
+
return;
|
|
481
609
|
}
|
|
482
|
-
|
|
610
|
+
params.append(key, String(value));
|
|
483
611
|
}
|
|
484
|
-
function
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
return { properties };
|
|
489
|
-
}
|
|
490
|
-
const json = findMediaType(content, "application/json");
|
|
491
|
-
const form = findMediaType(content, "application/x-www-form-urlencoded");
|
|
492
|
-
if (json === void 0 && form === void 0) {
|
|
493
|
-
const contentTypes = Object.keys(content);
|
|
494
|
-
return contentTypes.length > 0 ? { properties, unsupportedBodyContentType: contentTypes[0] } : { properties };
|
|
612
|
+
function appendQueryValue(query, name, style, value, explode) {
|
|
613
|
+
if (style === "deepObject") {
|
|
614
|
+
appendBracketPairs(query, name, value);
|
|
615
|
+
return;
|
|
495
616
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
617
|
+
if (style === "spaceDelimited" || style === "pipeDelimited") {
|
|
618
|
+
const items = Array.isArray(value) ? value : [value];
|
|
619
|
+
const separator = style === "spaceDelimited" ? " " : "|";
|
|
620
|
+
query.append(name, items.map(String).join(separator));
|
|
621
|
+
return;
|
|
500
622
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
623
|
+
if ((style === void 0 || style === "form") && value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
624
|
+
const entries = Object.entries(value);
|
|
625
|
+
if (explode === false) {
|
|
626
|
+
if (entries.length > 0) {
|
|
627
|
+
query.append(
|
|
628
|
+
name,
|
|
629
|
+
entries.flatMap(([key, item]) => [key, String(item)]).join(",")
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
for (const [key, item] of entries) {
|
|
634
|
+
query.append(key, String(item));
|
|
635
|
+
}
|
|
512
636
|
}
|
|
513
|
-
return
|
|
637
|
+
return;
|
|
514
638
|
}
|
|
515
|
-
if (
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
639
|
+
if ((style === void 0 || style === "form") && explode === false && Array.isArray(value) && value.length > 0) {
|
|
640
|
+
query.append(name, value.map(String).join(","));
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
644
|
+
query.append(name, String(item));
|
|
520
645
|
}
|
|
521
|
-
properties.set("body", {
|
|
522
|
-
required: _nullishCoalesce(_optionalChain([requestBody, 'optionalAccess', _28 => _28.required]), () => ( false)),
|
|
523
|
-
schema
|
|
524
|
-
});
|
|
525
|
-
return { bodyEncoding, properties, wholeBodyKey: "body" };
|
|
526
646
|
}
|
|
527
|
-
function
|
|
528
|
-
const
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
continue;
|
|
647
|
+
function assertNoSubstitutedDotSegments(route, resolvedPath) {
|
|
648
|
+
const templateSegments = new Set(route.path.split("/"));
|
|
649
|
+
for (const segment of resolvedPath.split("/")) {
|
|
650
|
+
if ((segment === "." || segment === "..") && !templateSegments.has(segment)) {
|
|
651
|
+
throw new (0, _chunkP56ABHAKcjs.UserError)(
|
|
652
|
+
`${route.method.toUpperCase()} ${route.path}: path parameter values must not produce a "${segment}" path segment.`
|
|
653
|
+
);
|
|
535
654
|
}
|
|
536
|
-
|
|
537
|
-
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
function encodeCookieValue(mapping, value) {
|
|
658
|
+
return (Array.isArray(value) ? value : [value]).map((item) => {
|
|
659
|
+
const text = String(item);
|
|
660
|
+
if (mapping.style !== "cookie") {
|
|
661
|
+
return encodePathComponent(text);
|
|
538
662
|
}
|
|
663
|
+
if (/[;,]/.test(text)) {
|
|
664
|
+
throw new (0, _chunkP56ABHAKcjs.UserError)(
|
|
665
|
+
`Cookie parameter "${mapping.name}" uses style "cookie" and its value contains ";" or ","`
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
return text;
|
|
669
|
+
}).join(",");
|
|
670
|
+
}
|
|
671
|
+
function encodeFormBody(payload) {
|
|
672
|
+
const params = new URLSearchParams();
|
|
673
|
+
if (payload && typeof payload === "object" && !Array.isArray(payload)) {
|
|
539
674
|
for (const [key, value] of Object.entries(
|
|
540
|
-
|
|
675
|
+
payload
|
|
541
676
|
)) {
|
|
542
|
-
if (
|
|
543
|
-
const [name = ""] = value.slice("#/$defs/".length).split("/");
|
|
544
|
-
if (allDefs[name] && !referenced.has(name)) {
|
|
545
|
-
referenced.add(name);
|
|
546
|
-
stack.push(allDefs[name]);
|
|
547
|
-
}
|
|
677
|
+
if (value === void 0) {
|
|
548
678
|
continue;
|
|
549
679
|
}
|
|
550
|
-
|
|
680
|
+
appendBracketPairs(params, key, value);
|
|
551
681
|
}
|
|
552
682
|
}
|
|
553
|
-
|
|
554
|
-
return void 0;
|
|
555
|
-
}
|
|
556
|
-
return Object.fromEntries(
|
|
557
|
-
[...referenced].map((name) => [name, allDefs[name]])
|
|
558
|
-
);
|
|
683
|
+
return params.toString();
|
|
559
684
|
}
|
|
560
|
-
function
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const key = Object.hasOwn(content, mediaType) ? mediaType : Object.keys(content).find(
|
|
565
|
-
(candidate) => candidate.split(";")[0].trim().toLowerCase() === mediaType
|
|
685
|
+
function encodePathComponent(value) {
|
|
686
|
+
return encodeURIComponent(value).replace(
|
|
687
|
+
/[!'()*]/g,
|
|
688
|
+
(character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
|
|
566
689
|
);
|
|
567
|
-
return key === void 0 ? void 0 : content[key];
|
|
568
690
|
}
|
|
569
|
-
function
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
return schema;
|
|
691
|
+
function encodePathValue(value, style, explode) {
|
|
692
|
+
if ((style === void 0 || style === "simple") && Array.isArray(value) && value.every((item) => item === null || typeof item !== "object")) {
|
|
693
|
+
return value.map((item) => encodePathComponent(String(item))).join(",");
|
|
573
694
|
}
|
|
574
|
-
if (
|
|
575
|
-
|
|
695
|
+
if ((style === void 0 || style === "simple") && value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
696
|
+
const entries = Object.entries(value);
|
|
697
|
+
if (entries.every(([, item]) => item === null || typeof item !== "object")) {
|
|
698
|
+
return entries.map(([key, item]) => {
|
|
699
|
+
const encodedKey = encodePathComponent(key);
|
|
700
|
+
const encodedValue = encodePathComponent(String(item));
|
|
701
|
+
return explode === true ? `${encodedKey}=${encodedValue}` : `${encodedKey},${encodedValue}`;
|
|
702
|
+
}).join(",");
|
|
703
|
+
}
|
|
576
704
|
}
|
|
577
|
-
|
|
578
|
-
return { ...unbounded, [exclusiveKey]: bound };
|
|
579
|
-
}
|
|
580
|
-
function normalizeExclusiveBounds(schema) {
|
|
581
|
-
return normalizeExclusiveBound(
|
|
582
|
-
normalizeExclusiveBound(schema, "exclusiveMinimum", "minimum"),
|
|
583
|
-
"exclusiveMaximum",
|
|
584
|
-
"maximum"
|
|
585
|
-
);
|
|
705
|
+
return encodeURIComponent(String(value));
|
|
586
706
|
}
|
|
587
|
-
function
|
|
588
|
-
if (!
|
|
589
|
-
return
|
|
590
|
-
}
|
|
591
|
-
const { nullable, ...rest } = schema;
|
|
592
|
-
if (nullable !== true) {
|
|
593
|
-
return rest;
|
|
594
|
-
}
|
|
595
|
-
const { type } = rest;
|
|
596
|
-
if (typeof type === "string") {
|
|
597
|
-
return { ...rest, type: [type, "null"] };
|
|
598
|
-
}
|
|
599
|
-
if (Array.isArray(type)) {
|
|
600
|
-
return { ...rest, type: [.../* @__PURE__ */ new Set(["null", ...type])] };
|
|
707
|
+
async function resolveHeaders(headers) {
|
|
708
|
+
if (!headers) {
|
|
709
|
+
return {};
|
|
601
710
|
}
|
|
602
|
-
return
|
|
711
|
+
return typeof headers === "function" ? await headers() : { ...headers };
|
|
603
712
|
}
|
|
604
|
-
function
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
if (Array.isArray(value)) {
|
|
609
|
-
return value.map((item) => rewriteNode(item, "schema", stripExamples));
|
|
610
|
-
}
|
|
611
|
-
if (!value || typeof value !== "object") {
|
|
612
|
-
return value;
|
|
713
|
+
function serializeQuery(query, allowReserved) {
|
|
714
|
+
const encoded = query.toString();
|
|
715
|
+
if (!allowReserved) {
|
|
716
|
+
return encoded;
|
|
613
717
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}
|
|
623
|
-
return [key, rewriteNode(entryValue, childMode(key), stripExamples)];
|
|
624
|
-
});
|
|
625
|
-
const rewritten = Object.fromEntries(entries);
|
|
626
|
-
return mode === "schemaMap" ? rewritten : normalizeExclusiveBounds(normalizeNullable(rewritten));
|
|
718
|
+
return encoded.split("&").map((pair) => {
|
|
719
|
+
const [name, value] = pair.split("=");
|
|
720
|
+
const expanded = value.replace(
|
|
721
|
+
/\+|%25([\da-f]{2})|%(21|24|27|28|29|2c|2f|3a|3b|3f|40|7e)/gi,
|
|
722
|
+
(match, triple) => triple ? `%${triple}` : match === "+" ? "%20" : decodeURIComponent(match)
|
|
723
|
+
);
|
|
724
|
+
return `${name}=${expanded}`;
|
|
725
|
+
}).join("&");
|
|
627
726
|
}
|
|
628
727
|
|
|
629
728
|
// src/openapi/resourceMapping.ts
|
|
@@ -806,7 +905,7 @@ async function fromOpenAPI(options) {
|
|
|
806
905
|
const selected = selectRoutes(routes, options);
|
|
807
906
|
const names = generateNames(selected, options.mcpNames);
|
|
808
907
|
const sharedDefs = buildSharedDefs(document);
|
|
809
|
-
const server = _nullishCoalesce(options.server, () => ( new (0,
|
|
908
|
+
const server = _nullishCoalesce(options.server, () => ( new (0, _chunkP56ABHAKcjs.FastMCP)({
|
|
810
909
|
name: _nullishCoalesce(_nullishCoalesce(options.name, () => ( _optionalChain([document, 'access', _31 => _31.info, 'optionalAccess', _32 => _32.title]))), () => ( "OpenAPI Server")),
|
|
811
910
|
version: _nullishCoalesce(options.version, () => ( "1.0.0"))
|
|
812
911
|
})));
|
|
@@ -852,20 +951,21 @@ async function fromOpenAPI(options) {
|
|
|
852
951
|
continue;
|
|
853
952
|
}
|
|
854
953
|
const outputSchemaJson = buildOutputSchema(route, sharedDefs);
|
|
855
|
-
const outputSchema = outputSchemaJson ?
|
|
954
|
+
const outputSchema = outputSchemaJson ? _chunkP56ABHAKcjs.jsonSchemaAdapter.call(void 0, outputSchemaJson) : void 0;
|
|
856
955
|
server.addTool({
|
|
857
956
|
description: _nullishCoalesce(route.summary, () => ( `${route.method.toUpperCase()} ${route.path}`)),
|
|
858
|
-
execute: async (args) => {
|
|
957
|
+
execute: async (args, { signal }) => {
|
|
859
958
|
const result = await executeRequest({
|
|
860
959
|
...execOptions,
|
|
861
960
|
args,
|
|
862
961
|
bodyEncoding,
|
|
962
|
+
signal,
|
|
863
963
|
wholeBodyKey
|
|
864
964
|
});
|
|
865
965
|
return resolveToolResult(result, outputSchema);
|
|
866
966
|
},
|
|
867
967
|
name,
|
|
868
|
-
parameters:
|
|
968
|
+
parameters: _chunkP56ABHAKcjs.jsonSchemaAdapter.call(void 0, flatSchema),
|
|
869
969
|
...outputSchema ? { outputSchema } : {}
|
|
870
970
|
});
|
|
871
971
|
}
|
|
@@ -922,7 +1022,7 @@ function wrapAsResourceResult({ text }) {
|
|
|
922
1022
|
try {
|
|
923
1023
|
JSON.parse(text);
|
|
924
1024
|
return { mimeType: "application/json", text };
|
|
925
|
-
} catch (
|
|
1025
|
+
} catch (e4) {
|
|
926
1026
|
return { mimeType: "text/plain", text };
|
|
927
1027
|
}
|
|
928
1028
|
}
|