feat: Add title field support for human-friendly display names
Add Title Field Support for Human-Friendly Display Names
- Implement BaseMetadata interface for consistent title handling
- Add Title field to Tool, Prompt, Resource, ResourceTemplate
- Add GetDisplayName() helper with title → annotations.title → name fallback
- Add WithTitle/WithPromptTitle/WithResourceTitle/WithTemplateTitle options
- Fix Tool JSON serialization to include title field
- Add comprehensive tests and update examples
- Fully backward compatible
Resolves #418
Description
This PR implements Task #418 by adding comprehensive title field support across all MCP object types to provide human-friendly display names while maintaining programmatic identification through the existing name fields.
What We've Implemented
Core Infrastructure:
- Created
BaseMetadatainterface withGetName()andGetTitle()methods for consistent behavior across all types - Added
GetDisplayName()helper function that implements the fallback logic:title → annotations.title → name - All MCP object types (Tool, Prompt, Resource, ResourceTemplate) now implement this interface
Title Field Support:
- Added
Titlefield to all relevant structs withjson:"title,omitempty"for optional serialization - Tool supports the full fallback chain: direct title → annotations.title → name
- Other types (Prompt, Resource, ResourceTemplate) support: title → name fallback
API Enhancements:
WithTitle()- Configure Tool title (takes precedence over annotation title)WithPromptTitle()- Configure Prompt titleWithResourceTitle()- Configure Resource titleWithTemplateTitle()- Configure ResourceTemplate title- Fixed
Tool.MarshalJSON()to properly serialize the title field
Current Behavior
// Tool with multiple title options
tool := NewTool("search-files",
WithTitle("File Search"), // Direct title (highest priority)
WithTitleAnnotation("Legacy Title"), // Annotation title (fallback)
)
// GetDisplayName() returns "File Search" (direct title wins)
displayName := GetDisplayName(&tool)
// Other types with simple title support
prompt := NewPrompt("user-prompt", WithPromptTitle("User Input Prompt"))
resource := NewResource("/api/data", "api-data", WithResourceTitle("API Data"))
Fallback Priority:
- Tool:
title→annotations.title→name - Others:
title→name
Testing & Compatibility
- Added comprehensive test suite covering all types and fallback scenarios
- Updated all examples to demonstrate title usage
- 100% backward compatible - existing code works unchanged
- All title fields are optional and won't affect existing JSON serialization
Fixes #418
Type of Change
- [x] New feature (non-breaking change that adds functionality)
- [x] MCP spec compatibility implementation
- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Code refactoring (no functional changes)
- [ ] Performance improvement
- [ ] Tests only (no functional changes)
- [ ] Other (please describe):
Checklist
- [x] My code follows the code style of this project
- [x] I have performed a self-review of my own code
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] I have updated the documentation accordingly
MCP Spec Compliance
- [x] Implementation follows the specification exactly
Additional Information
Design Decisions:
- Chose to implement
BaseMetadatainterface for consistency rather than individual methods per type - Tool maintains backward compatibility with existing
annotations.titlewhile adding directtitlesupport - Used functional options pattern to maintain API consistency with existing codebase
Testing Coverage:
- Interface compliance tests ensure all types implement BaseMetadata
- Fallback logic tests for each type and scenario
- JSON serialization/deserialization tests for Tool (most complex case)
- All tests pass and maintain existing functionality
This implementation provides a clean foundation for human-readable display names across the MCP ecosystem. Any feedback on the design approach, additional test scenarios, or edge cases would be greatly appreciated. Thank you for taking the time to review this PR!
Summary by CodeRabbit
-
New Features
- Added support for human-friendly display titles to tools, prompts, resources, and resource templates.
- Display titles can now be set via new options and appear in JSON output where applicable.
- Introduced a unified method to retrieve display names across these entities.
- Updated example tools and resources with descriptive titles for better clarity.
-
Tests
- Added tests to verify display name retrieval and JSON serialization of titles.
Walkthrough
The changes introduce a new optional Title field to several core types (Tool, Prompt, Resource, ResourceTemplate) to support human-friendly display names. Corresponding getter methods, functional options, and a BaseMetadata interface are added. Display name precedence logic and helper utilities are implemented, alongside comprehensive tests.
Changes
| Files / Grouped Files | Change Summary |
|---|---|
| mcp/types.go | Added Title field and GetTitle() to Resource and ResourceTemplate; introduced BaseMetadata interface. |
| mcp/prompts.go | Added Title field, GetTitle() method, and WithPromptTitle() option to Prompt. |
| mcp/tools.go | Added Title field, GetTitle(), WithTitle() option, and updated JSON marshaling for Tool. |
| mcp/resources.go | Added WithResourceTitle() and WithTemplateTitle() functional options. |
| mcp/utils.go | Added GetDisplayName() utility and interface assertions for BaseMetadata. |
| mcp/types_test.go | Added tests for display name logic and Tool JSON serialization/deserialization. |
| examples/custom_context/main.go | Added Title to "make_authenticated_request" tool. |
| examples/dynamic_path/main.go | Added Title to "echo" tool. |
| examples/everything/main.go | Added Title fields to resources, templates, prompts, and tools; refactored resource creation to use titles. |
| examples/in_process/main.go | Added Title to "dummy_tool" tool. |
| examples/typed_tools/main.go | Added Title to "greeting" tool. |
Assessment against linked issues
| Objective | Addressed | Explanation |
|---|---|---|
Create BaseMetadata interface with name and title (#418) |
✅ | |
Update Tool, Resource, Prompt, etc. to inherit from BaseMetadata (#418) |
✅ | |
Implement display name precedence: title → annotations.title → name (#418) |
✅ | |
| Add helper functions for getting display names (#418) | ✅ | |
Update all examples to include title fields (#418) |
✅ | Titles added to tools, resources, prompts, and templates in multiple example files. |
Assessment against linked issues: Out-of-scope changes
No out-of-scope changes found.
Possibly related PRs
- mark3labs/mcp-go#165: Modifies
Tool.MarshalJSONto includeAnnotationsand adds test assertions for annotations; related toToolmetadata handling but focuses on annotations rather thanTitle.
Suggested labels
type: enhancement, area: sdk
Suggested reviewers
- ezynda3
- pottekkat
[!WARNING] There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.
🔧 golangci-lint (1.64.8)
Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2 Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
📜 Recent review details
Configuration used: CodeRabbit UI Review profile: CHILL Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between dd458b4a6069a3f6c64dcdb4c271aac680636509 and d60749b620483d603b93478a0bcd28c3f7541b53.
📒 Files selected for processing (5)
examples/custom_context/main.go(1 hunks)examples/dynamic_path/main.go(1 hunks)examples/everything/main.go(6 hunks)examples/in_process/main.go(1 hunks)examples/typed_tools/main.go(1 hunks)
✅ Files skipped from review due to trivial changes (5)
- examples/typed_tools/main.go
- examples/in_process/main.go
- examples/custom_context/main.go
- examples/dynamic_path/main.go
- examples/everything/main.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: test
✨ Finishing Touches
- [ ] 📝 Generate Docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
🪧 Tips
Chat
There are 3 ways to chat with CodeRabbit:
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
I pushed a fix in commit <commit_id>, please review it.Explain this complex logic.Open a follow-up GitHub issue for this discussion.
- Files and specific lines of code (under the "Files changed" tab): Tag
@coderabbitaiin a new review comment at the desired location with your query. Examples:@coderabbitai explain this code block.@coderabbitai modularize this function.
- PR comments: Tag
@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.@coderabbitai read src/utils.ts and explain its main purpose.@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.@coderabbitai help me debug CodeRabbit configuration file.
Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.
CodeRabbit Commands (Invoked using PR comments)
@coderabbitai pauseto pause the reviews on a PR.@coderabbitai resumeto resume the paused reviews.@coderabbitai reviewto trigger an incremental review. This is useful when automatic reviews are disabled for the repository.@coderabbitai full reviewto do a full review from scratch and review all the files again.@coderabbitai summaryto regenerate the summary of the PR.@coderabbitai generate docstringsto generate docstrings for this PR.@coderabbitai generate sequence diagramto generate a sequence diagram of the changes in this PR.@coderabbitai resolveresolve all the CodeRabbit review comments.@coderabbitai configurationto show the current CodeRabbit configuration for the repository.@coderabbitai helpto get help.
Other keywords and placeholders
- Add
@coderabbitai ignoreanywhere in the PR description to prevent this PR from being reviewed. - Add
@coderabbitai summaryto generate the high-level summary at a specific location in the PR description. - Add
@coderabbitaianywhere in the PR title to generate the title automatically.
CodeRabbit Configuration File (.coderabbit.yaml)
- You can programmatically configure CodeRabbit by adding a
.coderabbit.yamlfile to the root of your repository. - Please see the configuration documentation for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation:
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
Documentation and Community
- Visit our Documentation for detailed information on how to use CodeRabbit.
- Join our Discord Community to get help, request features, and share feedback.
- Follow us on X/Twitter for updates and announcements.
I feel that, at least for the DisplayName topic, we should try to provide helper functions to make it easier for users. Or do you have any good ideas regarding the API design? I’d be happy to try making some adjustments.