8
8
import static net .javacrumbs .jsonunit .assertj .JsonAssertions .json ;
9
9
import static org .assertj .core .api .Assertions .assertThat ;
10
10
import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
11
+ import static org .assertj .core .api .Assertions .assertWith ;
11
12
import static org .awaitility .Awaitility .await ;
12
13
import static org .mockito .Mockito .mock ;
13
14
@@ -144,6 +145,8 @@ void testCreateMessageSuccess(String clientType) {
144
145
CallToolResult callResponse = new McpSchema .CallToolResult (List .of (new McpSchema .TextContent ("CALL RESPONSE" )),
145
146
null );
146
147
148
+ AtomicReference <CreateMessageResult > samplingResult = new AtomicReference <>();
149
+
147
150
McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
148
151
.tool (Tool .builder ().name ("tool1" ).description ("tool1 description" ).inputSchema (emptyJsonSchema ).build ())
149
152
.callHandler ((exchange , request ) -> {
@@ -159,37 +162,35 @@ void testCreateMessageSuccess(String clientType) {
159
162
.build ())
160
163
.build ();
161
164
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 );
172
168
})
173
169
.build ();
174
170
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 ();
180
172
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 ()) {
186
177
187
178
InitializeResult initResult = mcpClient .initialize ();
188
179
assertThat (initResult ).isNotNull ();
189
180
190
181
CallToolResult response = mcpClient .callTool (new McpSchema .CallToolRequest ("tool1" , Map .of ()));
191
182
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
+ });
193
194
}
194
195
mcpServer .close ();
195
196
}
@@ -225,6 +226,8 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr
225
226
CallToolResult callResponse = new McpSchema .CallToolResult (List .of (new McpSchema .TextContent ("CALL RESPONSE" )),
226
227
null );
227
228
229
+ AtomicReference <CreateMessageResult > samplingResult = new AtomicReference <>();
230
+
228
231
McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
229
232
.tool (Tool .builder ().name ("tool1" ).description ("tool1 description" ).inputSchema (emptyJsonSchema ).build ())
230
233
.callHandler ((exchange , request ) -> {
@@ -240,16 +243,9 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr
240
243
.build ())
241
244
.build ();
242
245
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 );
253
249
})
254
250
.build ();
255
251
@@ -266,6 +262,15 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr
266
262
assertThat (response ).isNotNull ();
267
263
assertThat (response ).isEqualTo (callResponse );
268
264
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
+
269
274
mcpClient .close ();
270
275
mcpServer .close ();
271
276
}
@@ -312,16 +317,7 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt
312
317
.build ())
313
318
.build ();
314
319
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 );
325
321
})
326
322
.build ();
327
323
@@ -335,7 +331,7 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt
335
331
336
332
assertThatExceptionOfType (McpError .class ).isThrownBy (() -> {
337
333
mcpClient .callTool (new McpSchema .CallToolRequest ("tool1" , Map .of ()));
338
- }).withMessageContaining ("Timeout " );
334
+ }).withMessageContaining ("1000ms " );
339
335
340
336
mcpClient .close ();
341
337
mcpServer .close ();
@@ -352,19 +348,14 @@ void testCreateElicitationWithoutElicitationCapabilities(String clientType) {
352
348
353
349
McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
354
350
.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 ))))
361
353
.build ();
362
354
363
355
var server = prepareAsyncServerBuilder ().serverInfo ("test-server" , "1.0.0" ).tools (tool ).build ();
364
356
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 ()) {
368
359
369
360
assertThat (client .initialize ()).isNotNull ();
370
361
@@ -440,17 +431,10 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
440
431
441
432
var clientBuilder = clientBuilders .get (clientType );
442
433
443
- Function <McpSchema . ElicitRequest , McpSchema . ElicitResult > elicitationHandler = request -> {
434
+ Function <ElicitRequest , ElicitResult > elicitationHandler = request -> {
444
435
assertThat (request .message ()).isNotEmpty ();
445
436
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 ()));
454
438
};
455
439
456
440
var mcpClient = clientBuilder .clientInfo (new McpSchema .Implementation ("Sample client" , "0.0.0" ))
@@ -461,6 +445,8 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
461
445
CallToolResult callResponse = new McpSchema .CallToolResult (List .of (new McpSchema .TextContent ("CALL RESPONSE" )),
462
446
null );
463
447
448
+ AtomicReference <ElicitResult > resultRef = new AtomicReference <>();
449
+
464
450
McpServerFeatures .AsyncToolSpecification tool = McpServerFeatures .AsyncToolSpecification .builder ()
465
451
.tool (Tool .builder ().name ("tool1" ).description ("tool1 description" ).inputSchema (emptyJsonSchema ).build ())
466
452
.callHandler ((exchange , request ) -> {
@@ -471,13 +457,9 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
471
457
Map .of ("type" , "object" , "properties" , Map .of ("message" , Map .of ("type" , "string" ))))
472
458
.build ();
473
459
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 ));
481
463
})
482
464
.build ();
483
465
@@ -493,6 +475,11 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
493
475
494
476
assertThat (response ).isNotNull ();
495
477
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
+ });
496
483
497
484
mcpClient .closeGracefully ();
498
485
mcpServer .closeGracefully ().block ();
@@ -870,7 +857,7 @@ void testToolListChangeHandlingSuccess(String clientType) {
870
857
})
871
858
.build ();
872
859
873
- AtomicReference <List <Tool >> rootsRef = new AtomicReference <>();
860
+ AtomicReference <List <Tool >> toolsRef = new AtomicReference <>();
874
861
875
862
var mcpServer = prepareSyncServerBuilder ().capabilities (ServerCapabilities .builder ().tools (true ).build ())
876
863
.tools (tool1 )
@@ -887,32 +874,31 @@ void testToolListChangeHandlingSuccess(String clientType) {
887
874
.build (), HttpResponse .BodyHandlers .ofString ());
888
875
String responseBody = response .body ();
889
876
assertThat (responseBody ).isNotBlank ();
877
+ toolsRef .set (toolsUpdate );
890
878
}
891
879
catch (Exception e ) {
892
880
e .printStackTrace ();
893
881
}
894
-
895
- rootsRef .set (toolsUpdate );
896
882
}).build ()) {
897
883
898
884
InitializeResult initResult = mcpClient .initialize ();
899
885
assertThat (initResult ).isNotNull ();
900
886
901
- assertThat (rootsRef .get ()).isNull ();
887
+ assertThat (toolsRef .get ()).isNull ();
902
888
903
889
assertThat (mcpClient .listTools ().tools ()).contains (tool1 .tool ());
904
890
905
891
mcpServer .notifyToolsListChanged ();
906
892
907
893
await ().atMost (Duration .ofSeconds (5 )).untilAsserted (() -> {
908
- assertThat (rootsRef .get ()).containsAll (List .of (tool1 .tool ()));
894
+ assertThat (toolsRef .get ()).containsAll (List .of (tool1 .tool ()));
909
895
});
910
896
911
897
// Remove a tool
912
898
mcpServer .removeTool ("tool1" );
913
899
914
900
await ().atMost (Duration .ofSeconds (5 )).untilAsserted (() -> {
915
- assertThat (rootsRef .get ()).isEmpty ();
901
+ assertThat (toolsRef .get ()).isEmpty ();
916
902
});
917
903
918
904
// Add a new tool
@@ -928,7 +914,7 @@ void testToolListChangeHandlingSuccess(String clientType) {
928
914
mcpServer .addTool (tool2 );
929
915
930
916
await ().atMost (Duration .ofSeconds (5 )).untilAsserted (() -> {
931
- assertThat (rootsRef .get ()).containsAll (List .of (tool2 .tool ()));
917
+ assertThat (toolsRef .get ()).containsAll (List .of (tool2 .tool ()));
932
918
});
933
919
}
934
920
0 commit comments