From 01d61792548ce73218878918b39d0e0267007a86 Mon Sep 17 00:00:00 2001 From: JiHwan Oh Date: Wed, 23 Apr 2025 23:22:48 +0900 Subject: [PATCH 1/2] Introduce RichJsonSchema and its builder --- .../modelcontextprotocol/spec/McpSchema.java | 209 +++++++++++++++++- 1 file changed, 207 insertions(+), 2 deletions(-) diff --git a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java index e77edb3b..bbb821f1 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java +++ b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java @@ -706,6 +706,208 @@ public record JsonSchema( // @formatter:off @JsonProperty("additionalProperties") Boolean additionalProperties) { } // @formatter:on + @JsonInclude(JsonInclude.Include.NON_ABSENT) + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class RichJsonSchema { + private String type; + private String title; + private String description; + private Map properties; + private List required; + private Boolean additionalProperties; + private Object defaultValue; + private List enumValues; + private Integer maxLength; + private Integer minLength; + private String pattern; + + @JsonProperty("type") + public String getType() { + return type; + } + + @JsonProperty("title") + public String getTitle() { + return title; + } + + @JsonProperty("description") + public String getDescription() { + return description; + } + + @JsonProperty("properties") + public Map getProperties() { + return properties; + } + + @JsonProperty("required") + public List getRequired() { + return required; + } + + @JsonProperty("additionalProperties") + public Boolean getAdditionalProperties() { + return additionalProperties; + } + + @JsonProperty("default") + public Object getDefault() { + return defaultValue; + } + + @JsonProperty("enum") + public List getEnum() { + return enumValues; + } + + @JsonProperty("maxLength") + public Integer getMaxLength() { + return maxLength; + } + + @JsonProperty("minLength") + public Integer getMinLength() { + return minLength; + } + + @JsonProperty("pattern") + public String getPattern() { + return pattern; + } + + public static RichJsonSchema from(JsonSchema schema) { + Assert.notNull(schema, "schema"); + return new RichJsonSchema.Builder(schema.type) + .properties(schema.properties) + .required(schema.required) + .build(); + } + + public static RichJsonSchema.Builder arrayBuilder() { + return new RichJsonSchema.Builder("array"); + } + + public static RichJsonSchema.Builder objectBuilder() { + return new RichJsonSchema.Builder("object"); + } + + public static RichJsonSchema.Builder numberBuilder() { + return new RichJsonSchema.Builder("number"); + } + + public static RichJsonSchema.Builder stringBuilder() { + return new RichJsonSchema.Builder("string"); + } + + public static RichJsonSchema.Builder booleanBuilder() { + return new RichJsonSchema.Builder("boolean"); + } + + public static class Builder { + private final RichJsonSchema schema = new RichJsonSchema(); + + private Builder() {} + private Builder(String type) { + this.schema.type = type; + } + + public Builder title(String title) { + Assert.notNull(title, "title must not be null"); + this.schema.title = title; + return this; + } + + public Builder description(String description) { + Assert.notNull(description, "description must not be null"); + this.schema.description = description; + return this; + } + + public Builder properties(Map properties) { + Assert.notNull(properties, "properties must not be null"); + this.schema.properties = properties; + return this; + } + + public Builder addProperty(String name, Object value) { + Assert.notNull(name, "name must not be null"); + Assert.notNull(value, "value must not be null"); + addProperty(name, value, false); + return this; + } + + public Builder addProperty(String name, Object value, Boolean required) { + Assert.notNull(name, "name must not be null"); + Assert.notNull(value, "value must not be null"); + Assert.notNull(required, "required must not be null"); + if (this.schema.properties == null) { + this.schema.properties = new HashMap<>(); + } + this.schema.properties.put(name, value); + if (required) { + addRequired(name); + } + return this; + } + + public Builder required(List required) { + Assert.notNull(required, "required must not be null"); + this.schema.required = required; + return this; + } + + public Builder addRequired(String required) { + Assert.notNull(required, "required must not be null"); + if (this.schema.required == null) { + this.schema.required = new ArrayList<>(); + } + this.schema.required.add(required); + return this; + } + + public Builder additionalProperties(Boolean additionalProperties) { + Assert.notNull(additionalProperties, "additionalProperties must not be null"); + this.schema.additionalProperties = additionalProperties; + return this; + } + + public Builder defaultValue(Object defaultValue) { + Assert.notNull(defaultValue, "defaultValue must not be null"); + this.schema.defaultValue = defaultValue; + return this; + } + + public Builder enumValues(List enumValues) { + Assert.notNull(enumValues, "enumValues must not be null"); + this.schema.enumValues = enumValues; + return this; + } + + public Builder maxLength(Integer maxLength) { + Assert.notNull(maxLength, "maxLength must not be null"); + this.schema.maxLength = maxLength; + return this; + } + + public Builder minLength(Integer minLength) { + Assert.notNull(minLength, "minLength must not be null"); + this.schema.minLength = minLength; + return this; + } + + public Builder pattern(String pattern) { + Assert.notNull(pattern, "pattern must not be null"); + this.schema.pattern = pattern; + return this; + } + + public RichJsonSchema build() { + return this.schema; + } + } + } + /** * Represents a tool that the server provides. Tools enable servers to expose * executable functionality to the system. Through these tools, you can interact with @@ -724,12 +926,15 @@ public record JsonSchema( // @formatter:off public record Tool( // @formatter:off @JsonProperty("name") String name, @JsonProperty("description") String description, - @JsonProperty("inputSchema") JsonSchema inputSchema) { + @JsonProperty("inputSchema") RichJsonSchema inputSchema) { public Tool(String name, String description, String schema) { this(name, description, parseSchema(schema)); } - + + public Tool(String name, String description, JsonSchema inputSchema) { + this(name, description, RichJsonSchema.from(inputSchema)); + } } // @formatter:on private static JsonSchema parseSchema(String schema) { From 1d94d2fae5aec98eb6ce935c557a8111c80fb8d9 Mon Sep 17 00:00:00 2001 From: JiHwan Oh Date: Wed, 23 Apr 2025 23:28:40 +0900 Subject: [PATCH 2/2] format --- .../modelcontextprotocol/spec/McpSchema.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java index bbb821f1..93ad0c9e 100644 --- a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java +++ b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java @@ -709,16 +709,27 @@ public record JsonSchema( // @formatter:off @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public static final class RichJsonSchema { + private String type; + private String title; + private String description; + private Map properties; + private List required; + private Boolean additionalProperties; + private Object defaultValue; + private List enumValues; + private Integer maxLength; + private Integer minLength; + private String pattern; @JsonProperty("type") @@ -778,10 +789,9 @@ public String getPattern() { public static RichJsonSchema from(JsonSchema schema) { Assert.notNull(schema, "schema"); - return new RichJsonSchema.Builder(schema.type) - .properties(schema.properties) - .required(schema.required) - .build(); + return new RichJsonSchema.Builder(schema.type).properties(schema.properties) + .required(schema.required) + .build(); } public static RichJsonSchema.Builder arrayBuilder() { @@ -805,9 +815,12 @@ public static RichJsonSchema.Builder booleanBuilder() { } public static class Builder { + private final RichJsonSchema schema = new RichJsonSchema(); - private Builder() {} + private Builder() { + } + private Builder(String type) { this.schema.type = type; } @@ -905,7 +918,9 @@ public Builder pattern(String pattern) { public RichJsonSchema build() { return this.schema; } + } + } /**