Skip to content

Commit 8edc5c7

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 5895b2e commit 8edc5c7

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
@@ -10,18 +10,20 @@
1010
import java.util.List;
1111
import java.util.Map;
1212

13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
1316
import com.fasterxml.jackson.annotation.JsonCreator;
1417
import com.fasterxml.jackson.annotation.JsonIgnore;
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
@@ -661,16 +663,54 @@ public ServerCapabilities build() {
661663
* past specs or fallback (if title isn't present).
662664
* @param title Intended for UI and end-user contexts
663665
* @param version The version of the implementation.
666+
* @param description An optional human-readable description of this implementation.
667+
* @param icons An optional list of icons for this implementation.
668+
* @param websiteUrl An optional URL of the website for this implementation.
664669
*/
665670
@JsonInclude(JsonInclude.Include.NON_ABSENT)
666671
@JsonIgnoreProperties(ignoreUnknown = true)
667672
public record Implementation( // @formatter:off
668673
@JsonProperty("name") String name,
669674
@JsonProperty("title") String title,
670-
@JsonProperty("version") String version) implements Identifier { // @formatter:on
675+
@JsonProperty("version") String version,
676+
@JsonProperty("description") String description,
677+
@JsonProperty("icons") List<Icon> icons,
678+
@JsonProperty("websiteUrl") String websiteUrl) implements Identifier { // @formatter:on
671679

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

@@ -792,6 +832,7 @@ public record Resource( // @formatter:off
792832
@JsonProperty("mimeType") String mimeType,
793833
@JsonProperty("size") Long size,
794834
@JsonProperty("annotations") Annotations annotations,
835+
@JsonProperty("icons") List<Icon> icons,
795836
@JsonProperty("_meta") Map<String, Object> meta) implements ResourceContent { // @formatter:on
796837

797838
public static Builder builder() {
@@ -814,6 +855,8 @@ public static class Builder {
814855

815856
private Annotations annotations;
816857

858+
private List<Icon> icons;
859+
817860
private Map<String, Object> meta;
818861

819862
public Builder uri(String uri) {
@@ -851,6 +894,11 @@ public Builder annotations(Annotations annotations) {
851894
return this;
852895
}
853896

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

863-
return new Resource(uri, name, title, description, mimeType, size, annotations, meta);
911+
return new Resource(uri, name, title, description, mimeType, size, annotations, icons, meta);
864912
}
865913

866914
}
@@ -893,18 +941,24 @@ public record ResourceTemplate( // @formatter:off
893941
@JsonProperty("description") String description,
894942
@JsonProperty("mimeType") String mimeType,
895943
@JsonProperty("annotations") Annotations annotations,
944+
@JsonProperty("icons") List<Icon> icons,
896945
@JsonProperty("_meta") Map<String, Object> meta) implements Annotated, Identifier, Meta { // @formatter:on
897946

898947
public ResourceTemplate(String uriTemplate, String name, String title, String description, String mimeType,
899948
Annotations annotations) {
900-
this(uriTemplate, name, title, description, mimeType, annotations, null);
949+
this(uriTemplate, name, title, description, mimeType, annotations, null, null);
901950
}
902951

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

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

924978
private Annotations annotations;
925979

980+
private List<Icon> icons;
981+
926982
private Map<String, Object> meta;
927983

928984
public Builder uriTemplate(String uri) {
@@ -955,6 +1011,11 @@ public Builder annotations(Annotations annotations) {
9551011
return this;
9561012
}
9571013

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

967-
return new ResourceTemplate(uriTemplate, name, title, description, mimeType, annotations, meta);
1028+
return new ResourceTemplate(uriTemplate, name, title, description, mimeType, annotations, icons, meta);
9681029
}
9691030

9701031
}
@@ -1168,14 +1229,20 @@ public record Prompt( // @formatter:off
11681229
@JsonProperty("title") String title,
11691230
@JsonProperty("description") String description,
11701231
@JsonProperty("arguments") List<PromptArgument> arguments,
1232+
@JsonProperty("icons") List<Icon> icons,
11711233
@JsonProperty("_meta") Map<String, Object> meta) implements Identifier { // @formatter:on
11721234

11731235
public Prompt(String name, String description, List<PromptArgument> arguments) {
1174-
this(name, null, description, arguments, null);
1236+
this(name, null, description, arguments, null, null);
11751237
}
11761238

11771239
public Prompt(String name, String title, String description, List<PromptArgument> arguments) {
1178-
this(name, title, description, arguments, null);
1240+
this(name, title, description, arguments, null, null);
1241+
}
1242+
1243+
public Prompt(String name, String title, String description, List<PromptArgument> arguments,
1244+
Map<String, Object> meta) {
1245+
this(name, title, description, arguments, null, meta);
11791246
}
11801247
}
11811248

@@ -1367,6 +1434,7 @@ public record Tool( // @formatter:off
13671434
@JsonProperty("inputSchema") Map<String, Object> inputSchema,
13681435
@JsonProperty("outputSchema") Map<String, Object> outputSchema,
13691436
@JsonProperty("annotations") ToolAnnotations annotations,
1437+
@JsonProperty("icons") List<Icon> icons,
13701438
@JsonProperty("_meta") Map<String, Object> meta) { // @formatter:on
13711439

13721440
public static Builder builder() {
@@ -1387,6 +1455,8 @@ public static class Builder {
13871455

13881456
private ToolAnnotations annotations;
13891457

1458+
private List<Icon> icons;
1459+
13901460
private Map<String, Object> meta;
13911461

13921462
public Builder name(String name) {
@@ -1450,14 +1520,19 @@ public Builder annotations(ToolAnnotations annotations) {
14501520
return this;
14511521
}
14521522

1523+
public Builder icons(List<Icon> icons) {
1524+
this.icons = icons;
1525+
return this;
1526+
}
1527+
14531528
public Builder meta(Map<String, Object> meta) {
14541529
this.meta = meta;
14551530
return this;
14561531
}
14571532

14581533
public Tool build() {
14591534
Assert.hasText(name, "name must not be empty");
1460-
return new Tool(name, title, description, inputSchema, outputSchema, annotations, meta);
1535+
return new Tool(name, title, description, inputSchema, outputSchema, annotations, icons, meta);
14611536
}
14621537

14631538
}

0 commit comments

Comments
 (0)