Add $defs to ToolSchema and tests (#526)
Add $defs support in ToolSchema and update tests. Motivation and Context Fix parsing when tool schemas include $defs. How Has This Been Tested? `./gradlew :kotlin-sdk-core:jvmTest --tests "io.modelcontextprotocol.kotlin.sdk.types.ToolsTest"` Breaking Changes No. Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update Checklist - [x] I have read the MCP Documentation - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [ ] I have added appropriate error handling - [ ] I have added or updated documentation as needed Additional context N/A
This commit is contained in:
parent
212cbfa325
commit
1b255a2baf
3 changed files with 125 additions and 5 deletions
|
|
@ -4525,13 +4525,15 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ToolListChangedNotif
|
|||
public final class io/modelcontextprotocol/kotlin/sdk/types/ToolSchema {
|
||||
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;)V
|
||||
public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;)V
|
||||
public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Lkotlinx/serialization/json/JsonObject;
|
||||
public final fun component2 ()Ljava/util/List;
|
||||
public final fun copy (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;)Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
|
||||
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
|
||||
public final fun component3 ()Lkotlinx/serialization/json/JsonObject;
|
||||
public final fun copy (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
|
||||
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getDefs ()Lkotlinx/serialization/json/JsonObject;
|
||||
public final fun getProperties ()Lkotlinx/serialization/json/JsonObject;
|
||||
public final fun getRequired ()Ljava/util/List;
|
||||
public final fun getType ()Ljava/lang/String;
|
||||
|
|
|
|||
|
|
@ -78,9 +78,15 @@ public data class Tool(
|
|||
* @property type Always "object" for tool schemas.
|
||||
* @property properties Optional map of property names to their schema definitions.
|
||||
* @property required Optional list of property names that are required.
|
||||
* @property defs Optional schema definitions available to references in [properties]. Serialized as `$defs`.
|
||||
*/
|
||||
@Serializable
|
||||
public data class ToolSchema(val properties: JsonObject? = null, val required: List<String>? = null) {
|
||||
public data class ToolSchema(
|
||||
val properties: JsonObject? = null,
|
||||
val required: List<String>? = null,
|
||||
@SerialName("\$defs")
|
||||
val defs: JsonObject? = null,
|
||||
) {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@EncodeDefault
|
||||
val type: String = "object"
|
||||
|
|
|
|||
|
|
@ -152,6 +152,57 @@ class ToolsTest {
|
|||
assertEquals("language", tool.meta?.get("category")?.jsonPrimitive?.content)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should serialize ToolSchema with defs`() {
|
||||
val tool = toolWithDefs()
|
||||
|
||||
val json = McpJson.encodeToString(tool)
|
||||
|
||||
json shouldEqualJson toolWithDefsJson()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should deserialize ToolSchema with defs`() {
|
||||
val json = $$"""
|
||||
{
|
||||
"name": "create-page",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"parentRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"page_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"parent": {
|
||||
"$ref": "#/$defs/parentRequest"
|
||||
}
|
||||
},
|
||||
"required": ["parent"]
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val tool = McpJson.decodeFromString<Tool>(json)
|
||||
|
||||
val schema = tool.inputSchema
|
||||
val defs = schema.defs
|
||||
assertNotNull(defs)
|
||||
val parentRequest = defs["parentRequest"]?.jsonObject
|
||||
assertNotNull(parentRequest)
|
||||
assertEquals("object", parentRequest["type"]?.jsonPrimitive?.content)
|
||||
assertEquals(
|
||||
$$"#/$defs/parentRequest",
|
||||
schema.properties?.get("parent")?.jsonObject?.get($$"$ref")?.jsonPrimitive?.content,
|
||||
)
|
||||
assertEquals(listOf("parent"), schema.required)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should serialize CallToolRequest with arguments`() {
|
||||
val request = CallToolRequest(
|
||||
|
|
@ -520,4 +571,65 @@ class ToolsTest {
|
|||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
private fun toolWithDefs(): Tool = Tool(
|
||||
name = "create-page",
|
||||
inputSchema = toolSchemaWithDefs(),
|
||||
)
|
||||
|
||||
private fun toolSchemaWithDefs(): ToolSchema = ToolSchema(
|
||||
properties = buildJsonObject {
|
||||
put(
|
||||
"parent",
|
||||
buildJsonObject {
|
||||
put($$"$ref", $$"#/$defs/parentRequest")
|
||||
},
|
||||
)
|
||||
},
|
||||
required = listOf("parent"),
|
||||
defs = buildJsonObject {
|
||||
put(
|
||||
"parentRequest",
|
||||
buildJsonObject {
|
||||
put("type", "object")
|
||||
put(
|
||||
"properties",
|
||||
buildJsonObject {
|
||||
put(
|
||||
"page_id",
|
||||
buildJsonObject {
|
||||
put("type", "string")
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
private fun toolWithDefsJson(): String = $$"""
|
||||
{
|
||||
"name": "create-page",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"$defs": {
|
||||
"parentRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"page_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"parent": {
|
||||
"$ref": "#/$defs/parentRequest"
|
||||
}
|
||||
},
|
||||
"required": ["parent"]
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue