11using Microsoft . Extensions . AI ;
2+ using Microsoft . Extensions . DependencyInjection ;
23using ModelContextProtocol . Protocol . Types ;
34using ModelContextProtocol . Utils ;
45using ModelContextProtocol . Utils . Json ;
@@ -60,6 +61,14 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
6061 options ) ;
6162 }
6263
64+ // TODO: Fix the need for this suppression.
65+ [ UnconditionalSuppressMessage ( "ReflectionAnalysis" , "IL2111:ReflectionToDynamicallyAccessedMembers" ,
66+ Justification = "AIFunctionFactory ensures that the Type passed to AIFunctionFactoryOptions.CreateInstance has public constructors preserved" ) ]
67+ internal static Func < Type , AIFunctionArguments , object > GetCreateInstanceFunc ( ) =>
68+ static ( [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ] type , args ) => args . Services is { } services ?
69+ ActivatorUtilities . CreateInstance ( services , type ) :
70+ Activator . CreateInstance ( type ) ! ;
71+
6372 private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions (
6473 MethodInfo method , McpServerToolCreateOptions ? options ) =>
6574 new ( )
@@ -68,7 +77,7 @@ private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
6877 Description = options ? . Description ,
6978 MarshalResult = static ( result , _ , cancellationToken ) => new ValueTask < object ? > ( result ) ,
7079 SerializerOptions = options ? . SerializerOptions ?? McpJsonUtilities . DefaultOptions ,
71- Services = options ? . Services ,
80+ CreateInstance = GetCreateInstanceFunc ( ) ,
7281 ConfigureParameterBinding = pi =>
7382 {
7483 if ( pi . ParameterType == typeof ( RequestContext < CallToolRequestParams > ) )
@@ -110,6 +119,32 @@ private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
110119 } ;
111120 }
112121
122+ if ( options ? . Services is { } services &&
123+ services . GetService < IServiceProviderIsService > ( ) is { } ispis &&
124+ ispis . IsService ( pi . ParameterType ) )
125+ {
126+ return new ( )
127+ {
128+ ExcludeFromSchema = true ,
129+ BindParameter = ( pi , args ) =>
130+ GetRequestContext ( args ) ? . Services ? . GetService ( pi . ParameterType ) ??
131+ ( pi . HasDefaultValue ? null :
132+ throw new ArgumentException ( "No service of the requested type was found." ) ) ,
133+ } ;
134+ }
135+
136+ if ( pi . GetCustomAttribute < FromKeyedServicesAttribute > ( ) is { } keyedAttr )
137+ {
138+ return new ( )
139+ {
140+ ExcludeFromSchema = true ,
141+ BindParameter = ( pi , args ) =>
142+ ( GetRequestContext ( args ) ? . Services as IKeyedServiceProvider ) ? . GetKeyedService ( pi . ParameterType , keyedAttr . Key ) ??
143+ ( pi . HasDefaultValue ? null :
144+ throw new ArgumentException ( "No service of the requested type was found." ) ) ,
145+ } ;
146+ }
147+
113148 return default ;
114149
115150 static RequestContext < CallToolRequestParams > ? GetRequestContext ( AIFunctionArguments args )
0 commit comments