Skip to content

Commit 6b0a8ee

Browse files
committed
feat: remove JsonSchema an use a Map for inputSchema
1 parent f7a460f commit 6b0a8ee

15 files changed

+107
-245
lines changed

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpSchema.java

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,27 +1330,6 @@ public ListToolsResult(List<Tool> tools, String nextCursor) {
13301330
}
13311331
}
13321332

1333-
/**
1334-
* A JSON Schema object that describes the expected structure of arguments or output.
1335-
*
1336-
* @param type The type of the schema (e.g., "object")
1337-
* @param properties The properties of the schema object
1338-
* @param required List of required property names
1339-
* @param additionalProperties Whether additional properties are allowed
1340-
* @param defs Schema definitions using the newer $defs keyword
1341-
* @param definitions Schema definitions using the legacy definitions keyword
1342-
*/
1343-
@JsonInclude(JsonInclude.Include.NON_ABSENT)
1344-
@JsonIgnoreProperties(ignoreUnknown = true)
1345-
public record JsonSchema( // @formatter:off
1346-
@JsonProperty("type") String type,
1347-
@JsonProperty("properties") Map<String, Object> properties,
1348-
@JsonProperty("required") List<String> required,
1349-
@JsonProperty("additionalProperties") Boolean additionalProperties,
1350-
@JsonProperty("$defs") Map<String, Object> defs,
1351-
@JsonProperty("definitions") Map<String, Object> definitions) { // @formatter:on
1352-
}
1353-
13541333
/**
13551334
* Additional properties describing a Tool to clients.
13561335
*
@@ -1395,7 +1374,7 @@ public record Tool( // @formatter:off
13951374
@JsonProperty("name") String name,
13961375
@JsonProperty("title") String title,
13971376
@JsonProperty("description") String description,
1398-
@JsonProperty("inputSchema") JsonSchema inputSchema,
1377+
@JsonProperty("inputSchema") Map<String, Object> inputSchema,
13991378
@JsonProperty("outputSchema") Map<String, Object> outputSchema,
14001379
@JsonProperty("annotations") ToolAnnotations annotations,
14011380
@JsonProperty("_meta") Map<String, Object> meta) { // @formatter:on
@@ -1412,7 +1391,7 @@ public static class Builder {
14121391

14131392
private String description;
14141393

1415-
private JsonSchema inputSchema;
1394+
private Map<String, Object> inputSchema;
14161395

14171396
private Map<String, Object> outputSchema;
14181397

@@ -1435,13 +1414,13 @@ public Builder description(String description) {
14351414
return this;
14361415
}
14371416

1438-
public Builder inputSchema(JsonSchema inputSchema) {
1417+
public Builder inputSchema(Map<String, Object> inputSchema) {
14391418
this.inputSchema = inputSchema;
14401419
return this;
14411420
}
14421421

14431422
public Builder inputSchema(McpJsonMapper jsonMapper, String inputSchema) {
1444-
this.inputSchema = parseSchema(jsonMapper, inputSchema);
1423+
this.inputSchema = schemaToMap(jsonMapper, inputSchema);
14451424
return this;
14461425
}
14471426

@@ -1482,15 +1461,6 @@ private static Map<String, Object> schemaToMap(McpJsonMapper jsonMapper, String
14821461
}
14831462
}
14841463

1485-
private static JsonSchema parseSchema(McpJsonMapper jsonMapper, String schema) {
1486-
try {
1487-
return jsonMapper.readValue(schema, JsonSchema.class);
1488-
}
1489-
catch (IOException e) {
1490-
throw new IllegalArgumentException("Invalid schema: " + schema, e);
1491-
}
1492-
}
1493-
14941464
/**
14951465
* Used by the client to call a tool provided by the server.
14961466
*

mcp-core/src/test/java/io/modelcontextprotocol/client/McpAsyncClientTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,10 @@ private McpClientTransport createMockTransportForToolValidation(boolean hasOutpu
4444
Map<String, Object> inputSchemaMap = Map.of("type", "object", "properties",
4545
Map.of("expression", Map.of("type", "string")), "required", List.of("expression"));
4646

47-
McpSchema.JsonSchema inputSchema = new McpSchema.JsonSchema("object", inputSchemaMap, null, null, null, null);
4847
McpSchema.Tool.Builder toolBuilder = McpSchema.Tool.builder()
4948
.name("calculator")
5049
.description("Performs mathematical calculations")
51-
.inputSchema(inputSchema);
50+
.inputSchema(inputSchemaMap);
5251

5352
if (hasOutputSchema) {
5453
Map<String, Object> outputSchema = Map.of("type", "object", "properties",

mcp-core/src/test/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.time.Duration;
88
import java.util.List;
9+
import java.util.Map;
910

1011
import io.modelcontextprotocol.spec.McpSchema;
1112
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
@@ -23,7 +24,6 @@
2324
import reactor.core.publisher.Mono;
2425
import reactor.test.StepVerifier;
2526

26-
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
2727
import static org.assertj.core.api.Assertions.assertThat;
2828
import static org.assertj.core.api.Assertions.assertThatCode;
2929
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -94,11 +94,7 @@ void testImmediateClose() {
9494
@Test
9595
@Deprecated
9696
void testAddTool() {
97-
Tool newTool = McpSchema.Tool.builder()
98-
.name("new-tool")
99-
.title("New test tool")
100-
.inputSchema(EMPTY_JSON_SCHEMA)
101-
.build();
97+
Tool newTool = McpSchema.Tool.builder().name("new-tool").title("New test tool").inputSchema(Map.of()).build();
10298
var mcpAsyncServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
10399
.capabilities(ServerCapabilities.builder().tools(true).build())
104100
.build();
@@ -113,11 +109,7 @@ void testAddTool() {
113109

114110
@Test
115111
void testAddToolCall() {
116-
Tool newTool = McpSchema.Tool.builder()
117-
.name("new-tool")
118-
.title("New test tool")
119-
.inputSchema(EMPTY_JSON_SCHEMA)
120-
.build();
112+
Tool newTool = McpSchema.Tool.builder().name("new-tool").title("New test tool").inputSchema(Map.of()).build();
121113

122114
var mcpAsyncServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
123115
.capabilities(ServerCapabilities.builder().tools(true).build())
@@ -138,7 +130,7 @@ void testAddDuplicateTool() {
138130
Tool duplicateTool = McpSchema.Tool.builder()
139131
.name(TEST_TOOL_NAME)
140132
.title("Duplicate tool")
141-
.inputSchema(EMPTY_JSON_SCHEMA)
133+
.inputSchema(Map.of())
142134
.build();
143135

144136
var mcpAsyncServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
@@ -160,7 +152,7 @@ void testAddDuplicateToolCall() {
160152
Tool duplicateTool = McpSchema.Tool.builder()
161153
.name(TEST_TOOL_NAME)
162154
.title("Duplicate tool")
163-
.inputSchema(EMPTY_JSON_SCHEMA)
155+
.inputSchema(Map.of())
164156
.build();
165157

166158
var mcpAsyncServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
@@ -184,7 +176,7 @@ void testDuplicateToolCallDuringBuilding() {
184176
Tool duplicateTool = McpSchema.Tool.builder()
185177
.name("duplicate-build-toolcall")
186178
.title("Duplicate toolcall during building")
187-
.inputSchema(EMPTY_JSON_SCHEMA)
179+
.inputSchema(Map.of())
188180
.build();
189181

190182
assertThatThrownBy(() -> prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
@@ -204,7 +196,7 @@ void testDuplicateToolsInBatchListRegistration() {
204196
Tool duplicateTool = McpSchema.Tool.builder()
205197
.name("batch-list-tool")
206198
.title("Duplicate tool in batch list")
207-
.inputSchema(EMPTY_JSON_SCHEMA)
199+
.inputSchema(Map.of())
208200
.build();
209201

210202
List<McpServerFeatures.AsyncToolSpecification> specs = List.of(
@@ -232,7 +224,7 @@ void testDuplicateToolsInBatchVarargsRegistration() {
232224
Tool duplicateTool = McpSchema.Tool.builder()
233225
.name("batch-varargs-tool")
234226
.title("Duplicate tool in batch varargs")
235-
.inputSchema(EMPTY_JSON_SCHEMA)
227+
.inputSchema(Map.of())
236228
.build();
237229

238230
assertThatThrownBy(() -> prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
@@ -254,11 +246,7 @@ void testDuplicateToolsInBatchVarargsRegistration() {
254246

255247
@Test
256248
void testRemoveTool() {
257-
Tool too = McpSchema.Tool.builder()
258-
.name(TEST_TOOL_NAME)
259-
.title("Duplicate tool")
260-
.inputSchema(EMPTY_JSON_SCHEMA)
261-
.build();
249+
Tool too = McpSchema.Tool.builder().name(TEST_TOOL_NAME).title("Duplicate tool").inputSchema(Map.of()).build();
262250

263251
var mcpAsyncServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
264252
.capabilities(ServerCapabilities.builder().tools(true).build())
@@ -285,11 +273,7 @@ void testRemoveNonexistentTool() {
285273

286274
@Test
287275
void testNotifyToolsListChanged() {
288-
Tool too = McpSchema.Tool.builder()
289-
.name(TEST_TOOL_NAME)
290-
.title("Duplicate tool")
291-
.inputSchema(EMPTY_JSON_SCHEMA)
292-
.build();
276+
Tool too = McpSchema.Tool.builder().name(TEST_TOOL_NAME).title("Duplicate tool").inputSchema(Map.of()).build();
293277

294278
var mcpAsyncServer = prepareAsyncServerBuilder().serverInfo("test-server", "1.0.0")
295279
.capabilities(ServerCapabilities.builder().tools(true).build())

mcp-core/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
import reactor.core.publisher.Mono;
5252
import reactor.test.StepVerifier;
5353

54-
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
5554
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
5655
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.json;
5756
import static org.assertj.core.api.Assertions.assertThat;
@@ -103,7 +102,7 @@ void testCreateMessageWithoutSamplingCapabilities(String clientType) {
103102
var clientBuilder = clientBuilders.get(clientType);
104103

105104
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
106-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
105+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
107106
.callHandler((exchange, request) -> {
108107
return exchange.createMessage(mock(McpSchema.CreateMessageRequest.class))
109108
.then(Mono.just(mock(CallToolResult.class)));
@@ -153,7 +152,7 @@ void testCreateMessageSuccess(String clientType) {
153152
AtomicReference<CreateMessageResult> samplingResult = new AtomicReference<>();
154153

155154
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
156-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
155+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
157156
.callHandler((exchange, request) -> {
158157

159158
var createMessageRequest = McpSchema.CreateMessageRequest.builder()
@@ -232,7 +231,7 @@ void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws Interr
232231
AtomicReference<CreateMessageResult> samplingResult = new AtomicReference<>();
233232

234233
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
235-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
234+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
236235
.callHandler((exchange, request) -> {
237236

238237
var createMessageRequest = McpSchema.CreateMessageRequest.builder()
@@ -307,7 +306,7 @@ void testCreateMessageWithRequestTimeoutFail(String clientType) throws Interrupt
307306
.build();
308307

309308
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
310-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
309+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
311310
.callHandler((exchange, request) -> {
312311

313312
var createMessageRequest = McpSchema.CreateMessageRequest.builder()
@@ -357,7 +356,7 @@ void testCreateElicitationWithoutElicitationCapabilities(String clientType) {
357356
var clientBuilder = clientBuilders.get(clientType);
358357

359358
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
360-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
359+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
361360
.callHandler((exchange, request) -> exchange.createElicitation(mock(ElicitRequest.class))
362361
.then(Mono.just(mock(CallToolResult.class))))
363362
.build();
@@ -401,7 +400,7 @@ void testCreateElicitationSuccess(String clientType) {
401400
.build();
402401

403402
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
404-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
403+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
405404
.callHandler((exchange, request) -> {
406405

407406
var elicitationRequest = McpSchema.ElicitRequest.builder()
@@ -459,7 +458,7 @@ void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
459458
AtomicReference<ElicitResult> resultRef = new AtomicReference<>();
460459

461460
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
462-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
461+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
463462
.callHandler((exchange, request) -> {
464463

465464
var elicitationRequest = McpSchema.ElicitRequest.builder()
@@ -530,7 +529,7 @@ void testCreateElicitationWithRequestTimeoutFail(String clientType) {
530529
AtomicReference<ElicitResult> resultRef = new AtomicReference<>();
531530

532531
McpServerFeatures.AsyncToolSpecification tool = McpServerFeatures.AsyncToolSpecification.builder()
533-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
532+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
534533
.callHandler((exchange, request) -> {
535534

536535
var elicitationRequest = ElicitRequest.builder()
@@ -628,7 +627,7 @@ void testRootsWithoutCapability(String clientType) {
628627
var clientBuilder = clientBuilders.get(clientType);
629628

630629
McpServerFeatures.SyncToolSpecification tool = McpServerFeatures.SyncToolSpecification.builder()
631-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
630+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
632631
.callHandler((exchange, request) -> {
633632

634633
exchange.listRoots(); // try to list roots
@@ -770,7 +769,7 @@ void testToolCallSuccess(String clientType) {
770769
.addContent(new McpSchema.TextContent("CALL RESPONSE; ctx=importantValue"))
771770
.build();
772771
McpServerFeatures.SyncToolSpecification tool1 = McpServerFeatures.SyncToolSpecification.builder()
773-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
772+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
774773
.callHandler((exchange, request) -> {
775774

776775
try {
@@ -821,11 +820,7 @@ void testThrowingToolCallIsCaughtBeforeTimeout(String clientType) {
821820
McpSyncServer mcpServer = prepareSyncServerBuilder()
822821
.capabilities(ServerCapabilities.builder().tools(true).build())
823822
.tools(McpServerFeatures.SyncToolSpecification.builder()
824-
.tool(Tool.builder()
825-
.name("tool1")
826-
.description("tool1 description")
827-
.inputSchema(EMPTY_JSON_SCHEMA)
828-
.build())
823+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
829824
.callHandler((exchange, request) -> {
830825
// We trigger a timeout on blocking read, raising an exception
831826
Mono.never().block(Duration.ofSeconds(1));
@@ -863,7 +858,7 @@ void testToolCallSuccessWithTransportContextExtraction(String clientType) {
863858
.addContent(new McpSchema.TextContent("CALL RESPONSE; ctx=value"))
864859
.build();
865860
McpServerFeatures.SyncToolSpecification tool1 = McpServerFeatures.SyncToolSpecification.builder()
866-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
861+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
867862
.callHandler((exchange, request) -> {
868863

869864
McpTransportContext transportContext = exchange.transportContext();
@@ -919,7 +914,7 @@ void testToolListChangeHandlingSuccess(String clientType) {
919914
.build();
920915

921916
McpServerFeatures.SyncToolSpecification tool1 = McpServerFeatures.SyncToolSpecification.builder()
922-
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build())
917+
.tool(Tool.builder().name("tool1").description("tool1 description").inputSchema(Map.of()).build())
923918
.callHandler((exchange, request) -> {
924919
// perform a blocking call to a remote service
925920
try {
@@ -985,11 +980,7 @@ void testToolListChangeHandlingSuccess(String clientType) {
985980

986981
// Add a new tool
987982
McpServerFeatures.SyncToolSpecification tool2 = McpServerFeatures.SyncToolSpecification.builder()
988-
.tool(Tool.builder()
989-
.name("tool2")
990-
.description("tool2 description")
991-
.inputSchema(EMPTY_JSON_SCHEMA)
992-
.build())
983+
.tool(Tool.builder().name("tool2").description("tool2 description").inputSchema(Map.of()).build())
993984
.callHandler((exchange, request) -> callResponse)
994985
.build();
995986

@@ -1040,7 +1031,7 @@ void testLoggingNotification(String clientType) throws InterruptedException {
10401031
.tool(Tool.builder()
10411032
.name("logging-test")
10421033
.description("Test logging notifications")
1043-
.inputSchema(EMPTY_JSON_SCHEMA)
1034+
.inputSchema(Map.of())
10441035
.build())
10451036
.callHandler((exchange, request) -> {
10461037

@@ -1157,7 +1148,7 @@ void testProgressNotification(String clientType) throws InterruptedException {
11571148
.tool(McpSchema.Tool.builder()
11581149
.name("progress-test")
11591150
.description("Test progress notifications")
1160-
.inputSchema(EMPTY_JSON_SCHEMA)
1151+
.inputSchema(Map.of())
11611152
.build())
11621153
.callHandler((exchange, request) -> {
11631154

@@ -1315,7 +1306,7 @@ void testPingSuccess(String clientType) {
13151306
.tool(Tool.builder()
13161307
.name("ping-async-test")
13171308
.description("Test ping async behavior")
1318-
.inputSchema(EMPTY_JSON_SCHEMA)
1309+
.inputSchema(Map.of())
13191310
.build())
13201311
.callHandler((exchange, request) -> {
13211312

0 commit comments

Comments
 (0)