Clean up AbstractMcpClientServerIntegrationTests
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
This commit is contained in:
parent
d1ef187c9c
commit
439dc90d25
3 changed files with 142 additions and 300 deletions
|
|
@ -12,7 +12,6 @@ import java.time.Duration;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -52,9 +51,7 @@ import io.modelcontextprotocol.spec.McpSchema.TextContent;
|
|||
import io.modelcontextprotocol.spec.McpSchema.Tool;
|
||||
import io.modelcontextprotocol.util.Utils;
|
||||
import net.javacrumbs.jsonunit.core.Option;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
|
||||
|
|
@ -72,26 +69,20 @@ import static org.mockito.Mockito.mock;
|
|||
|
||||
public abstract class AbstractMcpClientServerIntegrationTests {
|
||||
|
||||
protected ConcurrentHashMap<String, McpClient.SyncSpec> clientBuilders = new ConcurrentHashMap<>();
|
||||
|
||||
abstract protected void prepareClients(int port, String mcpEndpoint);
|
||||
|
||||
abstract protected McpServer.AsyncSpecification<?> prepareAsyncServerBuilder();
|
||||
|
||||
abstract protected McpServer.SyncSpecification<?> prepareSyncServerBuilder();
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void simple(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
abstract protected McpClient.SyncSpec getMcpClientBuilder();
|
||||
|
||||
@Test
|
||||
void simple() {
|
||||
var server = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
|
||||
.requestTimeout(Duration.ofSeconds(1000))
|
||||
.build();
|
||||
try (
|
||||
// Create client without sampling capabilities
|
||||
var client = clientBuilder
|
||||
var client = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample " + "client", "0.0.0").build())
|
||||
.requestTimeout(Duration.ofSeconds(1000))
|
||||
.build()) {
|
||||
|
|
@ -107,12 +98,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Sampling Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateMessageWithoutSamplingCapabilities(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateMessageWithoutSamplingCapabilities() {
|
||||
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
|
||||
.tool(Tool.builder("tool1", EMPTY_JSON_SCHEMA).description("tool1 description").build())
|
||||
.callHandler((exchange, request) -> {
|
||||
|
|
@ -125,7 +112,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
try (
|
||||
// Create client without sampling capabilities
|
||||
var client = clientBuilder
|
||||
var client = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample " + "client", "0.0.0").build())
|
||||
.build()) {
|
||||
|
||||
|
|
@ -144,12 +131,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateMessageSuccess(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateMessageSuccess() {
|
||||
Function<CreateMessageRequest, CreateMessageResult> samplingHandler = request -> {
|
||||
assertThat(request.messages()).hasSize(1);
|
||||
assertThat(request.messages().get(0).content()).isInstanceOf(McpSchema.TextContent.class);
|
||||
|
|
@ -190,7 +173,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.capabilities(ClientCapabilities.builder().sampling().build())
|
||||
.sampling(samplingHandler)
|
||||
|
|
@ -219,14 +202,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws InterruptedException {
|
||||
|
||||
// Client
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateMessageWithRequestTimeoutSuccess() {
|
||||
Function<CreateMessageRequest, CreateMessageResult> samplingHandler = request -> {
|
||||
assertThat(request.messages()).hasSize(1);
|
||||
assertThat(request.messages().get(0).content()).isInstanceOf(McpSchema.TextContent.class);
|
||||
|
|
@ -276,7 +253,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.requestTimeout(Duration.ofSeconds(4))
|
||||
.tools(tool)
|
||||
.build();
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.capabilities(ClientCapabilities.builder().sampling().build())
|
||||
.sampling(samplingHandler)
|
||||
|
|
@ -305,12 +282,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateMessageWithRequestTimeoutFail(String clientType) throws InterruptedException {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateMessageWithRequestTimeoutFail() {
|
||||
Function<CreateMessageRequest, CreateMessageResult> samplingHandler = request -> {
|
||||
assertThat(request.messages()).hasSize(1);
|
||||
assertThat(request.messages().get(0).content()).isInstanceOf(McpSchema.TextContent.class);
|
||||
|
|
@ -355,7 +328,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.capabilities(ClientCapabilities.builder().sampling().build())
|
||||
.sampling(samplingHandler)
|
||||
|
|
@ -376,12 +349,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Elicitation Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationWithoutElicitationCapabilities(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationWithoutElicitationCapabilities() {
|
||||
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
|
||||
.tool(Tool.builder("tool1", EMPTY_JSON_SCHEMA).description("tool1 description").build())
|
||||
.callHandler((exchange, request) -> exchange.createElicitation(mock(McpSchema.ElicitFormRequest.class))
|
||||
|
|
@ -391,7 +360,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
var server = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
// Create client without elicitation capabilities
|
||||
try (var client = clientBuilder.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
try (var client = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.build()) {
|
||||
|
||||
assertThat(client.initialize()).isNotNull();
|
||||
|
|
@ -409,12 +379,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationSuccess(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationSuccess() {
|
||||
Function<McpSchema.ElicitFormRequest, McpSchema.ElicitResult> formElicitationHandler = request -> {
|
||||
assertThat(request.message()).isNotEmpty();
|
||||
assertThat(request.requestedSchema()).isNotNull();
|
||||
|
|
@ -447,7 +413,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.capabilities(ClientCapabilities.builder().elicitation().build())
|
||||
.elicitation(formElicitationHandler)
|
||||
|
|
@ -472,12 +438,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationWithApplyDefaults(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationWithApplyDefaults() {
|
||||
// Client handler returns empty content — SDK should apply defaults
|
||||
Function<McpSchema.ElicitFormRequest, McpSchema.ElicitResult> elicitationHandler = request -> {
|
||||
assertThat(request.message()).isNotEmpty();
|
||||
|
|
@ -511,7 +473,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
try (var mcpClient = getMcpClientBuilder().clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
.capabilities(ClientCapabilities.builder().elicitation(true, false).build())
|
||||
.elicitation(elicitationHandler)
|
||||
.applyElicitationDefaults(true)
|
||||
|
|
@ -537,12 +499,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationWithApplyDefaultsAndUnmodifiableMap(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationWithApplyDefaultsAndUnmodifiableMap() {
|
||||
// Client handler returns an unmodifiable map (Map.of()) — SDK must copy into a
|
||||
// mutable map before applying defaults.
|
||||
Function<McpSchema.ElicitFormRequest, McpSchema.ElicitResult> elicitationHandler = request -> new McpSchema.ElicitResult(
|
||||
|
|
@ -573,7 +531,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
try (var mcpClient = getMcpClientBuilder().clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
.capabilities(ClientCapabilities.builder().elicitation(true, false).build())
|
||||
.elicitation(elicitationHandler)
|
||||
.applyElicitationDefaults(true)
|
||||
|
|
@ -597,12 +555,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationApplyDefaultsDisabledLeavesContentUntouched(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationApplyDefaultsDisabledLeavesContentUntouched() {
|
||||
Function<McpSchema.ElicitFormRequest, McpSchema.ElicitResult> elicitationHandler = request -> new McpSchema.ElicitResult(
|
||||
McpSchema.ElicitResult.Action.ACCEPT, new HashMap<>());
|
||||
|
||||
|
|
@ -629,7 +583,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
// applyElicitationDefaults intentionally NOT called — default false.
|
||||
try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
try (var mcpClient = getMcpClientBuilder().clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
.capabilities(ClientCapabilities.builder().elicitation(true, false).build())
|
||||
.elicitation(elicitationHandler)
|
||||
.build()) {
|
||||
|
|
@ -651,12 +605,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationApplyDefaultsSkippedOnDecline(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationApplyDefaultsSkippedOnDecline() {
|
||||
Function<McpSchema.ElicitFormRequest, McpSchema.ElicitResult> elicitationHandler = request -> new McpSchema.ElicitResult(
|
||||
McpSchema.ElicitResult.Action.DECLINE, new HashMap<>());
|
||||
|
||||
|
|
@ -682,7 +632,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
try (var mcpClient = getMcpClientBuilder().clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
.capabilities(ClientCapabilities.builder().elicitation(true, false).build())
|
||||
.elicitation(elicitationHandler)
|
||||
.applyElicitationDefaults(true)
|
||||
|
|
@ -705,12 +655,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationApplyDefaultsPreservesMeta(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationApplyDefaultsPreservesMeta() {
|
||||
Map<String, Object> meta = Map.of("trace-id", "abc-123");
|
||||
Function<McpSchema.ElicitFormRequest, McpSchema.ElicitResult> elicitationHandler = request -> new McpSchema.ElicitResult(
|
||||
McpSchema.ElicitResult.Action.ACCEPT, new HashMap<>(), meta);
|
||||
|
|
@ -737,7 +683,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
try (var mcpClient = getMcpClientBuilder().clientInfo(new McpSchema.Implementation("Sample client", "0.0.0"))
|
||||
.capabilities(ClientCapabilities.builder().elicitation(true, false).build())
|
||||
.elicitation(elicitationHandler)
|
||||
.applyElicitationDefaults(true)
|
||||
|
|
@ -761,12 +707,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCreateElicitationWithRequestTimeoutSuccess() {
|
||||
Function<ElicitFormRequest, ElicitResult> elicitationHandler = request -> {
|
||||
assertThat(request.message()).isNotEmpty();
|
||||
assertThat(((McpSchema.ElicitFormRequest) request).requestedSchema()).isNotNull();
|
||||
|
|
@ -801,7 +743,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.capabilities(ClientCapabilities.builder().elicitation().build())
|
||||
.elicitation(elicitationHandler)
|
||||
|
|
@ -826,14 +768,10 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateElicitationWithRequestTimeoutFail(String clientType) {
|
||||
|
||||
@Test
|
||||
void testCreateElicitationWithRequestTimeoutFail() {
|
||||
var latch = new CountDownLatch(1);
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
Function<ElicitFormRequest, ElicitResult> elicitationHandler = request -> {
|
||||
assertThat(request.message()).isNotEmpty();
|
||||
assertThat(request.requestedSchema()).isNotNull();
|
||||
|
|
@ -877,7 +815,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.capabilities(ClientCapabilities.builder().elicitation().build())
|
||||
.elicitation(elicitationHandler)
|
||||
|
|
@ -898,15 +836,12 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCreateUrlElicitationSuccess(String clientType) {
|
||||
@Test
|
||||
void testCreateUrlElicitationSuccess() {
|
||||
var elicitationRequest = McpSchema.ElicitUrlRequest
|
||||
.builder("Test message", "https://example.com/auth", "elicitation-123")
|
||||
.build();
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
Function<McpSchema.ElicitUrlRequest, McpSchema.ElicitResult> urlElicitationHandler = request -> {
|
||||
assertThat(request.message()).isEqualTo("Test message");
|
||||
assertThat(request.url()).isEqualTo("https://example.com/auth");
|
||||
|
|
@ -930,7 +865,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.capabilities(ClientCapabilities.builder().elicitation(false, true).build())
|
||||
.urlElicitation(urlElicitationHandler)
|
||||
|
|
@ -950,12 +885,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testElicitationCompleteNotification(String clientType) throws InterruptedException {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testElicitationCompleteNotification() throws InterruptedException {
|
||||
CountDownLatch notificationLatch = new CountDownLatch(1);
|
||||
AtomicReference<McpSchema.ElicitationCompleteNotification> notificationRef = new AtomicReference<>();
|
||||
AtomicReference<String> sessionId = new AtomicReference<>();
|
||||
|
|
@ -980,7 +911,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
var mcpServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").tools(tool).build();
|
||||
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.elicitationCompleteConsumer(elicitationCompleteConsumer)
|
||||
// enable elicitation so that we can register an elicitation complete consumer
|
||||
|
|
@ -1006,12 +937,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testElicitationRequiredError(String clientType) throws InterruptedException {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testElicitationRequiredError() {
|
||||
// Capture the session ID so we can trigger an "elicitation complete" notification
|
||||
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
|
||||
.tool(Tool.builder("tool1", EMPTY_JSON_SCHEMA).description("tool1 description").build())
|
||||
|
|
@ -1027,7 +954,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
Function<McpSchema.ElicitUrlRequest, ElicitResult> elicitationHandler = request -> ElicitResult
|
||||
.builder(ElicitResult.Action.ACCEPT)
|
||||
.build();
|
||||
try (var mcpClient = clientBuilder
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.clientInfo(McpSchema.Implementation.builder("Sample client", "0.0.0").build())
|
||||
.urlElicitation(elicitationHandler)
|
||||
.build()) {
|
||||
|
|
@ -1060,11 +987,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Roots Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testRootsSuccess(String clientType) {
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testRootsSuccess() {
|
||||
List<Root> roots = List.of(Root.builder("uri1://").name("root1").build(),
|
||||
Root.builder("uri2://").name("root2").build());
|
||||
|
||||
|
|
@ -1074,7 +998,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.rootsChangeHandler((exchange, rootsUpdate) -> rootsRef.set(rootsUpdate))
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
try (var mcpClient = getMcpClientBuilder().capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
.roots(roots)
|
||||
.build()) {
|
||||
|
||||
|
|
@ -1109,12 +1033,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testRootsWithoutCapability(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testRootsWithoutCapability() {
|
||||
McpServerFeatures.SyncToolSpecification tool = McpServerFeatures.SyncToolSpecification.builder()
|
||||
.tool(Tool.builder("tool1", EMPTY_JSON_SCHEMA).description("tool1 description").build())
|
||||
.callHandler((exchange, request) -> {
|
||||
|
|
@ -1131,7 +1051,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
try (
|
||||
// Create client without roots capability
|
||||
// No roots capability
|
||||
var mcpClient = clientBuilder.capabilities(ClientCapabilities.builder().build()).build()) {
|
||||
var mcpClient = getMcpClientBuilder().capabilities(ClientCapabilities.builder().build()).build()) {
|
||||
|
||||
assertThat(mcpClient.initialize()).isNotNull();
|
||||
|
||||
|
|
@ -1148,19 +1068,15 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testRootsNotificationWithEmptyRootsList(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testRootsNotificationWithEmptyRootsList() {
|
||||
AtomicReference<List<Root>> rootsRef = new AtomicReference<>();
|
||||
|
||||
var mcpServer = prepareSyncServerBuilder()
|
||||
.rootsChangeHandler((exchange, rootsUpdate) -> rootsRef.set(rootsUpdate))
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
try (var mcpClient = getMcpClientBuilder().capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
.roots(List.of()) // Empty roots list
|
||||
.build()) {
|
||||
|
||||
|
|
@ -1178,12 +1094,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testRootsWithMultipleHandlers(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testRootsWithMultipleHandlers() {
|
||||
List<Root> roots = List.of(Root.builder("uri1://").name("root1").build());
|
||||
|
||||
AtomicReference<List<Root>> rootsRef1 = new AtomicReference<>();
|
||||
|
|
@ -1194,7 +1106,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.rootsChangeHandler((exchange, rootsUpdate) -> rootsRef2.set(rootsUpdate))
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
try (var mcpClient = getMcpClientBuilder().capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
.roots(roots)
|
||||
.build()) {
|
||||
|
||||
|
|
@ -1212,12 +1124,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testRootsServerCloseWithActiveSubscription(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testRootsServerCloseWithActiveSubscription() {
|
||||
List<Root> roots = List.of(Root.builder("uri1://").name("root1").build());
|
||||
|
||||
AtomicReference<List<Root>> rootsRef = new AtomicReference<>();
|
||||
|
|
@ -1226,7 +1134,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.rootsChangeHandler((exchange, rootsUpdate) -> rootsRef.set(rootsUpdate))
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
try (var mcpClient = getMcpClientBuilder().capabilities(ClientCapabilities.builder().roots(true).build())
|
||||
.roots(roots)
|
||||
.build()) {
|
||||
|
||||
|
|
@ -1247,12 +1155,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Tools Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testToolCallSuccess(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testToolCallSuccess() {
|
||||
var responseBodyIsNullOrBlank = new AtomicBoolean(false);
|
||||
var callResponse = McpSchema.CallToolResult.builder()
|
||||
.addContent(McpSchema.TextContent.builder("CALL RESPONSE; ctx=importantValue").build())
|
||||
|
|
@ -1283,7 +1187,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool1)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
|
@ -1301,12 +1205,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testThrowingToolCallIsCaughtBeforeTimeout(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testThrowingToolCallIsCaughtBeforeTimeout() {
|
||||
McpSyncServer mcpServer = prepareSyncServerBuilder()
|
||||
.capabilities(ServerCapabilities.builder().tools(true).build())
|
||||
.tools(McpServerFeatures.SyncToolSpecification.builder()
|
||||
|
|
@ -1319,7 +1219,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.build())
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.requestTimeout(Duration.ofMillis(6666)).build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().requestTimeout(Duration.ofMillis(6666)).build()) {
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
||||
|
|
@ -1334,12 +1234,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testToolCallSuccessWithTranportContextExtraction(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testToolCallSuccessWithTranportContextExtraction() {
|
||||
var transportContextIsNull = new AtomicBoolean(false);
|
||||
var transportContextIsEmpty = new AtomicBoolean(false);
|
||||
var responseBodyIsNullOrBlank = new AtomicBoolean(false);
|
||||
|
|
@ -1374,7 +1270,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool1)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
|
@ -1394,11 +1290,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testToolWithNonAsciiCharacters(String clientType) {
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testToolWithNonAsciiCharacters() {
|
||||
String inputSchema = """
|
||||
{
|
||||
"type": "object",
|
||||
|
|
@ -1423,7 +1316,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(nonAsciiTool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
|
@ -1446,12 +1339,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testToolListChangeHandlingSuccess(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testToolListChangeHandlingSuccess() {
|
||||
var callResponse = McpSchema.CallToolResult.builder()
|
||||
.addContent(McpSchema.TextContent.builder("CALL RESPONSE").build())
|
||||
.build();
|
||||
|
|
@ -1483,7 +1372,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool1)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.toolsChangeConsumer(toolsUpdate -> {
|
||||
try (var mcpClient = getMcpClientBuilder().toolsChangeConsumer(toolsUpdate -> {
|
||||
// perform a blocking call to a remote service
|
||||
try {
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
|
|
@ -1538,15 +1427,11 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testInitialize(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testInitialize() {
|
||||
var mcpServer = prepareSyncServerBuilder().build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
|
@ -1559,16 +1444,13 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Logging Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testLoggingNotification(String clientType) throws InterruptedException {
|
||||
@Test
|
||||
void testLoggingNotification() throws InterruptedException {
|
||||
int expectedNotificationsCount = 3;
|
||||
CountDownLatch latch = new CountDownLatch(expectedNotificationsCount);
|
||||
// Create a list to store received logging notifications
|
||||
List<McpSchema.LoggingMessageNotification> receivedNotifications = new CopyOnWriteArrayList<>();
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
// Create server with a tool that sends logging notifications
|
||||
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
|
||||
.tool(Tool.builder("logging-test", EMPTY_JSON_SCHEMA).description("Test logging notifications").build())
|
||||
|
|
@ -1617,7 +1499,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
try (
|
||||
// Create client with logging notification handler
|
||||
var mcpClient = clientBuilder.loggingConsumer(notification -> {
|
||||
var mcpClient = getMcpClientBuilder().loggingConsumer(notification -> {
|
||||
receivedNotifications.add(notification);
|
||||
latch.countDown();
|
||||
}).build()) {
|
||||
|
|
@ -1667,17 +1549,14 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Progress Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testProgressNotification(String clientType) throws InterruptedException {
|
||||
@Test
|
||||
void testProgressNotification() throws InterruptedException {
|
||||
int expectedNotificationsCount = 4; // 3 notifications + 1 for another progress
|
||||
// token
|
||||
CountDownLatch latch = new CountDownLatch(expectedNotificationsCount);
|
||||
// Create a list to store received logging notifications
|
||||
List<McpSchema.ProgressNotification> receivedNotifications = new CopyOnWriteArrayList<>();
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
// Create server with a tool that sends logging notifications
|
||||
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
|
||||
.tool(McpSchema.Tool.builder("progress-test", EMPTY_JSON_SCHEMA)
|
||||
|
|
@ -1720,7 +1599,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
|
||||
try (
|
||||
// Create client with progress notification handler
|
||||
var mcpClient = clientBuilder.progressConsumer(notification -> {
|
||||
var mcpClient = getMcpClientBuilder().progressConsumer(notification -> {
|
||||
receivedNotifications.add(notification);
|
||||
latch.countDown();
|
||||
}).build()) {
|
||||
|
|
@ -1781,11 +1660,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Completion Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : Completion call")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testCompletionShouldReturnExpectedSuggestions(String clientType) {
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testCompletionShouldReturnExpectedSuggestions() {
|
||||
var expectedValues = List.of("python", "pytorch", "pyside");
|
||||
var completionResponse = new McpSchema.CompleteResult(
|
||||
new CompleteResult.CompleteCompletion(expectedValues, 10, true));
|
||||
|
|
@ -1811,7 +1687,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
McpSchema.PromptReference.builder("code_review").title("Code review").build(), completionHandler))
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
|
@ -1837,12 +1713,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Ping Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testPingSuccess(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testPingSuccess() {
|
||||
// Create server with a tool that uses ping functionality
|
||||
AtomicReference<String> executionOrder = new AtomicReference<>("");
|
||||
|
||||
|
|
@ -1876,7 +1748,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
|
||||
// Initialize client
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
|
|
@ -1900,11 +1772,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// ---------------------------------------
|
||||
// Tool Structured Output Schema Tests
|
||||
// ---------------------------------------
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testStructuredOutputValidationSuccess(String clientType) {
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testStructuredOutputValidationSuccess() {
|
||||
// Create a tool with output schema
|
||||
Map<String, Object> outputSchema = Map.of(
|
||||
"type", "object", "properties", Map.of("result", Map.of("type", "number"), "operation",
|
||||
|
|
@ -1933,7 +1802,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
||||
|
|
@ -1973,11 +1842,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@ValueSource(strings = { "httpclient" })
|
||||
void testStructuredOutputOfObjectArrayValidationSuccess(String clientType) {
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testStructuredOutputOfObjectArrayValidationSuccess() {
|
||||
// Create a tool with output schema that returns an array of objects
|
||||
Map<String, Object> outputSchema = Map
|
||||
.of( // @formatter:off
|
||||
|
|
@ -2008,7 +1874,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
assertThat(mcpClient.initialize()).isNotNull();
|
||||
|
||||
// Call tool with valid structured output of type array
|
||||
|
|
@ -2032,11 +1898,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@ValueSource(strings = { "httpclient" })
|
||||
void testStructuredOutputWithInHandlerError(String clientType) {
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testStructuredOutputWithInHandlerError() {
|
||||
// Create a tool with output schema
|
||||
Map<String, Object> outputSchema = Map.of(
|
||||
"type", "object", "properties", Map.of("result", Map.of("type", "number"), "operation",
|
||||
|
|
@ -2062,7 +1925,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
||||
|
|
@ -2088,12 +1951,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@ValueSource(strings = { "httpclient" })
|
||||
void testStructuredOutputValidationFailure(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testStructuredOutputValidationFailure() {
|
||||
// Create a tool with output schema
|
||||
Map<String, Object> outputSchema = Map.of("type", "object", "properties",
|
||||
Map.of("result", Map.of("type", "number"), "operation", Map.of("type", "string")), "required",
|
||||
|
|
@ -2121,7 +1980,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
||||
|
|
@ -2142,12 +2001,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testStructuredOutputMissingStructuredContent(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testStructuredOutputMissingStructuredContent() {
|
||||
// Create a tool with output schema
|
||||
Map<String, Object> outputSchema = Map.of("type", "object", "properties",
|
||||
Map.of("result", Map.of("type", "number")), "required", List.of("result"));
|
||||
|
|
@ -2170,7 +2025,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.tools(tool)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
||||
|
|
@ -2192,18 +2047,14 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testStructuredOutputRuntimeToolAddition(String clientType) {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testStructuredOutputRuntimeToolAddition() {
|
||||
// Start server without tools
|
||||
var mcpServer = prepareSyncServerBuilder().serverInfo("test-server", "1.0.0")
|
||||
.capabilities(ServerCapabilities.builder().tools(true).build())
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.build()) {
|
||||
try (var mcpClient = getMcpClientBuilder().build()) {
|
||||
InitializeResult initResult = mcpClient.initialize();
|
||||
assertThat(initResult).isNotNull();
|
||||
|
||||
|
|
@ -2273,12 +2124,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
// Resource Subscription Tests
|
||||
// ---------------------------------------
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testResourceSubscription(String clientType) throws InterruptedException {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testResourceSubscription() throws InterruptedException {
|
||||
String resourceUri = "test://subscribable-resource";
|
||||
var receivedContents = new AtomicReference<List<McpSchema.ResourceContents>>();
|
||||
var latch = new CountDownLatch(1);
|
||||
|
|
@ -2296,7 +2143,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.resources(resourceSpec)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.resourcesUpdateConsumer(contents -> {
|
||||
try (var mcpClient = getMcpClientBuilder().resourcesUpdateConsumer(contents -> {
|
||||
receivedContents.set(contents);
|
||||
latch.countDown();
|
||||
}).build()) {
|
||||
|
|
@ -2317,12 +2164,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@MethodSource("clientsForTesting")
|
||||
void testResourceSubscription_afterUnsubscribe_noNotification(String clientType) throws InterruptedException {
|
||||
|
||||
var clientBuilder = clientBuilders.get(clientType);
|
||||
|
||||
@Test
|
||||
void testResourceSubscription_afterUnsubscribe_noNotification() {
|
||||
String resourceUri = "test://subscribable-resource-unsub";
|
||||
var notificationCount = new java.util.concurrent.atomic.AtomicInteger(0);
|
||||
|
||||
|
|
@ -2337,7 +2180,8 @@ public abstract class AbstractMcpClientServerIntegrationTests {
|
|||
.resources(resourceSpec)
|
||||
.build();
|
||||
|
||||
try (var mcpClient = clientBuilder.resourcesUpdateConsumer(contents -> notificationCount.incrementAndGet())
|
||||
try (var mcpClient = getMcpClientBuilder()
|
||||
.resourcesUpdateConsumer(contents -> notificationCount.incrementAndGet())
|
||||
.build()) {
|
||||
|
||||
mcpClient.initialize();
|
||||
|
|
|
|||
|
|
@ -61,12 +61,6 @@ class HttpServletSseIntegrationTests extends AbstractMcpClientServerIntegrationT
|
|||
catch (Exception e) {
|
||||
throw new RuntimeException("Failed to start Tomcat", e);
|
||||
}
|
||||
|
||||
clientBuilders
|
||||
.put("httpclient",
|
||||
McpClient.sync(HttpClientSseClientTransport.builder("http://localhost:" + PORT)
|
||||
.sseEndpoint(CUSTOM_SSE_ENDPOINT)
|
||||
.build()).requestTimeout(Duration.ofHours(10)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -79,6 +73,15 @@ class HttpServletSseIntegrationTests extends AbstractMcpClientServerIntegrationT
|
|||
return McpServer.sync(this.mcpServerTransportProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected McpClient.SyncSpec getMcpClientBuilder() {
|
||||
return McpClient
|
||||
.sync(HttpClientSseClientTransport.builder("http://localhost:" + PORT)
|
||||
.sseEndpoint(CUSTOM_SSE_ENDPOINT)
|
||||
.build())
|
||||
.requestTimeout(Duration.ofHours(10));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() {
|
||||
if (mcpServerTransportProvider != null) {
|
||||
|
|
@ -95,10 +98,6 @@ class HttpServletSseIntegrationTests extends AbstractMcpClientServerIntegrationT
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareClients(int port, String mcpEndpoint) {
|
||||
}
|
||||
|
||||
static McpTransportContextExtractor<HttpServletRequest> TEST_CONTEXT_EXTRACTOR = (r) -> McpTransportContext
|
||||
.create(Map.of("important", "value"));
|
||||
|
||||
|
|
|
|||
|
|
@ -59,12 +59,6 @@ class HttpServletStreamableIntegrationTests extends AbstractMcpClientServerInteg
|
|||
catch (Exception e) {
|
||||
throw new RuntimeException("Failed to start Tomcat", e);
|
||||
}
|
||||
|
||||
clientBuilders
|
||||
.put("httpclient",
|
||||
McpClient.sync(HttpClientStreamableHttpTransport.builder("http://localhost:" + PORT)
|
||||
.endpoint(MESSAGE_ENDPOINT)
|
||||
.build()).requestTimeout(Duration.ofHours(10)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -77,6 +71,15 @@ class HttpServletStreamableIntegrationTests extends AbstractMcpClientServerInteg
|
|||
return McpServer.sync(this.mcpServerTransportProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected McpClient.SyncSpec getMcpClientBuilder() {
|
||||
return McpClient
|
||||
.sync(HttpClientStreamableHttpTransport.builder("http://localhost:" + PORT)
|
||||
.endpoint(MESSAGE_ENDPOINT)
|
||||
.build())
|
||||
.requestTimeout(Duration.ofHours(10));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() {
|
||||
if (mcpServerTransportProvider != null) {
|
||||
|
|
@ -93,10 +96,6 @@ class HttpServletStreamableIntegrationTests extends AbstractMcpClientServerInteg
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareClients(int port, String mcpEndpoint) {
|
||||
}
|
||||
|
||||
static McpTransportContextExtractor<HttpServletRequest> TEST_CONTEXT_EXTRACTOR = (r) -> McpTransportContext
|
||||
.create(Map.of("important", "value"));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue