Skip to content

Commit b5bbbb5

Browse files
authored
Move modern server tests to mcp-test (#1215)
- These tests rely on JSON serialization and as such should use Jackson 2 and 3 serialization. Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
1 parent 2aab403 commit b5bbbb5

11 files changed

Lines changed: 176 additions & 227 deletions

File tree

‎mcp-core/src/test/java/io/modelcontextprotocol/modern/server/feature/CompletionsFeatureTests.java‎

Lines changed: 0 additions & 57 deletions
This file was deleted.

mcp-core/src/test/java/io/modelcontextprotocol/modern/server/HmacRequestStateCodecTests.java renamed to mcp-test/src/test/java/io/modelcontextprotocol/modern/server/HmacRequestStateCodecTests.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import io.modelcontextprotocol.modern.McpSchema;
1717
import io.modelcontextprotocol.modern.McpSchema.ClientCapabilities;
1818
import io.modelcontextprotocol.modern.McpSchema.MetaKeys;
19-
import io.modelcontextprotocol.spec.json.gson.GsonMcpJsonMapper;
2019
import org.junit.jupiter.api.Test;
2120

2221
import static org.assertj.core.api.Assertions.assertThat;
@@ -32,11 +31,7 @@ private static McpRequestContext ctx(String method, String primitiveName, McpTra
3231
}
3332

3433
private static HmacRequestStateCodec codec(Clock clock) {
35-
return HmacRequestStateCodec.builder()
36-
.key("test-key-0123456789abcdef".getBytes())
37-
.clock(clock)
38-
.jsonMapper(new GsonMcpJsonMapper())
39-
.build();
34+
return HmacRequestStateCodec.builder().key("test-key-0123456789abcdef".getBytes()).clock(clock).build();
4035
}
4136

4237
@Test
@@ -96,7 +91,6 @@ public Instant instant() {
9691
.key("test-key-0123456789abcdef".getBytes())
9792
.clock(clock)
9893
.ttl(Duration.ofMinutes(1))
99-
.jsonMapper(new GsonMcpJsonMapper())
10094
.build();
10195
McpRequestContext ctx = ctx("tools/call", "echo", McpTransportContext.EMPTY);
10296
String sealed = codec.seal(ctx, "state");
@@ -112,7 +106,6 @@ void differentPrincipalIsRejected() {
112106
.key("test-key-0123456789abcdef".getBytes())
113107
.clock(clock)
114108
.principalExtractor(tc -> (String) tc.get("user"))
115-
.jsonMapper(new GsonMcpJsonMapper())
116109
.build();
117110
McpTransportContext alice = McpTransportContext.create(Map.of("user", "alice"));
118111
McpTransportContext bob = McpTransportContext.create(Map.of("user", "bob"));

mcp-core/src/test/java/io/modelcontextprotocol/modern/server/McpServerMrtrTests.java renamed to mcp-test/src/test/java/io/modelcontextprotocol/modern/server/McpServerMrtrTests.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Set;
1111
import java.util.concurrent.atomic.AtomicReference;
1212

13+
import io.modelcontextprotocol.json.McpJsonDefaults;
1314
import io.modelcontextprotocol.modern.JsonRpc.JSONRPCRequest;
1415
import io.modelcontextprotocol.modern.JsonRpc.JSONRPCResponse;
1516
import io.modelcontextprotocol.modern.McpSchema;
@@ -21,15 +22,14 @@
2122
import io.modelcontextprotocol.modern.McpSchema.InputRequired;
2223
import io.modelcontextprotocol.modern.McpSchema.InputRequiredResult;
2324
import io.modelcontextprotocol.modern.McpSchema.MetaKeys;
24-
import io.modelcontextprotocol.modern.McpSchema.Result;
2525
import io.modelcontextprotocol.modern.McpSchema.ReadResourceResult;
26+
import io.modelcontextprotocol.modern.McpSchema.Result;
2627
import io.modelcontextprotocol.modern.McpSchema.TextContent;
2728
import io.modelcontextprotocol.modern.McpSchema.TextResourceContents;
2829
import io.modelcontextprotocol.modern.server.feature.McpAsyncResourceRepository;
2930
import io.modelcontextprotocol.modern.server.feature.ResourcesFeature;
3031
import io.modelcontextprotocol.modern.server.feature.ResourcesPage;
3132
import io.modelcontextprotocol.modern.server.feature.ToolsFeature;
32-
import io.modelcontextprotocol.spec.json.gson.GsonMcpJsonMapper;
3333
import org.junit.jupiter.api.Test;
3434
import reactor.core.publisher.Mono;
3535

@@ -47,7 +47,7 @@ class McpServerMrtrTests {
4747
.build();
4848

4949
private static McpServer.Builder baseBuilder() {
50-
return McpServer.builder().serverInfo(SERVER_INFO).jsonMapper(new GsonMcpJsonMapper());
50+
return McpServer.builder().serverInfo(SERVER_INFO);
5151
}
5252

5353
private static Map<String, Object> metaWithElicitation() {
@@ -74,7 +74,7 @@ private static McpServer serverRecordingState(AtomicReference<String> seenReques
7474
}
7575
return Mono.just(McpAsyncResponse
7676
.result(InputRequiredResult.builder().elicit("q1", CONFIRM).requestState("secret-plaintext").build()));
77-
}), new GsonMcpJsonMapper(), PERMISSIVE_VALIDATOR, 0L, CacheScope.PRIVATE)).build();
77+
}), McpJsonDefaults.getMapper(), PERMISSIVE_VALIDATOR, 0L, CacheScope.PRIVATE)).build();
7878
}
7979

8080
@Test
@@ -137,9 +137,9 @@ void malformedInputResponsesAreRejectedBeforeTheHandler() {
137137
@SuppressWarnings("unchecked")
138138
void unparseableInputResponseIsInvalidParams() {
139139
McpServer server = baseBuilder().feature(ToolsFeature.ofAsync(tools((ctx, req) -> {
140-
InputResponses.get(req.inputResponses(), "q1", ElicitAnswer.class, new GsonMcpJsonMapper());
140+
InputResponses.get(req.inputResponses(), "q1", ElicitAnswer.class, McpJsonDefaults.getMapper());
141141
return Mono.just(McpAsyncResponse.result(CallToolResult.builder().build()));
142-
}), new GsonMcpJsonMapper(), PERMISSIVE_VALIDATOR, 0L, CacheScope.PRIVATE)).build();
142+
}), McpJsonDefaults.getMapper(), PERMISSIVE_VALIDATOR, 0L, CacheScope.PRIVATE)).build();
143143
JSONRPCRequest request = toolCall(1, metaWithElicitation(), null);
144144
((Map<String, Object>) request.params()).put("inputResponses",
145145
Map.of("q1", Map.of("action", "accept", "content", "not-an-object")));
@@ -162,7 +162,7 @@ void inputRequestsAreNotCheckedAgainstClientCapabilities() {
162162
tools((ctx,
163163
req) -> Mono.just(McpAsyncResponse
164164
.result(InputRequiredResult.builder().elicit("q1", CONFIRM).build()))),
165-
new GsonMcpJsonMapper(), PERMISSIVE_VALIDATOR, 0L, CacheScope.PRIVATE))
165+
McpJsonDefaults.getMapper(), PERMISSIVE_VALIDATOR, 0L, CacheScope.PRIVATE))
166166
.build();
167167

168168
JSONRPCResponse response = respond(server, toolCall(1, meta(), null)).block();
@@ -189,7 +189,7 @@ public Mono<McpAsyncResponse<McpSchema.ReadResourceOutcome>> read(McpRequestCont
189189
}
190190
};
191191
McpServer server = baseBuilder()
192-
.feature(ResourcesFeature.ofAsync(repo, new GsonMcpJsonMapper(), 0L, CacheScope.PRIVATE))
192+
.feature(ResourcesFeature.ofAsync(repo, McpJsonDefaults.getMapper(), 0L, CacheScope.PRIVATE))
193193
.build();
194194

195195
Map<String, Object> params = new HashMap<>();
@@ -201,8 +201,7 @@ public Mono<McpAsyncResponse<McpSchema.ReadResourceOutcome>> read(McpRequestCont
201201
@SuppressWarnings("unchecked")
202202
Map<String, Object> result = (Map<String, Object>) response.result();
203203
assertThat(((Number) result.get("ttlMs")).longValue()).isZero();
204-
// Gson ignores @JsonProperty on enums, so compare case-insensitively.
205-
assertThat((String) result.get("cacheScope")).isEqualToIgnoringCase("private");
204+
assertThat(result.get("cacheScope")).isEqualTo("private");
206205
}
207206

208207
@Test
@@ -227,7 +226,7 @@ public Mono<McpAsyncResponse<McpSchema.ReadResourceOutcome>> read(McpRequestCont
227226
}
228227
};
229228
McpServer server = baseBuilder()
230-
.feature(ResourcesFeature.ofAsync(repo, new GsonMcpJsonMapper(), 0L, CacheScope.PRIVATE))
229+
.feature(ResourcesFeature.ofAsync(repo, McpJsonDefaults.getMapper(), 0L, CacheScope.PRIVATE))
231230
.build();
232231

233232
Map<String, Object> first = new HashMap<>();

mcp-core/src/test/java/io/modelcontextprotocol/modern/server/McpServerTests.java renamed to mcp-test/src/test/java/io/modelcontextprotocol/modern/server/McpServerTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import io.modelcontextprotocol.modern.McpSchema.Result;
2525
import io.modelcontextprotocol.modern.McpSchema.ServerCapabilities;
2626
import io.modelcontextprotocol.modern.McpSchema.TextContent;
27-
import io.modelcontextprotocol.spec.json.gson.GsonMcpJsonMapper;
2827
import org.junit.jupiter.api.Test;
2928
import reactor.core.publisher.Mono;
3029
import reactor.test.StepVerifier;
@@ -39,7 +38,7 @@
3938
class McpServerTests {
4039

4140
private static McpServer.Builder baseBuilder() {
42-
return McpServer.builder().serverInfo(SERVER_INFO).jsonMapper(new GsonMcpJsonMapper());
41+
return McpServer.builder().serverInfo(SERVER_INFO);
4342
}
4443

4544
private static McpFeature feature(String method,

mcp-core/src/test/java/io/modelcontextprotocol/modern/server/ModernTestFixtures.java renamed to mcp-test/src/test/java/io/modelcontextprotocol/modern/server/ModernTestFixtures.java

File renamed without changes.

mcp-core/src/test/java/io/modelcontextprotocol/modern/server/SubscriptionsFeatureTests.java renamed to mcp-test/src/test/java/io/modelcontextprotocol/modern/server/SubscriptionsFeatureTests.java

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Map;
1010

1111
import io.modelcontextprotocol.common.McpTransportContext;
12+
import io.modelcontextprotocol.json.McpJsonDefaults;
1213
import io.modelcontextprotocol.modern.JsonRpc.JSONRPCNotification;
1314
import io.modelcontextprotocol.modern.JsonRpc.JSONRPCRequest;
1415
import io.modelcontextprotocol.modern.JsonRpc.JSONRPCResponse;
@@ -17,14 +18,15 @@
1718
import io.modelcontextprotocol.modern.McpSchema.MetaKeys;
1819
import io.modelcontextprotocol.modern.McpSchema.ReadResourceOutcome;
1920
import io.modelcontextprotocol.modern.McpSchema.ReadResourceRequest;
21+
import io.modelcontextprotocol.modern.McpSchema.SubscriptionFilter;
22+
import io.modelcontextprotocol.modern.McpSchema.SubscriptionsAcknowledgedParams;
2023
import io.modelcontextprotocol.modern.server.feature.McpAsyncResourceRepository;
2124
import io.modelcontextprotocol.modern.server.feature.McpChangeFeed;
2225
import io.modelcontextprotocol.modern.server.feature.McpChangePublisher;
2326
import io.modelcontextprotocol.modern.server.feature.ResourcesFeature;
2427
import io.modelcontextprotocol.modern.server.feature.ResourcesPage;
2528
import io.modelcontextprotocol.modern.server.feature.ServerChange;
2629
import io.modelcontextprotocol.modern.server.feature.ToolsFeature;
27-
import io.modelcontextprotocol.spec.json.gson.GsonMcpJsonMapper;
2830
import org.junit.jupiter.api.Test;
2931
import reactor.core.publisher.Mono;
3032
import reactor.test.StepVerifier;
@@ -43,8 +45,7 @@ void ackIsFirstAndReflectsHonouredSubset() {
4345
McpChangeFeed feed = new McpChangeFeed();
4446
McpServer server = McpServer.builder()
4547
.serverInfo(SERVER_INFO)
46-
.jsonMapper(new GsonMcpJsonMapper())
47-
.feature(ToolsFeature.ofAsync(emptyTools(), new GsonMcpJsonMapper(), PERMISSIVE_VALIDATOR, 0L,
48+
.feature(ToolsFeature.ofAsync(emptyTools(), McpJsonDefaults.getMapper(), PERMISSIVE_VALIDATOR, 0L,
4849
CacheScope.PRIVATE))
4950
.subscriptions(feed)
5051
.build();
@@ -62,13 +63,9 @@ void ackIsFirstAndReflectsHonouredSubset() {
6263
StepVerifier.create(invocation.messages()).assertNext(msg -> {
6364
JSONRPCNotification ack = (JSONRPCNotification) msg;
6465
assertThat(ack.method()).isEqualTo(McpSchema.METHOD_NOTIFICATION_SUBSCRIPTIONS_ACKNOWLEDGED);
65-
@SuppressWarnings("unchecked")
66-
Map<String, Object> ackParams = (Map<String, Object>) new GsonMcpJsonMapper().convertValue(ack.params(),
67-
Map.class);
68-
@SuppressWarnings("unchecked")
69-
Map<String, Object> notifications = (Map<String, Object>) ackParams.get("notifications");
70-
assertThat(notifications.get("toolsListChanged")).isEqualTo(true);
71-
assertThat(notifications.get("promptsListChanged")).isNull();
66+
SubscriptionFilter notifications = ((SubscriptionsAcknowledgedParams) ack.params()).notifications();
67+
assertThat(notifications.toolsListChanged()).isTrue();
68+
assertThat(notifications.promptsListChanged()).isNull();
7269
})
7370
.then(() -> feed.broadcast(new ServerChange.ToolsListChanged()))
7471
.assertNext(msg -> assertThat(((JSONRPCNotification) msg).method())
@@ -84,8 +81,7 @@ void unrequestedTypeIsNeverEmitted() {
8481
McpChangeFeed feed = new McpChangeFeed();
8582
McpServer server = McpServer.builder()
8683
.serverInfo(SERVER_INFO)
87-
.jsonMapper(new GsonMcpJsonMapper())
88-
.feature(ToolsFeature.ofAsync(emptyTools(), new GsonMcpJsonMapper(), PERMISSIVE_VALIDATOR, 0L,
84+
.feature(ToolsFeature.ofAsync(emptyTools(), McpJsonDefaults.getMapper(), PERMISSIVE_VALIDATOR, 0L,
8985
CacheScope.PRIVATE))
9086
.subscriptions(feed)
9187
.build();
@@ -115,8 +111,7 @@ void subscriptionIdMatchesRequestId() {
115111
McpChangeFeed feed = new McpChangeFeed();
116112
McpServer server = McpServer.builder()
117113
.serverInfo(SERVER_INFO)
118-
.jsonMapper(new GsonMcpJsonMapper())
119-
.feature(ToolsFeature.ofAsync(emptyTools(), new GsonMcpJsonMapper(), PERMISSIVE_VALIDATOR, 0L,
114+
.feature(ToolsFeature.ofAsync(emptyTools(), McpJsonDefaults.getMapper(), PERMISSIVE_VALIDATOR, 0L,
120115
CacheScope.PRIVATE))
121116
.subscriptions(feed)
122117
.build();
@@ -131,7 +126,7 @@ void subscriptionIdMatchesRequestId() {
131126

132127
StepVerifier.create(invocation.messages()).assertNext(msg -> {
133128
JSONRPCNotification ack = (JSONRPCNotification) msg;
134-
assertThat(subscriptionIdOf(ack)).isEqualTo(42L);
129+
assertThat(subscriptionIdOf(ack)).isEqualTo(42);
135130
}).assertNext(msg -> assertThat(msg).isInstanceOf(JSONRPCResponse.class)).verifyComplete();
136131
}
137132

@@ -183,8 +178,8 @@ void resourceSubscribeIsAdvertisedAndHonouredWhenRepositorySupportsIt() {
183178

184179
assertThat(resourcesCapability(server)).containsEntry("subscribe", true).containsEntry("listChanged", true);
185180
StepVerifier.create(listenToResource(server).messages())
186-
.assertNext(msg -> assertThat(acknowledgedNotifications((JSONRPCNotification) msg))
187-
.containsEntry("resourceSubscriptions", List.of("test://a")))
181+
.assertNext(msg -> assertThat(acknowledgedNotifications((JSONRPCNotification) msg).resourceSubscriptions())
182+
.containsExactly("test://a"))
188183
.then(server::closeGracefully)
189184
.expectNextMatches(msg -> msg instanceof JSONRPCResponse)
190185
.verifyComplete();
@@ -196,8 +191,7 @@ void resourceSubscribeIsNeitherAdvertisedNorHonouredByDefault() {
196191

197192
assertThat(resourcesCapability(server)).containsEntry("subscribe", false).containsEntry("listChanged", true);
198193
StepVerifier.create(listenToResource(server).messages())
199-
.assertNext(msg -> assertThat(acknowledgedNotifications((JSONRPCNotification) msg))
200-
.extractingByKey("resourceSubscriptions")
194+
.assertNext(msg -> assertThat(acknowledgedNotifications((JSONRPCNotification) msg).resourceSubscriptions())
201195
.isNull())
202196
.then(server::closeGracefully)
203197
.expectNextMatches(msg -> msg instanceof JSONRPCResponse)
@@ -231,8 +225,7 @@ public boolean supportsSubscribe() {
231225
};
232226
McpServer.Builder builder = McpServer.builder()
233227
.serverInfo(SERVER_INFO)
234-
.jsonMapper(new GsonMcpJsonMapper())
235-
.feature(ResourcesFeature.ofAsync(repository, new GsonMcpJsonMapper(), 0L, CacheScope.PRIVATE));
228+
.feature(ResourcesFeature.ofAsync(repository, McpJsonDefaults.getMapper(), 0L, CacheScope.PRIVATE));
236229
if (publisher != null) {
237230
builder.subscriptions(publisher);
238231
}
@@ -255,19 +248,15 @@ private static McpTransportResponse.Streaming listenToResource(McpServer server)
255248
return (McpTransportResponse.Streaming) server.handle(McpTransportContext.EMPTY, request).block();
256249
}
257250

258-
@SuppressWarnings("unchecked")
259-
private static Map<String, Object> acknowledgedNotifications(JSONRPCNotification ack) {
251+
private static SubscriptionFilter acknowledgedNotifications(JSONRPCNotification ack) {
260252
assertThat(ack.method()).isEqualTo(McpSchema.METHOD_NOTIFICATION_SUBSCRIPTIONS_ACKNOWLEDGED);
261-
Map<String, Object> params = (Map<String, Object>) new GsonMcpJsonMapper().convertValue(ack.params(),
262-
Map.class);
263-
return (Map<String, Object>) params.get("notifications");
253+
return ((SubscriptionsAcknowledgedParams) ack.params()).notifications();
264254
}
265255

266256
private static McpServer toolsServer(McpChangePublisher publisher) {
267257
return McpServer.builder()
268258
.serverInfo(SERVER_INFO)
269-
.jsonMapper(new GsonMcpJsonMapper())
270-
.feature(ToolsFeature.ofAsync(emptyTools(), new GsonMcpJsonMapper(), PERMISSIVE_VALIDATOR, 0L,
259+
.feature(ToolsFeature.ofAsync(emptyTools(), McpJsonDefaults.getMapper(), PERMISSIVE_VALIDATOR, 0L,
271260
CacheScope.PRIVATE))
272261
.subscriptions(publisher)
273262
.build();
@@ -281,12 +270,8 @@ private static McpTransportResponse.Streaming listen(McpServer server, int id) {
281270
return (McpTransportResponse.Streaming) server.handle(McpTransportContext.EMPTY, request).block();
282271
}
283272

284-
@SuppressWarnings("unchecked")
285273
private static Object subscriptionIdOf(JSONRPCNotification notification) {
286-
Map<String, Object> params = (Map<String, Object>) new GsonMcpJsonMapper().convertValue(notification.params(),
287-
Map.class);
288-
Map<String, Object> meta = (Map<String, Object>) params.get("meta");
289-
return meta.get(MetaKeys.SUBSCRIPTION_ID);
274+
return ((SubscriptionsAcknowledgedParams) notification.params()).meta().get(MetaKeys.SUBSCRIPTION_ID);
290275
}
291276

292277
}

0 commit comments

Comments
 (0)