1
1
using Microsoft . Extensions . AI ;
2
+ using Microsoft . Extensions . DependencyInjection ;
2
3
using ModelContextProtocol . Protocol . Types ;
3
4
using ModelContextProtocol . Utils ;
4
5
using ModelContextProtocol . Utils . Json ;
@@ -60,6 +61,14 @@ internal sealed class AIFunctionMcpServerTool : McpServerTool
60
61
options ) ;
61
62
}
62
63
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
+
63
72
private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions (
64
73
MethodInfo method , McpServerToolCreateOptions ? options ) =>
65
74
new ( )
@@ -68,7 +77,7 @@ private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
68
77
Description = options ? . Description ,
69
78
MarshalResult = static ( result , _ , cancellationToken ) => new ValueTask < object ? > ( result ) ,
70
79
SerializerOptions = options ? . SerializerOptions ?? McpJsonUtilities . DefaultOptions ,
71
- Services = options ? . Services ,
80
+ CreateInstance = GetCreateInstanceFunc ( ) ,
72
81
ConfigureParameterBinding = pi =>
73
82
{
74
83
if ( pi . ParameterType == typeof ( RequestContext < CallToolRequestParams > ) )
@@ -110,6 +119,32 @@ private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
110
119
} ;
111
120
}
112
121
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
+
113
148
return default ;
114
149
115
150
static RequestContext < CallToolRequestParams > ? GetRequestContext ( AIFunctionArguments args )
0 commit comments