2
2
using Microsoft . Extensions . DependencyInjection ;
3
3
using ModelContextProtocol . Protocol . Types ;
4
4
using ModelContextProtocol . Utils ;
5
- using ModelContextProtocol . Utils . Json ;
6
5
using System . Diagnostics . CodeAnalysis ;
7
6
using System . Reflection ;
8
7
using System . Text . Json ;
@@ -12,10 +11,6 @@ namespace ModelContextProtocol.Server;
12
11
/// <summary>Provides an <see cref="McpServerPrompt"/> that's implemented via an <see cref="AIFunction"/>.</summary>
13
12
internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
14
13
{
15
- /// <summary>Key used temporarily for flowing request context into an AIFunction.</summary>
16
- /// <remarks>This will be replaced with use of AIFunctionArguments.Context.</remarks>
17
- internal const string RequestContextKey = "__temporary_RequestContext" ;
18
-
19
14
/// <summary>
20
15
/// Creates an <see cref="McpServerPrompt"/> instance for a method, specified via a <see cref="Delegate"/> instance.
21
16
/// </summary>
@@ -40,17 +35,10 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
40
35
{
41
36
Throw . IfNull ( method ) ;
42
37
43
- // TODO: Once this repo consumes a new build of Microsoft.Extensions.AI containing
44
- // https://github.com/dotnet/extensions/pull/6158,
45
- // https://github.com/dotnet/extensions/pull/6162, and
46
- // https://github.com/dotnet/extensions/pull/6175, switch over to using the real
47
- // AIFunctionFactory, delete the TemporaryXx types, and fix-up the mechanism by
48
- // which the arguments are passed.
49
-
50
38
options = DeriveOptions ( method , options ) ;
51
39
52
40
return Create (
53
- TemporaryAIFunctionFactory . Create ( method , target , CreateAIFunctionFactoryOptions ( method , options ) ) ,
41
+ AIFunctionFactory . Create ( method , target , CreateAIFunctionFactoryOptions ( method , options ) ) ,
54
42
options ) ;
55
43
}
56
44
@@ -67,17 +55,17 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
67
55
options = DeriveOptions ( method , options ) ;
68
56
69
57
return Create (
70
- TemporaryAIFunctionFactory . Create ( method , targetType , CreateAIFunctionFactoryOptions ( method , options ) ) ,
58
+ AIFunctionFactory . Create ( method , targetType , CreateAIFunctionFactoryOptions ( method , options ) ) ,
71
59
options ) ;
72
60
}
73
61
74
- private static TemporaryAIFunctionFactoryOptions CreateAIFunctionFactoryOptions (
62
+ private static AIFunctionFactoryOptions CreateAIFunctionFactoryOptions (
75
63
MethodInfo method , McpServerPromptCreateOptions ? options ) =>
76
64
new ( )
77
65
{
78
66
Name = options ? . Name ?? method . GetCustomAttribute < McpServerPromptAttribute > ( ) ? . Name ,
79
67
Description = options ? . Description ,
80
- MarshalResult = static ( result , _ , cancellationToken ) => Task . FromResult ( result ) ,
68
+ MarshalResult = static ( result , _ , cancellationToken ) => new ValueTask < object ? > ( result ) ,
81
69
ConfigureParameterBinding = pi =>
82
70
{
83
71
if ( pi . ParameterType == typeof ( RequestContext < GetPromptRequestParams > ) )
@@ -129,9 +117,9 @@ private static TemporaryAIFunctionFactoryOptions CreateAIFunctionFactoryOptions(
129
117
130
118
return default ;
131
119
132
- static RequestContext < GetPromptRequestParams > ? GetRequestContext ( IReadOnlyDictionary < string , object ? > args )
120
+ static RequestContext < GetPromptRequestParams > ? GetRequestContext ( AIFunctionArguments args )
133
121
{
134
- if ( args . TryGetValue ( RequestContextKey , out var orc ) &&
122
+ if ( args . Context ? . TryGetValue ( typeof ( RequestContext < GetPromptRequestParams > ) , out var orc ) is true &&
135
123
orc is RequestContext < GetPromptRequestParams > requestContext )
136
124
{
137
125
return requestContext ;
@@ -204,14 +192,22 @@ public override async Task<GetPromptResult> GetAsync(
204
192
RequestContext < GetPromptRequestParams > request , CancellationToken cancellationToken = default )
205
193
{
206
194
Throw . IfNull ( request ) ;
207
-
208
195
cancellationToken . ThrowIfCancellationRequested ( ) ;
209
196
210
- // TODO: Once we shift to the real AIFunctionFactory, the request should be passed via AIFunctionArguments.Context.
211
- Dictionary < string , object ? > arguments = request . Params ? . Arguments is { } paramArgs ?
212
- paramArgs . ToDictionary ( entry => entry . Key , entry => entry . Value . AsObject ( ) ) :
213
- [ ] ;
214
- arguments [ RequestContextKey ] = request ;
197
+ AIFunctionArguments arguments = new ( )
198
+ {
199
+ Services = request . Server ? . Services ,
200
+ Context = new Dictionary < object , object ? > ( ) { [ typeof ( RequestContext < GetPromptRequestParams > ) ] = request }
201
+ } ;
202
+
203
+ var argDict = request . Params ? . Arguments ;
204
+ if ( argDict is not null )
205
+ {
206
+ foreach ( var kvp in argDict )
207
+ {
208
+ arguments [ kvp . Key ] = kvp . Value ;
209
+ }
210
+ }
215
211
216
212
object ? result = await AIFunction . InvokeAsync ( arguments , cancellationToken ) . ConfigureAwait ( false ) ;
217
213
0 commit comments