- 
                Notifications
    You must be signed in to change notification settings 
- Fork 704
Description
Expected Behavior
The McpSchema.Tool record should be able to represent the full structure of a JSON Schema provided for inputSchema, including top-level definitions specified using the $defs (or older definitions) keyword. This would allow server implementers to define complex, reusable types within the schema itself and use $ref within the properties to refer to them.
Ideally, the McpSchema.JsonSchema record would be enhanced, or an alternative mechanism provided, to retain this information.
Example of desired outcome:
// Hypothetical enhanced JsonSchema record
public record JsonSchema(
    @JsonProperty("type") String type,
    @JsonProperty("properties") Map<String, Object> properties,
    @JsonProperty("required") List<String> required,
    @JsonProperty("additionalProperties") Boolean additionalProperties,
    @JsonProperty("$defs") Map<String, Object> defs // Added field for definitions
) { }
// Or potentially keep JsonSchema simple and parse into a more generic Map
// Tool constructor might change:
public Tool(String name, String description, Map<String, Object> fullInputSchema) {
    // ... internal handling ...
}
// Example usage when creating a Tool:
String complexSchemaJson = """
{
  "type": "object",
  "$defs": {
    "Address": {
      "type": "object",
      "properties": {
        "street": {"type": "string"},
        "city": {"type": "string"}
      },
      "required": ["street", "city"]
    }
  },
  "properties": {
    "name": {"type": "string"},
    "shippingAddress": {"$ref": "#/$defs/Address"}
  },
  "required": ["name", "shippingAddress"]
}
""";
// Current SDK constructor loses $defs:
// McpSchema.Tool tool = new McpSchema.Tool("addressTool", "Handles addresses", complexSchemaJson);
// tool.inputSchema() would NOT contain the $defs section.
// Desired behavior:
// Somehow create a Tool object where the full structure, including $defs, is preserved
// and potentially accessible, allowing for more robust schema validation or generation
// on the client or server side based on the full definition.Current Behavior
Currently, the McpSchema.JsonSchema record only defines fields for type, properties, required, and additionalProperties.
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonIgnoreProperties(ignoreUnknown = true)
public record JsonSchema(
    @JsonProperty("type") String type,
    @JsonProperty("properties") Map<String, Object> properties,
    @JsonProperty("required") List<String> required,
    @JsonProperty("additionalProperties") Boolean additionalProperties
) { }When a JSON schema string is provided to the McpSchema.Tool(String name, String description, String schema) constructor, the internal parseSchema method deserializes this string directly into the McpSchema.JsonSchema record using Jackson (OBJECT_MAPPER.readValue(schema, JsonSchema.class)).
Due to the limited fields in the JsonSchema record and the @JsonIgnoreProperties(ignoreUnknown = true) annotation, any top-level properties in the JSON string that do not match the record's fields, specifically $defs (or definitions), are ignored and discarded during deserialization.
As a result, it's impossible to represent or convey tool input schemas that rely on internal definitions using $defs through the current McpSchema.Tool structure. The structural information about reusable types defined in $defs is lost.
Context
We are developing an MCP server using the Java SDK where our tools accept complex input structures. To promote consistency and avoid repetition, we want to define reusable data types within the tool's inputSchema using the standard JSON Schema $defs keyword and reference them using $ref within the properties.
The current limitation prevents us from accurately representing these schemas within the McpSchema.Tool object. This hinders:
- Client-side Validation: Clients receiving the Tooldefinition cannot perform complete validation if the schema relies on$defsthat are missing.
- Schema Clarity: The schema conveyed via MCP doesn't fully represent the intended structure.
- Code Generation: Tooling that might generate client-side code or documentation based on the inputSchemawill lack the necessary definitions.
Alternatives Considered:
- External References: Using $refto point to external URIs where the full schema (including definitions) is hosted. This adds complexity (hosting schemas) and potential latency.
- Inlining Definitions: Repeating the full definition of a reusable type everywhere it's used within the properties. This violates the DRY principle and makes schemas verbose and hard to maintain.
- Flattening Schemas: Pre-processing schemas to resolve all $refs and remove$defsbefore passing the string to theToolconstructor. This requires an external JSON Schema processing library and adds build complexity.
Workarounds:
- The primary workaround is schema flattening/pre-processing before creating the Toolobject, which is cumbersome.
Adding support for $defs directly within the SDK's schema representation would significantly improve the ability to define and communicate complex tool interfaces according to standard JSON Schema practices.