Skip to content

Commit 7c507bc

Browse files
authored
Add a McpClientTool.CallAsync helper (#367)
1 parent e457f0f commit 7c507bc

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

src/ModelContextProtocol/Client/McpClientExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,7 @@ public static Task UnsubscribeFromResourceAsync(this IMcpClient client, Uri uri,
779779
}
780780

781781
/// <summary>
782-
/// Invokes a tool on the server
782+
/// Invokes a tool on the server.
783783
/// </summary>
784784
/// <param name="client">The client instance used to communicate with the MCP server.</param>
785785
/// <param name="toolName">The name of the tool to call on the server..</param>

src/ModelContextProtocol/Client/McpClientTool.cs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,53 @@ internal McpClientTool(
8686
protected async override ValueTask<object?> InvokeCoreAsync(
8787
AIFunctionArguments arguments, CancellationToken cancellationToken)
8888
{
89-
CallToolResponse result = await _client.CallToolAsync(ProtocolTool.Name, arguments, _progress, JsonSerializerOptions, cancellationToken: cancellationToken).ConfigureAwait(false);
89+
CallToolResponse result = await CallAsync(arguments, _progress, JsonSerializerOptions, cancellationToken).ConfigureAwait(false);
9090
return JsonSerializer.SerializeToElement(result, McpJsonUtilities.JsonContext.Default.CallToolResponse);
9191
}
9292

93+
/// <summary>
94+
/// Invokes the tool on the server.
95+
/// </summary>
96+
/// <param name="arguments">An optional dictionary of arguments to pass to the tool. Each key represents a parameter name,
97+
/// and its associated value represents the argument value.
98+
/// </param>
99+
/// <param name="progress">
100+
/// An optional <see cref="IProgress{T}"/> to have progress notifications reported to it. Setting this to a non-<see langword="null"/>
101+
/// value will result in a progress token being included in the call, and any resulting progress notifications during the operation
102+
/// routed to this instance.
103+
/// </param>
104+
/// <param name="serializerOptions">
105+
/// The JSON serialization options governing argument serialization. If <see langword="null"/>, the default serialization options will be used.
106+
/// </param>
107+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
108+
/// <returns>
109+
/// A task containing the <see cref="CallToolResponse"/> from the tool execution. The response includes
110+
/// the tool's output content, which may be structured data, text, or an error message.
111+
/// </returns>
112+
/// <remarks>
113+
/// The base <see cref="AIFunction.InvokeAsync"/> method is overridden to invoke this <see cref="CallAsync"/> method.
114+
/// The only difference in behavior is <see cref="AIFunction.InvokeAsync"/> will serialize the resulting <see cref="CallToolResponse"/>"/>
115+
/// such that the <see cref="object"/> returned is a <see cref="JsonElement"/> containing the serialized <see cref="CallToolResponse"/>.
116+
/// This <see cref="CallToolResponse"/> method is intended to be called directly by user code, whereas the base <see cref="AIFunction.InvokeAsync"/>
117+
/// is intended to be used polymorphically via the base class, typically as part of an <see cref="IChatClient"/> operation.
118+
/// </remarks>
119+
/// <exception cref="McpException">The server could not find the requested tool, or the server encountered an error while processing the request.</exception>
120+
/// <example>
121+
/// <code>
122+
/// var result = await tool.CallAsync(
123+
/// new Dictionary&lt;string, object?&gt;
124+
/// {
125+
/// ["message"] = "Hello MCP!"
126+
/// });
127+
/// </code>
128+
/// </example>
129+
public Task<CallToolResponse> CallAsync(
130+
IReadOnlyDictionary<string, object?>? arguments = null,
131+
IProgress<ProgressNotificationValue>? progress = null,
132+
JsonSerializerOptions? serializerOptions = null,
133+
CancellationToken cancellationToken = default) =>
134+
_client.CallToolAsync(ProtocolTool.Name, arguments, progress, serializerOptions, cancellationToken);
135+
93136
/// <summary>
94137
/// Creates a new instance of the tool but modified to return the specified name from its <see cref="Name"/> property.
95138
/// </summary>
@@ -114,10 +157,8 @@ internal McpClientTool(
114157
/// the value returned from this instance's <see cref="AITool.Name"/>.
115158
/// </para>
116159
/// </remarks>
117-
public McpClientTool WithName(string name)
118-
{
119-
return new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, name, _description, _progress);
120-
}
160+
public McpClientTool WithName(string name) =>
161+
new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, name, _description, _progress);
121162

122163
/// <summary>
123164
/// Creates a new instance of the tool but modified to return the specified description from its <see cref="Description"/> property.
@@ -140,10 +181,8 @@ public McpClientTool WithName(string name)
140181
/// </para>
141182
/// </remarks>
142183
/// <returns>A new instance of <see cref="McpClientTool"/> with the provided description.</returns>
143-
public McpClientTool WithDescription(string description)
144-
{
145-
return new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, _name, description, _progress);
146-
}
184+
public McpClientTool WithDescription(string description) =>
185+
new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, _name, description, _progress);
147186

148187
/// <summary>
149188
/// Creates a new instance of the tool but modified to report progress via the specified <see cref="IProgress{T}"/>.

0 commit comments

Comments
 (0)