using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Protocol.Types;
using ModelContextProtocol.Utils;
using ModelContextProtocol.Utils.Json;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.Json;
namespace ModelContextProtocol.Server;
/// Provides an that's implemented via an .
internal sealed class AIFunctionMcpServerTool : McpServerTool
{
///
/// Creates an instance for a method, specified via a instance.
///
public static new AIFunctionMcpServerTool Create(
Delegate method,
McpServerToolCreateOptions? options)
{
Throw.IfNull(method);
options = DeriveOptions(method.Method, options);
return Create(method.Method, method.Target, options);
}
///
/// Creates an instance for a method, specified via a instance.
///
public static new AIFunctionMcpServerTool Create(
MethodInfo method,
object? target,
McpServerToolCreateOptions? options)
{
Throw.IfNull(method);
options = DeriveOptions(method, options);
return Create(
AIFunctionFactory.Create(method, target, CreateAIFunctionFactoryOptions(method, options)),
options);
}
///
/// Creates an instance for a method, specified via a instance.
///
public static new AIFunctionMcpServerTool Create(
MethodInfo method,
Func, object> createTargetFunc,
McpServerToolCreateOptions? options)
{
Throw.IfNull(method);
Throw.IfNull(createTargetFunc);
options = DeriveOptions(method, options);
return Create(
AIFunctionFactory.Create(method, args =>
{
var request = (RequestContext)args.Context![typeof(RequestContext)]!;
return createTargetFunc(request);
}, CreateAIFunctionFactoryOptions(method, options)),
options);
}
// TODO: Fix the need for this suppression.
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2111:ReflectionToDynamicallyAccessedMembers",
Justification = "AIFunctionFactory ensures that the Type passed to AIFunctionFactoryOptions.CreateInstance has public constructors preserved")]
internal static Func GetCreateInstanceFunc() =>
static ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] type, args) => args.Services is { } services ?
ActivatorUtilities.CreateInstance(services, type) :
Activator.CreateInstance(type)!;
private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
MethodInfo method, McpServerToolCreateOptions? options) =>
new()
{
Name = options?.Name ?? method.GetCustomAttribute()?.Name,
Description = options?.Description,
MarshalResult = static (result, _, cancellationToken) => new ValueTask