diff --git a/src/ModelContextProtocol/Client/McpClientExtensions.cs b/src/ModelContextProtocol/Client/McpClientExtensions.cs
index a86f7e60..513fc8c0 100644
--- a/src/ModelContextProtocol/Client/McpClientExtensions.cs
+++ b/src/ModelContextProtocol/Client/McpClientExtensions.cs
@@ -783,9 +783,14 @@ public static Task UnsubscribeFromResourceAsync(this IMcpClient client, Uri uri,
///
/// The client instance used to communicate with the MCP server.
/// The name of the tool to call on the server..
- /// Optional dictionary of arguments to pass to the tool. Each key represents a parameter name,
+ /// An optional dictionary of arguments to pass to the tool. Each key represents a parameter name,
/// and its associated value represents the argument value.
///
+ ///
+ /// An optional to have progress notifications reported to it. Setting this to a non-
+ /// value will result in a progress token being included in the call, and any resulting progress notifications during the operation
+ /// routed to this instance.
+ ///
///
/// The JSON serialization options governing argument serialization. If , the default serialization options will be used.
///
@@ -812,6 +817,7 @@ public static Task CallToolAsync(
this IMcpClient client,
string toolName,
IReadOnlyDictionary? arguments = null,
+ IProgress? progress = null,
JsonSerializerOptions? serializerOptions = null,
CancellationToken cancellationToken = default)
{
@@ -820,12 +826,56 @@ public static Task CallToolAsync(
serializerOptions ??= McpJsonUtilities.DefaultOptions;
serializerOptions.MakeReadOnly();
+ if (progress is not null)
+ {
+ return SendRequestWithProgressAsync(client, toolName, arguments, progress, serializerOptions, cancellationToken);
+ }
+
return client.SendRequestAsync(
RequestMethods.ToolsCall,
- new() { Name = toolName, Arguments = ToArgumentsDictionary(arguments, serializerOptions) },
+ new()
+ {
+ Name = toolName,
+ Arguments = ToArgumentsDictionary(arguments, serializerOptions),
+ },
McpJsonUtilities.JsonContext.Default.CallToolRequestParams,
McpJsonUtilities.JsonContext.Default.CallToolResponse,
cancellationToken: cancellationToken);
+
+ static async Task SendRequestWithProgressAsync(
+ IMcpClient client,
+ string toolName,
+ IReadOnlyDictionary? arguments,
+ IProgress progress,
+ JsonSerializerOptions serializerOptions,
+ CancellationToken cancellationToken)
+ {
+ ProgressToken progressToken = new(Guid.NewGuid().ToString("N"));
+
+ await using var _ = client.RegisterNotificationHandler(NotificationMethods.ProgressNotification,
+ (notification, cancellationToken) =>
+ {
+ if (JsonSerializer.Deserialize(notification.Params, McpJsonUtilities.JsonContext.Default.ProgressNotification) is { } pn &&
+ pn.ProgressToken == progressToken)
+ {
+ progress.Report(pn.Progress);
+ }
+
+ return default;
+ }).ConfigureAwait(false);
+
+ return await client.SendRequestAsync(
+ RequestMethods.ToolsCall,
+ new()
+ {
+ Name = toolName,
+ Arguments = ToArgumentsDictionary(arguments, serializerOptions),
+ Meta = new() { ProgressToken = progressToken },
+ },
+ McpJsonUtilities.JsonContext.Default.CallToolRequestParams,
+ McpJsonUtilities.JsonContext.Default.CallToolResponse,
+ cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
}
///
diff --git a/src/ModelContextProtocol/Client/McpClientTool.cs b/src/ModelContextProtocol/Client/McpClientTool.cs
index 7917f0af..759b9f9c 100644
--- a/src/ModelContextProtocol/Client/McpClientTool.cs
+++ b/src/ModelContextProtocol/Client/McpClientTool.cs
@@ -1,8 +1,9 @@
+using Microsoft.Extensions.AI;
using ModelContextProtocol.Protocol.Types;
+using ModelContextProtocol.Utils;
using ModelContextProtocol.Utils.Json;
-using Microsoft.Extensions.AI;
-using System.Text.Json;
using System.Collections.ObjectModel;
+using System.Text.Json;
namespace ModelContextProtocol.Client;
@@ -36,14 +37,22 @@ public sealed class McpClientTool : AIFunction
private readonly IMcpClient _client;
private readonly string _name;
private readonly string _description;
+ private readonly IProgress? _progress;
- internal McpClientTool(IMcpClient client, Tool tool, JsonSerializerOptions serializerOptions, string? name = null, string? description = null)
+ internal McpClientTool(
+ IMcpClient client,
+ Tool tool,
+ JsonSerializerOptions serializerOptions,
+ string? name = null,
+ string? description = null,
+ IProgress? progress = null)
{
_client = client;
ProtocolTool = tool;
JsonSerializerOptions = serializerOptions;
_name = name ?? tool.Name;
_description = description ?? tool.Description ?? string.Empty;
+ _progress = progress;
}
///
@@ -77,7 +86,7 @@ internal McpClientTool(IMcpClient client, Tool tool, JsonSerializerOptions seria
protected async override ValueTask