Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.startup.Tomcat;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
Expand All @@ -62,42 +60,17 @@ class HttpServletSseIntegrationTests extends AbstractMcpClientServerIntegrationT

protected static final int MAX_REQUEST_SIZE = 2048;

// Tomcat is started once for the whole class; each test swaps in its own transport
private static final TomcatTestUtil.DelegatingServlet MCP_SERVLET = new TomcatTestUtil.DelegatingServlet();

private static Tomcat tomcat;

private HttpServletSseServerTransportProvider mcpServerTransportProvider;

// One Tomcat per test, unlike other Servlet tests: the SSE transport may keep writing
// to a stream after its client has disconnected, and with a shared Tomcat these
// writes can land in a connection used by a later test.
private Tomcat tomcat;

static Stream<Arguments> clientsForTesting() {
return Stream.of(Arguments.of("httpclient"));
}

@BeforeAll
public static void beforeAll() {
tomcat = TomcatTestUtil.createTomcatServer("", PORT, MCP_SERVLET);
try {
tomcat.start();
assertThat(tomcat.getServer().getState()).isEqualTo(LifecycleState.STARTED);
}
catch (Exception e) {
throw new RuntimeException("Failed to start Tomcat", e);
}
}

@AfterAll
public static void afterAll() {
if (tomcat != null) {
try {
tomcat.stop();
tomcat.destroy();
}
catch (LifecycleException e) {
throw new RuntimeException("Failed to stop Tomcat", e);
}
}
}

@BeforeEach
public void before() {
// Create and configure the transport provider
Expand All @@ -107,7 +80,15 @@ public void before() {
.sseEndpoint(CUSTOM_SSE_ENDPOINT)
.maxRequestSize(MAX_REQUEST_SIZE)
.build();
MCP_SERVLET.setDelegate(mcpServerTransportProvider);

tomcat = TomcatTestUtil.createTomcatServer("", PORT, mcpServerTransportProvider);
try {
tomcat.start();
assertThat(tomcat.getServer().getState()).isEqualTo(LifecycleState.STARTED);
}
catch (Exception e) {
throw new RuntimeException("Failed to start Tomcat", e);
}

clientBuilders
.put("httpclient",
Expand All @@ -131,6 +112,15 @@ public void after() {
if (mcpServerTransportProvider != null) {
mcpServerTransportProvider.closeGracefully().block();
}
if (tomcat != null) {
try {
tomcat.stop();
tomcat.destroy();
}
catch (LifecycleException e) {
throw new RuntimeException("Failed to stop Tomcat", e);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.startup.Tomcat;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -80,9 +80,9 @@ class HttpServletStatelessIntegrationTests {

private static final int MAX_REQUEST_SIZE = 2048;

private static Tomcat tomcat;
private Tomcat tomcat;

private static HttpServletStatelessServerTransport mcpStatelessServerTransport;
private HttpServletStatelessServerTransport mcpStatelessServerTransport;

private final McpClient.SyncSpec clientBuilder = McpClient
.sync(HttpClientStreamableHttpTransport.builder("http://localhost:" + PORT)
Expand All @@ -91,8 +91,8 @@ class HttpServletStatelessIntegrationTests {
.initializationTimeout(Duration.ofHours(10))
.requestTimeout(Duration.ofHours(10));

@BeforeAll
public static void beforeAll() {
@BeforeEach
public void before() {
mcpStatelessServerTransport = HttpServletStatelessServerTransport.builder()
.messageEndpoint(CUSTOM_MESSAGE_ENDPOINT)
.maxRequestSize(MAX_REQUEST_SIZE)
Expand All @@ -108,8 +108,8 @@ public static void beforeAll() {
}
}

@AfterAll
public static void afterAll() {
@AfterEach
public void after() {
if (mcpStatelessServerTransport != null) {
mcpStatelessServerTransport.closeGracefully().block();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.startup.Tomcat;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.params.provider.Arguments;
Expand All @@ -42,49 +40,29 @@ class HttpServletStatelessSharedIntegrationTests extends AbstractStatelessIntegr
static McpTransportContextExtractor<HttpServletRequest> TEST_CONTEXT_EXTRACTOR = (request) -> McpTransportContext
.create(Map.of("important", "value"));

// Tomcat is started once for the whole class; each test swaps in its own transport
private static final TomcatTestUtil.DelegatingServlet MCP_SERVLET = new TomcatTestUtil.DelegatingServlet();

private static Tomcat tomcat;
private Tomcat tomcat;

private HttpServletStatelessServerTransport mcpServerTransport;

static Stream<Arguments> clientsForTesting() {
return Stream.of(Arguments.of("httpclient"));
}

@BeforeAll
public static void beforeAll() {
tomcat = TomcatTestUtil.createTomcatServer("", PORT, MCP_SERVLET);
try {
tomcat.start();
assertThat(tomcat.getServer().getState()).isEqualTo(LifecycleState.STARTED);
}
catch (Exception e) {
throw new RuntimeException("Failed to start Tomcat", e);
}
}

@AfterAll
public static void afterAll() {
if (tomcat != null) {
try {
tomcat.stop();
tomcat.destroy();
}
catch (LifecycleException e) {
throw new RuntimeException("Failed to stop Tomcat", e);
}
}
}

@BeforeEach
public void before() {
this.mcpServerTransport = HttpServletStatelessServerTransport.builder()
.contextExtractor(TEST_CONTEXT_EXTRACTOR)
.messageEndpoint(MESSAGE_ENDPOINT)
.build();
MCP_SERVLET.setDelegate(this.mcpServerTransport);

this.tomcat = TomcatTestUtil.createTomcatServer("", PORT, this.mcpServerTransport);
try {
this.tomcat.start();
assertThat(this.tomcat.getServer().getState()).isEqualTo(LifecycleState.STARTED);
}
catch (Exception e) {
throw new RuntimeException("Failed to start Tomcat", e);
}

prepareClients(PORT, MESSAGE_ENDPOINT);
}
Expand Down Expand Up @@ -112,6 +90,15 @@ public void after() {
if (this.mcpServerTransport != null) {
this.mcpServerTransport.closeGracefully().block();
}
if (this.tomcat != null) {
try {
this.tomcat.stop();
this.tomcat.destroy();
}
catch (LifecycleException e) {
throw new RuntimeException("Failed to stop Tomcat", e);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.startup.Tomcat;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
Expand Down Expand Up @@ -79,10 +77,10 @@ class HttpServletStreamableIntegrationTests extends AbstractMcpClientServerInteg

private static final String MESSAGE_ENDPOINT = "/mcp/message";

// Tomcat is started once for the whole class; each test swaps in its own transport
private static final TomcatTestUtil.DelegatingServlet MCP_SERVLET = new TomcatTestUtil.DelegatingServlet();
// Some tests swap in another transport, and the servlet tracks the SSE stream
private final TomcatTestUtil.DelegatingServlet mcpServlet = new TomcatTestUtil.DelegatingServlet();

private static Tomcat tomcat;
private Tomcat tomcat;

private HttpServletStreamableServerTransportProvider mcpServerTransportProvider;

Expand All @@ -102,7 +100,7 @@ class HttpServletStreamableIntegrationTests extends AbstractMcpClientServerInteg
protected void awaitClientStreamEstablished() {
var timeout = Duration.ofSeconds(5);
await().atMost(timeout).untilAsserted(() -> {
assertThat(MCP_SERVLET.isStreamEstablished())
assertThat(mcpServlet.isStreamEstablished())
.withFailMessage("[Failed to observe MCP Client connection within %s]", timeout)
.isTrue();
});
Expand All @@ -112,31 +110,6 @@ static Stream<Arguments> clientsForTesting() {
return Stream.of(Arguments.of("httpclient"));
}

@BeforeAll
public static void beforeAll() {
tomcat = TomcatTestUtil.createTomcatServer("", PORT, MCP_SERVLET);
try {
tomcat.start();
assertThat(tomcat.getServer().getState()).isEqualTo(LifecycleState.STARTED);
}
catch (Exception e) {
throw new RuntimeException("Failed to start Tomcat", e);
}
}

@AfterAll
public static void afterAll() {
if (tomcat != null) {
try {
tomcat.stop();
tomcat.destroy();
}
catch (LifecycleException e) {
throw new RuntimeException("Failed to stop Tomcat", e);
}
}
}

@BeforeEach
public void before() {
// Create and configure the transport provider
Expand All @@ -147,7 +120,16 @@ public void before() {
.maxRequestSize(MAX_REQUEST_SIZE)
.sessionSweepInterval(SESSION_SWEEP_INTERVAL)
.build();
MCP_SERVLET.setDelegate(mcpServerTransportProvider);
mcpServlet.setDelegate(mcpServerTransportProvider);

tomcat = TomcatTestUtil.createTomcatServer("", PORT, mcpServlet);
try {
tomcat.start();
assertThat(tomcat.getServer().getState()).isEqualTo(LifecycleState.STARTED);
}
catch (Exception e) {
throw new RuntimeException("Failed to start Tomcat", e);
}

clientBuilders
.put("httpclient",
Expand All @@ -171,6 +153,15 @@ public void after() {
if (mcpServerTransportProvider != null) {
mcpServerTransportProvider.closeGracefully().block();
}
if (tomcat != null) {
try {
tomcat.stop();
tomcat.destroy();
}
catch (LifecycleException e) {
throw new RuntimeException("Failed to stop Tomcat", e);
}
}
}

@Test
Expand Down Expand Up @@ -813,7 +804,7 @@ private void withTransportProvider(Duration keepAliveInterval, Duration sessionS
// no sweeping: the session must survive every keep-alive round
.sessionSweepInterval(sessionSweepInterval)
.build();
MCP_SERVLET.setDelegate(mcpServerTransportProvider);
mcpServlet.setDelegate(mcpServerTransportProvider);
prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0").build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import org.apache.catalina.LifecycleState;
import org.apache.catalina.startup.Tomcat;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.modelcontextprotocol.client.McpClient;
Expand Down Expand Up @@ -52,15 +52,15 @@ class McpCompletionTests {

private static final String CUSTOM_MESSAGE_ENDPOINT = "/otherPath/mcp/message";

private static HttpServletSseServerTransportProvider mcpServerTransportProvider;
private HttpServletSseServerTransportProvider mcpServerTransportProvider;

private static Tomcat tomcat;
private Tomcat tomcat;

final McpClient.SyncSpec clientBuilder = McpClient
.sync(HttpClientSseClientTransport.builder("http://localhost:" + PORT).build());

@BeforeAll
public static void beforeAll() {
@BeforeEach
public void before() {
// Create and configure the transport provider
mcpServerTransportProvider = HttpServletSseServerTransportProvider.builder()
.messageEndpoint(CUSTOM_MESSAGE_ENDPOINT)
Expand All @@ -76,8 +76,8 @@ public static void beforeAll() {
}
}

@AfterAll
public static void afterAll() {
@AfterEach
public void after() {
if (mcpServerTransportProvider != null) {
mcpServerTransportProvider.closeGracefully().block();
}
Expand Down
Loading
Loading