diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxSseIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxSseIT.java
index f0b68bf4e65..e331e54740f 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxSseIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxSseIT.java
@@ -16,8 +16,11 @@
package org.springframework.ai.mcp;
+import java.net.HttpURLConnection;
+import java.net.URL;
import java.time.Duration;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import io.modelcontextprotocol.AbstractMcpClientServerIntegrationTests;
@@ -28,11 +31,13 @@
import io.modelcontextprotocol.server.McpServer.AsyncSpecification;
import io.modelcontextprotocol.server.McpServer.SingleSessionSyncSpecification;
import io.modelcontextprotocol.server.McpTransportContextExtractor;
+import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.params.provider.Arguments;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import reactor.netty.DisposableServer;
import reactor.netty.http.server.HttpServer;
@@ -44,10 +49,11 @@
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
-@Disabled("Flaky test - needs investigation")
@Timeout(45)
class WebFluxSseIT extends AbstractMcpClientServerIntegrationTests {
+ private static final Logger log = LoggerFactory.getLogger(WebFluxSseIT.class);
+
private static final String CUSTOM_SSE_ENDPOINT = "/somePath/sse";
private static final String CUSTOM_MESSAGE_ENDPOINT = "/otherPath/mcp/message";
@@ -102,9 +108,35 @@ public void before() {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(this.mcpServerTransportProvider.getRouterFunction());
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
-
- prepareClients(this.httpServer.port(), null);
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
+
+ int port = this.httpServer.port();
+ log.info("Reactor Netty server bound to host='{}' port={}", this.httpServer.host(), port);
+
+ String probeUrl = "http://127.0.0.1:" + port + CUSTOM_SSE_ENDPOINT;
+ Awaitility.await()
+ .alias("MCP server reachable at " + probeUrl)
+ .atMost(10, TimeUnit.SECONDS)
+ .pollInterval(200, TimeUnit.MILLISECONDS)
+ .untilAsserted(() -> {
+ HttpURLConnection conn = (HttpURLConnection) new URL(probeUrl).openConnection();
+ conn.setConnectTimeout(1000);
+ conn.setReadTimeout(1000);
+ conn.setRequestMethod("GET");
+ try {
+ int status = conn.getResponseCode();
+ log.info("Sanity probe {} -> HTTP {}", probeUrl, status);
+ // SSE endpoint returns 200 (it streams); message endpoint returns 4xx
+ // for a bare GET. Either way, any HTTP response means the server is
+ // up.
+ org.assertj.core.api.Assertions.assertThat(status).isGreaterThan(0);
+ }
+ finally {
+ conn.disconnect();
+ }
+ });
+
+ prepareClients(port, null);
}
@AfterEach
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStatelessIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStatelessIT.java
index ebc54ad5916..b162ee0a329 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStatelessIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStatelessIT.java
@@ -86,7 +86,7 @@ public void before() {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(this.mcpStreamableServerTransport.getRouterFunction());
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
prepareClients(this.httpServer.port(), null);
}
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableHttpVersionNegotiationIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableHttpVersionNegotiationIT.java
index 79dd3395e47..57ef4cda0ee 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableHttpVersionNegotiationIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableHttpVersionNegotiationIT.java
@@ -32,7 +32,6 @@
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import reactor.netty.DisposableServer;
import reactor.netty.http.server.HttpServer;
@@ -50,7 +49,6 @@
import static org.assertj.core.api.Assertions.assertThat;
-@Disabled("Flaky in CI, needs investigation")
class WebFluxStreamableHttpVersionNegotiationIT {
private DisposableServer httpServer;
@@ -90,7 +88,7 @@ void setUp() {
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
this.port = this.httpServer.port();
}
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableIT.java
index d1e05fac4ff..41f524bd4f4 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/WebFluxStreamableIT.java
@@ -97,7 +97,7 @@ public void before() {
HttpHandler httpHandler = RouterFunctions
.toHttpHandler(this.mcpStreamableServerTransportProvider.getRouterFunction());
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
prepareClients(this.httpServer.port(), null);
}
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/AsyncServerMcpTransportContextIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/AsyncServerMcpTransportContextIT.java
index 4f609a454e9..52287bd10e9 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/AsyncServerMcpTransportContextIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/AsyncServerMcpTransportContextIT.java
@@ -259,7 +259,7 @@ private void startHttpServer(RouterFunction> routerFunction) {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(routerFunction);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
int port = this.httpServer.port();
this.asyncStreamableClient = McpClient
.async(WebClientStreamableHttpTransport
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/SyncServerMcpTransportContextIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/SyncServerMcpTransportContextIT.java
index 8708cb24f20..5958f8b6513 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/SyncServerMcpTransportContextIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/common/SyncServerMcpTransportContextIT.java
@@ -245,7 +245,7 @@ private void startHttpServer(RouterFunction> routerFunction) {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(routerFunction);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
int port = this.httpServer.port();
this.streamableClient = McpClient.sync(WebClientStreamableHttpTransport.builder(WebClient.builder()
.baseUrl("http://127.0.0.1:" + port)
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/security/WebFluxServerTransportSecurityIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/security/WebFluxServerTransportSecurityIT.java
index f8f986549dd..a96d69b0b56 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/security/WebFluxServerTransportSecurityIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/security/WebFluxServerTransportSecurityIT.java
@@ -167,7 +167,7 @@ void messageHostNotAllowed() {
private static void startServer(RouterFunction> routerFunction) {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(routerFunction);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
baseUrl = "http://localhost:" + httpServer.port();
}
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpAsyncServerIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpAsyncServerIT.java
index 3fdc74cfdf5..2ae484a80a1 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpAsyncServerIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpAsyncServerIT.java
@@ -46,7 +46,7 @@ private McpServerTransportProvider createMcpTransportProvider() {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(transportProvider.getRouterFunction());
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
return transportProvider;
}
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpSyncServerIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpSyncServerIT.java
index a6387083700..1e038db212e 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpSyncServerIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxSseMcpSyncServerIT.java
@@ -57,7 +57,7 @@ private McpServerTransportProvider createMcpTransportProvider() {
protected void onStart() {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(this.transportProvider.getRouterFunction());
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
}
@Override
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpAsyncServerIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpAsyncServerIT.java
index 5dae985f68d..b833dc167c0 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpAsyncServerIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpAsyncServerIT.java
@@ -49,7 +49,7 @@ private McpStreamableServerTransportProvider createMcpTransportProvider() {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(transportProvider.getRouterFunction());
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
return transportProvider;
}
diff --git a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpSyncServerIT.java b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpSyncServerIT.java
index ad51f8830c2..38cf503e11d 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpSyncServerIT.java
+++ b/mcp/transport/mcp-spring-webflux/src/test/java/org/springframework/ai/mcp/server/webflux/transport/WebFluxStreamableMcpSyncServerIT.java
@@ -49,7 +49,7 @@ private McpStreamableServerTransportProvider createMcpTransportProvider() {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(transportProvider.getRouterFunction());
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
- this.httpServer = HttpServer.create().port(0).handle(adapter).bindNow();
+ this.httpServer = HttpServer.create().port(0).host("0.0.0.0").handle(adapter).bindNow();
return transportProvider;
}
diff --git a/mcp/transport/mcp-spring-webflux/src/test/resources/logback.xml b/mcp/transport/mcp-spring-webflux/src/test/resources/logback.xml
index abc831d13bd..ed6f505f12b 100644
--- a/mcp/transport/mcp-spring-webflux/src/test/resources/logback.xml
+++ b/mcp/transport/mcp-spring-webflux/src/test/resources/logback.xml
@@ -8,15 +8,8 @@
-
-
-
-
-
-
-
-
-
+
+