Remove fast-path cancellation check from CallTool (#48)

This commit is contained in:
Stephen Toub 2025-03-09 06:18:21 -04:00 • committed by GitHub
commit 04af21046b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,7 @@
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Text.Json; using System.Text.Json;
using McpDotNet.Configuration; using McpDotNet.Configuration;
using McpDotNet.Protocol.Types; using McpDotNet.Protocol.Types;
@ -171,44 +172,49 @@ public static partial class McpServerBuilderExtensions
private static async Task<CallToolResponse> CallTool(RequestContext<CallToolRequestParams> request, MethodInfo method, CancellationToken cancellationToken) private static async Task<CallToolResponse> CallTool(RequestContext<CallToolRequestParams> request, MethodInfo method, CancellationToken cancellationToken)
{ {
cancellationToken.ThrowIfCancellationRequested();
var methodParameters = method.GetParameters(); var methodParameters = method.GetParameters();
List<object?> parameters = ResolveParameters(request, methodParameters, cancellationToken); List<object?> parameters = ResolveParameters(request, methodParameters, cancellationToken);
if (cancellationToken.IsCancellationRequested) using var scope = request.Server.ServiceProvider?.CreateScope();
return new CallToolResponse { Content = [new Content { Text = "Operation was cancelled" }] }; var objectInstance = CreateObjectInstance(method, scope?.ServiceProvider);
object? result;
try try
{ {
using var scope = request.Server.ServiceProvider?.CreateScope(); const BindingFlags InvokeFlags =
var objectInstance = CreateObjectInstance(method, scope?.ServiceProvider); #if NET
var result = method.Invoke(objectInstance, parameters.ToArray()); BindingFlags.DoNotWrapExceptions |
#endif
BindingFlags.Default;
if (result is Task task) result = method.Invoke(objectInstance, InvokeFlags, binder: null, parameters.ToArray(), culture: null);
{
await task.ConfigureAwait(false);
var resultProperty = task.GetType().GetProperty("Result");
result = resultProperty?.GetValue(task);
}
if (result is string resultString)
return new CallToolResponse { Content = [new Content() { Text = resultString, Type = "text" }] };
if (result is string[] resultStringArray)
return new CallToolResponse { Content = resultStringArray.Select(s => new Content() { Text = s, Type = "text" }).ToList() };
if (result is null)
return new CallToolResponse { Content = [new Content() { Text = "null" }] };
if (result is JsonElement jsonElement)
return new CallToolResponse { Content = [new Content() { Text = jsonElement.GetRawText(), Type = "text" }] };
return new CallToolResponse { Content = [new Content() { Text = result.ToString(), Type = "text" }] };
} }
catch (TargetInvocationException e) catch (TargetInvocationException e) when (e.InnerException is not null)
{ {
throw new McpServerException(e.Message, e); ExceptionDispatchInfo.Capture(e.InnerException).Throw();
throw; // unreachable
} }
if (result is Task task)
{
await task.ConfigureAwait(false);
var resultProperty = task.GetType().GetProperty("Result");
result = resultProperty?.GetValue(task);
}
if (result is string resultString)
return new CallToolResponse { Content = [new Content() { Text = resultString, Type = "text" }] };
if (result is string[] resultStringArray)
return new CallToolResponse { Content = resultStringArray.Select(s => new Content() { Text = s, Type = "text" }).ToList() };
if (result is null)
return new CallToolResponse { Content = [new Content() { Text = "null" }] };
if (result is JsonElement jsonElement)
return new CallToolResponse { Content = [new Content() { Text = jsonElement.GetRawText(), Type = "text" }] };
return new CallToolResponse { Content = [new Content() { Text = result.ToString(), Type = "text" }] };
} }
private static List<object?> ResolveParameters(RequestContext<CallToolRequestParams> request, ParameterInfo[] methodParameters, CancellationToken cancellationToken) private static List<object?> ResolveParameters(RequestContext<CallToolRequestParams> request, ParameterInfo[] methodParameters, CancellationToken cancellationToken)