diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServerExchange.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServerExchange.java index e27d6128f..3c09b98f3 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServerExchange.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServerExchange.java @@ -225,6 +225,13 @@ public Mono listRoots() { * @return A Mono that emits the list of roots result containing */ public Mono listRoots(String cursor) { + if (this.clientCapabilities == null) { + return Mono + .error(new IllegalStateException("Client must be initialized. Call the initialize method first!")); + } + if (this.clientCapabilities.roots() == null) { + return Mono.error(new IllegalStateException("Roots not supported")); + } return this.session.sendRequest(McpSchema.METHOD_ROOTS_LIST, new McpSchema.PaginatedRequest(cursor), LIST_ROOTS_RESULT_TYPE_REF); } diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/server/McpAsyncServerExchangeTests.java b/mcp-core/src/test/java/io/modelcontextprotocol/server/McpAsyncServerExchangeTests.java index f4f76b159..52126db4e 100644 --- a/mcp-core/src/test/java/io/modelcontextprotocol/server/McpAsyncServerExchangeTests.java +++ b/mcp-core/src/test/java/io/modelcontextprotocol/server/McpAsyncServerExchangeTests.java @@ -59,6 +59,34 @@ void setUp() { McpTransportContext.EMPTY); } + @Test + void testListRootsWithNullCapabilities() { + McpAsyncServerExchange exchangeWithNullCapabilities = new McpAsyncServerExchange("testSessionId", mockSession, + null, clientInfo, McpTransportContext.EMPTY); + + StepVerifier.create(exchangeWithNullCapabilities.listRoots()).verifyErrorSatisfies(error -> { + assertThat(error).isInstanceOf(IllegalStateException.class) + .hasMessage("Client must be initialized. Call the initialize method first!"); + }); + + verify(mockSession, never()).sendRequest(eq(McpSchema.METHOD_ROOTS_LIST), any(McpSchema.PaginatedRequest.class), + any(TypeRef.class)); + } + + @Test + void testListRootsWithoutRootsCapability() { + McpSchema.ClientCapabilities capabilitiesWithoutRoots = McpSchema.ClientCapabilities.builder().build(); + McpAsyncServerExchange exchangeWithoutRoots = new McpAsyncServerExchange("testSessionId", mockSession, + capabilitiesWithoutRoots, clientInfo, McpTransportContext.EMPTY); + + StepVerifier.create(exchangeWithoutRoots.listRoots("someCursor")).verifyErrorSatisfies(error -> { + assertThat(error).isInstanceOf(IllegalStateException.class).hasMessage("Roots not supported"); + }); + + verify(mockSession, never()).sendRequest(eq(McpSchema.METHOD_ROOTS_LIST), any(McpSchema.PaginatedRequest.class), + any(TypeRef.class)); + } + @Test void testListRootsWithSinglePage() {