1010import java .util .List ;
1111import java .util .Map ;
1212
13+ import org .slf4j .Logger ;
14+ import org .slf4j .LoggerFactory ;
15+
1316import com .fasterxml .jackson .annotation .JsonCreator ;
1417import com .fasterxml .jackson .annotation .JsonIgnore ;
1518import com .fasterxml .jackson .annotation .JsonIgnoreProperties ;
1619import com .fasterxml .jackson .annotation .JsonInclude ;
1720import com .fasterxml .jackson .annotation .JsonProperty ;
1821import com .fasterxml .jackson .annotation .JsonSubTypes ;
1922import com .fasterxml .jackson .annotation .JsonTypeInfo ;
23+
2024import io .modelcontextprotocol .json .McpJsonMapper ;
2125import io .modelcontextprotocol .json .TypeRef ;
2226import 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