Implement SEP-2663 Tasks Extension (#1579)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Pranav Senthilnathan 2026-06-11 13:10:45 -07:00 • committed by GitHub
commit dbb7a20176
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -154,23 +154,6 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
tool.Meta = function.UnderlyingMethod is not null ?
CreateMetaFromAttributes(function.UnderlyingMethod, options.Meta) :
options.Meta;
// Apply user-specified Execution settings if provided
if (options.Execution is not null)
{
tool.Execution = options.Execution;
}
}
// Auto-detect async methods and mark with taskSupport = "optional" unless explicitly configured.
// This enables implicit task support for async tools: clients can choose to invoke them
// synchronously (wait for completion) or as a task (receive taskId, poll for result).
if (function.UnderlyingMethod is not null &&
IsAsyncMethod(function.UnderlyingMethod) &&
tool.Execution?.TaskSupport is null)
{
tool.Execution ??= new ToolExecution();
tool.Execution.TaskSupport = ToolTaskSupport.Optional;
}
return new AIFunctionMcpServerTool(function, tool, options?.Services, structuredOutputRequiresWrapping, options?.Metadata ?? []);
@ -218,12 +201,6 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
serializerOptions: newOptions.SerializerOptions ?? McpJsonUtilities.DefaultOptions,
inferenceOptions: newOptions.SchemaCreateOptions);
}
if (toolAttr._taskSupport is { } taskSupport)
{
newOptions.Execution ??= new ToolExecution();
newOptions.Execution.TaskSupport ??= taskSupport;
}
}
if (method.GetCustomAttribute<DescriptionAttribute>() is { } descAttr)
@ -350,27 +327,27 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
// Case the name based on the provided naming policy.
return (policy ?? JsonNamingPolicy.SnakeCaseLower).ConvertName(name) ?? name;
}
private static bool IsAsyncMethod(MethodInfo method)
{
Type t = method.ReturnType;
if (t == typeof(Task) || t == typeof(ValueTask))
static bool IsAsyncMethod(MethodInfo method)
{
return true;
}
Type t = method.ReturnType;
if (t.IsGenericType)
{
t = t.GetGenericTypeDefinition();
if (t == typeof(Task<>) || t == typeof(ValueTask<>) || t == typeof(IAsyncEnumerable<>))
if (t == typeof(Task) || t == typeof(ValueTask))
{
return true;
}
}
return false;
if (t.IsGenericType)
{
t = t.GetGenericTypeDefinition();
if (t == typeof(Task<>) || t == typeof(ValueTask<>) || t == typeof(IAsyncEnumerable<>))
{
return true;
}
}
return false;
}
}
/// <summary>Creates metadata from attributes on the specified method and its declaring class, with the MethodInfo as the first item.</summary>