Skip to content

Commit c1e1331

Browse files
author
Sainath Reddy Bobbala
committed
feat: Add SEP-973 icons and metadata support
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
1 parent 8fd9903 commit c1e1331

2 files changed

Lines changed: 254 additions & 17 deletions

File tree

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

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@
1111
import java.util.List;
1212
import java.util.Map;
1313

14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
1417
import com.fasterxml.jackson.annotation.JsonCreator;
1518
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
1619
import com.fasterxml.jackson.annotation.JsonInclude;
1720
import com.fasterxml.jackson.annotation.JsonProperty;
1821
import com.fasterxml.jackson.annotation.JsonSubTypes;
1922
import com.fasterxml.jackson.annotation.JsonTypeInfo;
23+
2024
import io.modelcontextprotocol.json.McpJsonMapper;
2125
import io.modelcontextprotocol.json.TypeRef;
2226
import io.modelcontextprotocol.util.Assert;
23-
import org.slf4j.Logger;
24-
import org.slf4j.LoggerFactory;
2527

2628
/**
2729
* Based on the <a href="http://www.jsonrpc.org/specification">JSON-RPC 2.0
@@ -662,16 +664,54 @@ public ServerCapabilities build() {
662664
* past specs or fallback (if title isn't present).
663665
* @param title Intended for UI and end-user contexts
664666
* @param version The version of the implementation.
667+
* @param description An optional human-readable description of this implementation.
668+
* @param icons An optional list of icons for this implementation.
669+
* @param websiteUrl An optional URL of the website for this implementation.
665670
*/
666671
@JsonInclude(JsonInclude.Include.NON_ABSENT)
667672
@JsonIgnoreProperties(ignoreUnknown = true)
668673
public record Implementation( // @formatter:off
669674
@JsonProperty("name") String name,
670675
@JsonProperty("title") String title,
671-
@JsonProperty("version") String version) implements Identifier { // @formatter:on
676+
@JsonProperty("version") String version,
677+
@JsonProperty("description") String description,
678+
@JsonProperty("icons") List<Icon> icons,
679+
@JsonProperty("websiteUrl") String websiteUrl) implements Identifier { // @formatter:on
672680

673681
public Implementation(String name, String version) {
674-
this(name, null, version);
682+
this(name, null, version, null, null, null);
683+
}
684+
685+
public Implementation(String name, String title, String version) {
686+
this(name, title, version, null, null, null);
687+
}
688+
}
689+
690+
/**
691+
* Represents an icon that can be displayed in a user interface.
692+
*
693+
* @param src A URI pointing to an icon resource or a base64-encoded data URI.
694+
* @param mimeType Optional MIME type override if the server's MIME type is missing or
695+
* generic.
696+
* @param sizes Optional array of strings specifying sizes at which the icon can be
697+
* used. Each string should be in WxH format (e.g., "48x48", "96x96") or "any" for
698+
* scalable formats like SVG.
699+
* @see <a href=
700+
* "https://github.com/modelcontextprotocol/modelcontextprotocol/issues/973">SEP-973</a>
701+
*/
702+
@JsonInclude(JsonInclude.Include.NON_ABSENT)
703+
@JsonIgnoreProperties(ignoreUnknown = true)
704+
public record Icon( // @formatter:off
705+
@JsonProperty("src") String src,
706+
@JsonProperty("mimeType") String mimeType,
707+
@JsonProperty("sizes") List<String> sizes) { // @formatter:on
708+
709+
public Icon {
710+
Assert.hasText(src, "Icon src must not be empty");
711+
}
712+
713+
public Icon(String src, String mimeType) {
714+
this(src, mimeType, null);
675715
}
676716
}
677717

@@ -793,6 +833,7 @@ public record Resource( // @formatter:off
793833
@JsonProperty("mimeType") String mimeType,
794834
@JsonProperty("size") Long size,
795835
@JsonProperty("annotations") Annotations annotations,
836+
@JsonProperty("icons") List<Icon> icons,
796837
@JsonProperty("_meta") Map<String, Object> meta) implements ResourceContent { // @formatter:on
797838

798839
public static Builder builder() {
@@ -815,6 +856,8 @@ public static class Builder {
815856

816857
private Annotations annotations;
817858

859+
private List<Icon> icons;
860+
818861
private Map<String, Object> meta;
819862

820863
public Builder uri(String uri) {
@@ -852,6 +895,11 @@ public Builder annotations(Annotations annotations) {
852895
return this;
853896
}
854897

898+
public Builder icons(List<Icon> icons) {
899+
this.icons = icons;
900+
return this;
901+
}
902+
855903
public Builder meta(Map<String, Object> meta) {
856904
this.meta = meta;
857905
return this;
@@ -861,7 +909,7 @@ public Resource build() {
861909
Assert.hasText(uri, "uri must not be empty");
862910
Assert.hasText(name, "name must not be empty");
863911

864-
return new Resource(uri, name, title, description, mimeType, size, annotations, meta);
912+
return new Resource(uri, name, title, description, mimeType, size, annotations, icons, meta);
865913
}
866914

867915
}
@@ -894,18 +942,24 @@ public record ResourceTemplate( // @formatter:off
894942
@JsonProperty("description") String description,
895943
@JsonProperty("mimeType") String mimeType,
896944
@JsonProperty("annotations") Annotations annotations,
945+
@JsonProperty("icons") List<Icon> icons,
897946
@JsonProperty("_meta") Map<String, Object> meta) implements Annotated, Identifier, Meta { // @formatter:on
898947

899948
public ResourceTemplate(String uriTemplate, String name, String title, String description, String mimeType,
900949
Annotations annotations) {
901-
this(uriTemplate, name, title, description, mimeType, annotations, null);
950+
this(uriTemplate, name, title, description, mimeType, annotations, null, null);
902951
}
903952

904953
public ResourceTemplate(String uriTemplate, String name, String description, String mimeType,
905954
Annotations annotations) {
906955
this(uriTemplate, name, null, description, mimeType, annotations);
907956
}
908957

958+
public ResourceTemplate(String uriTemplate, String name, String title, String description, String mimeType,
959+
Annotations annotations, Map<String, Object> meta) {
960+
this(uriTemplate, name, title, description, mimeType, annotations, null, meta);
961+
}
962+
909963
public static Builder builder() {
910964
return new Builder();
911965
}
@@ -924,6 +978,8 @@ public static class Builder {
924978

925979
private Annotations annotations;
926980

981+
private List<Icon> icons;
982+
927983
private Map<String, Object> meta;
928984

929985
public Builder uriTemplate(String uri) {
@@ -956,6 +1012,11 @@ public Builder annotations(Annotations annotations) {
9561012
return this;
9571013
}
9581014

1015+
public Builder icons(List<Icon> icons) {
1016+
this.icons = icons;
1017+
return this;
1018+
}
1019+
9591020
public Builder meta(Map<String, Object> meta) {
9601021
this.meta = meta;
9611022
return this;
@@ -965,7 +1026,7 @@ public ResourceTemplate build() {
9651026
Assert.hasText(uriTemplate, "uri must not be empty");
9661027
Assert.hasText(name, "name must not be empty");
9671028

968-
return new ResourceTemplate(uriTemplate, name, title, description, mimeType, annotations, meta);
1029+
return new ResourceTemplate(uriTemplate, name, title, description, mimeType, annotations, icons, meta);
9691030
}
9701031

9711032
}
@@ -1169,14 +1230,20 @@ public record Prompt( // @formatter:off
11691230
@JsonProperty("title") String title,
11701231
@JsonProperty("description") String description,
11711232
@JsonProperty("arguments") List<PromptArgument> arguments,
1233+
@JsonProperty("icons") List<Icon> icons,
11721234
@JsonProperty("_meta") Map<String, Object> meta) implements Identifier { // @formatter:on
11731235

11741236
public Prompt(String name, String description, List<PromptArgument> arguments) {
1175-
this(name, null, description, arguments != null ? arguments : new ArrayList<>());
1237+
this(name, null, description, arguments != null ? arguments : new ArrayList<>(), null, null);
11761238
}
11771239

11781240
public Prompt(String name, String title, String description, List<PromptArgument> arguments) {
1179-
this(name, title, description, arguments != null ? arguments : new ArrayList<>(), null);
1241+
this(name, title, description, arguments != null ? arguments : new ArrayList<>(), null, null);
1242+
}
1243+
1244+
public Prompt(String name, String title, String description, List<PromptArgument> arguments,
1245+
Map<String, Object> meta) {
1246+
this(name, title, description, arguments != null ? arguments : new ArrayList<>(), null, meta);
11801247
}
11811248
}
11821249

@@ -1366,6 +1433,7 @@ public record Tool( // @formatter:off
13661433
@JsonProperty("inputSchema") JsonSchema inputSchema,
13671434
@JsonProperty("outputSchema") Map<String, Object> outputSchema,
13681435
@JsonProperty("annotations") ToolAnnotations annotations,
1436+
@JsonProperty("icons") List<Icon> icons,
13691437
@JsonProperty("_meta") Map<String, Object> meta) { // @formatter:on
13701438

13711439
public static Builder builder() {
@@ -1386,6 +1454,8 @@ public static class Builder {
13861454

13871455
private ToolAnnotations annotations;
13881456

1457+
private List<Icon> icons;
1458+
13891459
private Map<String, Object> meta;
13901460

13911461
public Builder name(String name) {
@@ -1428,14 +1498,19 @@ public Builder annotations(ToolAnnotations annotations) {
14281498
return this;
14291499
}
14301500

1501+
public Builder icons(List<Icon> icons) {
1502+
this.icons = icons;
1503+
return this;
1504+
}
1505+
14311506
public Builder meta(Map<String, Object> meta) {
14321507
this.meta = meta;
14331508
return this;
14341509
}
14351510

14361511
public Tool build() {
14371512
Assert.hasText(name, "name must not be empty");
1438-
return new Tool(name, title, description, inputSchema, outputSchema, annotations, meta);
1513+
return new Tool(name, title, description, inputSchema, outputSchema, annotations, icons, meta);
14391514
}
14401515

14411516
}

0 commit comments

Comments
 (0)