fastmcp 4.22.0 → 4.22.2

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.
@@ -2,7 +2,7 @@ import {
2
2
  FastMCP,
3
3
  UserError,
4
4
  jsonSchemaAdapter
5
- } from "../chunk-43N2Q6ZI.js";
5
+ } from "../chunk-TFX7BV4K.js";
6
6
  import "../chunk-XPKMA7DH.js";
7
7
  import "../chunk-UMDUIBFW.js";
8
8
 
@@ -231,123 +231,6 @@ async function resolveHeaders(headers) {
231
231
  return typeof headers === "function" ? await headers() : { ...headers };
232
232
  }
233
233
 
234
- // src/openapi/resourceMapping.ts
235
- function buildResourceMapping(route, name, parameterMap, requiredKeys) {
236
- const entries = Object.entries(parameterMap);
237
- if (entries.length === 0) {
238
- return { kind: "resource", uri: `openapi://${name}${route.path}` };
239
- }
240
- const required = new Set(requiredKeys ?? []);
241
- const args = [];
242
- const queryKeys = [];
243
- let path = route.path;
244
- for (const [flatKey, mapping] of entries) {
245
- if (mapping.in === "path") {
246
- if (flatKey !== mapping.name) {
247
- path = path.replaceAll(`{${mapping.name}}`, `{${flatKey}}`);
248
- }
249
- } else {
250
- queryKeys.push(flatKey);
251
- }
252
- args.push({ name: flatKey, required: required.has(flatKey) });
253
- }
254
- const uriTemplate = `openapi://${name}${path}` + (queryKeys.length > 0 ? `{?${queryKeys.join(",")}}` : "");
255
- return { args, kind: "template", uriTemplate };
256
- }
257
- function isEligibleForResource(route) {
258
- return route.parameters.every((param) => {
259
- if (param.in === "header" || param.in === "cookie") {
260
- return false;
261
- }
262
- return param.schema?.type !== "array";
263
- });
264
- }
265
-
266
- // src/openapi/routes.ts
267
- var HTTP_METHODS = ["get", "put", "post", "delete", "patch"];
268
- function extractRoutes(document) {
269
- const routes = [];
270
- for (const [path, rawPathItem] of Object.entries(document.paths ?? {})) {
271
- const pathItem = resolvePathItem(document, rawPathItem);
272
- const pathLevelParams = (pathItem.parameters ?? []).map(
273
- (param) => resolveRef(document, param)
274
- );
275
- for (const method of HTTP_METHODS) {
276
- const operation = pathItem[method];
277
- if (!operation) {
278
- continue;
279
- }
280
- const operationParams = (operation.parameters ?? []).map(
281
- (param) => resolveRef(document, param)
282
- );
283
- routes.push({
284
- deprecated: operation.deprecated ?? false,
285
- method,
286
- operationId: operation.operationId,
287
- parameters: mergeParameters(pathLevelParams, operationParams),
288
- path,
289
- requestBody: operation.requestBody ? resolveRef(document, operation.requestBody) : void 0,
290
- responses: resolveResponses(document, operation.responses),
291
- servers: [operation.servers, pathItem.servers, document.servers].find(
292
- (servers) => servers?.length
293
- ),
294
- summary: operation.summary,
295
- tags: operation.tags ?? []
296
- });
297
- }
298
- }
299
- return routes;
300
- }
301
- function mergeParameters(pathLevel, operationLevel) {
302
- const overridden = new Set(
303
- operationLevel.map((param) => `${param.in}:${param.name}`)
304
- );
305
- return [
306
- ...pathLevel.filter(
307
- (param) => !overridden.has(`${param.in}:${param.name}`)
308
- ),
309
- ...operationLevel
310
- ];
311
- }
312
- function resolvePathItem(document, pathItem) {
313
- const visited = /* @__PURE__ */ new Set();
314
- let resolved = pathItem;
315
- while (resolved.$ref && !visited.has(resolved.$ref)) {
316
- visited.add(resolved.$ref);
317
- const { $ref, ...siblings } = resolved;
318
- resolved = { ...resolveRef(document, { $ref }), ...siblings };
319
- }
320
- return resolved;
321
- }
322
- function resolveRef(document, value) {
323
- if (!value || typeof value !== "object" || !("$ref" in value)) {
324
- return value;
325
- }
326
- const pointer = value.$ref;
327
- if (!pointer.startsWith("#/")) {
328
- throw new Error(`Unexpected external $ref after bundling: ${pointer}`);
329
- }
330
- const segments = pointer.slice(2).split("/").map(
331
- (segment) => decodeURIComponent(segment.replaceAll("~1", "/").replaceAll("~0", "~"))
332
- );
333
- let node = document;
334
- for (const segment of segments) {
335
- node = node?.[segment];
336
- }
337
- return node;
338
- }
339
- function resolveResponses(document, rawResponses) {
340
- if (!rawResponses) {
341
- return void 0;
342
- }
343
- return Object.fromEntries(
344
- Object.entries(rawResponses).map(([code, response]) => [
345
- code,
346
- resolveRef(document, response)
347
- ])
348
- );
349
- }
350
-
351
234
  // src/openapi/schemas.ts
352
235
  var SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
353
236
  "$defs",
@@ -377,10 +260,23 @@ function buildFlatSchema(route, sharedDefs) {
377
260
  const properties = {};
378
261
  const required = [];
379
262
  const parameterMap = {};
263
+ const used = new Set(bodyProperties.keys());
264
+ for (const [name, occurrences] of byName) {
265
+ if (occurrences.length === 1 && !bodyProperties.has(name)) {
266
+ used.add(name);
267
+ }
268
+ }
380
269
  for (const [name, occurrences] of byName) {
381
270
  const collides = occurrences.length > 1 || bodyProperties.has(name);
382
271
  for (const param of occurrences) {
383
- const key = collides ? `${name}__${param.in}` : name;
272
+ const base = collides ? `${name}__${param.in}` : name;
273
+ let key = base;
274
+ let suffix = 1;
275
+ while (collides && used.has(key)) {
276
+ suffix += 1;
277
+ key = `${base}_${suffix}`;
278
+ }
279
+ used.add(key);
384
280
  properties[key] = rewriteComponentRefs(
385
281
  param.schema ?? { type: "string" }
386
282
  );
@@ -456,6 +352,22 @@ function buildOutputSchema(route, sharedDefs) {
456
352
  } : {}
457
353
  };
458
354
  }
355
+ function resolveComponentRef(schema, sharedDefs) {
356
+ const seen = /* @__PURE__ */ new Set();
357
+ let current = schema;
358
+ let ref = current.$ref;
359
+ while (typeof ref === "string") {
360
+ const name = componentSchemaName(ref);
361
+ const target = name === void 0 ? void 0 : sharedDefs?.[name];
362
+ if (name === void 0 || target === void 0 || seen.has(name)) {
363
+ break;
364
+ }
365
+ seen.add(name);
366
+ current = target;
367
+ ref = current.$ref;
368
+ }
369
+ return current;
370
+ }
459
371
  function rewriteComponentRefs(value, stripExamples = false) {
460
372
  return rewriteNode(value, "schema", stripExamples);
461
373
  }
@@ -584,22 +496,6 @@ function normalizeNullable(schema) {
584
496
  }
585
497
  return rest;
586
498
  }
587
- function resolveComponentRef(schema, sharedDefs) {
588
- const seen = /* @__PURE__ */ new Set();
589
- let current = schema;
590
- let ref = current.$ref;
591
- while (typeof ref === "string") {
592
- const name = componentSchemaName(ref);
593
- const target = name === void 0 ? void 0 : sharedDefs?.[name];
594
- if (name === void 0 || target === void 0 || seen.has(name)) {
595
- break;
596
- }
597
- seen.add(name);
598
- current = target;
599
- ref = current.$ref;
600
- }
601
- return current;
602
- }
603
499
  function rewriteNode(value, mode, stripExamples = false) {
604
500
  if (mode === "data") {
605
501
  return value;
@@ -625,6 +521,124 @@ function rewriteNode(value, mode, stripExamples = false) {
625
521
  return mode === "schemaMap" ? rewritten : normalizeExclusiveBounds(normalizeNullable(rewritten));
626
522
  }
627
523
 
524
+ // src/openapi/resourceMapping.ts
525
+ function buildResourceMapping(route, name, parameterMap, requiredKeys) {
526
+ const entries = Object.entries(parameterMap);
527
+ if (entries.length === 0) {
528
+ return { kind: "resource", uri: `openapi://${name}${route.path}` };
529
+ }
530
+ const required = new Set(requiredKeys ?? []);
531
+ const args = [];
532
+ const queryKeys = [];
533
+ let path = route.path;
534
+ for (const [flatKey, mapping] of entries) {
535
+ if (mapping.in === "path") {
536
+ if (flatKey !== mapping.name) {
537
+ path = path.replaceAll(`{${mapping.name}}`, `{${flatKey}}`);
538
+ }
539
+ } else {
540
+ queryKeys.push(flatKey);
541
+ }
542
+ args.push({ name: flatKey, required: required.has(flatKey) });
543
+ }
544
+ const uriTemplate = `openapi://${name}${path}` + (queryKeys.length > 0 ? `{?${queryKeys.join(",")}}` : "");
545
+ return { args, kind: "template", uriTemplate };
546
+ }
547
+ function isEligibleForResource(route, sharedDefs) {
548
+ return route.parameters.every((param) => {
549
+ if (param.in === "header" || param.in === "cookie") {
550
+ return false;
551
+ }
552
+ const type = resolveComponentRef(param.schema ?? {}, sharedDefs).type;
553
+ return type !== "array" && (!Array.isArray(type) || !type.includes("array"));
554
+ });
555
+ }
556
+
557
+ // src/openapi/routes.ts
558
+ var HTTP_METHODS = ["get", "put", "post", "delete", "patch"];
559
+ function extractRoutes(document) {
560
+ const routes = [];
561
+ for (const [path, rawPathItem] of Object.entries(document.paths ?? {})) {
562
+ const pathItem = resolvePathItem(document, rawPathItem);
563
+ const pathLevelParams = (pathItem.parameters ?? []).map(
564
+ (param) => resolveRef(document, param)
565
+ );
566
+ for (const method of HTTP_METHODS) {
567
+ const operation = pathItem[method];
568
+ if (!operation) {
569
+ continue;
570
+ }
571
+ const operationParams = (operation.parameters ?? []).map(
572
+ (param) => resolveRef(document, param)
573
+ );
574
+ routes.push({
575
+ deprecated: operation.deprecated ?? false,
576
+ method,
577
+ operationId: operation.operationId,
578
+ parameters: mergeParameters(pathLevelParams, operationParams),
579
+ path,
580
+ requestBody: operation.requestBody ? resolveRef(document, operation.requestBody) : void 0,
581
+ responses: resolveResponses(document, operation.responses),
582
+ servers: [operation.servers, pathItem.servers, document.servers].find(
583
+ (servers) => servers?.length
584
+ ),
585
+ summary: operation.summary,
586
+ tags: operation.tags ?? []
587
+ });
588
+ }
589
+ }
590
+ return routes;
591
+ }
592
+ function mergeParameters(pathLevel, operationLevel) {
593
+ const overridden = new Set(
594
+ operationLevel.map((param) => `${param.in}:${param.name}`)
595
+ );
596
+ return [
597
+ ...pathLevel.filter(
598
+ (param) => !overridden.has(`${param.in}:${param.name}`)
599
+ ),
600
+ ...operationLevel
601
+ ];
602
+ }
603
+ function resolvePathItem(document, pathItem) {
604
+ const visited = /* @__PURE__ */ new Set();
605
+ let resolved = pathItem;
606
+ while (resolved.$ref && !visited.has(resolved.$ref)) {
607
+ visited.add(resolved.$ref);
608
+ const { $ref, ...siblings } = resolved;
609
+ resolved = { ...resolveRef(document, { $ref }), ...siblings };
610
+ }
611
+ return resolved;
612
+ }
613
+ function resolveRef(document, value) {
614
+ if (!value || typeof value !== "object" || !("$ref" in value)) {
615
+ return value;
616
+ }
617
+ const pointer = value.$ref;
618
+ if (!pointer.startsWith("#/")) {
619
+ throw new Error(`Unexpected external $ref after bundling: ${pointer}`);
620
+ }
621
+ const segments = pointer.slice(2).split("/").map(
622
+ (segment) => decodeURIComponent(segment.replaceAll("~1", "/").replaceAll("~0", "~"))
623
+ );
624
+ let node = document;
625
+ for (const segment of segments) {
626
+ node = node?.[segment];
627
+ }
628
+ return node;
629
+ }
630
+ function resolveResponses(document, rawResponses) {
631
+ if (!rawResponses) {
632
+ return void 0;
633
+ }
634
+ return Object.fromEntries(
635
+ Object.entries(rawResponses).map(([code, response]) => [
636
+ code,
637
+ resolveRef(document, response)
638
+ ])
639
+ );
640
+ }
641
+
628
642
  // src/openapi/selection.ts
629
643
  var DEFAULT_MAX_OPERATIONS = 40;
630
644
  var METHOD_PRIORITY = {
@@ -704,7 +718,7 @@ async function fromOpenAPI(options) {
704
718
  route,
705
719
  servers: route.servers
706
720
  };
707
- if (options.resources && route.method === "get" && isEligibleForResource(route)) {
721
+ if (options.resources && route.method === "get" && isEligibleForResource(route, sharedDefs)) {
708
722
  registerResource(
709
723
  server,
710
724
  route,