Skip to content

Commit 3e1a889

Browse files
committed
Added a test
Signed-off-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com>
1 parent 2be29c7 commit 3e1a889

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

mcp/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,6 @@ public class McpAsyncClient {
270270
this.transport.setExceptionHandler(this::handleException);
271271
this.sessionSupplier = ctx -> new McpClientSession(requestTimeout, transport, requestHandlers,
272272
notificationHandlers, con -> con.contextWrite(ctx));
273-
274273
}
275274

276275
private void handleException(Throwable t) {
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package io.modelcontextprotocol.client;
2+
3+
import com.fasterxml.jackson.core.type.TypeReference;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import io.modelcontextprotocol.spec.McpClientTransport;
6+
import io.modelcontextprotocol.spec.McpSchema;
7+
import org.junit.jupiter.api.Test;
8+
import reactor.core.publisher.Mono;
9+
10+
import java.util.concurrent.atomic.AtomicReference;
11+
import java.util.function.Function;
12+
13+
import static org.assertj.core.api.Assertions.assertThatCode;
14+
15+
class McpAsyncClientTests {
16+
17+
public static final McpSchema.Implementation MOCK_SERVER_INFO = new McpSchema.Implementation("test-server",
18+
"1.0.0");
19+
20+
public static final McpSchema.ServerCapabilities MOCK_SERVER_CAPABILITIES = McpSchema.ServerCapabilities.builder()
21+
.build();
22+
23+
public static final McpSchema.InitializeResult MOCK_INIT_RESULT = new McpSchema.InitializeResult(
24+
McpSchema.LATEST_PROTOCOL_VERSION, MOCK_SERVER_CAPABILITIES, MOCK_SERVER_INFO, "Test instructions");
25+
26+
private static final String CONTEXT_KEY = "context.key";
27+
28+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
29+
30+
@Test
31+
void validateContextPassedToTransportConnect() {
32+
McpClientTransport transport = new McpClientTransport() {
33+
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler;
34+
35+
final AtomicReference<String> contextValue = new AtomicReference<>();
36+
37+
@Override
38+
public Mono<Void> connect(
39+
Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchema.JSONRPCMessage>> handler) {
40+
return Mono.deferContextual(ctx -> {
41+
this.handler = handler;
42+
if (ctx.hasKey(CONTEXT_KEY)) {
43+
this.contextValue.set(ctx.get(CONTEXT_KEY));
44+
}
45+
return Mono.empty();
46+
});
47+
}
48+
49+
@Override
50+
public Mono<Void> closeGracefully() {
51+
return Mono.empty();
52+
}
53+
54+
@Override
55+
public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
56+
if (!"hello".equals(this.contextValue.get())) {
57+
return Mono.error(new RuntimeException("Context value not propagated via #connect method"));
58+
}
59+
// We're only interested in handling the init request to provide an init
60+
// response
61+
if (!(message instanceof McpSchema.JSONRPCRequest)) {
62+
return Mono.empty();
63+
}
64+
McpSchema.JSONRPCResponse initResponse = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION,
65+
((McpSchema.JSONRPCRequest) message).id(), MOCK_INIT_RESULT, null);
66+
return handler.apply(Mono.just(initResponse)).then();
67+
}
68+
69+
@Override
70+
public <T> T unmarshalFrom(Object data, TypeReference<T> typeRef) {
71+
return OBJECT_MAPPER.convertValue(data, typeRef);
72+
}
73+
};
74+
75+
assertThatCode(() -> {
76+
McpAsyncClient client = McpClient.async(transport).build();
77+
client.initialize().contextWrite(ctx -> ctx.put(CONTEXT_KEY, "hello")).block();
78+
}).doesNotThrowAnyException();
79+
}
80+
81+
}

0 commit comments

Comments
 (0)