Skip to content

Commit 24587e3

Browse files
committed
fix: #902 stabilize testCompletionErrorOnMissingContext with client retry logic
1 parent cbb235f commit 24587e3

File tree

1 file changed

+43
-22
lines changed

1 file changed

+43
-22
lines changed

mcp-test/src/test/java/io/modelcontextprotocol/server/McpCompletionTests.java

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import org.apache.catalina.LifecycleException;
1313
import org.apache.catalina.LifecycleState;
1414
import org.apache.catalina.startup.Tomcat;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
1517

1618
import static org.assertj.core.api.Assertions.assertThat;
1719
import org.junit.jupiter.api.AfterEach;
@@ -44,6 +46,8 @@
4446
*/
4547
class McpCompletionTests {
4648

49+
private static final Logger logger = LoggerFactory.getLogger(McpCompletionTests.class);
50+
4751
private HttpServletSseServerTransportProvider mcpServerTransportProvider;
4852

4953
private static final int PORT = TomcatTestUtil.findAvailablePort();
@@ -255,6 +259,10 @@ else if ("products_db".equals(db)) {
255259
mcpServer.close();
256260
}
257261

262+
// Flaky test: Under CI load, the SSE connection may close mid-test (EOF on chunked
263+
// transfer), causing the server to remove the session. Subsequent requests then
264+
// fail with "Session not found". Retrying with a fresh client establishes a new
265+
// SSE connection and session.
258266
@Test
259267
void testCompletionErrorOnMissingContext() {
260268
BiFunction<McpSyncServerExchange, CompleteRequest, CompleteResult> completionHandler = (exchange, request) -> {
@@ -297,28 +305,41 @@ void testCompletionErrorOnMissingContext() {
297305
new ResourceReference(ResourceReference.TYPE, "db://{database}/{table}"), completionHandler))
298306
.build();
299307

300-
try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample" + "client", "0.0.0"))
301-
.build();) {
302-
InitializeResult initResult = mcpClient.initialize();
303-
assertThat(initResult).isNotNull();
304-
305-
// Try to complete table without database context - should raise error
306-
CompleteRequest requestWithoutContext = new CompleteRequest(
307-
new ResourceReference(ResourceReference.TYPE, "db://{database}/{table}"),
308-
new CompleteRequest.CompleteArgument("table", ""));
309-
310-
assertThatExceptionOfType(McpError.class)
311-
.isThrownBy(() -> mcpClient.completeCompletion(requestWithoutContext))
312-
.withMessageContaining("Please select a database first");
313-
314-
// Now complete with proper context - should work normally
315-
CompleteRequest requestWithContext = new CompleteRequest(
316-
new ResourceReference(ResourceReference.TYPE, "db://{database}/{table}"),
317-
new CompleteRequest.CompleteArgument("table", ""),
318-
new CompleteRequest.CompleteContext(Map.of("database", "test_db")));
319-
320-
CompleteResult resultWithContext = mcpClient.completeCompletion(requestWithContext);
321-
assertThat(resultWithContext.completion().values()).containsExactly("users", "orders", "products");
308+
int maxAttempts = 3;
309+
RuntimeException lastError = null;
310+
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
311+
try (var mcpClient = clientBuilder.clientInfo(new McpSchema.Implementation("Sample" + "client", "0.0.0"))
312+
.build()) {
313+
InitializeResult initResult = mcpClient.initialize();
314+
assertThat(initResult).isNotNull();
315+
316+
// Try to complete table without database context - should raise error
317+
CompleteRequest requestWithoutContext = new CompleteRequest(
318+
new ResourceReference(ResourceReference.TYPE, "db://{database}/{table}"),
319+
new CompleteRequest.CompleteArgument("table", ""));
320+
321+
assertThatExceptionOfType(McpError.class)
322+
.isThrownBy(() -> mcpClient.completeCompletion(requestWithoutContext))
323+
.withMessageContaining("Please select a database first");
324+
325+
// Now complete with proper context - should work normally
326+
CompleteRequest requestWithContext = new CompleteRequest(
327+
new ResourceReference(ResourceReference.TYPE, "db://{database}/{table}"),
328+
new CompleteRequest.CompleteArgument("table", ""),
329+
new CompleteRequest.CompleteContext(Map.of("database", "test_db")));
330+
331+
CompleteResult resultWithContext = mcpClient.completeCompletion(requestWithContext);
332+
assertThat(resultWithContext.completion().values()).containsExactly("users", "orders", "products");
333+
lastError = null;
334+
break; // Success
335+
}
336+
catch (RuntimeException e) {
337+
lastError = e;
338+
logger.warn("Attempt {} failed, retrying with fresh client", attempt, e);
339+
}
340+
}
341+
if (lastError != null) {
342+
throw lastError;
322343
}
323344

324345
mcpServer.close();

0 commit comments

Comments
 (0)