diff --git a/mcp/pom.xml b/mcp/pom.xml
index 2bd3e9d..2170ffe 100644
--- a/mcp/pom.xml
+++ b/mcp/pom.xml
@@ -11,7 +11,7 @@
mcp
jar
Java MCP SDK
- Java SDK implementation of the Model Context Protocol, enabling seamless integration with language models and AI tools
+ Java SDK implementation of the Model Context Protocol, enabling seamless integration with language models and AI tools
https://github.com/modelcontextprotocol/java-sdk
@@ -51,7 +51,7 @@
-
+
org.apache.maven.plugins
maven-jar-plugin
@@ -158,12 +158,20 @@
test
+
+ net.javacrumbs.json-unit
+ json-unit-assertj
+ ${json-unit-assertj.version}
+ test
+
+
+
jakarta.servlet
jakarta.servlet-api
${jakarta.servlet.version}
- provided
+ provided
@@ -183,4 +191,4 @@
-
+
\ No newline at end of file
diff --git a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java
index e721468..3ce2068 100644
--- a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java
+++ b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java
@@ -964,7 +964,18 @@ public record CompleteCompletion(// @formatter:off
@JsonSubTypes.Type(value = EmbeddedResource.class, name = "resource") })
public sealed interface Content permits TextContent, ImageContent, EmbeddedResource {
- String type();
+ default String type() {
+ if (this instanceof TextContent) {
+ return "text";
+ }
+ else if (this instanceof ImageContent) {
+ return "image";
+ }
+ else if (this instanceof EmbeddedResource) {
+ return "resource";
+ }
+ throw new IllegalArgumentException("Unknown content type: " + this);
+ }
}
@@ -972,19 +983,10 @@ public sealed interface Content permits TextContent, ImageContent, EmbeddedResou
public record TextContent( // @formatter:off
@JsonProperty("audience") List audience,
@JsonProperty("priority") Double priority,
- @JsonProperty("type") String type,
@JsonProperty("text") String text) implements Content { // @formatter:on
- public TextContent {
- type = "text";
- }
-
- public String type() {
- return type;
- }
-
public TextContent(String content) {
- this(null, null, "text", content);
+ this(null, null, content);
}
}
@@ -992,33 +994,15 @@ public TextContent(String content) {
public record ImageContent( // @formatter:off
@JsonProperty("audience") List audience,
@JsonProperty("priority") Double priority,
- @JsonProperty("type") String type,
@JsonProperty("data") String data,
@JsonProperty("mimeType") String mimeType) implements Content { // @formatter:on
-
- public ImageContent {
- type = "image";
- }
-
- public String type() {
- return type;
- }
}
@JsonInclude(JsonInclude.Include.NON_ABSENT)
public record EmbeddedResource( // @formatter:off
@JsonProperty("audience") List audience,
@JsonProperty("priority") Double priority,
- @JsonProperty("type") String type,
@JsonProperty("resource") ResourceContents resource) implements Content { // @formatter:on
-
- public EmbeddedResource {
- type = "resource";
- }
-
- public String type() {
- return type;
- }
}
// ---------------------------
diff --git a/mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java b/mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java
new file mode 100644
index 0000000..05e2ce2
--- /dev/null
+++ b/mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java
@@ -0,0 +1,592 @@
+/*
+* Copyright 2025 - 2025 the original author or authors.
+*/
+package io.modelcontextprotocol.spec;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
+import io.modelcontextprotocol.spec.McpSchema.TextResourceContents;
+import net.javacrumbs.jsonunit.core.Option;
+import org.junit.jupiter.api.Test;
+
+import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
+import static net.javacrumbs.jsonunit.assertj.JsonAssertions.json;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/**
+ * @author Christian Tzolov
+ */
+public class McpSchemaTests {
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ // Content Types Tests
+
+ @Test
+ void testTextContent() throws Exception {
+ McpSchema.TextContent test = new McpSchema.TextContent("XXX");
+ String value = mapper.writeValueAsString(test);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"type":"text","text":"XXX"}"""));
+ }
+
+ @Test
+ void testTextContentDeserialization() throws Exception {
+ McpSchema.TextContent textContent = mapper.readValue("""
+ {"type":"text","text":"XXX"}""", McpSchema.TextContent.class);
+
+ assertThat(textContent).isNotNull();
+ assertThat(textContent.type()).isEqualTo("text");
+ assertThat(textContent.text()).isEqualTo("XXX");
+ }
+
+ @Test
+ void testContentDeserializationWrongType() throws Exception {
+
+ assertThatThrownBy(() -> mapper.readValue("""
+ {"type":"WRONG","text":"XXX"}""", McpSchema.TextContent.class))
+ .isInstanceOf(InvalidTypeIdException.class)
+ .hasMessageContaining(
+ "Could not resolve type id 'WRONG' as a subtype of `io.modelcontextprotocol.spec.McpSchema$TextContent`: known type ids = [image, resource, text]");
+ }
+
+ @Test
+ void testImageContent() throws Exception {
+ McpSchema.ImageContent test = new McpSchema.ImageContent(null, null, "base64encodeddata", "image/png");
+ String value = mapper.writeValueAsString(test);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"type":"image","data":"base64encodeddata","mimeType":"image/png"}"""));
+ }
+
+ @Test
+ void testImageContentDeserialization() throws Exception {
+ McpSchema.ImageContent imageContent = mapper.readValue("""
+ {"type":"image","data":"base64encodeddata","mimeType":"image/png"}""", McpSchema.ImageContent.class);
+ assertThat(imageContent).isNotNull();
+ assertThat(imageContent.type()).isEqualTo("image");
+ assertThat(imageContent.data()).isEqualTo("base64encodeddata");
+ assertThat(imageContent.mimeType()).isEqualTo("image/png");
+ }
+
+ @Test
+ void testEmbeddedResource() throws Exception {
+ McpSchema.TextResourceContents resourceContents = new McpSchema.TextResourceContents("resource://test",
+ "text/plain", "Sample resource content");
+
+ McpSchema.EmbeddedResource test = new McpSchema.EmbeddedResource(null, null, resourceContents);
+
+ String value = mapper.writeValueAsString(test);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"type":"resource","resource":{"uri":"resource://test","mimeType":"text/plain","text":"Sample resource content"}}"""));
+ }
+
+ @Test
+ void testEmbeddedResourceDeserialization() throws Exception {
+ McpSchema.EmbeddedResource embeddedResource = mapper.readValue(
+ """
+ {"type":"resource","resource":{"uri":"resource://test","mimeType":"text/plain","text":"Sample resource content"}}""",
+ McpSchema.EmbeddedResource.class);
+ assertThat(embeddedResource).isNotNull();
+ assertThat(embeddedResource.type()).isEqualTo("resource");
+ assertThat(embeddedResource.resource()).isNotNull();
+ assertThat(embeddedResource.resource().uri()).isEqualTo("resource://test");
+ assertThat(embeddedResource.resource().mimeType()).isEqualTo("text/plain");
+ assertThat(((TextResourceContents) embeddedResource.resource()).text()).isEqualTo("Sample resource content");
+ }
+
+ @Test
+ void testEmbeddedResourceWithBlobContents() throws Exception {
+ McpSchema.BlobResourceContents resourceContents = new McpSchema.BlobResourceContents("resource://test",
+ "application/octet-stream", "base64encodedblob");
+
+ McpSchema.EmbeddedResource test = new McpSchema.EmbeddedResource(null, null, resourceContents);
+
+ String value = mapper.writeValueAsString(test);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"type":"resource","resource":{"uri":"resource://test","mimeType":"application/octet-stream","blob":"base64encodedblob"}}"""));
+ }
+
+ @Test
+ void testEmbeddedResourceWithBlobContentsDeserialization() throws Exception {
+ McpSchema.EmbeddedResource embeddedResource = mapper.readValue(
+ """
+ {"type":"resource","resource":{"uri":"resource://test","mimeType":"application/octet-stream","blob":"base64encodedblob"}}""",
+ McpSchema.EmbeddedResource.class);
+ assertThat(embeddedResource).isNotNull();
+ assertThat(embeddedResource.type()).isEqualTo("resource");
+ assertThat(embeddedResource.resource()).isNotNull();
+ assertThat(embeddedResource.resource().uri()).isEqualTo("resource://test");
+ assertThat(embeddedResource.resource().mimeType()).isEqualTo("application/octet-stream");
+ assertThat(((McpSchema.BlobResourceContents) embeddedResource.resource()).blob())
+ .isEqualTo("base64encodedblob");
+ }
+
+ // JSON-RPC Message Types Tests
+
+ @Test
+ void testJSONRPCRequest() throws Exception {
+ Map params = new HashMap<>();
+ params.put("key", "value");
+
+ McpSchema.JSONRPCRequest request = new McpSchema.JSONRPCRequest(McpSchema.JSONRPC_VERSION, "method_name", 1,
+ params);
+
+ String value = mapper.writeValueAsString(request);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"jsonrpc":"2.0","method":"method_name","id":1,"params":{"key":"value"}}"""));
+ }
+
+ @Test
+ void testJSONRPCNotification() throws Exception {
+ Map params = new HashMap<>();
+ params.put("key", "value");
+
+ McpSchema.JSONRPCNotification notification = new McpSchema.JSONRPCNotification(McpSchema.JSONRPC_VERSION,
+ "notification_method", params);
+
+ String value = mapper.writeValueAsString(notification);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"jsonrpc":"2.0","method":"notification_method","params":{"key":"value"}}"""));
+ }
+
+ @Test
+ void testJSONRPCResponse() throws Exception {
+ Map result = new HashMap<>();
+ result.put("result_key", "result_value");
+
+ McpSchema.JSONRPCResponse response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, 1, result, null);
+
+ String value = mapper.writeValueAsString(response);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"jsonrpc":"2.0","id":1,"result":{"result_key":"result_value"}}"""));
+ }
+
+ @Test
+ void testJSONRPCResponseWithError() throws Exception {
+ McpSchema.JSONRPCResponse.JSONRPCError error = new McpSchema.JSONRPCResponse.JSONRPCError(
+ McpSchema.ErrorCodes.INVALID_REQUEST, "Invalid request", null);
+
+ McpSchema.JSONRPCResponse response = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, 1, null, error);
+
+ String value = mapper.writeValueAsString(response);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"jsonrpc":"2.0","id":1,"error":{"code":-32600,"message":"Invalid request"}}"""));
+ }
+
+ // Initialization Tests
+
+ @Test
+ void testInitializeRequest() throws Exception {
+ McpSchema.ClientCapabilities capabilities = McpSchema.ClientCapabilities.builder()
+ .roots(true)
+ .sampling()
+ .build();
+
+ McpSchema.Implementation clientInfo = new McpSchema.Implementation("test-client", "1.0.0");
+
+ McpSchema.InitializeRequest request = new McpSchema.InitializeRequest("2024-11-05", capabilities, clientInfo);
+
+ String value = mapper.writeValueAsString(request);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"protocolVersion":"2024-11-05","capabilities":{"roots":{"listChanged":true},"sampling":{}},"clientInfo":{"name":"test-client","version":"1.0.0"}}"""));
+ }
+
+ @Test
+ void testInitializeResult() throws Exception {
+ McpSchema.ServerCapabilities capabilities = McpSchema.ServerCapabilities.builder()
+ .logging()
+ .prompts(true)
+ .resources(true, true)
+ .tools(true)
+ .build();
+
+ McpSchema.Implementation serverInfo = new McpSchema.Implementation("test-server", "1.0.0");
+
+ McpSchema.InitializeResult result = new McpSchema.InitializeResult("2024-11-05", capabilities, serverInfo,
+ "Server initialized successfully");
+
+ String value = mapper.writeValueAsString(result);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"protocolVersion":"2024-11-05","capabilities":{"logging":{},"prompts":{"listChanged":true},"resources":{"subscribe":true,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"test-server","version":"1.0.0"},"instructions":"Server initialized successfully"}"""));
+ }
+
+ // Resource Tests
+
+ @Test
+ void testResource() throws Exception {
+ McpSchema.Annotations annotations = new McpSchema.Annotations(
+ Arrays.asList(McpSchema.Role.USER, McpSchema.Role.ASSISTANT), 0.8);
+
+ McpSchema.Resource resource = new McpSchema.Resource("resource://test", "Test Resource", "A test resource",
+ "text/plain", annotations);
+
+ String value = mapper.writeValueAsString(resource);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"uri":"resource://test","name":"Test Resource","description":"A test resource","mimeType":"text/plain","annotations":{"audience":["user","assistant"],"priority":0.8}}"""));
+ }
+
+ @Test
+ void testResourceTemplate() throws Exception {
+ McpSchema.Annotations annotations = new McpSchema.Annotations(Arrays.asList(McpSchema.Role.USER), 0.5);
+
+ McpSchema.ResourceTemplate template = new McpSchema.ResourceTemplate("resource://{param}/test", "Test Template",
+ "A test resource template", "text/plain", annotations);
+
+ String value = mapper.writeValueAsString(template);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"uriTemplate":"resource://{param}/test","name":"Test Template","description":"A test resource template","mimeType":"text/plain","annotations":{"audience":["user"],"priority":0.5}}"""));
+ }
+
+ @Test
+ void testListResourcesResult() throws Exception {
+ McpSchema.Resource resource1 = new McpSchema.Resource("resource://test1", "Test Resource 1",
+ "First test resource", "text/plain", null);
+
+ McpSchema.Resource resource2 = new McpSchema.Resource("resource://test2", "Test Resource 2",
+ "Second test resource", "application/json", null);
+
+ McpSchema.ListResourcesResult result = new McpSchema.ListResourcesResult(Arrays.asList(resource1, resource2),
+ "next-cursor");
+
+ String value = mapper.writeValueAsString(result);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"resources":[{"uri":"resource://test1","name":"Test Resource 1","description":"First test resource","mimeType":"text/plain"},{"uri":"resource://test2","name":"Test Resource 2","description":"Second test resource","mimeType":"application/json"}],"nextCursor":"next-cursor"}"""));
+ }
+
+ @Test
+ void testListResourceTemplatesResult() throws Exception {
+ McpSchema.ResourceTemplate template1 = new McpSchema.ResourceTemplate("resource://{param}/test1",
+ "Test Template 1", "First test template", "text/plain", null);
+
+ McpSchema.ResourceTemplate template2 = new McpSchema.ResourceTemplate("resource://{param}/test2",
+ "Test Template 2", "Second test template", "application/json", null);
+
+ McpSchema.ListResourceTemplatesResult result = new McpSchema.ListResourceTemplatesResult(
+ Arrays.asList(template1, template2), "next-cursor");
+
+ String value = mapper.writeValueAsString(result);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"resourceTemplates":[{"uriTemplate":"resource://{param}/test1","name":"Test Template 1","description":"First test template","mimeType":"text/plain"},{"uriTemplate":"resource://{param}/test2","name":"Test Template 2","description":"Second test template","mimeType":"application/json"}],"nextCursor":"next-cursor"}"""));
+ }
+
+ @Test
+ void testReadResourceRequest() throws Exception {
+ McpSchema.ReadResourceRequest request = new McpSchema.ReadResourceRequest("resource://test");
+
+ String value = mapper.writeValueAsString(request);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"uri":"resource://test"}"""));
+ }
+
+ @Test
+ void testReadResourceResult() throws Exception {
+ McpSchema.TextResourceContents contents1 = new McpSchema.TextResourceContents("resource://test1", "text/plain",
+ "Sample text content");
+
+ McpSchema.BlobResourceContents contents2 = new McpSchema.BlobResourceContents("resource://test2",
+ "application/octet-stream", "base64encodedblob");
+
+ McpSchema.ReadResourceResult result = new McpSchema.ReadResourceResult(Arrays.asList(contents1, contents2));
+
+ String value = mapper.writeValueAsString(result);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"contents":[{"uri":"resource://test1","mimeType":"text/plain","text":"Sample text content"},{"uri":"resource://test2","mimeType":"application/octet-stream","blob":"base64encodedblob"}]}"""));
+ }
+
+ // Prompt Tests
+
+ @Test
+ void testPrompt() throws Exception {
+ McpSchema.PromptArgument arg1 = new McpSchema.PromptArgument("arg1", "First argument", true);
+
+ McpSchema.PromptArgument arg2 = new McpSchema.PromptArgument("arg2", "Second argument", false);
+
+ McpSchema.Prompt prompt = new McpSchema.Prompt("test-prompt", "A test prompt", Arrays.asList(arg1, arg2));
+
+ String value = mapper.writeValueAsString(prompt);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"name":"test-prompt","description":"A test prompt","arguments":[{"name":"arg1","description":"First argument","required":true},{"name":"arg2","description":"Second argument","required":false}]}"""));
+ }
+
+ @Test
+ void testPromptMessage() throws Exception {
+ McpSchema.TextContent content = new McpSchema.TextContent("Hello, world!");
+
+ McpSchema.PromptMessage message = new McpSchema.PromptMessage(McpSchema.Role.USER, content);
+
+ String value = mapper.writeValueAsString(message);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"role":"user","content":{"type":"text","text":"Hello, world!"}}"""));
+ }
+
+ @Test
+ void testListPromptsResult() throws Exception {
+ McpSchema.PromptArgument arg = new McpSchema.PromptArgument("arg", "An argument", true);
+
+ McpSchema.Prompt prompt1 = new McpSchema.Prompt("prompt1", "First prompt", Collections.singletonList(arg));
+
+ McpSchema.Prompt prompt2 = new McpSchema.Prompt("prompt2", "Second prompt", Collections.emptyList());
+
+ McpSchema.ListPromptsResult result = new McpSchema.ListPromptsResult(Arrays.asList(prompt1, prompt2),
+ "next-cursor");
+
+ String value = mapper.writeValueAsString(result);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"prompts":[{"name":"prompt1","description":"First prompt","arguments":[{"name":"arg","description":"An argument","required":true}]},{"name":"prompt2","description":"Second prompt","arguments":[]}],"nextCursor":"next-cursor"}"""));
+ }
+
+ @Test
+ void testGetPromptRequest() throws Exception {
+ Map arguments = new HashMap<>();
+ arguments.put("arg1", "value1");
+ arguments.put("arg2", 42);
+
+ McpSchema.GetPromptRequest request = new McpSchema.GetPromptRequest("test-prompt", arguments);
+
+ assertThat(mapper.readValue("""
+ {"name":"test-prompt","arguments":{"arg1":"value1","arg2":42}}""", McpSchema.GetPromptRequest.class))
+ .isEqualTo(request);
+ }
+
+ @Test
+ void testGetPromptResult() throws Exception {
+ McpSchema.TextContent content1 = new McpSchema.TextContent("System message");
+ McpSchema.TextContent content2 = new McpSchema.TextContent("User message");
+
+ McpSchema.PromptMessage message1 = new McpSchema.PromptMessage(McpSchema.Role.ASSISTANT, content1);
+
+ McpSchema.PromptMessage message2 = new McpSchema.PromptMessage(McpSchema.Role.USER, content2);
+
+ McpSchema.GetPromptResult result = new McpSchema.GetPromptResult("A test prompt result",
+ Arrays.asList(message1, message2));
+
+ String value = mapper.writeValueAsString(result);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"description":"A test prompt result","messages":[{"role":"assistant","content":{"type":"text","text":"System message"}},{"role":"user","content":{"type":"text","text":"User message"}}]}"""));
+ }
+
+ // Tool Tests
+
+ @Test
+ void testTool() throws Exception {
+ String schemaJson = """
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "number"
+ }
+ },
+ "required": ["name"]
+ }
+ """;
+
+ McpSchema.Tool tool = new McpSchema.Tool("test-tool", "A test tool", schemaJson);
+
+ String value = mapper.writeValueAsString(tool);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"name":"test-tool","description":"A test tool","inputSchema":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"number"}},"required":["name"]}}"""));
+ }
+
+ @Test
+ void testCallToolRequest() throws Exception {
+ Map arguments = new HashMap<>();
+ arguments.put("name", "test");
+ arguments.put("value", 42);
+
+ McpSchema.CallToolRequest request = new McpSchema.CallToolRequest("test-tool", arguments);
+
+ String value = mapper.writeValueAsString(request);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"name":"test-tool","arguments":{"name":"test","value":42}}"""));
+ }
+
+ @Test
+ void testCallToolResult() throws Exception {
+ McpSchema.TextContent content = new McpSchema.TextContent("Tool execution result");
+
+ McpSchema.CallToolResult result = new McpSchema.CallToolResult(Collections.singletonList(content), false);
+
+ String value = mapper.writeValueAsString(result);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"content":[{"type":"text","text":"Tool execution result"}],"isError":false}"""));
+ }
+
+ // Sampling Tests
+
+ @Test
+ void testCreateMessageRequest() throws Exception {
+ McpSchema.TextContent content = new McpSchema.TextContent("User message");
+
+ McpSchema.SamplingMessage message = new McpSchema.SamplingMessage(McpSchema.Role.USER, content);
+
+ McpSchema.ModelHint hint = new McpSchema.ModelHint("gpt-4");
+
+ McpSchema.ModelPreferences preferences = new McpSchema.ModelPreferences(Collections.singletonList(hint), 0.3,
+ 0.7, 0.9);
+
+ Map metadata = new HashMap<>();
+ metadata.put("session", "test-session");
+
+ McpSchema.CreateMessageRequest request = new McpSchema.CreateMessageRequest(Collections.singletonList(message),
+ preferences, "You are a helpful assistant",
+ McpSchema.CreateMessageRequest.ContextInclusionStrategy.THIS_SERVER, 0.7, 1000,
+ Arrays.asList("STOP", "END"), metadata);
+
+ String value = mapper.writeValueAsString(request);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"messages":[{"role":"user","content":{"type":"text","text":"User message"}}],"modelPreferences":{"hints":[{"name":"gpt-4"}],"costPriority":0.3,"speedPriority":0.7,"intelligencePriority":0.9},"systemPrompt":"You are a helpful assistant","includeContext":"this_server","temperature":0.7,"maxTokens":1000,"stopSequences":["STOP","END"],"metadata":{"session":"test-session"}}"""));
+ }
+
+ @Test
+ void testCreateMessageResult() throws Exception {
+ McpSchema.TextContent content = new McpSchema.TextContent("Assistant response");
+
+ McpSchema.CreateMessageResult result = new McpSchema.CreateMessageResult(McpSchema.Role.ASSISTANT, content,
+ "gpt-4", McpSchema.CreateMessageResult.StopReason.END_TURN);
+
+ String value = mapper.writeValueAsString(result);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"role":"assistant","content":{"type":"text","text":"Assistant response"},"model":"gpt-4","stopReason":"end_turn"}"""));
+ }
+
+ // Roots Tests
+
+ @Test
+ void testRoot() throws Exception {
+ McpSchema.Root root = new McpSchema.Root("file:///path/to/root", "Test Root");
+
+ String value = mapper.writeValueAsString(root);
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(json("""
+ {"uri":"file:///path/to/root","name":"Test Root"}"""));
+ }
+
+ @Test
+ void testListRootsResult() throws Exception {
+ McpSchema.Root root1 = new McpSchema.Root("file:///path/to/root1", "First Root");
+
+ McpSchema.Root root2 = new McpSchema.Root("file:///path/to/root2", "Second Root");
+
+ McpSchema.ListRootsResult result = new McpSchema.ListRootsResult(Arrays.asList(root1, root2));
+
+ String value = mapper.writeValueAsString(result);
+
+ assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER)
+ .when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
+ .isObject()
+ .isEqualTo(
+ json("""
+ {"roots":[{"uri":"file:///path/to/root1","name":"First Root"},{"uri":"file:///path/to/root2","name":"Second Root"}]}"""));
+
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 9551c4d..893e5eb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,6 +92,8 @@
6.1.0
4.2.0
7.1.0
+ 4.1.0
+