Skip to content

Commit 9977a06

Browse files
bzsurbhitzolov
andcommitted
feat: Add title field support to MCP schema classes (#372)
- Add BaseMetadata interface with name() and title() methods for consistent metadata handling - The Prompt, PromptArgument, Resource, ResourceTemplate, ResuorceLink, PromptReference, Tool, and Implementation classes implement the BaseMetadata interface, adding a new, optional title field - Update constructors to support backward compatibility while allowing title specification - Modify ResourceContent interface to extend BaseMetadata - Update all test cases to accommodate new title parameter The title field provides human-readable display names optimized for UI contexts, while name remains for programmatic/logical use. This change maintains backward compatibility. Signed-off-by: Christian Tzolov <[email protected]> Co-authored-by: Christian Tzolov <[email protected]>
1 parent b5a1e3b commit 9977a06

File tree

11 files changed

+1053
-929
lines changed

11 files changed

+1053
-929
lines changed

mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/WebFluxSseIntegrationTests.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -996,19 +996,20 @@ void testCompletionShouldReturnExpectedSuggestions(String clientType) {
996996
var mcpServer = McpServer.sync(mcpServerTransportProvider)
997997
.capabilities(ServerCapabilities.builder().completions().build())
998998
.prompts(new McpServerFeatures.SyncPromptSpecification(
999-
new Prompt("code_review", "this is code review prompt",
1000-
List.of(new PromptArgument("language", "string", false))),
999+
new Prompt("code_review", "Code review", "this is code review prompt",
1000+
List.of(new PromptArgument("language", "Language", "string", false))),
10011001
(mcpSyncServerExchange, getPromptRequest) -> null))
10021002
.completions(new McpServerFeatures.SyncCompletionSpecification(
1003-
new McpSchema.PromptReference("ref/prompt", "code_review"), completionHandler))
1003+
new McpSchema.PromptReference("ref/prompt", "code_review", "Code review"), completionHandler))
10041004
.build();
10051005

10061006
try (var mcpClient = clientBuilder.build()) {
10071007

10081008
InitializeResult initResult = mcpClient.initialize();
10091009
assertThat(initResult).isNotNull();
10101010

1011-
CompleteRequest request = new CompleteRequest(new PromptReference("ref/prompt", "code_review"),
1011+
CompleteRequest request = new CompleteRequest(
1012+
new PromptReference("ref/prompt", "code_review", "Code review"),
10121013
new CompleteRequest.CompleteArgument("language", "py"));
10131014

10141015
CompleteResult result = mcpClient.completeCompletion(request);

mcp-test/src/main/java/io/modelcontextprotocol/client/AbstractMcpAsyncClientTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ void testListAllPromptsReturnsImmutableList() {
420420
.consumeNextWith(result -> {
421421
assertThat(result.prompts()).isNotNull();
422422
// Verify that the returned list is immutable
423-
assertThatThrownBy(() -> result.prompts().add(new Prompt("test", "test", null)))
423+
assertThatThrownBy(() -> result.prompts().add(new Prompt("test", "Test", "test", null)))
424424
.isInstanceOf(UnsupportedOperationException.class);
425425
})
426426
.verifyComplete();
@@ -604,7 +604,7 @@ void testListAllResourceTemplatesReturnsImmutableList() {
604604
assertThat(result.resourceTemplates()).isNotNull();
605605
// Verify that the returned list is immutable
606606
assertThatThrownBy(() -> result.resourceTemplates()
607-
.add(new McpSchema.ResourceTemplate("test://template", "test", null, null, null)))
607+
.add(new McpSchema.ResourceTemplate("test://template", "test", "test", null, null, null)))
608608
.isInstanceOf(UnsupportedOperationException.class);
609609
})
610610
.verifyComplete();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ void testAddPromptWithoutCapability() {
302302
.serverInfo("test-server", "1.0.0")
303303
.build();
304304

305-
Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of());
305+
Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of());
306306
McpServerFeatures.AsyncPromptSpecification specification = new McpServerFeatures.AsyncPromptSpecification(
307307
prompt, (exchange, req) -> Mono.just(new GetPromptResult("Test prompt description", List
308308
.of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content"))))));
@@ -330,7 +330,7 @@ void testRemovePromptWithoutCapability() {
330330
void testRemovePrompt() {
331331
String TEST_PROMPT_NAME_TO_REMOVE = "TEST_PROMPT_NAME678";
332332

333-
Prompt prompt = new Prompt(TEST_PROMPT_NAME_TO_REMOVE, "Test Prompt", List.of());
333+
Prompt prompt = new Prompt(TEST_PROMPT_NAME_TO_REMOVE, "Test Prompt", "Test Prompt", List.of());
334334
McpServerFeatures.AsyncPromptSpecification specification = new McpServerFeatures.AsyncPromptSpecification(
335335
prompt, (exchange, req) -> Mono.just(new GetPromptResult("Test prompt description", List
336336
.of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content"))))));

mcp-test/src/main/java/io/modelcontextprotocol/server/AbstractMcpSyncServerTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ void testAddPromptWithoutCapability() {
289289
.serverInfo("test-server", "1.0.0")
290290
.build();
291291

292-
Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of());
292+
Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of());
293293
McpServerFeatures.SyncPromptSpecification specification = new McpServerFeatures.SyncPromptSpecification(prompt,
294294
(exchange, req) -> new GetPromptResult("Test prompt description", List
295295
.of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content")))));
@@ -310,7 +310,7 @@ void testRemovePromptWithoutCapability() {
310310

311311
@Test
312312
void testRemovePrompt() {
313-
Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", List.of());
313+
Prompt prompt = new Prompt(TEST_PROMPT_NAME, "Test Prompt", "Test Prompt", List.of());
314314
McpServerFeatures.SyncPromptSpecification specification = new McpServerFeatures.SyncPromptSpecification(prompt,
315315
(exchange, req) -> new GetPromptResult("Test prompt description", List
316316
.of(new PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent("Test content")))));

mcp/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,8 @@ private List<McpSchema.ResourceTemplate> getResourceTemplates() {
462462
.filter(uri -> uri.contains("{"))
463463
.map(uri -> {
464464
var resource = this.resources.get(uri).resource();
465-
var template = new McpSchema.ResourceTemplate(resource.uri(), resource.name(), resource.description(),
466-
resource.mimeType(), resource.annotations());
465+
var template = new McpSchema.ResourceTemplate(resource.uri(), resource.name(), resource.title(),
466+
resource.description(), resource.mimeType(), resource.annotations());
467467
return template;
468468
})
469469
.toList();
@@ -725,7 +725,8 @@ private McpSchema.CompleteRequest parseCompletionParams(Object object) {
725725
String refType = (String) refMap.get("type");
726726

727727
McpSchema.CompleteReference ref = switch (refType) {
728-
case "ref/prompt" -> new McpSchema.PromptReference(refType, (String) refMap.get("name"));
728+
case "ref/prompt" -> new McpSchema.PromptReference(refType, (String) refMap.get("name"),
729+
refMap.get("title") != null ? (String) refMap.get("title") : null);
729730
case "ref/resource" -> new McpSchema.ResourceReference(refType, (String) refMap.get("uri"));
730731
default -> throw new IllegalArgumentException("Invalid ref type: " + refType);
731732
};

0 commit comments

Comments
 (0)