Skip to content

Commit 4f5b71c

Browse files
kakoochclaude
andcommitted
Implement SEP-973: Add icons and metadata support
This commit implements SEP-973 by adding icon support to MCP schema types, enabling clients to visually identify servers, tools, resources, and prompts. Changes: - Add new Icon record with src, mimeType, and sizes fields - Add icons and websiteUrl fields to Implementation - Add icons field to Tool, Resource, and Prompt records - Update Builder classes to support new fields - Maintain backward compatibility with existing constructors The Icon type supports: - HTTP/HTTPS URLs for remote icons - Data URIs for embedded base64-encoded icons - Multiple sizes following Web Manifest format (e.g., "48x48", "any") - Common image MIME types (image/png, image/svg+xml, etc.) Resolves: #532 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 06fdc71 commit 4f5b71c

File tree

1 file changed

+98
-9
lines changed

1 file changed

+98
-9
lines changed

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpSchema.java

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -610,16 +610,38 @@ public ServerCapabilities build() {
610610
* past specs or fallback (if title isn't present).
611611
* @param title Intended for UI and end-user contexts
612612
* @param version The version of the implementation.
613+
* @param icons Optional list of icons that can be used to visually represent this
614+
* implementation in client UIs. Multiple icons can be provided for different sizes
615+
* and formats.
616+
* @param websiteUrl Optional URL to the website or documentation for this
617+
* implementation.
613618
*/
614619
@JsonInclude(JsonInclude.Include.NON_ABSENT)
615620
@JsonIgnoreProperties(ignoreUnknown = true)
616621
public record Implementation( // @formatter:off
617622
@JsonProperty("name") String name,
618623
@JsonProperty("title") String title,
619-
@JsonProperty("version") String version) implements Identifier { // @formatter:on
624+
@JsonProperty("version") String version,
625+
@JsonProperty("icons") List<Icon> icons,
626+
@JsonProperty("websiteUrl") String websiteUrl) implements Identifier { // @formatter:on
620627

628+
/**
629+
* Creates an Implementation with just name and version.
630+
* @param name The implementation name
631+
* @param version The implementation version
632+
*/
621633
public Implementation(String name, String version) {
622-
this(name, null, version);
634+
this(name, null, version, null, null);
635+
}
636+
637+
/**
638+
* Creates an Implementation with name, title, and version.
639+
* @param name The implementation name
640+
* @param title The display title
641+
* @param version The implementation version
642+
*/
643+
public Implementation(String name, String title, String version) {
644+
this(name, title, version, null, null);
623645
}
624646
}
625647

@@ -713,6 +735,50 @@ public interface Identifier {
713735

714736
}
715737

738+
/**
739+
* Represents an icon that can be used to visually identify servers, tools, resources,
740+
* or prompts in client UIs.
741+
*
742+
* <p>
743+
* Icons can be provided as HTTP/HTTPS URLs or as data URIs containing base64-encoded
744+
* image data. Clients should display icons at appropriate sizes based on their UI
745+
* context.
746+
*
747+
* @param src The URI of the icon. Can be an HTTP/HTTPS URL or a data URI (e.g.,
748+
* "data:image/png;base64,...").
749+
* @param mimeType Optional MIME type of the icon (e.g., "image/png",
750+
* "image/svg+xml"). If not provided, clients should infer the type from the URI or
751+
* content.
752+
* @param sizes Optional size specification following Web Manifest format. Can be a
753+
* single size (e.g., "48x48"), multiple sizes separated by spaces (e.g., "48x48
754+
* 96x96"), or "any" for scalable formats like SVG.
755+
* @see <a href=
756+
* "https://spec.modelcontextprotocol.io/specification/2025-06-18/base-protocol/#icons">MCP
757+
* Icons Specification</a>
758+
*/
759+
@JsonInclude(JsonInclude.Include.NON_ABSENT)
760+
@JsonIgnoreProperties(ignoreUnknown = true)
761+
public record Icon( // @formatter:off
762+
@JsonProperty("src") String src,
763+
@JsonProperty("mimeType") String mimeType,
764+
@JsonProperty("sizes") String sizes) { // @formatter:on
765+
766+
/**
767+
* Creates an Icon with just a source URL.
768+
* @param src The URI of the icon
769+
*/
770+
public Icon(String src) {
771+
this(src, null, null);
772+
}
773+
774+
/**
775+
* Canonical constructor with validation.
776+
*/
777+
public Icon {
778+
Assert.hasText(src, "Icon src must not be null or empty");
779+
}
780+
}
781+
716782
/**
717783
* A known resource that the server is capable of reading.
718784
*
@@ -729,6 +795,8 @@ public interface Identifier {
729795
* sizes and estimate context window usage.
730796
* @param annotations Optional annotations for the client. The client can use
731797
* annotations to inform how objects are used or displayed.
798+
* @param icons Optional list of icons that can be used to visually represent this
799+
* resource in client UIs.
732800
* @param meta See specification for notes on _meta usage
733801
*/
734802
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@@ -741,6 +809,7 @@ public record Resource( // @formatter:off
741809
@JsonProperty("mimeType") String mimeType,
742810
@JsonProperty("size") Long size,
743811
@JsonProperty("annotations") Annotations annotations,
812+
@JsonProperty("icons") List<Icon> icons,
744813
@JsonProperty("_meta") Map<String, Object> meta) implements ResourceContent { // @formatter:on
745814

746815
/**
@@ -750,7 +819,7 @@ public record Resource( // @formatter:off
750819
@Deprecated
751820
public Resource(String uri, String name, String title, String description, String mimeType, Long size,
752821
Annotations annotations) {
753-
this(uri, name, title, description, mimeType, size, annotations, null);
822+
this(uri, name, title, description, mimeType, size, annotations, null, null);
754823
}
755824

756825
/**
@@ -760,7 +829,7 @@ public Resource(String uri, String name, String title, String description, Strin
760829
@Deprecated
761830
public Resource(String uri, String name, String description, String mimeType, Long size,
762831
Annotations annotations) {
763-
this(uri, name, null, description, mimeType, size, annotations, null);
832+
this(uri, name, null, description, mimeType, size, annotations, null, null);
764833
}
765834

766835
/**
@@ -769,7 +838,7 @@ public Resource(String uri, String name, String description, String mimeType, Lo
769838
*/
770839
@Deprecated
771840
public Resource(String uri, String name, String description, String mimeType, Annotations annotations) {
772-
this(uri, name, null, description, mimeType, null, annotations, null);
841+
this(uri, name, null, description, mimeType, null, annotations, null, null);
773842
}
774843

775844
public static Builder builder() {
@@ -792,6 +861,8 @@ public static class Builder {
792861

793862
private Annotations annotations;
794863

864+
private List<Icon> icons;
865+
795866
private Map<String, Object> meta;
796867

797868
public Builder uri(String uri) {
@@ -829,6 +900,11 @@ public Builder annotations(Annotations annotations) {
829900
return this;
830901
}
831902

903+
public Builder icons(List<Icon> icons) {
904+
this.icons = icons;
905+
return this;
906+
}
907+
832908
public Builder meta(Map<String, Object> meta) {
833909
this.meta = meta;
834910
return this;
@@ -838,7 +914,7 @@ public Resource build() {
838914
Assert.hasText(uri, "uri must not be empty");
839915
Assert.hasText(name, "name must not be empty");
840916

841-
return new Resource(uri, name, title, description, mimeType, size, annotations, meta);
917+
return new Resource(uri, name, title, description, mimeType, size, annotations, icons, meta);
842918
}
843919

844920
}
@@ -1137,6 +1213,8 @@ public BlobResourceContents(String uri, String mimeType, String blob) {
11371213
* @param title An optional title for the prompt.
11381214
* @param description An optional description of what this prompt provides.
11391215
* @param arguments A list of arguments to use for templating the prompt.
1216+
* @param icons Optional list of icons that can be used to visually represent this
1217+
* prompt in client UIs.
11401218
* @param meta See specification for notes on _meta usage
11411219
*/
11421220
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@@ -1146,14 +1224,15 @@ public record Prompt( // @formatter:off
11461224
@JsonProperty("title") String title,
11471225
@JsonProperty("description") String description,
11481226
@JsonProperty("arguments") List<PromptArgument> arguments,
1227+
@JsonProperty("icons") List<Icon> icons,
11491228
@JsonProperty("_meta") Map<String, Object> meta) implements Identifier { // @formatter:on
11501229

11511230
public Prompt(String name, String description, List<PromptArgument> arguments) {
1152-
this(name, null, description, arguments != null ? arguments : new ArrayList<>());
1231+
this(name, null, description, arguments != null ? arguments : new ArrayList<>(), null, null);
11531232
}
11541233

11551234
public Prompt(String name, String title, String description, List<PromptArgument> arguments) {
1156-
this(name, title, description, arguments != null ? arguments : new ArrayList<>(), null);
1235+
this(name, title, description, arguments != null ? arguments : new ArrayList<>(), null, null);
11571236
}
11581237
}
11591238

@@ -1332,6 +1411,8 @@ public record ToolAnnotations( // @formatter:off
13321411
* @param outputSchema An optional JSON Schema object defining the structure of the
13331412
* tool's output returned in the structuredContent field of a CallToolResult.
13341413
* @param annotations Optional additional tool information.
1414+
* @param icons Optional list of icons that can be used to visually represent this
1415+
* tool in client UIs.
13351416
* @param meta See specification for notes on _meta usage
13361417
*/
13371418
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@@ -1343,6 +1424,7 @@ public record Tool( // @formatter:off
13431424
@JsonProperty("inputSchema") JsonSchema inputSchema,
13441425
@JsonProperty("outputSchema") Map<String, Object> outputSchema,
13451426
@JsonProperty("annotations") ToolAnnotations annotations,
1427+
@JsonProperty("icons") List<Icon> icons,
13461428
@JsonProperty("_meta") Map<String, Object> meta) { // @formatter:on
13471429

13481430
public static Builder builder() {
@@ -1363,6 +1445,8 @@ public static class Builder {
13631445

13641446
private ToolAnnotations annotations;
13651447

1448+
private List<Icon> icons;
1449+
13661450
private Map<String, Object> meta;
13671451

13681452
public Builder name(String name) {
@@ -1405,14 +1489,19 @@ public Builder annotations(ToolAnnotations annotations) {
14051489
return this;
14061490
}
14071491

1492+
public Builder icons(List<Icon> icons) {
1493+
this.icons = icons;
1494+
return this;
1495+
}
1496+
14081497
public Builder meta(Map<String, Object> meta) {
14091498
this.meta = meta;
14101499
return this;
14111500
}
14121501

14131502
public Tool build() {
14141503
Assert.hasText(name, "name must not be empty");
1415-
return new Tool(name, title, description, inputSchema, outputSchema, annotations, meta);
1504+
return new Tool(name, title, description, inputSchema, outputSchema, annotations, icons, meta);
14161505
}
14171506

14181507
}

0 commit comments

Comments
 (0)