88import static net .javacrumbs .jsonunit .assertj .JsonAssertions .json ;
99import static org .assertj .core .api .Assertions .assertThat ;
1010import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
11+ import static org .assertj .core .api .Assertions .assertWith ;
1112import static org .awaitility .Awaitility .await ;
1213import static org .mockito .Mockito .mock ;
1314
@@ -144,6 +145,8 @@ void testCreateMessageSuccess(String clientType) {
144145 CallToolResult callResponse = new McpSchema .CallToolResult (List .of (new McpSchema .TextContent ("CALL RESPONSE" )),
145146 null );
146147
148+ AtomicReference <CreateMessageResult > samplingResult = new AtomicReference <>();
149+
147150 McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
148151 .tool (Tool .builder ().name ("tool1" ).description ("tool1 description" ).inputSchema (emptyJsonSchema ).build ())
149152 .callHandler ((exchange , request ) -> {
@@ -159,37 +162,35 @@ void testCreateMessageSuccess(String clientType) {
159162 .build ())
160163 .build ();
161164
162- StepVerifier .create (exchange .createMessage (createMessageRequest )).consumeNextWith (result -> {
163- assertThat (result ).isNotNull ();
164- assertThat (result .role ()).isEqualTo (Role .USER );
165- assertThat (result .content ()).isInstanceOf (McpSchema .TextContent .class );
166- assertThat (((McpSchema .TextContent ) result .content ()).text ()).isEqualTo ("Test message" );
167- assertThat (result .model ()).isEqualTo ("MockModelName" );
168- assertThat (result .stopReason ()).isEqualTo (CreateMessageResult .StopReason .STOP_SEQUENCE );
169- }).verifyComplete ();
170-
171- return Mono .just (callResponse );
165+ return exchange .createMessage (createMessageRequest )
166+ .doOnNext (samplingResult ::set )
167+ .thenReturn (callResponse );
172168 })
173169 .build ();
174170
175- //@formatter:off
176- var mcpServer = prepareAsyncServerBuilder ()
177- .serverInfo ("test-server" , "1.0.0" )
178- .tools (tool )
179- .build ();
171+ var mcpServer = prepareAsyncServerBuilder ().serverInfo ("test-server" , "1.0.0" ).tools (tool ).build ();
180172
181- try (
182- var mcpClient = clientBuilder .clientInfo (new McpSchema .Implementation ("Sample client" , "0.0.0" ))
183- .capabilities (ClientCapabilities .builder ().sampling ().build ())
184- .sampling (samplingHandler )
185- .build ()) {//@formatter:on
173+ try (var mcpClient = clientBuilder .clientInfo (new McpSchema .Implementation ("Sample client" , "0.0.0" ))
174+ .capabilities (ClientCapabilities .builder ().sampling ().build ())
175+ .sampling (samplingHandler )
176+ .build ()) {
186177
187178 InitializeResult initResult = mcpClient .initialize ();
188179 assertThat (initResult ).isNotNull ();
189180
190181 CallToolResult response = mcpClient .callTool (new McpSchema .CallToolRequest ("tool1" , Map .of ()));
191182
192- assertThat (response ).isNotNull ().isEqualTo (callResponse );
183+ assertThat (response ).isNotNull ();
184+ assertThat (response ).isEqualTo (callResponse );
185+
186+ assertWith (samplingResult .get (), result -> {
187+ assertThat (result ).isNotNull ();
188+ assertThat (result .role ()).isEqualTo (Role .USER );
189+ assertThat (result .content ()).isInstanceOf (McpSchema .TextContent .class );
190+ assertThat (((McpSchema .TextContent ) result .content ()).text ()).isEqualTo ("Test message" );
191+ assertThat (result .model ()).isEqualTo ("MockModelName" );
192+ assertThat (result .stopReason ()).isEqualTo (CreateMessageResult .StopReason .STOP_SEQUENCE );
193+ });
193194 }
194195 mcpServer .close ();
195196 }
@@ -225,6 +226,8 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr
225226 CallToolResult callResponse = new McpSchema .CallToolResult (List .of (new McpSchema .TextContent ("CALL RESPONSE" )),
226227 null );
227228
229+ AtomicReference <CreateMessageResult > samplingResult = new AtomicReference <>();
230+
228231 McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
229232 .tool (Tool .builder ().name ("tool1" ).description ("tool1 description" ).inputSchema (emptyJsonSchema ).build ())
230233 .callHandler ((exchange , request ) -> {
@@ -240,16 +243,9 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr
240243 .build ())
241244 .build ();
242245
243- StepVerifier .create (exchange .createMessage (createMessageRequest )).consumeNextWith (result -> {
244- assertThat (result ).isNotNull ();
245- assertThat (result .role ()).isEqualTo (Role .USER );
246- assertThat (result .content ()).isInstanceOf (McpSchema .TextContent .class );
247- assertThat (((McpSchema .TextContent ) result .content ()).text ()).isEqualTo ("Test message" );
248- assertThat (result .model ()).isEqualTo ("MockModelName" );
249- assertThat (result .stopReason ()).isEqualTo (CreateMessageResult .StopReason .STOP_SEQUENCE );
250- }).verifyComplete ();
251-
252- return Mono .just (callResponse );
246+ return exchange .createMessage (createMessageRequest )
247+ .doOnNext (samplingResult ::set )
248+ .thenReturn (callResponse );
253249 })
254250 .build ();
255251
@@ -266,6 +262,15 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr
266262 assertThat (response ).isNotNull ();
267263 assertThat (response ).isEqualTo (callResponse );
268264
265+ assertWith (samplingResult .get (), result -> {
266+ assertThat (result ).isNotNull ();
267+ assertThat (result .role ()).isEqualTo (Role .USER );
268+ assertThat (result .content ()).isInstanceOf (McpSchema .TextContent .class );
269+ assertThat (((McpSchema .TextContent ) result .content ()).text ()).isEqualTo ("Test message" );
270+ assertThat (result .model ()).isEqualTo ("MockModelName" );
271+ assertThat (result .stopReason ()).isEqualTo (CreateMessageResult .StopReason .STOP_SEQUENCE );
272+ });
273+
269274 mcpClient .close ();
270275 mcpServer .close ();
271276 }
@@ -312,16 +317,7 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt
312317 .build ())
313318 .build ();
314319
315- StepVerifier .create (exchange .createMessage (createMessageRequest )).consumeNextWith (result -> {
316- assertThat (result ).isNotNull ();
317- assertThat (result .role ()).isEqualTo (Role .USER );
318- assertThat (result .content ()).isInstanceOf (McpSchema .TextContent .class );
319- assertThat (((McpSchema .TextContent ) result .content ()).text ()).isEqualTo ("Test message" );
320- assertThat (result .model ()).isEqualTo ("MockModelName" );
321- assertThat (result .stopReason ()).isEqualTo (CreateMessageResult .StopReason .STOP_SEQUENCE );
322- }).verifyComplete ();
323-
324- return Mono .just (callResponse );
320+ return exchange .createMessage (createMessageRequest ).thenReturn (callResponse );
325321 })
326322 .build ();
327323
@@ -335,7 +331,7 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt
335331
336332 assertThatExceptionOfType (McpError .class ).isThrownBy (() -> {
337333 mcpClient .callTool (new McpSchema .CallToolRequest ("tool1" , Map .of ()));
338- }).withMessageContaining ("Timeout " );
334+ }).withMessageContaining ("1000ms " );
339335
340336 mcpClient .close ();
341337 mcpServer .close ();
@@ -352,19 +348,14 @@ void testCreateElicitationWithoutElicitationCapabilities(String clientType) {
352348
353349 McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
354350 .tool (Tool .builder ().name ("tool1" ).description ("tool1 description" ).inputSchema (emptyJsonSchema ).build ())
355- .callHandler ((exchange , request ) -> {
356-
357- exchange .createElicitation (mock (McpSchema .ElicitRequest .class )).block ();
358-
359- return Mono .just (mock (CallToolResult .class ));
360- })
351+ .callHandler ((exchange , request ) -> exchange .createElicitation (mock (ElicitRequest .class ))
352+ .then (Mono .just (mock (CallToolResult .class ))))
361353 .build ();
362354
363355 var server = prepareAsyncServerBuilder ().serverInfo ("test-server" , "1.0.0" ).tools (tool ).build ();
364356
365- try (
366- // Create client without elicitation capabilities
367- var client = clientBuilder .clientInfo (new McpSchema .Implementation ("Sample client" , "0.0.0" )).build ()) {
357+ // Create client without elicitation capabilities
358+ try (var client = clientBuilder .clientInfo (new McpSchema .Implementation ("Sample client" , "0.0.0" )).build ()) {
368359
369360 assertThat (client .initialize ()).isNotNull ();
370361
@@ -440,17 +431,10 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
440431
441432 var clientBuilder = clientBuilders .get (clientType );
442433
443- Function <McpSchema . ElicitRequest , McpSchema . ElicitResult > elicitationHandler = request -> {
434+ Function <ElicitRequest , ElicitResult > elicitationHandler = request -> {
444435 assertThat (request .message ()).isNotEmpty ();
445436 assertThat (request .requestedSchema ()).isNotNull ();
446- try {
447- TimeUnit .SECONDS .sleep (2 );
448- }
449- catch (InterruptedException e ) {
450- throw new RuntimeException (e );
451- }
452- return new McpSchema .ElicitResult (McpSchema .ElicitResult .Action .ACCEPT ,
453- Map .of ("message" , request .message ()));
437+ return new ElicitResult (ElicitResult .Action .ACCEPT , Map .of ("message" , request .message ()));
454438 };
455439
456440 var mcpClient = clientBuilder .clientInfo (new McpSchema .Implementation ("Sample client" , "0.0.0" ))
@@ -461,6 +445,8 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
461445 CallToolResult callResponse = new McpSchema .CallToolResult (List .of (new McpSchema .TextContent ("CALL RESPONSE" )),
462446 null );
463447
448+ AtomicReference <ElicitResult > resultRef = new AtomicReference <>();
449+
464450 McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
465451 .tool (Tool .builder ().name ("tool1" ).description ("tool1 description" ).inputSchema (emptyJsonSchema ).build ())
466452 .callHandler ((exchange , request ) -> {
@@ -471,13 +457,9 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
471457 Map .of ("type" , "object" , "properties" , Map .of ("message" , Map .of ("type" , "string" ))))
472458 .build ();
473459
474- StepVerifier .create (exchange .createElicitation (elicitationRequest )).consumeNextWith (result -> {
475- assertThat (result ).isNotNull ();
476- assertThat (result .action ()).isEqualTo (McpSchema .ElicitResult .Action .ACCEPT );
477- assertThat (result .content ().get ("message" )).isEqualTo ("Test message" );
478- }).verifyComplete ();
479-
480- return Mono .just (callResponse );
460+ return exchange .createElicitation (elicitationRequest )
461+ .doOnNext (resultRef ::set )
462+ .then (Mono .just (callResponse ));
481463 })
482464 .build ();
483465
@@ -493,6 +475,11 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
493475
494476 assertThat (response ).isNotNull ();
495477 assertThat (response ).isEqualTo (callResponse );
478+ assertWith (resultRef .get (), result -> {
479+ assertThat (result ).isNotNull ();
480+ assertThat (result .action ()).isEqualTo (McpSchema .ElicitResult .Action .ACCEPT );
481+ assertThat (result .content ().get ("message" )).isEqualTo ("Test message" );
482+ });
496483
497484 mcpClient .closeGracefully ();
498485 mcpServer .closeGracefully ().block ();
@@ -870,7 +857,7 @@ void testToolListChangeHandlingSuccess(String clientType) {
870857 })
871858 .build ();
872859
873- AtomicReference <List <Tool >> rootsRef = new AtomicReference <>();
860+ AtomicReference <List <Tool >> toolsRef = new AtomicReference <>();
874861
875862 var mcpServer = prepareSyncServerBuilder ().capabilities (ServerCapabilities .builder ().tools (true ).build ())
876863 .tools (tool1 )
@@ -887,32 +874,31 @@ void testToolListChangeHandlingSuccess(String clientType) {
887874 .build (), HttpResponse .BodyHandlers .ofString ());
888875 String responseBody = response .body ();
889876 assertThat (responseBody ).isNotBlank ();
877+ toolsRef .set (toolsUpdate );
890878 }
891879 catch (Exception e ) {
892880 e .printStackTrace ();
893881 }
894-
895- rootsRef .set (toolsUpdate );
896882 }).build ()) {
897883
898884 InitializeResult initResult = mcpClient .initialize ();
899885 assertThat (initResult ).isNotNull ();
900886
901- assertThat (rootsRef .get ()).isNull ();
887+ assertThat (toolsRef .get ()).isNull ();
902888
903889 assertThat (mcpClient .listTools ().tools ()).contains (tool1 .tool ());
904890
905891 mcpServer .notifyToolsListChanged ();
906892
907893 await ().atMost (Duration .ofSeconds (5 )).untilAsserted (() -> {
908- assertThat (rootsRef .get ()).containsAll (List .of (tool1 .tool ()));
894+ assertThat (toolsRef .get ()).containsAll (List .of (tool1 .tool ()));
909895 });
910896
911897 // Remove a tool
912898 mcpServer .removeTool ("tool1" );
913899
914900 await ().atMost (Duration .ofSeconds (5 )).untilAsserted (() -> {
915- assertThat (rootsRef .get ()).isEmpty ();
901+ assertThat (toolsRef .get ()).isEmpty ();
916902 });
917903
918904 // Add a new tool
@@ -928,7 +914,7 @@ void testToolListChangeHandlingSuccess(String clientType) {
928914 mcpServer .addTool (tool2 );
929915
930916 await ().atMost (Duration .ofSeconds (5 )).untilAsserted (() -> {
931- assertThat (rootsRef .get ()).containsAll (List .of (tool2 .tool ()));
917+ assertThat (toolsRef .get ()).containsAll (List .of (tool2 .tool ()));
932918 });
933919 }
934920
0 commit comments