diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpSchema.java b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpSchema.java index 734cff237..2c0561e41 100644 --- a/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpSchema.java +++ b/mcp-core/src/main/java/io/modelcontextprotocol/spec/McpSchema.java @@ -610,16 +610,38 @@ public ServerCapabilities build() { * past specs or fallback (if title isn't present). * @param title Intended for UI and end-user contexts * @param version The version of the implementation. + * @param icons Optional list of icons that can be used to visually represent this + * implementation in client UIs. Multiple icons can be provided for different sizes + * and formats. + * @param websiteUrl Optional URL to the website or documentation for this + * implementation. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record Implementation( // @formatter:off @JsonProperty("name") String name, @JsonProperty("title") String title, - @JsonProperty("version") String version) implements Identifier { // @formatter:on + @JsonProperty("version") String version, + @JsonProperty("icons") List icons, + @JsonProperty("websiteUrl") String websiteUrl) implements Identifier { // @formatter:on + /** + * Creates an Implementation with just name and version. + * @param name The implementation name + * @param version The implementation version + */ public Implementation(String name, String version) { - this(name, null, version); + this(name, null, version, null, null); + } + + /** + * Creates an Implementation with name, title, and version. + * @param name The implementation name + * @param title The display title + * @param version The implementation version + */ + public Implementation(String name, String title, String version) { + this(name, title, version, null, null); } } @@ -713,6 +735,50 @@ public interface Identifier { } + /** + * Represents an icon that can be used to visually identify servers, tools, resources, + * or prompts in client UIs. + * + *

+ * Icons can be provided as HTTP/HTTPS URLs or as data URIs containing base64-encoded + * image data. Clients should display icons at appropriate sizes based on their UI + * context. + * + * @param src The URI of the icon. Can be an HTTP/HTTPS URL or a data URI (e.g., + * "data:image/png;base64,..."). + * @param mimeType Optional MIME type of the icon (e.g., "image/png", + * "image/svg+xml"). If not provided, clients should infer the type from the URI or + * content. + * @param sizes Optional size specification following Web Manifest format. Can be a + * single size (e.g., "48x48"), multiple sizes separated by spaces (e.g., "48x48 + * 96x96"), or "any" for scalable formats like SVG. + * @see MCP + * Icons Specification + */ + @JsonInclude(JsonInclude.Include.NON_ABSENT) + @JsonIgnoreProperties(ignoreUnknown = true) + public record Icon( // @formatter:off + @JsonProperty("src") String src, + @JsonProperty("mimeType") String mimeType, + @JsonProperty("sizes") String sizes) { // @formatter:on + + /** + * Creates an Icon with just a source URL. + * @param src The URI of the icon + */ + public Icon(String src) { + this(src, null, null); + } + + /** + * Canonical constructor with validation. + */ + public Icon { + Assert.hasText(src, "Icon src must not be null or empty"); + } + } + /** * A known resource that the server is capable of reading. * @@ -729,6 +795,8 @@ public interface Identifier { * sizes and estimate context window usage. * @param annotations Optional annotations for the client. The client can use * annotations to inform how objects are used or displayed. + * @param icons Optional list of icons that can be used to visually represent this + * resource in client UIs. * @param meta See specification for notes on _meta usage */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @@ -741,6 +809,7 @@ public record Resource( // @formatter:off @JsonProperty("mimeType") String mimeType, @JsonProperty("size") Long size, @JsonProperty("annotations") Annotations annotations, + @JsonProperty("icons") List icons, @JsonProperty("_meta") Map meta) implements ResourceContent { // @formatter:on /** @@ -750,7 +819,7 @@ public record Resource( // @formatter:off @Deprecated public Resource(String uri, String name, String title, String description, String mimeType, Long size, Annotations annotations) { - this(uri, name, title, description, mimeType, size, annotations, null); + this(uri, name, title, description, mimeType, size, annotations, null, null); } /** @@ -760,7 +829,7 @@ public Resource(String uri, String name, String title, String description, Strin @Deprecated public Resource(String uri, String name, String description, String mimeType, Long size, Annotations annotations) { - this(uri, name, null, description, mimeType, size, annotations, null); + this(uri, name, null, description, mimeType, size, annotations, null, null); } /** @@ -769,7 +838,7 @@ public Resource(String uri, String name, String description, String mimeType, Lo */ @Deprecated public Resource(String uri, String name, String description, String mimeType, Annotations annotations) { - this(uri, name, null, description, mimeType, null, annotations, null); + this(uri, name, null, description, mimeType, null, annotations, null, null); } public static Builder builder() { @@ -792,6 +861,8 @@ public static class Builder { private Annotations annotations; + private List icons; + private Map meta; public Builder uri(String uri) { @@ -829,6 +900,11 @@ public Builder annotations(Annotations annotations) { return this; } + public Builder icons(List icons) { + this.icons = icons; + return this; + } + public Builder meta(Map meta) { this.meta = meta; return this; @@ -838,7 +914,7 @@ public Resource build() { Assert.hasText(uri, "uri must not be empty"); Assert.hasText(name, "name must not be empty"); - return new Resource(uri, name, title, description, mimeType, size, annotations, meta); + return new Resource(uri, name, title, description, mimeType, size, annotations, icons, meta); } } @@ -1137,6 +1213,8 @@ public BlobResourceContents(String uri, String mimeType, String blob) { * @param title An optional title for the prompt. * @param description An optional description of what this prompt provides. * @param arguments A list of arguments to use for templating the prompt. + * @param icons Optional list of icons that can be used to visually represent this + * prompt in client UIs. * @param meta See specification for notes on _meta usage */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @@ -1146,14 +1224,15 @@ public record Prompt( // @formatter:off @JsonProperty("title") String title, @JsonProperty("description") String description, @JsonProperty("arguments") List arguments, + @JsonProperty("icons") List icons, @JsonProperty("_meta") Map meta) implements Identifier { // @formatter:on public Prompt(String name, String description, List arguments) { - this(name, null, description, arguments != null ? arguments : new ArrayList<>()); + this(name, null, description, arguments != null ? arguments : new ArrayList<>(), null, null); } public Prompt(String name, String title, String description, List arguments) { - this(name, title, description, arguments != null ? arguments : new ArrayList<>(), null); + this(name, title, description, arguments != null ? arguments : new ArrayList<>(), null, null); } } @@ -1332,6 +1411,8 @@ public record ToolAnnotations( // @formatter:off * @param outputSchema An optional JSON Schema object defining the structure of the * tool's output returned in the structuredContent field of a CallToolResult. * @param annotations Optional additional tool information. + * @param icons Optional list of icons that can be used to visually represent this + * tool in client UIs. * @param meta See specification for notes on _meta usage */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @@ -1343,6 +1424,7 @@ public record Tool( // @formatter:off @JsonProperty("inputSchema") JsonSchema inputSchema, @JsonProperty("outputSchema") Map outputSchema, @JsonProperty("annotations") ToolAnnotations annotations, + @JsonProperty("icons") List icons, @JsonProperty("_meta") Map meta) { // @formatter:on public static Builder builder() { @@ -1363,6 +1445,8 @@ public static class Builder { private ToolAnnotations annotations; + private List icons; + private Map meta; public Builder name(String name) { @@ -1405,6 +1489,11 @@ public Builder annotations(ToolAnnotations annotations) { return this; } + public Builder icons(List icons) { + this.icons = icons; + return this; + } + public Builder meta(Map meta) { this.meta = meta; return this; @@ -1412,7 +1501,7 @@ public Builder meta(Map meta) { public Tool build() { Assert.hasText(name, "name must not be empty"); - return new Tool(name, title, description, inputSchema, outputSchema, annotations, meta); + return new Tool(name, title, description, inputSchema, outputSchema, annotations, icons, meta); } }