feat: add support for meta parameter in client paginated list queries (#906)
* feat: add support for meta parameter in client paginated list queries# - resources/list - resources/templates/list - prompts/list - tools/list paginated list operations extended in this review: - listResources(String cursor, Map<String, Object> meta) - listResourceTemplates(String cursor, Map<String, Object> meta) - listPrompts(String cursor, Map<String, Object> meta) Closes #907 Co-authored-by: SHEETAL MOHITE <mohishee@amazon.com> Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
This commit is contained in:
parent
8fd9903e62
commit
eaa0c691f0
1 changed files with 733 additions and 8 deletions
|
|
@ -307,4 +307,561 @@ class McpAsyncClientTests {
|
|||
assertThat(names).containsExactlyInAnyOrder("subtract", "add");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListToolsWithCursorAndMeta() {
|
||||
McpSchema.Tool addTool = McpSchema.Tool.builder().name("add").description("calculate add").build();
|
||||
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();
|
||||
|
||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||
McpSchema.ListToolsResult toolsResult = client.listTools("cursor-1", meta).block();
|
||||
assertThat(toolsResult).isNotNull();
|
||||
assertThat(toolsResult.tools()).hasSize(1);
|
||||
assertThat(capturedRequest[0]).isNotNull();
|
||||
assertThat(capturedRequest[0].cursor()).isEqualTo("cursor-1");
|
||||
assertThat(capturedRequest[0].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
|
||||
void testListResourcesWithCursorAndMeta() {
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
McpAsyncClient client = McpClient.async(transport).build();
|
||||
|
||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||
McpSchema.ListResourcesResult result = client.listResources("cursor-1", meta).block();
|
||||
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
|
||||
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
|
||||
void testListResourceTemplatesWithCursorAndMeta() {
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
McpAsyncClient client = McpClient.async(transport).build();
|
||||
|
||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||
McpSchema.ListResourceTemplatesResult result = client.listResourceTemplates("cursor-1", meta).block();
|
||||
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
|
||||
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
|
||||
void testListPromptsWithCursorAndMeta() {
|
||||
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();
|
||||
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();
|
||||
|
||||
Map<String, Object> meta = Map.of("customKey", "customValue");
|
||||
McpSchema.ListPromptsResult result = client.listPrompts("cursor-1", meta).block();
|
||||
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");
|
||||
}
|
||||
|
||||
@Test
|
||||
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();
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
McpSyncClient client = McpClient.sync(transport).build();
|
||||
|
||||
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