diff --git a/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/WebFluxSseIntegrationTests.java b/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/WebFluxSseIntegrationTests.java index 73aff4629..c2ad1d68e 100644 --- a/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/WebFluxSseIntegrationTests.java +++ b/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/WebFluxSseIntegrationTests.java @@ -996,11 +996,11 @@ void testCompletionShouldReturnExpectedSuggestions(String clientType) { var mcpServer = McpServer.sync(mcpServerTransportProvider) .capabilities(ServerCapabilities.builder().completions().build()) .prompts(new McpServerFeatures.SyncPromptSpecification( - new Prompt("code_review", "this is code review prompt", - List.of(new PromptArgument("language", "string", false))), + new Prompt("code_review", "Code review", "this is code review prompt", + List.of(new PromptArgument("language", "Language", "string", false))), (mcpSyncServerExchange, getPromptRequest) -> null)) .completions(new McpServerFeatures.SyncCompletionSpecification( - new McpSchema.PromptReference("ref/prompt", "code_review"), completionHandler)) + new McpSchema.PromptReference("ref/prompt", "code_review", "Code review"), completionHandler)) .build(); try (var mcpClient = clientBuilder.build()) { @@ -1008,7 +1008,8 @@ void testCompletionShouldReturnExpectedSuggestions(String clientType) { InitializeResult initResult = mcpClient.initialize(); assertThat(initResult).isNotNull(); - CompleteRequest request = new CompleteRequest(new PromptReference("ref/prompt", "code_review"), + CompleteRequest request = new CompleteRequest( + new PromptReference("ref/prompt", "code_review", "Code review"), new CompleteRequest.CompleteArgument("language", "py")); CompleteResult result = mcpClient.completeCompletion(request); diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java b/mcp-test/src/main/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java index 9cccd3965..659a3222e 100644 --- a/mcp-test/src/main/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java +++ b/mcp-test/src/main/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java @@ -420,7 +420,7 @@ void testListAllPromptsReturnsImmutableList() { .consumeNextWith(result -> { assertThat(result.prompts()).isNotNull(); // Verify that the returned list is immutable - assertThatThrownBy(() -> result.prompts().add(new Prompt("test", "test", null))) + assertThatThrownBy(() -> result.prompts().add(new Prompt("test", "Test", "test", null))) .isInstanceOf(UnsupportedOperationException.class); }) .verifyComplete(); @@ -604,7 +604,7 @@ void testListAllResourceTemplatesReturnsImmutableList() { assertThat(result.resourceTemplates()).isNotNull(); // Verify that the returned list is immutable assertThatThrownBy(() -> result.resourceTemplates() - .add(new McpSchema.ResourceTemplate("test://template", "test", null, null, null))) + .add(new McpSchema.ResourceTemplate("test://template", "test", "test", null, null, null))) .isInstanceOf(UnsupportedOperationException.class); }) .verifyComplete(); diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java b/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java index 12827f469..1f6730638 100644 --- a/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java +++ b/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java @@ -302,7 +302,7 @@ void testAddPromptWithoutCapability() { .serverInfo("test-server", "1.0.0") .build(); - Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.AsyncPromptSpecification specification = new McpServerFeatures.AsyncPromptSpecification( prompt, (exchange, req) -> Mono.just(new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content")))))); @@ -330,7 +330,7 @@ void testRemovePromptWithoutCapability() { void testRemovePrompt() { String TEST_PROMPT_NAME_TO_REMOVE = "TEST_PROMPT_NAME678"; - Prompt prompt = new Prompt(TEST_PROMPT_NAME_TO_REMOVE, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME_TO_REMOVE, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.AsyncPromptSpecification specification = new McpServerFeatures.AsyncPromptSpecification( prompt, (exchange, req) -> Mono.just(new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content")))))); diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java b/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java index eefcdf9a3..5dac6f6a5 100644 --- a/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java +++ b/mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java @@ -289,7 +289,7 @@ void testAddPromptWithoutCapability() { .serverInfo("test-server", "1.0.0") .build(); - Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.SyncPromptSpecification specification = new McpServerFeatures.SyncPromptSpecification(prompt, (exchange, req) -> new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content"))))); @@ -310,7 +310,7 @@ void testRemovePromptWithoutCapability() { @Test void testRemovePrompt() { - Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.SyncPromptSpecification specification = new McpServerFeatures.SyncPromptSpecification(prompt, (exchange, req) -> new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content"))))); diff --git a/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java b/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java index 02ad955b9..6efe58de4 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java +++ b/mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java @@ -462,8 +462,8 @@ private List getResourceTemplates() { .filter(uri -> uri.contains("{")) .map(uri -> { var resource = this.resources.get(uri).resource(); - var template = new McpSchema.ResourceTemplate(resource.uri(), resource.name(), resource.description(), - resource.mimeType(), resource.annotations()); + var template = new McpSchema.ResourceTemplate(resource.uri(), resource.name(), resource.title(), + resource.description(), resource.mimeType(), resource.annotations()); return template; }) .toList(); @@ -725,7 +725,8 @@ private McpSchema.CompleteRequest parseCompletionParams(Object object) { String refType = (String) refMap.get("type"); McpSchema.CompleteReference ref = switch (refType) { - case "ref/prompt" -> new McpSchema.PromptReference(refType, (String) refMap.get("name")); + case "ref/prompt" -> new McpSchema.PromptReference(refType, (String) refMap.get("name"), + refMap.get("title") != null ? (String) refMap.get("title") : null); case "ref/resource" -> new McpSchema.ResourceReference(refType, (String) refMap.get("uri")); default -> throw new IllegalArgumentException("Invalid ref type: " + refType); }; diff --git a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java index 9be585cea..a816325be 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java +++ b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java @@ -32,6 +32,7 @@ * * @author Christian Tzolov * @author Luca Chang + * @author Surbhi Bansal */ public final class McpSchema { @@ -451,7 +452,12 @@ public ServerCapabilities build() { @JsonIgnoreProperties(ignoreUnknown = true) public record Implementation(// @formatter:off @JsonProperty("name") String name, - @JsonProperty("version") String version) { + @JsonProperty("title") String title, + @JsonProperty("version") String version) implements BaseMetadata { + + public Implementation(String name, String version) { + this(name, null, version); + } } // @formatter:on // Existing Enums and Base Types (from previous implementation) @@ -499,12 +505,10 @@ public record Annotations( // @formatter:off * interface is implemented by both {@link Resource} and {@link ResourceLink} to * provide a consistent way to access resource metadata. */ - public interface ResourceContent { + public interface ResourceContent extends BaseMetadata { String uri(); - String name(); - String description(); String mimeType(); @@ -515,6 +519,28 @@ public interface ResourceContent { } + /** + * Base interface for metadata with name (identifier) and title (display name) + * properties. + */ + public interface BaseMetadata { + + /** + * Intended for programmatic or logical use, but used as a display name in past + * specs or fallback (if title isn't present). + */ + String name(); + + /** + * Intended for UI and end-user contexts — optimized to be human-readable and + * easily understood, even by those unfamiliar with domain-specific terminology. + * + * If not provided, the name should be used for display. + */ + String title(); + + } + /** * A known resource that the server is capable of reading. * @@ -536,6 +562,7 @@ public interface ResourceContent { public record Resource( // @formatter:off @JsonProperty("uri") String uri, @JsonProperty("name") String name, + @JsonProperty("title") String title, @JsonProperty("description") String description, @JsonProperty("mimeType") String mimeType, @JsonProperty("size") Long size, @@ -547,7 +574,7 @@ public record Resource( // @formatter:off */ @Deprecated public Resource(String uri, String name, String description, String mimeType, Annotations annotations) { - this(uri, name, description, mimeType, null, annotations); + this(uri, name, null, description, mimeType, null, annotations); } public static Builder builder() { @@ -557,6 +584,7 @@ public static Builder builder() { public static class Builder { private String uri; private String name; + private String title; private String description; private String mimeType; private Long size; @@ -572,6 +600,11 @@ public Builder name(String name) { return this; } + public Builder title(String title) { + this.title = title; + return this; + } + public Builder description(String description) { this.description = description; return this; @@ -596,7 +629,7 @@ public Resource build() { Assert.hasText(uri, "uri must not be empty"); Assert.hasText(name, "name must not be empty"); - return new Resource(uri, name, description, mimeType, size, annotations); + return new Resource(uri, name, title, description, mimeType, size, annotations); } } } // @formatter:on @@ -622,9 +655,10 @@ public Resource build() { public record ResourceTemplate( // @formatter:off @JsonProperty("uriTemplate") String uriTemplate, @JsonProperty("name") String name, + @JsonProperty("title") String title, @JsonProperty("description") String description, @JsonProperty("mimeType") String mimeType, - @JsonProperty("annotations") Annotations annotations) implements Annotated { + @JsonProperty("annotations") Annotations annotations) implements Annotated, BaseMetadata { } // @formatter:on @JsonInclude(JsonInclude.Include.NON_ABSENT) @@ -746,8 +780,9 @@ public record BlobResourceContents( // @formatter:off @JsonIgnoreProperties(ignoreUnknown = true) public record Prompt( // @formatter:off @JsonProperty("name") String name, + @JsonProperty("title") String title, @JsonProperty("description") String description, - @JsonProperty("arguments") List arguments) { + @JsonProperty("arguments") List arguments) implements BaseMetadata { } // @formatter:on /** @@ -761,8 +796,9 @@ public record Prompt( // @formatter:off @JsonIgnoreProperties(ignoreUnknown = true) public record PromptArgument( // @formatter:off @JsonProperty("name") String name, + @JsonProperty("title") String title, @JsonProperty("description") String description, - @JsonProperty("required") Boolean required) { + @JsonProperty("required") Boolean required) implements BaseMetadata { }// @formatter:on /** @@ -883,16 +919,60 @@ public record ToolAnnotations( // @formatter:off @JsonIgnoreProperties(ignoreUnknown = true) public record Tool( // @formatter:off @JsonProperty("name") String name, + @JsonProperty("title") String title, @JsonProperty("description") String description, @JsonProperty("inputSchema") JsonSchema inputSchema, - @JsonProperty("annotations") ToolAnnotations annotations) { + @JsonProperty("annotations") ToolAnnotations annotations) implements BaseMetadata { public Tool(String name, String description, String schema) { - this(name, description, parseSchema(schema), null); + this(name, null, description, parseSchema(schema), null); } public Tool(String name, String description, String schema, ToolAnnotations annotations) { - this(name, description, parseSchema(schema), annotations); + this(name, null, description, parseSchema(schema), annotations); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String name; + private String title; + private String description; + private JsonSchema inputSchema; + private ToolAnnotations annotations; + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder title(String title) { + this.title = title; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder inputSchema(JsonSchema inputSchema) { + this.inputSchema = inputSchema; + return this; + } + + public Builder annotations(ToolAnnotations annotations) { + this.annotations = annotations; + return this; + } + + public Tool build() { + Assert.hasText(name, "name must not be empty"); + + return new Tool(name, title, description, inputSchema, annotations); + } } } // @formatter:on @@ -1579,10 +1659,11 @@ public sealed interface CompleteReference permits PromptReference, ResourceRefer @JsonIgnoreProperties(ignoreUnknown = true) public record PromptReference(// @formatter:off @JsonProperty("type") String type, - @JsonProperty("name") String name) implements McpSchema.CompleteReference { + @JsonProperty("name") String name, + @JsonProperty("title") String title ) implements McpSchema.CompleteReference, BaseMetadata { public PromptReference(String name) { - this("ref/prompt", name); + this("ref/prompt", name, null); } @Override @@ -1794,6 +1875,7 @@ public Double priority() { @JsonIgnoreProperties(ignoreUnknown = true) public record ResourceLink( // @formatter:off @JsonProperty("name") String name, + @JsonProperty("title") String title, @JsonProperty("uri") String uri, @JsonProperty("description") String description, @JsonProperty("mimeType") String mimeType, @@ -1808,6 +1890,8 @@ public static class Builder { private String name; + private String title; + private String uri; private String description; @@ -1823,6 +1907,11 @@ public Builder name(String name) { return this; } + public Builder title(String title) { + this.title = title; + return this; + } + public Builder uri(String uri) { this.uri = uri; return this; @@ -1852,7 +1941,7 @@ public ResourceLink build() { Assert.hasText(uri, "uri must not be empty"); Assert.hasText(name, "name must not be empty"); - return new ResourceLink(name, uri, description, mimeType, size, annotations); + return new ResourceLink(name, title, uri, description, mimeType, size, annotations); } } diff --git a/mcp/src/test/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java b/mcp/src/test/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java index a3edda2b9..154937d21 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java @@ -421,7 +421,7 @@ void testListAllPromptsReturnsImmutableList() { .consumeNextWith(result -> { assertThat(result.prompts()).isNotNull(); // Verify that the returned list is immutable - assertThatThrownBy(() -> result.prompts().add(new Prompt("test", "test", null))) + assertThatThrownBy(() -> result.prompts().add(new Prompt("test", "test", "test", null))) .isInstanceOf(UnsupportedOperationException.class); }) .verifyComplete(); @@ -605,7 +605,7 @@ void testListAllResourceTemplatesReturnsImmutableList() { assertThat(result.resourceTemplates()).isNotNull(); // Verify that the returned list is immutable assertThatThrownBy(() -> result.resourceTemplates() - .add(new McpSchema.ResourceTemplate("test://template", "test", null, null, null))) + .add(new McpSchema.ResourceTemplate("test://template", "test", "test", null, null, null))) .isInstanceOf(UnsupportedOperationException.class); }) .verifyComplete(); diff --git a/mcp/src/test/java/io/modelcontextprotocol/client/McpAsyncClientResponseHandlerTests.java b/mcp/src/test/java/io/modelcontextprotocol/client/McpAsyncClientResponseHandlerTests.java index 3e89c8cef..e773c8381 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/client/McpAsyncClientResponseHandlerTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/client/McpAsyncClientResponseHandlerTests.java @@ -251,8 +251,8 @@ void testPromptsChangeNotificationHandling() { assertThat(asyncMcpClient.initialize().block()).isNotNull(); // Create a mock prompts list that the server will return - McpSchema.Prompt mockPrompt = new McpSchema.Prompt("test-prompt", "Test Prompt Description", - List.of(new McpSchema.PromptArgument("arg1", "Test argument", true))); + McpSchema.Prompt mockPrompt = new McpSchema.Prompt("test-prompt", "Test Prompt", "Test Prompt Description", + List.of(new McpSchema.PromptArgument("arg1", "Test argument", "Test argument", true))); McpSchema.ListPromptsResult mockPromptsResult = new McpSchema.ListPromptsResult(List.of(mockPrompt), null); // Simulate server sending prompts/list_changed notification diff --git a/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java b/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java index dd9f65895..41bf0e640 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpAsyncServerTests.java @@ -301,7 +301,7 @@ void testAddPromptWithoutCapability() { .serverInfo("test-server", "1.0.0") .build(); - Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.AsyncPromptSpecification specification = new McpServerFeatures.AsyncPromptSpecification( prompt, (exchange, req) -> Mono.just(new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content")))))); @@ -329,7 +329,7 @@ void testRemovePromptWithoutCapability() { void testRemovePrompt() { String TEST_PROMPT_NAME_TO_REMOVE = "TEST_PROMPT_NAME678"; - Prompt prompt = new Prompt(TEST_PROMPT_NAME_TO_REMOVE, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME_TO_REMOVE, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.AsyncPromptSpecification specification = new McpServerFeatures.AsyncPromptSpecification( prompt, (exchange, req) -> Mono.just(new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content")))))); diff --git a/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java b/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java index 6cbb8632c..8a79e3427 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java @@ -288,7 +288,7 @@ void testAddPromptWithoutCapability() { .serverInfo("test-server", "1.0.0") .build(); - Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.SyncPromptSpecification specification = new McpServerFeatures.SyncPromptSpecification(prompt, (exchange, req) -> new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content"))))); @@ -309,7 +309,7 @@ void testRemovePromptWithoutCapability() { @Test void testRemovePrompt() { - Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of()); + Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of()); McpServerFeatures.SyncPromptSpecification specification = new McpServerFeatures.SyncPromptSpecification(prompt, (exchange, req) -> new GetPromptResult("Test prompt description", List .of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content"))))); diff --git a/mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java b/mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java index ea063e4e3..786be3294 100644 --- a/mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java +++ b/mcp/src/test/java/io/modelcontextprotocol/spec/McpSchemaTests.java @@ -207,8 +207,8 @@ void testEmbeddedResourceWithBlobContentsDeserialization() throws Exception { @Test void testResourceLink() throws Exception { - McpSchema.ResourceLink resourceLink = new McpSchema.ResourceLink("main.rs", "file:///project/src/main.rs", - "Primary application entry point", "text/x-rust", null, null); + McpSchema.ResourceLink resourceLink = new McpSchema.ResourceLink("main.rs", "Main file", + "file:///project/src/main.rs", "Primary application entry point", "text/x-rust", null, null); String value = mapper.writeValueAsString(resourceLink); assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER) @@ -216,7 +216,7 @@ void testResourceLink() throws Exception { .isObject() .isEqualTo( json(""" - {"type":"resource_link","name":"main.rs","uri":"file:///project/src/main.rs","description":"Primary application entry point","mimeType":"text/x-rust"}""")); + {"type":"resource_link","name":"main.rs","title":"Main file","uri":"file:///project/src/main.rs","description":"Primary application entry point","mimeType":"text/x-rust"}""")); } @Test @@ -419,7 +419,7 @@ 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); + "Test Template", "A test resource template", "text/plain", annotations); String value = mapper.writeValueAsString(template); assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER) @@ -427,7 +427,7 @@ void testResourceTemplate() throws Exception { .isObject() .isEqualTo( json(""" - {"uriTemplate":"resource://{param}/test","name":"Test Template","description":"A test resource template","mimeType":"text/plain","annotations":{"audience":["user"],"priority":0.5}}""")); + {"uriTemplate":"resource://{param}/test","name":"Test Template","title":"Test Template","description":"A test resource template","mimeType":"text/plain","annotations":{"audience":["user"],"priority":0.5}}""")); } @Test @@ -453,10 +453,10 @@ void testListResourcesResult() throws Exception { @Test void testListResourceTemplatesResult() throws Exception { McpSchema.ResourceTemplate template1 = new McpSchema.ResourceTemplate("resource://{param}/test1", - "Test Template 1", "First test template", "text/plain", null); + "Test Template 1", "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); + "Test Template 2", "Test Template 2", "Second test template", "application/json", null); McpSchema.ListResourceTemplatesResult result = new McpSchema.ListResourceTemplatesResult( Arrays.asList(template1, template2), "next-cursor"); @@ -467,7 +467,7 @@ void testListResourceTemplatesResult() throws Exception { .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"}""")); + {"resourceTemplates":[{"uriTemplate":"resource://{param}/test1","name":"Test Template 1","title":"Test Template 1","description":"First test template","mimeType":"text/plain"},{"uriTemplate":"resource://{param}/test2","name":"Test Template 2","title":"Test Template 2","description":"Second test template","mimeType":"application/json"}],"nextCursor":"next-cursor"}""")); } @Test @@ -535,11 +535,13 @@ void testReadResourceResult() throws Exception { @Test void testPrompt() throws Exception { - McpSchema.PromptArgument arg1 = new McpSchema.PromptArgument("arg1", "First argument", true); + McpSchema.PromptArgument arg1 = new McpSchema.PromptArgument("arg1", "First argument", "First argument", true); - McpSchema.PromptArgument arg2 = new McpSchema.PromptArgument("arg2", "Second argument", false); + McpSchema.PromptArgument arg2 = new McpSchema.PromptArgument("arg2", "Second argument", "Second argument", + false); - McpSchema.Prompt prompt = new McpSchema.Prompt("test-prompt", "A test prompt", Arrays.asList(arg1, arg2)); + McpSchema.Prompt prompt = new McpSchema.Prompt("test-prompt", "Test Prompt", "A test prompt", + Arrays.asList(arg1, arg2)); String value = mapper.writeValueAsString(prompt); assertThatJson(value).when(Option.IGNORING_ARRAY_ORDER) @@ -547,7 +549,7 @@ void testPrompt() throws Exception { .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}]}""")); + {"name":"test-prompt","title":"Test Prompt","description":"A test prompt","arguments":[{"name":"arg1","title":"First argument","description":"First argument","required":true},{"name":"arg2","title":"Second argument","description":"Second argument","required":false}]}""")); } @Test @@ -566,11 +568,13 @@ void testPromptMessage() throws Exception { @Test void testListPromptsResult() throws Exception { - McpSchema.PromptArgument arg = new McpSchema.PromptArgument("arg", "An argument", true); + McpSchema.PromptArgument arg = new McpSchema.PromptArgument("arg", "Argument", "An argument", true); - McpSchema.Prompt prompt1 = new McpSchema.Prompt("prompt1", "First prompt", Collections.singletonList(arg)); + McpSchema.Prompt prompt1 = new McpSchema.Prompt("prompt1", "First prompt", "First prompt", + Collections.singletonList(arg)); - McpSchema.Prompt prompt2 = new McpSchema.Prompt("prompt2", "Second prompt", Collections.emptyList()); + McpSchema.Prompt prompt2 = new McpSchema.Prompt("prompt2", "Second prompt", "Second prompt", + Collections.emptyList()); McpSchema.ListPromptsResult result = new McpSchema.ListPromptsResult(Arrays.asList(prompt1, prompt2), "next-cursor"); @@ -581,7 +585,7 @@ void testListPromptsResult() throws Exception { .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"}""")); + {"prompts":[{"name":"prompt1","title":"First prompt","description":"First prompt","arguments":[{"name":"arg","title":"Argument","description":"An argument","required":true}]},{"name":"prompt2","title":"Second prompt","description":"Second prompt","arguments":[]}],"nextCursor":"next-cursor"}""")); } @Test