66using ModelContextProtocol . Protocol . Transport ;
77using ModelContextProtocol . Protocol . Types ;
88using ModelContextProtocol . Server ;
9- using ModelContextProtocol . Tests . Transport ;
109using ModelContextProtocol . Tests . Utils ;
1110using System . ComponentModel ;
1211using System . IO . Pipelines ;
1312using System . Threading . Channels ;
1413
14+ #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
15+
1516namespace ModelContextProtocol . Tests . Configuration ;
1617
1718public class McpServerBuilderExtensionsPromptsTests : LoggedTest , IAsyncDisposable
@@ -28,7 +29,70 @@ public McpServerBuilderExtensionsPromptsTests(ITestOutputHelper testOutputHelper
2829 {
2930 ServiceCollection sc = new ( ) ;
3031 sc . AddSingleton ( LoggerFactory ) ;
31- _builder = sc . AddMcpServer ( ) . WithStdioServerTransport ( ) . WithPrompts < SimplePrompts > ( ) ;
32+ _builder = sc
33+ . AddMcpServer ( )
34+ . WithStdioServerTransport ( )
35+ . WithListPromptsHandler ( async ( request , cancellationToken ) =>
36+ {
37+ var cursor = request . Params ? . Cursor ;
38+ switch ( cursor )
39+ {
40+ case null :
41+ return new ( )
42+ {
43+ NextCursor = "abc" ,
44+ Prompts = [ new ( )
45+ {
46+ Name = "FirstCustomPrompt" ,
47+ Description = "First prompt returned by custom handler" ,
48+ } ] ,
49+ } ;
50+
51+ case "abc" :
52+ return new ( )
53+ {
54+ NextCursor = "def" ,
55+ Prompts = [ new ( )
56+ {
57+ Name = "SecondCustomPrompt" ,
58+ Description = "Second prompt returned by custom handler" ,
59+ } ] ,
60+ } ;
61+
62+ case "def" :
63+ return new ( )
64+ {
65+ NextCursor = null ,
66+ Prompts = [ new ( )
67+ {
68+ Name = "FinalCustomPrompt" ,
69+ Description = "Final prompt returned by custom handler" ,
70+ } ] ,
71+ } ;
72+
73+ default :
74+ throw new Exception ( "Unexpected cursor" ) ;
75+ }
76+ } )
77+ . WithGetPromptHandler ( async ( request , cancellationToken ) =>
78+ {
79+ switch ( request . Params ? . Name )
80+ {
81+ case "FirstCustomPrompt" :
82+ case "SecondCustomPrompt" :
83+ case "FinalCustomPrompt" :
84+ return new GetPromptResult ( )
85+ {
86+ Messages = [ new ( ) { Role = Role . User , Content = new ( ) { Text = $ "hello from { request . Params . Name } ", Type = "text" } } ] ,
87+ } ;
88+
89+ default :
90+ throw new Exception ( $ "Unknown prompt '{ request . Params ? . Name } '") ;
91+ }
92+ } )
93+ . WithPrompts < SimplePrompts > ( ) ;
94+
95+
3296 // Call WithStdioServerTransport to get the IMcpServer registration, then overwrite default transport with a pipe transport.
3397 sc . AddSingleton < ITransport > ( new StreamServerTransport ( _clientToServerPipe . Reader . AsStream ( ) , _serverToClientPipe . Writer . AsStream ( ) , loggerFactory : LoggerFactory ) ) ;
3498 sc . AddSingleton ( new ObjectWithId ( ) ) ;
@@ -85,7 +149,7 @@ public async Task Can_List_And_Call_Registered_Prompts()
85149 IMcpClient client = await CreateMcpClientForServer ( ) ;
86150
87151 var prompts = await client . ListPromptsAsync ( TestContext . Current . CancellationToken ) ;
88- Assert . Equal ( 3 , prompts . Count ) ;
152+ Assert . Equal ( 6 , prompts . Count ) ;
89153
90154 var prompt = prompts . First ( t => t . Name == nameof ( SimplePrompts . ReturnsChatMessages ) ) ;
91155 Assert . Equal ( "Returns chat messages" , prompt . Description ) ;
@@ -98,6 +162,14 @@ public async Task Can_List_And_Call_Registered_Prompts()
98162 Assert . Equal ( 2 , chatMessages . Count ) ;
99163 Assert . Equal ( "The prompt is: hello" , chatMessages [ 0 ] . Text ) ;
100164 Assert . Equal ( "Summarize." , chatMessages [ 1 ] . Text ) ;
165+
166+ prompt = prompts . First ( t => t . Name == "SecondCustomPrompt" ) ;
167+ Assert . Equal ( "Second prompt returned by custom handler" , prompt . Description ) ;
168+ result = await prompt . GetAsync ( cancellationToken : TestContext . Current . CancellationToken ) ;
169+ chatMessages = result . ToChatMessages ( ) ;
170+ Assert . NotNull ( chatMessages ) ;
171+ Assert . Single ( chatMessages ) ;
172+ Assert . Equal ( "hello from SecondCustomPrompt" , chatMessages [ 0 ] . Text ) ;
101173 }
102174
103175 [ Fact ]
@@ -106,7 +178,7 @@ public async Task Can_Be_Notified_Of_Prompt_Changes()
106178 IMcpClient client = await CreateMcpClientForServer ( ) ;
107179
108180 var prompts = await client . ListPromptsAsync ( TestContext . Current . CancellationToken ) ;
109- Assert . Equal ( 3 , prompts . Count ) ;
181+ Assert . Equal ( 6 , prompts . Count ) ;
110182
111183 Channel < JsonRpcNotification > listChanged = Channel . CreateUnbounded < JsonRpcNotification > ( ) ;
112184 client . AddNotificationHandler ( "notifications/prompts/list_changed" , notification =>
@@ -127,7 +199,7 @@ public async Task Can_Be_Notified_Of_Prompt_Changes()
127199 await notificationRead ;
128200
129201 prompts = await client . ListPromptsAsync ( TestContext . Current . CancellationToken ) ;
130- Assert . Equal ( 4 , prompts . Count ) ;
202+ Assert . Equal ( 7 , prompts . Count ) ;
131203 Assert . Contains ( prompts , t => t . Name == "NewPrompt" ) ;
132204
133205 notificationRead = listChanged . Reader . ReadAsync ( TestContext . Current . CancellationToken ) ;
@@ -136,7 +208,7 @@ public async Task Can_Be_Notified_Of_Prompt_Changes()
136208 await notificationRead ;
137209
138210 prompts = await client . ListPromptsAsync ( TestContext . Current . CancellationToken ) ;
139- Assert . Equal ( 3 , prompts . Count ) ;
211+ Assert . Equal ( 6 , prompts . Count ) ;
140212 Assert . DoesNotContain ( prompts , t => t . Name == "NewPrompt" ) ;
141213 }
142214
0 commit comments