1111import java .util .List ;
1212import java .util .Map ;
1313
14+ import org .slf4j .Logger ;
15+ import org .slf4j .LoggerFactory ;
16+
1417import com .fasterxml .jackson .annotation .JsonCreator ;
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
@@ -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