fastmcp 4.21.1 → 4.21.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.
package/README.md CHANGED
@@ -633,10 +633,12 @@ server.addTool({
633
633
 
634
634
  Works for `outputSchema` too. Note that FastMCP advertises input schemas with
635
635
  `additionalProperties: false`, whatever your schema said — the same treatment
636
- Zod and Valibot schemas get. The exception is a dictionary (an object with no
637
- `properties` and an `additionalProperties` schema, like `z.record()`), which
638
- keeps its value schema. Output schemas keep whatever additional-properties
639
- rule your schema declared.
636
+ Zod and Valibot schemas get. The exception is an object made only of
637
+ additional properties: a dictionary (no `properties` and an
638
+ `additionalProperties` schema, like `z.record()`) keeps its value schema, and a
639
+ free-form argument (`{ type: "object" }`, or `additionalProperties: true`)
640
+ stays open. Output schemas keep whatever additional-properties rule your schema
641
+ declared.
640
642
 
641
643
  Unlike the schema libraries above, a plain JSON Schema carries no TypeScript
642
644
  types, so `execute` receives `unknown` arguments. Cast or narrow them yourself.
@@ -750,6 +752,11 @@ server.addTool({
750
752
  });
751
753
  ```
752
754
 
755
+ A server without an `authenticate` function has no auth to check, so every
756
+ session sees every tool. With one, a session that still ends up without auth —
757
+ on stdio, where the server carries on when `authenticate` throws or returns
758
+ nothing — sees none of the tools that have `canAccess`.
759
+
753
760
  #### Returning a string
754
761
 
755
762
  `execute` can return a string:
package/dist/FastMCP.cjs CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
 
13
13
 
14
- var _chunkIKH7YBYPcjs = require('./chunk-IKH7YBYP.cjs');
14
+ var _chunkC5VOVQPCcjs = require('./chunk-C5VOVQPC.cjs');
15
15
 
16
16
 
17
17
 
@@ -25,6 +25,7 @@ var _chunkIKH7YBYPcjs = require('./chunk-IKH7YBYP.cjs');
25
25
 
26
26
 
27
27
  var _chunkGTPK7A57cjs = require('./chunk-GTPK7A57.cjs');
28
+ require('./chunk-O22SYZMC.cjs');
28
29
 
29
30
 
30
31
 
@@ -49,5 +50,5 @@ var _chunkGTPK7A57cjs = require('./chunk-GTPK7A57.cjs');
49
50
 
50
51
 
51
52
 
52
- exports.AuthProvider = _chunkGTPK7A57cjs.AuthProvider; exports.AzureProvider = _chunkGTPK7A57cjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkIKH7YBYPcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkIKH7YBYPcjs.FastMCP; exports.FastMCPError = _chunkIKH7YBYPcjs.FastMCPError; exports.FastMCPSession = _chunkIKH7YBYPcjs.FastMCPSession; exports.GitHubProvider = _chunkGTPK7A57cjs.GitHubProvider; exports.GoogleProvider = _chunkGTPK7A57cjs.GoogleProvider; exports.MEDIA_FETCH_TIMEOUT_MS = _chunkIKH7YBYPcjs.MEDIA_FETCH_TIMEOUT_MS; exports.OAuthProvider = _chunkGTPK7A57cjs.OAuthProvider; exports.ServerState = _chunkIKH7YBYPcjs.ServerState; exports.SessionError = _chunkIKH7YBYPcjs.SessionError; exports.UnexpectedStateError = _chunkIKH7YBYPcjs.UnexpectedStateError; exports.UserError = _chunkIKH7YBYPcjs.UserError; exports.audioContent = _chunkIKH7YBYPcjs.audioContent; exports.getAuthSession = _chunkGTPK7A57cjs.getAuthSession; exports.imageContent = _chunkIKH7YBYPcjs.imageContent; exports.jsonSchemaAdapter = _chunkIKH7YBYPcjs.jsonSchemaAdapter; exports.requireAll = _chunkGTPK7A57cjs.requireAll; exports.requireAny = _chunkGTPK7A57cjs.requireAny; exports.requireAuth = _chunkGTPK7A57cjs.requireAuth; exports.requireRole = _chunkGTPK7A57cjs.requireRole; exports.requireScopes = _chunkGTPK7A57cjs.requireScopes;
53
+ exports.AuthProvider = _chunkGTPK7A57cjs.AuthProvider; exports.AzureProvider = _chunkGTPK7A57cjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkC5VOVQPCcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkC5VOVQPCcjs.FastMCP; exports.FastMCPError = _chunkC5VOVQPCcjs.FastMCPError; exports.FastMCPSession = _chunkC5VOVQPCcjs.FastMCPSession; exports.GitHubProvider = _chunkGTPK7A57cjs.GitHubProvider; exports.GoogleProvider = _chunkGTPK7A57cjs.GoogleProvider; exports.MEDIA_FETCH_TIMEOUT_MS = _chunkC5VOVQPCcjs.MEDIA_FETCH_TIMEOUT_MS; exports.OAuthProvider = _chunkGTPK7A57cjs.OAuthProvider; exports.ServerState = _chunkC5VOVQPCcjs.ServerState; exports.SessionError = _chunkC5VOVQPCcjs.SessionError; exports.UnexpectedStateError = _chunkC5VOVQPCcjs.UnexpectedStateError; exports.UserError = _chunkC5VOVQPCcjs.UserError; exports.audioContent = _chunkC5VOVQPCcjs.audioContent; exports.getAuthSession = _chunkGTPK7A57cjs.getAuthSession; exports.imageContent = _chunkC5VOVQPCcjs.imageContent; exports.jsonSchemaAdapter = _chunkC5VOVQPCcjs.jsonSchemaAdapter; exports.requireAll = _chunkGTPK7A57cjs.requireAll; exports.requireAny = _chunkGTPK7A57cjs.requireAny; exports.requireAuth = _chunkGTPK7A57cjs.requireAuth; exports.requireRole = _chunkGTPK7A57cjs.requireRole; exports.requireScopes = _chunkGTPK7A57cjs.requireScopes;
53
54
  //# sourceMappingURL=FastMCP.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/fastmcp/fastmcp/dist/FastMCP.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,0yCAAC","file":"/home/runner/work/fastmcp/fastmcp/dist/FastMCP.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/fastmcp/fastmcp/dist/FastMCP.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,0yCAAC","file":"/home/runner/work/fastmcp/fastmcp/dist/FastMCP.cjs"}
@@ -916,8 +916,14 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
916
916
  */
917
917
  get sessionId(): string | undefined;
918
918
  set sessionId(value: string | undefined);
919
- constructor({ auth, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
919
+ constructor({ auth, authRequired, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
920
920
  auth?: T;
921
+ /**
922
+ * Whether the server authenticates its sessions (`authenticate` is
923
+ * configured). A session that has no auth even so sees none of the tools
924
+ * gated by `canAccess` (see `toolsVisibleTo`).
925
+ */
926
+ authRequired?: boolean;
921
927
  /**
922
928
  * Whether the server has any tools at all, including ones this session's
923
929
  * `canAccess` filtering removed from `tools`. Defaults to `tools.length > 0`.
package/dist/FastMCP.d.ts CHANGED
@@ -916,8 +916,14 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
916
916
  */
917
917
  get sessionId(): string | undefined;
918
918
  set sessionId(value: string | undefined);
919
- constructor({ auth, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
919
+ constructor({ auth, authRequired, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
920
920
  auth?: T;
921
+ /**
922
+ * Whether the server authenticates its sessions (`authenticate` is
923
+ * configured). A session that has no auth even so sees none of the tools
924
+ * gated by `canAccess` (see `toolsVisibleTo`).
925
+ */
926
+ authRequired?: boolean;
921
927
  /**
922
928
  * Whether the server has any tools at all, including ones this session's
923
929
  * `canAccess` filtering removed from `tools`. Defaults to `tools.length > 0`.
package/dist/FastMCP.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  audioContent,
12
12
  imageContent,
13
13
  jsonSchemaAdapter
14
- } from "./chunk-JNP6BG5L.js";
14
+ } from "./chunk-QMRS4ZLD.js";
15
15
  import {
16
16
  AuthProvider,
17
17
  AzureProvider,
@@ -25,6 +25,7 @@ import {
25
25
  requireRole,
26
26
  requireScopes
27
27
  } from "./chunk-AR3LVWUF.js";
28
+ import "./chunk-UMDUIBFW.js";
28
29
  export {
29
30
  AuthProvider,
30
31
  AzureProvider,
@@ -2,6 +2,9 @@
2
2
 
3
3
  var _chunkGTPK7A57cjs = require('./chunk-GTPK7A57.cjs');
4
4
 
5
+
6
+ var _chunkO22SYZMCcjs = require('./chunk-O22SYZMC.cjs');
7
+
5
8
  // src/FastMCP.ts
6
9
  var _indexjs = require('@modelcontextprotocol/sdk/server/index.js');
7
10
  var _stdiojs = require('@modelcontextprotocol/sdk/server/stdio.js');
@@ -376,21 +379,6 @@ function assertToolSchemas(tool) {
376
379
  assertStandardSchema(tool.name, "outputSchema", tool.outputSchema);
377
380
  }
378
381
  }
379
- function strictInputSchema(schema) {
380
- const isDictionary = typeof schema.additionalProperties === "object" && Object.keys(_nullishCoalesce(schema.properties, () => ( {}))).length === 0;
381
- return {
382
- ...schema,
383
- additionalProperties: isDictionary ? schema.additionalProperties : false,
384
- ...schema.properties && {
385
- properties: Object.fromEntries(
386
- Object.entries(schema.properties).map(([key, value]) => [
387
- key,
388
- typeof value === "object" && value.type === "object" ? strictInputSchema(value) : value
389
- ])
390
- )
391
- }
392
- };
393
- }
394
382
  var STREAM_KEEPALIVE_LOGGER = "fastmcp-keepalive";
395
383
  var STREAM_KEEPALIVE_DEFAULT_INTERVAL_MS = 2e4;
396
384
  var TextContentZodSchema = _zod.z.object({
@@ -537,6 +525,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
537
525
  */
538
526
  #abortController = new AbortController();
539
527
  #auth;
528
+ #authRequired;
540
529
  #capabilities = {};
541
530
  #clientCapabilities;
542
531
  #connectionState = "connecting";
@@ -575,6 +564,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
575
564
  #utils;
576
565
  constructor({
577
566
  auth,
567
+ authRequired = false,
578
568
  hasTools,
579
569
  icons,
580
570
  instructions,
@@ -598,6 +588,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
598
588
  }) {
599
589
  super();
600
590
  this.#auth = auth;
591
+ this.#authRequired = authRequired;
601
592
  this.#logger = logger;
602
593
  this.#onToolCall = onToolCall;
603
594
  this.#pingConfig = ping;
@@ -804,7 +795,9 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
804
795
  }
805
796
  }
806
797
  toolsListChanged(tools) {
807
- this.setupToolHandlers(toolsVisibleTo(tools, this.#auth));
798
+ this.setupToolHandlers(
799
+ toolsVisibleTo(tools, this.#auth, this.#authRequired)
800
+ );
808
801
  this.triggerListChangedNotification("notifications/tools/list_changed");
809
802
  }
810
803
  async triggerListChangedNotification(method) {
@@ -1067,9 +1060,10 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1067
1060
  const ref = request.params.ref;
1068
1061
  const prompt = "name" in ref && this.#prompts.get(ref.name);
1069
1062
  if (!prompt) {
1070
- throw new UnexpectedStateError("Unknown prompt", {
1071
- request
1072
- });
1063
+ throw new (0, _typesjs.McpError)(
1064
+ _typesjs.ErrorCode.InvalidParams,
1065
+ `Unknown prompt: ${ref.name}`
1066
+ );
1073
1067
  }
1074
1068
  if (!prompt.complete) {
1075
1069
  throw new UnexpectedStateError("Prompt does not support completion", {
@@ -1095,9 +1089,10 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1095
1089
  (resource2) => resource2.uriTemplate === ref.uri
1096
1090
  );
1097
1091
  if (!resource) {
1098
- throw new UnexpectedStateError("Unknown resource", {
1099
- request
1100
- });
1092
+ throw new (0, _typesjs.McpError)(
1093
+ _typesjs.ErrorCode.InvalidParams,
1094
+ `Unknown resource template: ${ref.uri}`
1095
+ );
1101
1096
  }
1102
1097
  if (!("uriTemplate" in resource)) {
1103
1098
  throw new UnexpectedStateError("Unexpected resource");
@@ -1387,7 +1382,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1387
1382
  return {
1388
1383
  annotations: tool.annotations,
1389
1384
  description: tool.description,
1390
- inputSchema: tool.parameters ? strictInputSchema(await _xsschema.toJsonSchema.call(void 0, tool.parameters)) : {
1385
+ inputSchema: tool.parameters ? _chunkO22SYZMCcjs.strictInputSchema.call(void 0, await _xsschema.toJsonSchema.call(void 0, tool.parameters)) : {
1391
1386
  additionalProperties: false,
1392
1387
  properties: {},
1393
1388
  type: "object"
@@ -1645,8 +1640,13 @@ function stripBasePath(path, basePath) {
1645
1640
  }
1646
1641
  return null;
1647
1642
  }
1648
- function toolsVisibleTo(tools, auth) {
1649
- return auth ? tools.filter((tool) => tool.canAccess ? tool.canAccess(auth) : true) : tools;
1643
+ function toolsVisibleTo(tools, auth, authRequired) {
1644
+ if (auth) {
1645
+ return tools.filter(
1646
+ (tool) => tool.canAccess ? tool.canAccess(auth) : true
1647
+ );
1648
+ }
1649
+ return authRequired ? tools.filter((tool) => !tool.canAccess) : tools;
1650
1650
  }
1651
1651
  var FastMCPEventEmitterBase = _events.EventEmitter;
1652
1652
  var FastMCPEventEmitter = class extends FastMCPEventEmitterBase {
@@ -2027,6 +2027,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2027
2027
  if (config.transportType === "stdio") {
2028
2028
  const transport = new (0, _stdiojs.StdioServerTransport)();
2029
2029
  let auth;
2030
+ const authRequired = this.#authenticate !== void 0;
2030
2031
  if (this.#authenticate) {
2031
2032
  try {
2032
2033
  auth = await _asyncNullishCoalesce(await this.#authenticate(
@@ -2038,9 +2039,15 @@ var FastMCP = class extends FastMCPEventEmitter {
2038
2039
  error instanceof Error ? error.message : String(error)
2039
2040
  );
2040
2041
  }
2042
+ if (!auth && this.#tools.some((tool) => tool.canAccess)) {
2043
+ this.#logger.warn(
2044
+ "[FastMCP warning] The stdio session has no auth, so tools gated by canAccess are hidden from it."
2045
+ );
2046
+ }
2041
2047
  }
2042
2048
  const session = new FastMCPSession({
2043
2049
  auth,
2050
+ authRequired,
2044
2051
  hasTools: this.#tools.length > 0,
2045
2052
  icons: this.#options.icons,
2046
2053
  instructions: this.#options.instructions,
@@ -2054,7 +2061,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2054
2061
  roots: this.#options.roots,
2055
2062
  streamKeepalive: this.#options.streamKeepalive,
2056
2063
  title: this.#options.title,
2057
- tools: toolsVisibleTo(this.#tools, auth),
2064
+ tools: toolsVisibleTo(this.#tools, auth, authRequired),
2058
2065
  transportType: "stdio",
2059
2066
  utils: this.#options.utils,
2060
2067
  version: this.#options.version,
@@ -2224,8 +2231,10 @@ var FastMCP = class extends FastMCPEventEmitter {
2224
2231
  const errorMessage = "error" in auth && typeof auth.error === "string" ? auth.error : "Authentication failed";
2225
2232
  throw this.#createUnauthorizedResponse(errorMessage);
2226
2233
  }
2234
+ const authRequired = this.#authenticate !== void 0;
2227
2235
  return new FastMCPSession({
2228
2236
  auth,
2237
+ authRequired,
2229
2238
  hasTools: this.#tools.length > 0,
2230
2239
  icons: this.#options.icons,
2231
2240
  instructions: this.#options.instructions,
@@ -2241,7 +2250,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2241
2250
  stateless,
2242
2251
  streamKeepalive: this.#options.streamKeepalive,
2243
2252
  title: this.#options.title,
2244
- tools: toolsVisibleTo(this.#tools, auth),
2253
+ tools: toolsVisibleTo(this.#tools, auth, authRequired),
2245
2254
  transportType: "httpStream",
2246
2255
  utils: this.#options.utils,
2247
2256
  version: this.#options.version,
@@ -2937,4 +2946,4 @@ var FastMCP = class extends FastMCPEventEmitter {
2937
2946
 
2938
2947
 
2939
2948
  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;
2940
- //# sourceMappingURL=chunk-IKH7YBYP.cjs.map
2949
+ //# sourceMappingURL=chunk-C5VOVQPC.cjs.map