Fix: McpAsyncClient#listTools prevent infinite recursion (#631)

* Fix: prevent infinite recursion in listTools() when nextCursor is empty string

Signed-off-by: lance <leehaut@gmail.com>
This commit is contained in:
lance 2025-10-30 18:59:34 +08:00 • committed by GitHub
commit e91fe7fbc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -402,6 +402,7 @@ public class McpAsyncClient {
// --------------------------
// Initialization
// --------------------------
/**
* The initialization phase should be the first interaction between client and server.
* The client will ensure it happens in case it has not been explicitly called and in
@ -448,6 +449,7 @@ public class McpAsyncClient {
// --------------------------
// Roots
// --------------------------
/**
* Adds a new root to the client's root list.
* @param root The root to add.
@ -625,13 +627,13 @@ public class McpAsyncClient {
* @return A Mono that emits the list of all tools result
*/
public Mono<McpSchema.ListToolsResult> listTools() {
return this.listTools(McpSchema.FIRST_PAGE)
.expand(result -> (result.nextCursor() != null) ? this.listTools(result.nextCursor()) : Mono.empty())
.reduce(new McpSchema.ListToolsResult(new ArrayList<>(), null), (allToolsResult, result) -> {
allToolsResult.tools().addAll(result.tools());
return allToolsResult;
})
.map(result -> new McpSchema.ListToolsResult(Collections.unmodifiableList(result.tools()), null));
return this.listTools(McpSchema.FIRST_PAGE).expand(result -> {
String next = result.nextCursor();
return (next != null && !next.isEmpty()) ? this.listTools(next) : Mono.empty();
}).reduce(new McpSchema.ListToolsResult(new ArrayList<>(), null), (allToolsResult, result) -> {
allToolsResult.tools().addAll(result.tools());
return allToolsResult;
}).map(result -> new McpSchema.ListToolsResult(Collections.unmodifiableList(result.tools()), null));
}
/**