fastmcp 4.10.0 → 4.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1228,15 +1228,32 @@ server.addTool({
1228
1228
  });
1229
1229
  ```
1230
1230
 
1231
+ `reportProgress` accepts an optional human-readable `message` alongside the numeric fields, which clients can display next to the progress indicator:
1232
+
1233
+ ```js
1234
+ await reportProgress({
1235
+ progress: 40,
1236
+ total: 100,
1237
+ message: "Downloading chunk 4 of 10…",
1238
+ });
1239
+ ```
1240
+
1241
+ Progress notifications are only emitted when the client opts in by supplying a `progressToken` on the tool call; otherwise `reportProgress` is a no-op. Because `notifications/progress` is part of the MCP specification (the `message` field since revision 2025-03-26), this is the portable way to send incremental updates during a long-running tool call — see [Streaming Output](#streaming-output) below for the difference.
1242
+
1231
1243
  #### Streaming Output
1232
1244
 
1233
- FastMCP supports streaming partial results from tools while they're still executing, enabling responsive UIs and real-time feedback. This is particularly useful for:
1245
+ FastMCP can stream partial results from tools while they're still executing, enabling responsive UIs and real-time feedback. This is particularly useful for:
1234
1246
 
1235
1247
  - Long-running operations that generate content incrementally
1236
1248
  - Progressive generation of text, images, or other media
1237
1249
  - Operations where users benefit from seeing immediate partial results
1238
1250
 
1239
- To enable streaming for a tool, add the `streamingHint` annotation and use the `streamContent` method:
1251
+ > [!IMPORTANT]
1252
+ > `streamContent` is a **FastMCP extension, not part of the MCP specification**. It emits a `notifications/tool/streamContent` notification, which the MCP specification does not define — as of revision `2025-11-25` there is no standard mechanism for streaming tool output ([SEP-2998](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2998) is the in-progress proposal to add one).
1253
+ >
1254
+ > Clients discard notifications they have no handler registered for, silently and without error. A client only sees streamed content if it registers a handler for the method (or sets a `fallbackNotificationHandler`), and **no client is known to render it as tool output** — MCP Inspector, for example, logs it in its notifications pane via a fallback handler, but the tool result itself still shows only what `execute` returned. Streaming is therefore mainly useful when you also control the client — see [Consuming streamed content](#consuming-streamed-content) below. If you need incremental updates that work on any client, use [`reportProgress`](#progress) with a `message` instead.
1255
+
1256
+ To stream from a tool, use the `streamContent` method:
1240
1257
 
1241
1258
  ```js
1242
1259
  server.addTool({
@@ -1246,7 +1263,7 @@ server.addTool({
1246
1263
  prompt: z.string(),
1247
1264
  }),
1248
1265
  annotations: {
1249
- streamingHint: true, // Signals this tool uses streaming
1266
+ streamingHint: true, // Advisory only; see below
1250
1267
  readOnlyHint: true,
1251
1268
  },
1252
1269
  execute: async (args, { streamContent }) => {
@@ -1260,19 +1277,45 @@ server.addTool({
1260
1277
  await new Promise((resolve) => setTimeout(resolve, 300)); // Simulate delay
1261
1278
  }
1262
1279
 
1263
- // When using streamContent, you can:
1264
- // 1. Return void (if all content was streamed)
1265
- // 2. Return a final result (which will be appended to streamed content)
1280
+ // Always return a final result. Returning nothing sends an empty tool
1281
+ // result, so clients that ignore the streamed notifications see no output
1282
+ // at all.
1283
+ return "The quick brown fox jumps over the lazy dog.";
1284
+ },
1285
+ });
1286
+ ```
1266
1287
 
1267
- // Option 1: All content was streamed, so return void
1268
- return;
1288
+ > [!WARNING]
1289
+ > Returning `undefined` from `execute` produces a tool result with empty `content`. If you stream everything and return nothing, the tool call resolves to an empty result with no indication that anything was lost — including on clients that do log the notification. Return the complete result as well, and treat streamed content purely as a progressive-rendering enhancement.
1269
1290
 
1270
- // Option 2: Return final content that will be appended
1271
- // return "Generation complete!";
1272
- },
1291
+ The `streamingHint` annotation is advisory metadata. It is forwarded verbatim to clients in `tools/list`, but it does not enable or gate `streamContent`, and FastMCP itself never reads it. No client is known to act on it today, though [SEP-2998](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2998) proposes standardizing the same annotation name.
1292
+
1293
+ ##### Consuming streamed content
1294
+
1295
+ A client sees these notifications only if it registers a handler for the method (or sets a `fallbackNotificationHandler`):
1296
+
1297
+ ```ts
1298
+ import { z } from "zod";
1299
+
1300
+ const StreamContentNotificationSchema = z.object({
1301
+ method: z.literal("notifications/tool/streamContent"),
1302
+ params: z.object({
1303
+ content: z.array(z.any()),
1304
+ toolName: z.string(),
1305
+ }),
1273
1306
  });
1307
+
1308
+ client.setNotificationHandler(
1309
+ StreamContentNotificationSchema,
1310
+ (notification) => {
1311
+ const { content, toolName } = notification.params;
1312
+ // Render the partial content however you like.
1313
+ },
1314
+ );
1274
1315
  ```
1275
1316
 
1317
+ Note that notifications carry only `toolName`, not a request or progress token, so concurrent calls to the same tool on one session cannot be told apart.
1318
+
1276
1319
  Streaming works with all content types (text, image, audio) and can be combined with progress reporting:
1277
1320
 
1278
1321
  ```js
@@ -1289,10 +1332,14 @@ server.addTool({
1289
1332
  const total = args.datasetSize;
1290
1333
 
1291
1334
  for (let i = 0; i < total; i++) {
1292
- // Report numeric progress
1293
- await reportProgress({ progress: i, total });
1335
+ // Standard progress notification: reaches every spec-compliant client
1336
+ await reportProgress({
1337
+ progress: i,
1338
+ total,
1339
+ message: `Processed ${i} of ${total} items`,
1340
+ });
1294
1341
 
1295
- // Stream intermediate results
1342
+ // Richer partial content: only reaches clients that opt in
1296
1343
  if (i % 10 === 0) {
1297
1344
  await streamContent({
1298
1345
  type: "text",
package/dist/FastMCP.cjs CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkGF4ORBWZcjs = require('./chunk-GF4ORBWZ.cjs');
11
+ var _chunkISO2WPB5cjs = require('./chunk-ISO2WPB5.cjs');
12
12
 
13
13
 
14
14
 
@@ -43,5 +43,5 @@ var _chunkDZYT6QAHcjs = require('./chunk-DZYT6QAH.cjs');
43
43
 
44
44
 
45
45
 
46
- exports.AuthProvider = _chunkDZYT6QAHcjs.AuthProvider; exports.AzureProvider = _chunkDZYT6QAHcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkGF4ORBWZcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkGF4ORBWZcjs.FastMCP; exports.FastMCPSession = _chunkGF4ORBWZcjs.FastMCPSession; exports.GitHubProvider = _chunkDZYT6QAHcjs.GitHubProvider; exports.GoogleProvider = _chunkDZYT6QAHcjs.GoogleProvider; exports.OAuthProvider = _chunkDZYT6QAHcjs.OAuthProvider; exports.ServerState = _chunkGF4ORBWZcjs.ServerState; exports.UnexpectedStateError = _chunkGF4ORBWZcjs.UnexpectedStateError; exports.UserError = _chunkGF4ORBWZcjs.UserError; exports.audioContent = _chunkGF4ORBWZcjs.audioContent; exports.getAuthSession = _chunkDZYT6QAHcjs.getAuthSession; exports.imageContent = _chunkGF4ORBWZcjs.imageContent; exports.jsonSchemaAdapter = _chunkGF4ORBWZcjs.jsonSchemaAdapter; exports.requireAll = _chunkDZYT6QAHcjs.requireAll; exports.requireAny = _chunkDZYT6QAHcjs.requireAny; exports.requireAuth = _chunkDZYT6QAHcjs.requireAuth; exports.requireRole = _chunkDZYT6QAHcjs.requireRole; exports.requireScopes = _chunkDZYT6QAHcjs.requireScopes;
46
+ exports.AuthProvider = _chunkDZYT6QAHcjs.AuthProvider; exports.AzureProvider = _chunkDZYT6QAHcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkISO2WPB5cjs.DiscoveryDocumentCache; exports.FastMCP = _chunkISO2WPB5cjs.FastMCP; exports.FastMCPSession = _chunkISO2WPB5cjs.FastMCPSession; exports.GitHubProvider = _chunkDZYT6QAHcjs.GitHubProvider; exports.GoogleProvider = _chunkDZYT6QAHcjs.GoogleProvider; exports.OAuthProvider = _chunkDZYT6QAHcjs.OAuthProvider; exports.ServerState = _chunkISO2WPB5cjs.ServerState; exports.UnexpectedStateError = _chunkISO2WPB5cjs.UnexpectedStateError; exports.UserError = _chunkISO2WPB5cjs.UserError; exports.audioContent = _chunkISO2WPB5cjs.audioContent; exports.getAuthSession = _chunkDZYT6QAHcjs.getAuthSession; exports.imageContent = _chunkISO2WPB5cjs.imageContent; exports.jsonSchemaAdapter = _chunkISO2WPB5cjs.jsonSchemaAdapter; exports.requireAll = _chunkDZYT6QAHcjs.requireAll; exports.requireAny = _chunkDZYT6QAHcjs.requireAny; exports.requireAuth = _chunkDZYT6QAHcjs.requireAuth; exports.requireRole = _chunkDZYT6QAHcjs.requireRole; exports.requireScopes = _chunkDZYT6QAHcjs.requireScopes;
47
47
  //# sourceMappingURL=FastMCP.cjs.map
@@ -185,6 +185,22 @@ type Context<T extends FastMCPSessionAuth> = {
185
185
  * counters, or maintain user-specific data across multiple requests.
186
186
  */
187
187
  sessionId?: string;
188
+ /**
189
+ * Streams incremental content while the tool is still executing, by emitting
190
+ * a `notifications/tool/streamContent` notification.
191
+ *
192
+ * NOTE: this is a FastMCP extension, not part of the MCP specification. As of
193
+ * revision 2025-11-25 the spec has no streaming tool output primitive (see
194
+ * SEP-2998 for the in-progress proposal). A client only receives these
195
+ * notifications if it registers a handler for the method or sets a
196
+ * `fallbackNotificationHandler`; otherwise the SDK drops them silently. No
197
+ * client is known to render them as tool output.
198
+ *
199
+ * Always return a final result from `execute` rather than relying on streamed
200
+ * content alone, otherwise clients that ignore the notification see an empty
201
+ * tool result. For incremental status that works everywhere, prefer
202
+ * {@link Context.reportProgress} with a `message`.
203
+ */
188
204
  streamContent: (content: Content | Content[]) => Promise<void>;
189
205
  };
190
206
  type Extra = unknown;
@@ -199,6 +215,13 @@ type Literal = boolean | null | number | string | undefined;
199
215
  */
200
216
  type LoadContext<T extends FastMCPSessionAuth> = Omit<Context<T>, "reportProgress" | "streamContent">;
201
217
  type Progress = {
218
+ /**
219
+ * An optional human-readable message describing the current progress.
220
+ *
221
+ * Part of `notifications/progress` since MCP revision 2025-03-26, so unlike
222
+ * `streamContent` this reaches any spec-compliant client.
223
+ */
224
+ message?: string;
202
225
  /**
203
226
  * The progress thus far. This should increase every time progress is made, even if the total is unknown.
204
227
  */
@@ -681,8 +704,11 @@ type Tool<T extends FastMCPSessionAuth, Params extends ToolParameters = ToolPara
681
704
  };
682
705
  annotations?: {
683
706
  /**
684
- * When true, the tool leverages incremental content streaming
685
- * Return void for tools that handle all their output via streaming
707
+ * Advisory metadata signalling that the tool streams incremental content
708
+ * via {@link Context.streamContent}. Forwarded verbatim in `tools/list`.
709
+ *
710
+ * This has no effect on FastMCP's behavior: it neither enables nor is
711
+ * required by `streamContent`. No known client interprets it today.
686
712
  */
687
713
  streamingHint?: boolean;
688
714
  } & ToolAnnotations;
package/dist/FastMCP.d.ts CHANGED
@@ -185,6 +185,22 @@ type Context<T extends FastMCPSessionAuth> = {
185
185
  * counters, or maintain user-specific data across multiple requests.
186
186
  */
187
187
  sessionId?: string;
188
+ /**
189
+ * Streams incremental content while the tool is still executing, by emitting
190
+ * a `notifications/tool/streamContent` notification.
191
+ *
192
+ * NOTE: this is a FastMCP extension, not part of the MCP specification. As of
193
+ * revision 2025-11-25 the spec has no streaming tool output primitive (see
194
+ * SEP-2998 for the in-progress proposal). A client only receives these
195
+ * notifications if it registers a handler for the method or sets a
196
+ * `fallbackNotificationHandler`; otherwise the SDK drops them silently. No
197
+ * client is known to render them as tool output.
198
+ *
199
+ * Always return a final result from `execute` rather than relying on streamed
200
+ * content alone, otherwise clients that ignore the notification see an empty
201
+ * tool result. For incremental status that works everywhere, prefer
202
+ * {@link Context.reportProgress} with a `message`.
203
+ */
188
204
  streamContent: (content: Content | Content[]) => Promise<void>;
189
205
  };
190
206
  type Extra = unknown;
@@ -199,6 +215,13 @@ type Literal = boolean | null | number | string | undefined;
199
215
  */
200
216
  type LoadContext<T extends FastMCPSessionAuth> = Omit<Context<T>, "reportProgress" | "streamContent">;
201
217
  type Progress = {
218
+ /**
219
+ * An optional human-readable message describing the current progress.
220
+ *
221
+ * Part of `notifications/progress` since MCP revision 2025-03-26, so unlike
222
+ * `streamContent` this reaches any spec-compliant client.
223
+ */
224
+ message?: string;
202
225
  /**
203
226
  * The progress thus far. This should increase every time progress is made, even if the total is unknown.
204
227
  */
@@ -681,8 +704,11 @@ type Tool<T extends FastMCPSessionAuth, Params extends ToolParameters = ToolPara
681
704
  };
682
705
  annotations?: {
683
706
  /**
684
- * When true, the tool leverages incremental content streaming
685
- * Return void for tools that handle all their output via streaming
707
+ * Advisory metadata signalling that the tool streams incremental content
708
+ * via {@link Context.streamContent}. Forwarded verbatim in `tools/list`.
709
+ *
710
+ * This has no effect on FastMCP's behavior: it neither enables nor is
711
+ * required by `streamContent`. No known client interprets it today.
686
712
  */
687
713
  streamingHint?: boolean;
688
714
  } & ToolAnnotations;
package/dist/FastMCP.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  audioContent,
9
9
  imageContent,
10
10
  jsonSchemaAdapter
11
- } from "./chunk-MGP2FVUH.js";
11
+ } from "./chunk-JOZJUFKE.js";
12
12
  import {
13
13
  AuthProvider,
14
14
  AzureProvider,
@@ -2445,4 +2445,4 @@ var FastMCP = class extends FastMCPEventEmitter {
2445
2445
 
2446
2446
 
2447
2447
  exports.DiscoveryDocumentCache = DiscoveryDocumentCache; exports.jsonSchemaAdapter = jsonSchemaAdapter; exports.imageContent = imageContent; exports.audioContent = audioContent; exports.UnexpectedStateError = UnexpectedStateError; exports.UserError = UserError; exports.ServerState = ServerState; exports.FastMCPSession = FastMCPSession; exports.FastMCP = FastMCP;
2448
- //# sourceMappingURL=chunk-GF4ORBWZ.cjs.map
2448
+ //# sourceMappingURL=chunk-ISO2WPB5.cjs.map