Skip to content

Commit 8d1f63e

Browse files
committed
Remaining required fields
Signed-off-by: Dariusz Jędrzejczyk <2554306+chemicL@users.noreply.github.com>
1 parent c47f9c9 commit 8d1f63e

8 files changed

Lines changed: 662 additions & 21 deletions

File tree

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

Lines changed: 625 additions & 3 deletions
Large diffs are not rendered by default.

mcp-core/src/main/java/io/modelcontextprotocol/util/ToolInputValidator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private ToolInputValidator() {
3636
*/
3737
public static CallToolResult validate(McpSchema.Tool tool, Map<String, Object> arguments,
3838
boolean validateToolInputs, JsonSchemaValidator validator) {
39-
if (!validateToolInputs || tool.inputSchema() == null || validator == null) {
39+
if (!validateToolInputs || tool.inputSchema() == null || tool.inputSchema().isEmpty() || validator == null) {
4040
return null;
4141
}
4242
Map<String, Object> args = arguments != null ? arguments : Map.of();

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ void tearDown() {
193193

194194
@Test
195195
void defaultShouldThrowOnInvalidName() {
196-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
196+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
197197

198198
assertThatThrownBy(
199199
() -> McpServer.async(transportProvider).toolCall(invalidTool, (exchange, request) -> null))
@@ -204,7 +204,7 @@ void defaultShouldThrowOnInvalidName() {
204204
@Test
205205
void lenientDefaultShouldLogOnInvalidName() {
206206
System.setProperty(ToolNameValidator.STRICT_VALIDATION_PROPERTY, "false");
207-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
207+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
208208

209209
assertThatCode(() -> McpServer.async(transportProvider).toolCall(invalidTool, (exchange, request) -> null))
210210
.doesNotThrowAnyException();
@@ -213,7 +213,7 @@ void lenientDefaultShouldLogOnInvalidName() {
213213

214214
@Test
215215
void lenientConfigurationShouldLogOnInvalidName() {
216-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
216+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
217217

218218
assertThatCode(() -> McpServer.async(transportProvider)
219219
.strictToolNameValidation(false)
@@ -224,7 +224,7 @@ void lenientConfigurationShouldLogOnInvalidName() {
224224
@Test
225225
void serverConfigurationShouldOverrideDefault() {
226226
System.setProperty(ToolNameValidator.STRICT_VALIDATION_PROPERTY, "false");
227-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
227+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
228228

229229
assertThatThrownBy(() -> McpServer.async(transportProvider)
230230
.strictToolNameValidation(true)

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ void tearDown() {
138138

139139
@Test
140140
void defaultShouldThrowOnInvalidName() {
141-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
141+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
142142

143143
assertThatThrownBy(
144144
() -> McpServer.sync(transportProvider).toolCall(invalidTool, (exchange, request) -> null))
@@ -149,7 +149,7 @@ void defaultShouldThrowOnInvalidName() {
149149
@Test
150150
void lenientDefaultShouldLogOnInvalidName() {
151151
System.setProperty(ToolNameValidator.STRICT_VALIDATION_PROPERTY, "false");
152-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
152+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
153153

154154
assertThatCode(() -> McpServer.sync(transportProvider).toolCall(invalidTool, (exchange, request) -> null))
155155
.doesNotThrowAnyException();
@@ -158,7 +158,7 @@ void lenientDefaultShouldLogOnInvalidName() {
158158

159159
@Test
160160
void lenientConfigurationShouldLogOnInvalidName() {
161-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
161+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
162162

163163
assertThatCode(() -> McpServer.sync(transportProvider)
164164
.strictToolNameValidation(false)
@@ -169,7 +169,7 @@ void lenientConfigurationShouldLogOnInvalidName() {
169169
@Test
170170
void serverConfigurationShouldOverrideDefault() {
171171
System.setProperty(ToolNameValidator.STRICT_VALIDATION_PROPERTY, "false");
172-
Tool invalidTool = Tool.builder().name("invalid tool name").build();
172+
Tool invalidTool = Tool.builder().name("invalid tool name").inputSchema(EMPTY_JSON_SCHEMA).build();
173173

174174
assertThatThrownBy(() -> McpServer.sync(transportProvider)
175175
.strictToolNameValidation(true)

mcp-core/src/test/java/io/modelcontextprotocol/util/ToolInputValidatorTests.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616

1717
import static org.assertj.core.api.Assertions.assertThat;
1818
import static org.mockito.ArgumentMatchers.any;
19-
import static org.mockito.Mockito.mock;
20-
import static org.mockito.Mockito.never;
21-
import static org.mockito.Mockito.verify;
22-
import static org.mockito.Mockito.when;
19+
import static org.mockito.Mockito.*;
2320

2421
/**
2522
* Tests for {@link ToolInputValidator}.
@@ -39,7 +36,10 @@ class ToolInputValidatorTests {
3936
.inputSchema(inputSchema)
4037
.build();
4138

42-
private final Tool toolWithoutSchema = Tool.builder().name("test-tool").description("Test tool").build();
39+
private final Tool toolWithoutSchema = Tool.builder()
40+
.name("test-tool")
41+
.description("Test tool")
42+
.build();
4343

4444
@Test
4545
void validate_whenDisabled_returnsNull() {
@@ -51,10 +51,12 @@ void validate_whenDisabled_returnsNull() {
5151

5252
@Test
5353
void validate_whenNoSchema_returnsNull() {
54+
when(validator.validate(any(), any())).thenReturn(ValidationResponse.asValid(null));
55+
5456
CallToolResult result = ToolInputValidator.validate(toolWithoutSchema, Map.of("name", "test"), true, validator);
5557

5658
assertThat(result).isNull();
57-
verify(validator, never()).validate(any(), any());
59+
verify(validator).validate(any(), any());
5860
}
5961

6062
@Test

mcp-test/src/test/java/io/modelcontextprotocol/server/McpServerProtocolVersionTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class McpServerProtocolVersionTests {
2626

2727
private McpSchema.JSONRPCRequest jsonRpcInitializeRequest(String requestId, String protocolVersion) {
2828
return new McpSchema.JSONRPCRequest(McpSchema.JSONRPC_VERSION, McpSchema.METHOD_INITIALIZE, requestId,
29-
new McpSchema.InitializeRequest(protocolVersion, null, CLIENT_INFO));
29+
new McpSchema.InitializeRequest(protocolVersion, McpSchema.ClientCapabilities.builder().build(),
30+
CLIENT_INFO));
3031
}
3132

3233
@Test

mcp-test/src/test/java/io/modelcontextprotocol/server/ResourceSubscriptionTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ private static McpAsyncServer buildServer(MockMcpServerTransportProvider transpo
3737

3838
private static McpSchema.JSONRPCRequest initRequest() {
3939
return new McpSchema.JSONRPCRequest(McpSchema.JSONRPC_VERSION, McpSchema.METHOD_INITIALIZE,
40-
UUID.randomUUID().toString(),
41-
new McpSchema.InitializeRequest(ProtocolVersions.MCP_2025_11_25, null, CLIENT_INFO));
40+
UUID.randomUUID().toString(), new McpSchema.InitializeRequest(ProtocolVersions.MCP_2025_11_25,
41+
McpSchema.ClientCapabilities.builder().build(), CLIENT_INFO));
4242
}
4343

4444
private static McpSchema.JSONRPCNotification initializedNotification() {

mcp-test/src/test/java/io/modelcontextprotocol/spec/CompleteReferenceJsonTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
import static io.modelcontextprotocol.util.McpJsonMapperUtils.JSON_MAPPER;
88
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
99
import static org.assertj.core.api.Assertions.assertThat;
10+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
1011

1112
import java.io.IOException;
1213

1314
import io.modelcontextprotocol.json.McpJsonMapper;
1415
import io.modelcontextprotocol.json.TypeRef;
1516
import org.junit.jupiter.api.Test;
17+
import tools.jackson.databind.exc.ValueInstantiationException;
1618

1719
/**
1820
* Verifies that {@link McpSchema.CompleteReference} polymorphic dispatch works via direct
@@ -82,6 +84,20 @@ void completeRequestConvertValueFromMapDispatchesPromptRef() throws IOException
8284
assertThat(req.ref().identifier()).isEqualTo("my-prompt");
8385
}
8486

87+
@Test
88+
void completeRequestMissingRefFailsToInstantiate() throws IOException {
89+
String json = """
90+
{"argument":{"name":"lang","value":"java"}}
91+
""";
92+
93+
// This is the real in-process path: params arrives as a Map from JSON-RPC
94+
Object paramsMap = mapper.readValue(json, Object.class);
95+
96+
assertThatThrownBy(() -> mapper.convertValue(paramsMap, new TypeRef<McpSchema.CompleteRequest>() {
97+
})).isInstanceOf(ValueInstantiationException.class).hasMessageContaining("ref must not be null");
98+
99+
}
100+
85101
@Test
86102
void typeDiscriminatorAppearsExactlyOnce() throws IOException {
87103
McpSchema.PromptReference ref = new McpSchema.PromptReference("p");

0 commit comments

Comments
 (0)