Skip to content

feat: Add SEP-973 icons and metadata support#912

Open
sainathreddyb wants to merge 5 commits intomodelcontextprotocol:mainfrom
sainathreddyb:feature/sep-973-metadata-icons
Open

feat: Add SEP-973 icons and metadata support#912
sainathreddyb wants to merge 5 commits intomodelcontextprotocol:mainfrom
sainathreddyb:feature/sep-973-metadata-icons

Conversation

@sainathreddyb
Copy link
Copy Markdown

Add Icon record and icons field to Implementation, Resource, ResourceTemplate, Prompt, and Tool records per SEP-973. Add websiteUrl and description fields to Implementation.

All fields are optional and backward compatible. Existing constructors and builders continue to work unchanged. Icon.src is validated as required per the spec.

Includes serialization, deserialization, round-trip, and backward compatibility tests for all modified records.

Closes #694

Motivation and Context

SEP-973 adds visual metadata (icons, website URLs) to MCP protocol types so that client UIs can display icons next to tools, resources, prompts, and server implementations. This is already implemented in the TypeScript SDK and Python SDK. The Java SDK is the remaining SDK without this support.

How Has This Been Tested?

  • 12 new unit tests covering Icon serialization, deserialization, round-trip, required src validation, and backward compatibility
  • Tests for icons on Implementation, Tool, Resource, ResourceTemplate, and Prompt
  • Full test suite passes: 760 tests, 0 failures (./mvnw clean test)
  • Verified backward compatibility: all existing constructors and builders work unchanged

Breaking Changes

None. All new fields are optional and default to null. Existing code compiles and runs without modification.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

  • Matches the TypeScript SDK's IconSchema/IconsSchema approach (commit 856d9ec)
  • The Python SDK already has full icons support across all types
  • Icon.src is validated as non-empty in the compact constructor, consistent with how Resource.uri and Resource.name are validated in their builder
  • @JsonIgnoreProperties(ignoreUnknown = true) on Icon ensures forward compatibility if the spec adds more fields later

@sainathreddyb sainathreddyb force-pushed the feature/sep-973-metadata-icons branch from c1e1331 to 8edc5c7 Compare April 24, 2026 19:15
Add Icon record and icons field to Implementation, Resource,
ResourceTemplate, Prompt, and Tool records per SEP-973. Add
websiteUrl and description fields to Implementation.

All fields are optional and backward compatible. Existing
constructors and builders continue to work unchanged.
Icon.src is validated as required per the spec.
Icon.theme field supports light/dark theme variants.

Includes serialization, deserialization, round-trip, and backward
compatibility tests for all modified records.

Closes modelcontextprotocol#694
@sainathreddyb sainathreddyb force-pushed the feature/sep-973-metadata-icons branch from 8edc5c7 to d22688b Compare April 27, 2026 22:48
Copy link
Copy Markdown
Member

@chemicL chemicL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a brief look but had to stop after I noticed a few violations of the process. Please refine according to the comments and apply to the rest of the contribution. Also, please merge the main branch into your work.

@JsonProperty("title") String title,
@JsonProperty("version") String version) implements Identifier { // @formatter:on
@JsonProperty("version") String version,
@JsonProperty("description") String description,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 new optional fields indicate we need to add a builder with a static method that creates the builder instance with the required fields (name version) and all the others are optionally configured.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added Implementation.builder(String name, String version) with optional .title(), .description(), .icons(), .websiteUrl() setters. The existing 2-arg and 3-arg constructors are preserved as @Deprecated overloads for backward compatibility.

Comment on lines +708 to +711
@JsonProperty("src") String src,
@JsonProperty("mimeType") String mimeType,
@JsonProperty("sizes") List<String> sizes,
@JsonProperty("theme") String theme) { // @formatter:on
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a builder that accepts src as the required argument and allows configuring the other fields as optional.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added Icon.builder(String src) with optional .mimeType(), .sizes(), .theme(). Also added a @JsonCreator fromJson factory per Case B Rule 2 so deserialization doesn't crash if a peer omits src.

Comment on lines +717 to +722
public Icon(String src, String mimeType) {
this(src, mimeType, null, null);
}

public Icon(String src, String mimeType, List<String> sizes) {
this(src, mimeType, sizes, null);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove these constructors and use the builder pattern as documented in the CONTRIBUTING.md file.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. The only constructors on Icon now are the canonical 4-arg constructor and the fromJson factory. All public construction goes through the builder.

@JsonProperty("mimeType") String mimeType,
@JsonProperty("size") Long size,
@JsonProperty("annotations") Annotations annotations,
@JsonProperty("icons") List<Icon> icons,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a backwards incompatible change. Please check the process described in CONTRIBUTING.md

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Added deprecated backward-compatible overload constructors for Resource, ResourceTemplate, Prompt, and Tool that delegate to the new canonical constructor with null for icons. Existing callers compile unchanged. Applied the same pattern to all modified records.

Sainath Reddy Bobbala added 2 commits May 8, 2026 23:45
Integrates upstream changes through modelcontextprotocol#949 (SEP-1613 JSON Schema 2020-12
meta-schema validation) and addresses reviewer feedback on PR modelcontextprotocol#912.

Review feedback addressed
-------------------------
- Append icons between annotations and _meta in Resource,
  ResourceTemplate, Prompt, and Tool, preserving the _meta-always-last
  convention used throughout the schema (Case A Rule 1).
- Icon: switch compact constructor guard from Assert.hasText to
  Assert.notNull and add @JsonCreator fromJson lenient factory that
  defaults missing 'src' to '' with a WARN log (Case B Rules 1-2).
  Prevents deserialization crashes on malformed peer messages.
- Icon: remove newly-introduced convenience constructors Icon(src,
  mimeType) and Icon(src, mimeType, sizes); callers use the Builder.
- Implementation: add description, icons, websiteUrl at the end of the
  component list; add required-first builder(name, version) with
  builder methods for all new optional fields (Case A Rule 9,
  Case B Rule 3).
- Javadoc: add @param icons to Implementation, Resource,
  ResourceTemplate, Prompt, and Tool.

Tests
-----
- Add unknown-field tolerance tests for Icon, Implementation, Resource,
  ResourceTemplate, Prompt, Tool (Case A Rule 8).
- Add null-src, missing-src-deserialization, and lenient-default tests
  for Icon.
- Add backward-compatibility test for the pre-existing 2-arg
  Implementation constructor.

Closes modelcontextprotocol#694
Reconciles divergent merge history between local (which merged upstream/main
and added review feedback fixes) and remote (which had two earlier sync merges
from main). No code changes; local tree already contains everything from
both sides.
@sainathreddyb sainathreddyb requested a review from chemicL May 9, 2026 00:17
@sainathreddyb
Copy link
Copy Markdown
Author

Thanks for the review @chemicL — all points addressed in the latest commit.

These were missed because I initially modeled the changes after the TypeScript/Python SDKs which don't have the same wire-compatibility constraints as Java records. I've since gone through CONTRIBUTING.md rule by rule and applied the full Case A / Case B checklist:

  • Builder with required-first factory on Icon and Implementation
  • No convenience constructors — builder pattern only
  • Deprecated backward-compat overloads on all modified records
  • @JsonCreator fromJson on Icon for lenient deserialization (Case B Rule 2)
  • Three tests per new field (deserialize-without, serialize-null-omits, unknown-field-tolerant)
  • Main branch merged in

Let me know if anything else needs attention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SEP-973: Expose additional metadata for Implementations, Resources, Tools and Prompts

2 participants