fastmcp 4.23.6 → 4.23.7

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.
@@ -1,4 +1,5 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/strictInputSchema.ts
2
+ var _zod2 = require('zod');
2
3
  function strictInputSchema(schema, nested = false) {
3
4
  const { additionalProperties, properties } = schema;
4
5
  const keepsAdditionalProperties = Object.keys(_nullishCoalesce(properties, () => ( {}))).length === 0 && (typeof additionalProperties === "object" || additionalProperties === true || nested && additionalProperties === void 0 && !properties);
@@ -15,8 +16,21 @@ function strictInputSchema(schema, nested = false) {
15
16
  }
16
17
  };
17
18
  }
19
+ function zodInputSchema(schema, target) {
20
+ return _zod2.z.toJSONSchema(schema, {
21
+ io: "input",
22
+ override: ({ jsonSchema, zodSchema }) => {
23
+ const def = zodSchema._zod.def;
24
+ if (def.type === "object" && !def.catchall && jsonSchema.additionalProperties === void 0) {
25
+ jsonSchema.additionalProperties = false;
26
+ }
27
+ },
28
+ target
29
+ });
30
+ }
31
+
18
32
 
19
33
 
20
34
 
21
- exports.strictInputSchema = strictInputSchema;
22
- //# sourceMappingURL=chunk-O22SYZMC.cjs.map
35
+ exports.strictInputSchema = strictInputSchema; exports.zodInputSchema = zodInputSchema;
36
+ //# sourceMappingURL=chunk-MPFPOZ2H.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/fastmcp/fastmcp/dist/chunk-MPFPOZ2H.cjs","../src/strictInputSchema.ts"],"names":[],"mappings":"AAAA;ACEA,2BAAkB;AAsBX,SAAS,iBAAA,CACd,MAAA,EACA,OAAA,EAAS,KAAA,EACG;AACZ,EAAA,MAAM,EAAE,oBAAA,EAAsB,WAAW,EAAA,EAAI,MAAA;AAC7C,EAAA,MAAM,0BAAA,EACJ,MAAA,CAAO,IAAA,kBAAK,UAAA,UAAc,CAAC,GAAC,CAAA,CAAE,OAAA,IAAW,EAAA,GAAA,CACxC,OAAO,qBAAA,IAAyB,SAAA,GAC/B,qBAAA,IAAyB,KAAA,GACxB,OAAA,GAAU,qBAAA,IAAyB,KAAA,EAAA,GAAa,CAAC,UAAA,CAAA;AAEtD,EAAA,OAAO;AAAA,IACL,GAAG,MAAA;AAAA,IACH,GAAI,0BAAA,EAA4B,CAAC,EAAA,EAAI,EAAE,oBAAA,EAAsB,MAAM,CAAA;AAAA,IACnE,GAAI,WAAA,GAAc;AAAA,MAChB,UAAA,EAAY,MAAA,CAAO,WAAA;AAAA,QACjB,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,EAAA,GAAM;AAAA,UAC/C,GAAA;AAAA,UACA,OAAO,MAAA,IAAU,SAAA,GAAY,KAAA,CAAM,KAAA,IAAS,SAAA,EACxC,iBAAA,CAAkB,KAAA,EAAO,IAAI,EAAA,EAC7B;AAAA,QACN,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAA;AACF;AAWO,SAAS,cAAA,CACd,MAAA,EACA,MAAA,EACY;AACZ,EAAA,OAAO,OAAA,CAAE,YAAA,CAAa,MAAA,EAAQ;AAAA,IAC5B,EAAA,EAAI,OAAA;AAAA,IACJ,QAAA,EAAU,CAAC,EAAE,UAAA,EAAY,UAAU,CAAA,EAAA,GAAM;AACvC,MAAA,MAAM,IAAA,EAAM,SAAA,CAAU,IAAA,CAAK,GAAA;AAC3B,MAAA,GAAA,CACE,GAAA,CAAI,KAAA,IAAS,SAAA,GACb,CAAC,GAAA,CAAI,SAAA,GACL,UAAA,CAAW,qBAAA,IAAyB,KAAA,CAAA,EACpC;AACA,QAAA,UAAA,CAAW,qBAAA,EAAuB,KAAA;AAAA,MACpC;AAAA,IACF,CAAA;AAAA,IACA;AAAA,EACF,CAAC,CAAA;AACH;ADhDA;AACA;AACE;AACA;AACF,uFAAC","file":"/home/runner/work/fastmcp/fastmcp/dist/chunk-MPFPOZ2H.cjs","sourcesContent":[null,"import type { JsonSchema } from \"xsschema\";\n\nimport { z } from \"zod\";\n\n/**\n * Closes tool input objects to undeclared keys, like xsschema's\n * `strictJsonSchema`, except for objects made only of additional properties.\n * Closing one of those advertises an object that accepts nothing but `{}`,\n * while the tool's own validation still takes any key, so it keeps whatever\n * `additionalProperties` it declared — or none:\n *\n * - a dictionary, whose `additionalProperties` is a schema (`z.record()`, an\n * OpenAPI map), keeps its value schema;\n * - a free-form object, which declares `additionalProperties: true`, or, as an\n * argument, is a bare `{ type: \"object\" }` (OpenAPI's usual spelling), stays\n * open.\n *\n * An object that declares an empty `properties`, or a bare one at the top of\n * the input, is still closed: that is how a schema says \"no keys\" —\n * `z.object({})`, or a tool without arguments.\n *\n * Shared by both runtimes, so a tool's advertised input schema does not depend\n * on whether it is served by `FastMCP` or `EdgeFastMCP`.\n */\nexport function strictInputSchema(\n schema: JsonSchema,\n nested = false,\n): JsonSchema {\n const { additionalProperties, properties } = schema;\n const keepsAdditionalProperties =\n Object.keys(properties ?? {}).length === 0 &&\n (typeof additionalProperties === \"object\" ||\n additionalProperties === true ||\n (nested && additionalProperties === undefined && !properties));\n\n return {\n ...schema,\n ...(keepsAdditionalProperties ? {} : { additionalProperties: false }),\n ...(properties && {\n properties: Object.fromEntries(\n Object.entries(properties).map(([key, value]) => [\n key,\n typeof value === \"object\" && value.type === \"object\"\n ? strictInputSchema(value, true)\n : value,\n ]),\n ),\n }),\n };\n}\n\n/**\n * Converts Zod 4 tool parameters by what a call may send (`io: \"input\"`), so a\n * transformed field advertises the type it parses and a defaulted one is\n * optional. Input-side conversion leaves a plain `z.object()` open, since it\n * strips undeclared keys rather than rejecting them; this closes it, as\n * output-side conversion did, at any depth — including inside arrays, unions\n * and record values, which `strictInputSchema` does not reach. Explicit\n * catchalls (`z.looseObject()`, `.catchall()`) keep what they declare.\n */\nexport function zodInputSchema(\n schema: z.ZodType,\n target?: \"draft-7\",\n): JsonSchema {\n return z.toJSONSchema(schema, {\n io: \"input\",\n override: ({ jsonSchema, zodSchema }) => {\n const def = zodSchema._zod.def;\n if (\n def.type === \"object\" &&\n !def.catchall &&\n jsonSchema.additionalProperties === undefined\n ) {\n jsonSchema.additionalProperties = false;\n }\n },\n target,\n }) as JsonSchema;\n}\n"]}
@@ -3,7 +3,8 @@
3
3
  var _chunkC7TBI7A5cjs = require('./chunk-C7TBI7A5.cjs');
4
4
 
5
5
 
6
- var _chunkO22SYZMCcjs = require('./chunk-O22SYZMC.cjs');
6
+
7
+ var _chunkMPFPOZ2Hcjs = require('./chunk-MPFPOZ2H.cjs');
7
8
 
8
9
  // src/FastMCP.ts
9
10
  var _indexjs = require('@modelcontextprotocol/sdk/server/index.js');
@@ -542,6 +543,8 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
542
543
  #capabilities = {};
543
544
  #clientCapabilities;
544
545
  #connectionState = "connecting";
546
+ // Caller-supplied transports leave the response mode unspecified.
547
+ #enableJsonResponse;
545
548
  #logger;
546
549
  /**
547
550
  * The minimum level the client asked for with `logging/setLevel`, or
@@ -590,6 +593,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
590
593
  constructor({
591
594
  auth,
592
595
  authRequired = false,
596
+ enableJsonResponse,
593
597
  hasTools,
594
598
  icons,
595
599
  instructions,
@@ -614,6 +618,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
614
618
  super();
615
619
  this.#auth = auth;
616
620
  this.#authRequired = authRequired;
621
+ this.#enableJsonResponse = enableJsonResponse;
617
622
  this.#logger = logger;
618
623
  this.#onToolCall = onToolCall;
619
624
  this.#pingConfig = ping;
@@ -875,6 +880,19 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
875
880
  }
876
881
  return false;
877
882
  }
883
+ /**
884
+ * When `start()` streams responses, an elicitation goes out on its request's
885
+ * own SSE stream, as the SDK's `extra.sendRequest` does, so it reaches a
886
+ * client that never opened the optional standalone GET stream. A JSON
887
+ * response cannot carry it, and a transport passed to `connect()` does not
888
+ * say which mode it uses, so those keep the session's standalone stream.
889
+ */
890
+ #createElicit(requestId) {
891
+ return (params, options) => this.#server.elicitInput(
892
+ params,
893
+ this.#enableJsonResponse === false ? { ...options, relatedRequestId: requestId } : options
894
+ );
895
+ }
878
896
  /**
879
897
  * Builds the context object passed as the third argument to
880
898
  * `resource.load` / `resourceTemplate.load` / `prompt.load`.
@@ -885,12 +903,12 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
885
903
  * are tied to a tool call's progress token / streaming notification,
886
904
  * which resource and prompt reads do not have.
887
905
  */
888
- #createLoadContext(meta, sendNotification) {
906
+ #createLoadContext(meta, sendNotification, requestId) {
889
907
  return {
890
908
  client: {
891
909
  version: this.#server.getClientVersion()
892
910
  },
893
- elicit: (params, options) => this.#server.elicitInput(params, options),
911
+ elicit: this.#createElicit(requestId),
894
912
  log: this.#createLog(sendNotification),
895
913
  requestId: typeof _optionalChain([meta, 'optionalAccess', _21 => _21.requestId]) === "string" ? meta.requestId : void 0,
896
914
  session: this.#auth,
@@ -1328,7 +1346,8 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1328
1346
  this.#auth,
1329
1347
  this.#createLoadContext(
1330
1348
  _optionalChain([request, 'access', _39 => _39.params, 'optionalAccess', _40 => _40._meta]),
1331
- extra.sendNotification
1349
+ extra.sendNotification,
1350
+ extra.requestId
1332
1351
  )
1333
1352
  );
1334
1353
  } catch (error) {
@@ -1397,7 +1416,8 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1397
1416
  this.#auth,
1398
1417
  this.#createLoadContext(
1399
1418
  _optionalChain([request, 'access', _41 => _41.params, 'optionalAccess', _42 => _42._meta]),
1400
- extra.sendNotification
1419
+ extra.sendNotification,
1420
+ extra.requestId
1401
1421
  )
1402
1422
  );
1403
1423
  const resources = Array.isArray(result) ? result : [result];
@@ -1426,7 +1446,8 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1426
1446
  this.#auth,
1427
1447
  this.#createLoadContext(
1428
1448
  _optionalChain([request, 'access', _43 => _43.params, 'optionalAccess', _44 => _44._meta]),
1429
- extra.sendNotification
1449
+ extra.sendNotification,
1450
+ extra.requestId
1430
1451
  )
1431
1452
  );
1432
1453
  } catch (error) {
@@ -1541,7 +1562,9 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1541
1562
  return {
1542
1563
  annotations: tool.annotations,
1543
1564
  description: tool.description,
1544
- inputSchema: tool.parameters ? _chunkO22SYZMCcjs.strictInputSchema.call(void 0, await _xsschema.toJsonSchema.call(void 0, tool.parameters)) : {
1565
+ inputSchema: tool.parameters ? _chunkMPFPOZ2Hcjs.strictInputSchema.call(void 0,
1566
+ tool.parameters["~standard"].vendor === "zod" && "_zod" in tool.parameters ? _chunkMPFPOZ2Hcjs.zodInputSchema.call(void 0, tool.parameters, "draft-7") : await _xsschema.toJsonSchema.call(void 0, tool.parameters)
1567
+ ) : {
1545
1568
  additionalProperties: false,
1546
1569
  properties: {},
1547
1570
  type: "object"
@@ -1650,7 +1673,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1650
1673
  client: {
1651
1674
  version: this.#server.getClientVersion()
1652
1675
  },
1653
- elicit: (params, options) => this.#server.elicitInput(params, options),
1676
+ elicit: this.#createElicit(extra.requestId),
1654
1677
  log,
1655
1678
  reportProgress,
1656
1679
  requestId: typeof _optionalChain([request, 'access', _50 => _50.params, 'optionalAccess', _51 => _51._meta, 'optionalAccess', _52 => _52.requestId]) === "string" ? request.params._meta.requestId : void 0,
@@ -2330,7 +2353,12 @@ var FastMCP = class extends FastMCPEventEmitter {
2330
2353
  auth = this.#requireAuthenticated(await authenticate(request));
2331
2354
  }
2332
2355
  const sessionId = Array.isArray(request.headers["mcp-session-id"]) ? request.headers["mcp-session-id"][0] : request.headers["mcp-session-id"];
2333
- return this.#createSession(auth, sessionId, true);
2356
+ return this.#createSession(
2357
+ auth,
2358
+ sessionId,
2359
+ true,
2360
+ httpConfig.enableJsonResponse
2361
+ );
2334
2362
  },
2335
2363
  enableJsonResponse: httpConfig.enableJsonResponse,
2336
2364
  eventStore: httpConfig.eventStore,
@@ -2372,7 +2400,12 @@ var FastMCP = class extends FastMCPEventEmitter {
2372
2400
  auth = this.#requireAuthenticated(await authenticate(request));
2373
2401
  }
2374
2402
  const sessionId = Array.isArray(request.headers["mcp-session-id"]) ? request.headers["mcp-session-id"][0] : request.headers["mcp-session-id"];
2375
- return this.#createSession(auth, sessionId);
2403
+ return this.#createSession(
2404
+ auth,
2405
+ sessionId,
2406
+ false,
2407
+ httpConfig.enableJsonResponse
2408
+ );
2376
2409
  },
2377
2410
  enableJsonResponse: httpConfig.enableJsonResponse,
2378
2411
  eventStore: httpConfig.eventStore,
@@ -2461,7 +2494,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2461
2494
  * Creates a new FastMCPSession instance with the current configuration.
2462
2495
  * Used both for regular sessions and stateless requests.
2463
2496
  */
2464
- #createSession(auth, sessionId, stateless = false) {
2497
+ #createSession(auth, sessionId, stateless = false, enableJsonResponse) {
2465
2498
  if (auth && typeof auth === "object" && "authenticated" in auth && !auth.authenticated) {
2466
2499
  const errorMessage = "error" in auth && typeof auth.error === "string" ? auth.error : "Authentication failed";
2467
2500
  throw this.#createUnauthorizedResponse(errorMessage);
@@ -2470,6 +2503,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2470
2503
  return new FastMCPSession({
2471
2504
  auth,
2472
2505
  authRequired,
2506
+ enableJsonResponse,
2473
2507
  hasTools: this.#tools.length > 0,
2474
2508
  icons: this.#options.icons,
2475
2509
  instructions: this.#options.instructions,
@@ -3213,4 +3247,4 @@ var FastMCP = class extends FastMCPEventEmitter {
3213
3247
 
3214
3248
 
3215
3249
  exports.DiscoveryDocumentCache = DiscoveryDocumentCache; exports.jsonSchemaAdapter = jsonSchemaAdapter; exports.MEDIA_FETCH_TIMEOUT_MS = MEDIA_FETCH_TIMEOUT_MS; exports.imageContent = imageContent; exports.audioContent = audioContent; exports.FastMCPError = FastMCPError; exports.SessionError = SessionError; exports.UnexpectedStateError = UnexpectedStateError; exports.UserError = UserError; exports.ServerState = ServerState; exports.FastMCPSession = FastMCPSession; exports.FastMCP = FastMCP;
3216
- //# sourceMappingURL=chunk-2PXF6JQB.cjs.map
3250
+ //# sourceMappingURL=chunk-TBMRFQ6M.cjs.map