Polish gh-906
This commit is contained in:
parent
92bb47b67c
commit
141063c99c
4 changed files with 116 additions and 588 deletions
|
|
@ -654,12 +654,12 @@ public class McpAsyncClient {
|
||||||
* @param meta Optional metadata to include in the request (_meta field)
|
* @param meta Optional metadata to include in the request (_meta field)
|
||||||
* @return A Mono that emits the list of tools result
|
* @return A Mono that emits the list of tools result
|
||||||
*/
|
*/
|
||||||
public Mono<McpSchema.ListToolsResult> listTools(String cursor, java.util.Map<String, Object> meta) {
|
public Mono<McpSchema.ListToolsResult> listTools(String cursor, Map<String, Object> meta) {
|
||||||
return this.initializer.withInitialization("listing tools", init -> this.listToolsInternal(init, cursor, meta));
|
return this.initializer.withInitialization("listing tools", init -> this.listToolsInternal(init, cursor, meta));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<McpSchema.ListToolsResult> listToolsInternal(Initialization init, String cursor,
|
private Mono<McpSchema.ListToolsResult> listToolsInternal(Initialization init, String cursor,
|
||||||
java.util.Map<String, Object> meta) {
|
Map<String, Object> meta) {
|
||||||
|
|
||||||
if (init.initializeResult().capabilities().tools() == null) {
|
if (init.initializeResult().capabilities().tools() == null) {
|
||||||
return Mono.error(new IllegalStateException("Server does not provide tools capability"));
|
return Mono.error(new IllegalStateException("Server does not provide tools capability"));
|
||||||
|
|
@ -749,12 +749,11 @@ public class McpAsyncClient {
|
||||||
* @see McpSchema.ListResourcesResult
|
* @see McpSchema.ListResourcesResult
|
||||||
* @see #readResource(McpSchema.Resource)
|
* @see #readResource(McpSchema.Resource)
|
||||||
*/
|
*/
|
||||||
public Mono<McpSchema.ListResourcesResult> listResources(String cursor, java.util.Map<String, Object> meta) {
|
public Mono<McpSchema.ListResourcesResult> listResources(String cursor, Map<String, Object> meta) {
|
||||||
return this.listResourcesInternal(cursor, meta);
|
return this.listResourcesInternal(cursor, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<McpSchema.ListResourcesResult> listResourcesInternal(String cursor,
|
private Mono<McpSchema.ListResourcesResult> listResourcesInternal(String cursor, Map<String, Object> meta) {
|
||||||
java.util.Map<String, Object> meta) {
|
|
||||||
return this.initializer.withInitialization("listing resources", init -> {
|
return this.initializer.withInitialization("listing resources", init -> {
|
||||||
if (init.initializeResult().capabilities().resources() == null) {
|
if (init.initializeResult().capabilities().resources() == null) {
|
||||||
return Mono.error(new IllegalStateException("Server does not provide the resources capability"));
|
return Mono.error(new IllegalStateException("Server does not provide the resources capability"));
|
||||||
|
|
@ -837,13 +836,12 @@ public class McpAsyncClient {
|
||||||
* @return A Mono that completes with the list of resource templates result.
|
* @return A Mono that completes with the list of resource templates result.
|
||||||
* @see McpSchema.ListResourceTemplatesResult
|
* @see McpSchema.ListResourceTemplatesResult
|
||||||
*/
|
*/
|
||||||
public Mono<McpSchema.ListResourceTemplatesResult> listResourceTemplates(String cursor,
|
public Mono<McpSchema.ListResourceTemplatesResult> listResourceTemplates(String cursor, Map<String, Object> meta) {
|
||||||
java.util.Map<String, Object> meta) {
|
|
||||||
return this.listResourceTemplatesInternal(cursor, meta);
|
return this.listResourceTemplatesInternal(cursor, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<McpSchema.ListResourceTemplatesResult> listResourceTemplatesInternal(String cursor,
|
private Mono<McpSchema.ListResourceTemplatesResult> listResourceTemplatesInternal(String cursor,
|
||||||
java.util.Map<String, Object> meta) {
|
Map<String, Object> meta) {
|
||||||
return this.initializer.withInitialization("listing resource templates", init -> {
|
return this.initializer.withInitialization("listing resource templates", init -> {
|
||||||
if (init.initializeResult().capabilities().resources() == null) {
|
if (init.initializeResult().capabilities().resources() == null) {
|
||||||
return Mono.error(new IllegalStateException("Server does not provide the resources capability"));
|
return Mono.error(new IllegalStateException("Server does not provide the resources capability"));
|
||||||
|
|
@ -955,11 +953,11 @@ public class McpAsyncClient {
|
||||||
* @see McpSchema.ListPromptsResult
|
* @see McpSchema.ListPromptsResult
|
||||||
* @see #getPrompt(GetPromptRequest)
|
* @see #getPrompt(GetPromptRequest)
|
||||||
*/
|
*/
|
||||||
public Mono<ListPromptsResult> listPrompts(String cursor, java.util.Map<String, Object> meta) {
|
public Mono<ListPromptsResult> listPrompts(String cursor, Map<String, Object> meta) {
|
||||||
return this.listPromptsInternal(cursor, meta);
|
return this.listPromptsInternal(cursor, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<ListPromptsResult> listPromptsInternal(String cursor, java.util.Map<String, Object> meta) {
|
private Mono<ListPromptsResult> listPromptsInternal(String cursor, Map<String, Object> meta) {
|
||||||
return this.initializer.withInitialization("listing prompts",
|
return this.initializer.withInitialization("listing prompts",
|
||||||
init -> init.mcpSession()
|
init -> init.mcpSession()
|
||||||
.sendRequest(McpSchema.METHOD_PROMPT_LIST, new PaginatedRequest(cursor, meta),
|
.sendRequest(McpSchema.METHOD_PROMPT_LIST, new PaginatedRequest(cursor, meta),
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package io.modelcontextprotocol.client;
|
package io.modelcontextprotocol.client;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
@ -267,7 +268,7 @@ public class McpSyncClient implements AutoCloseable {
|
||||||
* with a name, description, and input schema - nextCursor: Optional cursor for
|
* with a name, description, and input schema - nextCursor: Optional cursor for
|
||||||
* pagination if more tools are available
|
* pagination if more tools are available
|
||||||
*/
|
*/
|
||||||
public McpSchema.ListToolsResult listTools(String cursor, java.util.Map<String, Object> meta) {
|
public McpSchema.ListToolsResult listTools(String cursor, Map<String, Object> meta) {
|
||||||
return withProvidedContext(this.delegate.listTools(cursor, meta)).block();
|
return withProvidedContext(this.delegate.listTools(cursor, meta)).block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,7 +301,7 @@ public class McpSyncClient implements AutoCloseable {
|
||||||
* @param meta Optional metadata to include in the request (_meta field)
|
* @param meta Optional metadata to include in the request (_meta field)
|
||||||
* @return The list of resources result
|
* @return The list of resources result
|
||||||
*/
|
*/
|
||||||
public McpSchema.ListResourcesResult listResources(String cursor, java.util.Map<String, Object> meta) {
|
public McpSchema.ListResourcesResult listResources(String cursor, Map<String, Object> meta) {
|
||||||
return withProvidedContext(this.delegate.listResources(cursor, meta)).block();
|
return withProvidedContext(this.delegate.listResources(cursor, meta)).block();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -356,8 +357,7 @@ public class McpSyncClient implements AutoCloseable {
|
||||||
* @param meta Optional metadata to include in the request (_meta field)
|
* @param meta Optional metadata to include in the request (_meta field)
|
||||||
* @return The list of resource templates result.
|
* @return The list of resource templates result.
|
||||||
*/
|
*/
|
||||||
public McpSchema.ListResourceTemplatesResult listResourceTemplates(String cursor,
|
public McpSchema.ListResourceTemplatesResult listResourceTemplates(String cursor, Map<String, Object> meta) {
|
||||||
java.util.Map<String, Object> meta) {
|
|
||||||
return withProvidedContext(this.delegate.listResourceTemplates(cursor, meta)).block();
|
return withProvidedContext(this.delegate.listResourceTemplates(cursor, meta)).block();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -414,7 +414,7 @@ public class McpSyncClient implements AutoCloseable {
|
||||||
* @param meta Optional metadata to include in the request (_meta field)
|
* @param meta Optional metadata to include in the request (_meta field)
|
||||||
* @return The list of prompts result.
|
* @return The list of prompts result.
|
||||||
*/
|
*/
|
||||||
public ListPromptsResult listPrompts(String cursor, java.util.Map<String, Object> meta) {
|
public ListPromptsResult listPrompts(String cursor, Map<String, Object> meta) {
|
||||||
return withProvidedContext(this.delegate.listPrompts(cursor, meta)).block();
|
return withProvidedContext(this.delegate.listPrompts(cursor, meta)).block();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ public abstract class AbstractMcpSyncClientTests {
|
||||||
void testListToolsWithMeta() {
|
void testListToolsWithMeta() {
|
||||||
withClient(createMcpTransport(), mcpSyncClient -> {
|
withClient(createMcpTransport(), mcpSyncClient -> {
|
||||||
mcpSyncClient.initialize();
|
mcpSyncClient.initialize();
|
||||||
java.util.Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
||||||
ListToolsResult tools = mcpSyncClient.listTools(McpSchema.FIRST_PAGE, meta);
|
ListToolsResult tools = mcpSyncClient.listTools(McpSchema.FIRST_PAGE, meta);
|
||||||
|
|
||||||
assertThat(tools).isNotNull().satisfies(result -> {
|
assertThat(tools).isNotNull().satisfies(result -> {
|
||||||
|
|
@ -695,7 +695,7 @@ public abstract class AbstractMcpSyncClientTests {
|
||||||
void testListResourcesWithMeta() {
|
void testListResourcesWithMeta() {
|
||||||
withClient(createMcpTransport(), mcpSyncClient -> {
|
withClient(createMcpTransport(), mcpSyncClient -> {
|
||||||
mcpSyncClient.initialize();
|
mcpSyncClient.initialize();
|
||||||
java.util.Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
||||||
ListResourcesResult resources = mcpSyncClient.listResources(McpSchema.FIRST_PAGE, meta);
|
ListResourcesResult resources = mcpSyncClient.listResources(McpSchema.FIRST_PAGE, meta);
|
||||||
|
|
||||||
assertThat(resources).isNotNull().satisfies(result -> {
|
assertThat(resources).isNotNull().satisfies(result -> {
|
||||||
|
|
@ -708,7 +708,7 @@ public abstract class AbstractMcpSyncClientTests {
|
||||||
void testListResourceTemplatesWithMeta() {
|
void testListResourceTemplatesWithMeta() {
|
||||||
withClient(createMcpTransport(), mcpSyncClient -> {
|
withClient(createMcpTransport(), mcpSyncClient -> {
|
||||||
mcpSyncClient.initialize();
|
mcpSyncClient.initialize();
|
||||||
java.util.Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
||||||
ListResourceTemplatesResult result = mcpSyncClient.listResourceTemplates(McpSchema.FIRST_PAGE, meta);
|
ListResourceTemplatesResult result = mcpSyncClient.listResourceTemplates(McpSchema.FIRST_PAGE, meta);
|
||||||
|
|
||||||
assertThat(result).isNotNull().satisfies(r -> {
|
assertThat(result).isNotNull().satisfies(r -> {
|
||||||
|
|
@ -721,7 +721,7 @@ public abstract class AbstractMcpSyncClientTests {
|
||||||
void testListPromptsWithMeta() {
|
void testListPromptsWithMeta() {
|
||||||
withClient(createMcpTransport(), mcpSyncClient -> {
|
withClient(createMcpTransport(), mcpSyncClient -> {
|
||||||
mcpSyncClient.initialize();
|
mcpSyncClient.initialize();
|
||||||
java.util.Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
Map<String, Object> meta = java.util.Map.of("requestId", "test-123");
|
||||||
McpSchema.ListPromptsResult result = mcpSyncClient.listPrompts(McpSchema.FIRST_PAGE, meta);
|
McpSchema.ListPromptsResult result = mcpSyncClient.listPrompts(McpSchema.FIRST_PAGE, meta);
|
||||||
|
|
||||||
assertThat(result).isNotNull().satisfies(r -> {
|
assertThat(result).isNotNull().satisfies(r -> {
|
||||||
|
|
|
||||||
|
|
@ -238,580 +238,71 @@ class McpAsyncClientTests {
|
||||||
StepVerifier.create(client.closeGracefully()).verifyComplete();
|
StepVerifier.create(client.closeGracefully()).verifyComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void testListToolsWithEmptyCursor() {
|
|
||||||
McpSchema.Tool addTool = McpSchema.Tool.builder().name("add").description("calculate add").build();
|
|
||||||
McpSchema.Tool subtractTool = McpSchema.Tool.builder()
|
|
||||||
.name("subtract")
|
|
||||||
.description("calculate subtract")
|
|
||||||
.build();
|
|
||||||
McpSchema.ListToolsResult mockToolsResult = new McpSchema.ListToolsResult(List.of(addTool, subtractTool), "");
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), MOCK_INIT_RESULT,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_TOOLS_LIST.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockToolsResult,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpAsyncClient client = McpClient.async(transport).enableCallToolSchemaCaching(true).build();
|
|
||||||
|
|
||||||
Mono<McpSchema.ListToolsResult> mono = client.listTools();
|
|
||||||
McpSchema.ListToolsResult toolsResult = mono.block();
|
|
||||||
assertThat(toolsResult).isNotNull();
|
|
||||||
|
|
||||||
Set<String> names = toolsResult.tools().stream().map(McpSchema.Tool::name).collect(Collectors.toSet());
|
|
||||||
assertThat(names).containsExactlyInAnyOrder("subtract", "add");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testListToolsWithCursorAndMeta() {
|
void testListToolsWithCursorAndMeta() {
|
||||||
McpSchema.Tool addTool = McpSchema.Tool.builder().name("add").description("calculate add").build();
|
var transport = new TestMcpClientTransport();
|
||||||
McpSchema.ListToolsResult mockToolsResult = new McpSchema.ListToolsResult(List.of(addTool), null);
|
|
||||||
|
|
||||||
// Use array to capture from anonymous class
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), MOCK_INIT_RESULT,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_TOOLS_LIST.equals(request.method())) {
|
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockToolsResult,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpAsyncClient client = McpClient.async(transport).build();
|
McpAsyncClient client = McpClient.async(transport).build();
|
||||||
|
|
||||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||||
McpSchema.ListToolsResult toolsResult = client.listTools("cursor-1", meta).block();
|
McpSchema.ListToolsResult result = client.listTools("cursor-1", meta).block();
|
||||||
assertThat(toolsResult).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
assertThat(toolsResult.tools()).hasSize(1);
|
assertThat(result.tools()).hasSize(1);
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
assertThat(transport.getCapturedRequest()).isNotNull();
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
assertThat(transport.getCapturedRequest().cursor()).isEqualTo("cursor-1");
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("customKey", "customValue");
|
assertThat(transport.getCapturedRequest().meta()).containsEntry("customKey", "customValue");
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSyncListToolsWithCursorAndMeta() {
|
|
||||||
McpSchema.Tool addTool = McpSchema.Tool.builder().name("add").description("calculate add").build();
|
|
||||||
McpSchema.ListToolsResult mockToolsResult = new McpSchema.ListToolsResult(List.of(addTool), null);
|
|
||||||
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), MOCK_INIT_RESULT,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_TOOLS_LIST.equals(request.method())) {
|
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockToolsResult,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpSyncClient client = McpClient.sync(transport).build();
|
|
||||||
|
|
||||||
Map<String, Object> meta = Map.of("requestId", "test-123");
|
|
||||||
McpSchema.ListToolsResult toolsResult = client.listTools("cursor-1", meta);
|
|
||||||
assertThat(toolsResult).isNotNull();
|
|
||||||
assertThat(toolsResult.tools()).hasSize(1);
|
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("requestId", "test-123");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testListResourcesWithCursorAndMeta() {
|
void testListResourcesWithCursorAndMeta() {
|
||||||
McpSchema.Resource mockResource = McpSchema.Resource.builder().uri("file:///test.txt").name("test.txt").build();
|
var transport = new TestMcpClientTransport();
|
||||||
McpSchema.ListResourcesResult mockResult = new McpSchema.ListResourcesResult(List.of(mockResource), null);
|
|
||||||
|
|
||||||
McpSchema.ServerCapabilities caps = McpSchema.ServerCapabilities.builder().resources(false, false).build();
|
|
||||||
McpSchema.InitializeResult initResult = new McpSchema.InitializeResult(ProtocolVersions.MCP_2024_11_05, caps,
|
|
||||||
MOCK_SERVER_INFO, null);
|
|
||||||
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), initResult, null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_RESOURCES_LIST.equals(request.method())) {
|
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockResult, null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpAsyncClient client = McpClient.async(transport).build();
|
McpAsyncClient client = McpClient.async(transport).build();
|
||||||
|
|
||||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||||
McpSchema.ListResourcesResult result = client.listResources("cursor-1", meta).block();
|
McpSchema.ListResourcesResult result = client.listResources("cursor-1", meta).block();
|
||||||
assertThat(result).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
assertThat(result.resources()).hasSize(1);
|
assertThat(result.resources()).hasSize(1);
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
assertThat(transport.getCapturedRequest()).isNotNull();
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
assertThat(transport.getCapturedRequest().cursor()).isEqualTo("cursor-1");
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("customKey", "customValue");
|
assertThat(transport.getCapturedRequest().meta()).containsEntry("customKey", "customValue");
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSyncListResourcesWithCursorAndMeta() {
|
|
||||||
McpSchema.Resource mockResource = McpSchema.Resource.builder().uri("file:///test.txt").name("test.txt").build();
|
|
||||||
McpSchema.ListResourcesResult mockResult = new McpSchema.ListResourcesResult(List.of(mockResource), null);
|
|
||||||
|
|
||||||
McpSchema.ServerCapabilities caps = McpSchema.ServerCapabilities.builder().resources(false, false).build();
|
|
||||||
McpSchema.InitializeResult initResult = new McpSchema.InitializeResult(ProtocolVersions.MCP_2024_11_05, caps,
|
|
||||||
MOCK_SERVER_INFO, null);
|
|
||||||
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), initResult, null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_RESOURCES_LIST.equals(request.method())) {
|
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockResult, null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpSyncClient client = McpClient.sync(transport).build();
|
|
||||||
|
|
||||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
|
||||||
McpSchema.ListResourcesResult result = client.listResources("cursor-1", meta);
|
|
||||||
assertThat(result).isNotNull();
|
|
||||||
assertThat(result.resources()).hasSize(1);
|
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("customKey", "customValue");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testListResourceTemplatesWithCursorAndMeta() {
|
void testListResourceTemplatesWithCursorAndMeta() {
|
||||||
McpSchema.ResourceTemplate mockTemplate = new McpSchema.ResourceTemplate("file:///{name}", "template", null,
|
var transport = new TestMcpClientTransport();
|
||||||
null, null);
|
|
||||||
McpSchema.ListResourceTemplatesResult mockResult = new McpSchema.ListResourceTemplatesResult(
|
|
||||||
List.of(mockTemplate), null);
|
|
||||||
|
|
||||||
McpSchema.ServerCapabilities caps = McpSchema.ServerCapabilities.builder().resources(false, false).build();
|
|
||||||
McpSchema.InitializeResult initResult = new McpSchema.InitializeResult(ProtocolVersions.MCP_2024_11_05, caps,
|
|
||||||
MOCK_SERVER_INFO, null);
|
|
||||||
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), initResult, null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_RESOURCES_TEMPLATES_LIST.equals(request.method())) {
|
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockResult, null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpAsyncClient client = McpClient.async(transport).build();
|
McpAsyncClient client = McpClient.async(transport).build();
|
||||||
|
|
||||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||||
McpSchema.ListResourceTemplatesResult result = client.listResourceTemplates("cursor-1", meta).block();
|
McpSchema.ListResourceTemplatesResult result = client.listResourceTemplates("cursor-1", meta).block();
|
||||||
assertThat(result).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
assertThat(result.resourceTemplates()).hasSize(1);
|
assertThat(result.resourceTemplates()).hasSize(1);
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
assertThat(transport.getCapturedRequest()).isNotNull();
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
assertThat(transport.getCapturedRequest().cursor()).isEqualTo("cursor-1");
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("customKey", "customValue");
|
assertThat(transport.getCapturedRequest().meta()).containsEntry("customKey", "customValue");
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSyncListResourceTemplatesWithCursorAndMeta() {
|
|
||||||
McpSchema.ResourceTemplate mockTemplate = new McpSchema.ResourceTemplate("file:///{name}", "template", null,
|
|
||||||
null, null);
|
|
||||||
McpSchema.ListResourceTemplatesResult mockResult = new McpSchema.ListResourceTemplatesResult(
|
|
||||||
List.of(mockTemplate), null);
|
|
||||||
|
|
||||||
McpSchema.ServerCapabilities caps = McpSchema.ServerCapabilities.builder().resources(false, false).build();
|
|
||||||
McpSchema.InitializeResult initResult = new McpSchema.InitializeResult(ProtocolVersions.MCP_2024_11_05, caps,
|
|
||||||
MOCK_SERVER_INFO, null);
|
|
||||||
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), initResult, null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_RESOURCES_TEMPLATES_LIST.equals(request.method())) {
|
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockResult, null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpSyncClient client = McpClient.sync(transport).build();
|
|
||||||
|
|
||||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
|
||||||
McpSchema.ListResourceTemplatesResult result = client.listResourceTemplates("cursor-1", meta);
|
|
||||||
assertThat(result).isNotNull();
|
|
||||||
assertThat(result.resourceTemplates()).hasSize(1);
|
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("customKey", "customValue");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testListPromptsWithCursorAndMeta() {
|
void testListPromptsWithCursorAndMeta() {
|
||||||
McpSchema.Prompt mockPrompt = new McpSchema.Prompt("test-prompt", "A test prompt", List.of());
|
var transport = new TestMcpClientTransport();
|
||||||
McpSchema.ListPromptsResult mockResult = new McpSchema.ListPromptsResult(List.of(mockPrompt), null);
|
|
||||||
|
|
||||||
McpSchema.ServerCapabilities caps = McpSchema.ServerCapabilities.builder().prompts(false).build();
|
|
||||||
McpSchema.InitializeResult initResult = new McpSchema.InitializeResult(ProtocolVersions.MCP_2024_11_05, caps,
|
|
||||||
MOCK_SERVER_INFO, null);
|
|
||||||
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> connect(
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
|
||||||
this.handler = handler;
|
|
||||||
return Mono.empty();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> closeGracefully() {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
|
|
||||||
if (!(message instanceof McpSchema.JSONRPCRequest request)) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
McpSchema.JSONRPCResponse response;
|
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), initResult, null);
|
|
||||||
}
|
|
||||||
else if (McpSchema.METHOD_PROMPT_LIST.equals(request.method())) {
|
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockResult, null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
return handler.apply(Mono.just(response)).then();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unmarshalFrom(Object data, TypeRef<T> typeRef) {
|
|
||||||
return JSON_MAPPER.convertValue(data, new TypeRef<>() {
|
|
||||||
@Override
|
|
||||||
public java.lang.reflect.Type getType() {
|
|
||||||
return typeRef.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
McpAsyncClient client = McpClient.async(transport).build();
|
McpAsyncClient client = McpClient.async(transport).build();
|
||||||
|
|
||||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||||
McpSchema.ListPromptsResult result = client.listPrompts("cursor-1", meta).block();
|
McpSchema.ListPromptsResult result = client.listPrompts("cursor-1", meta).block();
|
||||||
assertThat(result).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
assertThat(result.prompts()).hasSize(1);
|
assertThat(result.prompts()).hasSize(1);
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
assertThat(transport.getCapturedRequest()).isNotNull();
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
assertThat(transport.getCapturedRequest().cursor()).isEqualTo("cursor-1");
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("customKey", "customValue");
|
assertThat(transport.getCapturedRequest().meta()).containsEntry("customKey", "customValue");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
static class TestMcpClientTransport implements McpClientTransport {
|
||||||
void testSyncListPromptsWithCursorAndMeta() {
|
|
||||||
McpSchema.Prompt mockPrompt = new McpSchema.Prompt("test-prompt", "A test prompt", List.of());
|
|
||||||
McpSchema.ListPromptsResult mockResult = new McpSchema.ListPromptsResult(List.of(mockPrompt), null);
|
|
||||||
|
|
||||||
McpSchema.ServerCapabilities caps = McpSchema.ServerCapabilities.builder().prompts(false).build();
|
private Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
||||||
McpSchema.InitializeResult initResult = new McpSchema.InitializeResult(ProtocolVersions.MCP_2024_11_05, caps,
|
|
||||||
MOCK_SERVER_INFO, null);
|
|
||||||
|
|
||||||
McpSchema.PaginatedRequest[] capturedRequest = new McpSchema.PaginatedRequest[1];
|
private McpSchema.PaginatedRequest capturedRequest = null;
|
||||||
|
|
||||||
McpClientTransport transport = new McpClientTransport() {
|
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> connect(
|
public Mono<Void> connect(Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
||||||
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
|
|
||||||
return Mono.deferContextual(ctx -> {
|
return Mono.deferContextual(ctx -> {
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
|
|
@ -830,11 +321,56 @@ class McpAsyncClientTests {
|
||||||
}
|
}
|
||||||
McpSchema.JSONRPCResponse response;
|
McpSchema.JSONRPCResponse response;
|
||||||
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
if (McpSchema.METHOD_INITIALIZE.equals(request.method())) {
|
||||||
|
McpSchema.ServerCapabilities caps = McpSchema.ServerCapabilities.builder()
|
||||||
|
.prompts(false)
|
||||||
|
.resources(false, false)
|
||||||
|
.tools(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
McpSchema.InitializeResult initResult = new McpSchema.InitializeResult(ProtocolVersions.MCP_2024_11_05,
|
||||||
|
caps, MOCK_SERVER_INFO, null);
|
||||||
|
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), initResult, null);
|
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), initResult, null);
|
||||||
}
|
}
|
||||||
else if (McpSchema.METHOD_PROMPT_LIST.equals(request.method())) {
|
else if (McpSchema.METHOD_PROMPT_LIST.equals(request.method())) {
|
||||||
capturedRequest[0] = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
capturedRequest = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
||||||
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockResult, null);
|
|
||||||
|
McpSchema.Prompt mockPrompt = new McpSchema.Prompt("test-prompt", "A test prompt", List.of());
|
||||||
|
McpSchema.ListPromptsResult mockPromptResult = new McpSchema.ListPromptsResult(List.of(mockPrompt),
|
||||||
|
null);
|
||||||
|
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockPromptResult,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
else if (McpSchema.METHOD_RESOURCES_TEMPLATES_LIST.equals(request.method())) {
|
||||||
|
capturedRequest = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
||||||
|
|
||||||
|
McpSchema.ResourceTemplate mockTemplate = new McpSchema.ResourceTemplate("file:///{name}", "template",
|
||||||
|
null, null, null);
|
||||||
|
McpSchema.ListResourceTemplatesResult mockResourceTemplateResult = new McpSchema.ListResourceTemplatesResult(
|
||||||
|
List.of(mockTemplate), null);
|
||||||
|
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(),
|
||||||
|
mockResourceTemplateResult, null);
|
||||||
|
}
|
||||||
|
else if (McpSchema.METHOD_RESOURCES_LIST.equals(request.method())) {
|
||||||
|
capturedRequest = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
||||||
|
|
||||||
|
McpSchema.Resource mockResource = McpSchema.Resource.builder()
|
||||||
|
.uri("file:///test.txt")
|
||||||
|
.name("test.txt")
|
||||||
|
.build();
|
||||||
|
McpSchema.ListResourcesResult mockResourceResult = new McpSchema.ListResourcesResult(
|
||||||
|
List.of(mockResource), null);
|
||||||
|
|
||||||
|
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockResourceResult,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
else if (McpSchema.METHOD_TOOLS_LIST.equals(request.method())) {
|
||||||
|
capturedRequest = JSON_MAPPER.convertValue(request.params(), McpSchema.PaginatedRequest.class);
|
||||||
|
|
||||||
|
McpSchema.Tool addTool = McpSchema.Tool.builder().name("add").description("calculate add").build();
|
||||||
|
McpSchema.ListToolsResult mockToolsResult = new McpSchema.ListToolsResult(List.of(addTool), null);
|
||||||
|
response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), mockToolsResult,
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
|
|
@ -851,17 +387,11 @@ class McpAsyncClientTests {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
McpSyncClient client = McpClient.sync(transport).build();
|
public McpSchema.PaginatedRequest getCapturedRequest() {
|
||||||
|
return capturedRequest;
|
||||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
}
|
||||||
McpSchema.ListPromptsResult result = client.listPrompts("cursor-1", meta);
|
|
||||||
assertThat(result).isNotNull();
|
|
||||||
assertThat(result.prompts()).hasSize(1);
|
|
||||||
assertThat(capturedRequest[0]).isNotNull();
|
|
||||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
|
||||||
assertThat(capturedRequest[0].meta()).containsEntry("customKey", "customValue");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue