Skip to content

Commit 61fab2f

Browse files
authored
feat: add $schema field to ToolSchema per SEP-1613 (#696)
Add optional `$schema` field to `ToolSchema`, establishing JSON Schema 2020-12 as the default dialect per SEP-1613. closes #422 ## How Has This Been Tested? unit tests ## Breaking Changes none ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] 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](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed
1 parent 081a635 commit 61fab2f

3 files changed

Lines changed: 72 additions & 7 deletions

File tree

kotlin-sdk-core/api/kotlin-sdk-core.api

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5135,17 +5135,19 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ToolListChangedNotif
51355135
public final class io/modelcontextprotocol/kotlin/sdk/types/ToolSchema {
51365136
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema$Companion;
51375137
public fun <init> ()V
5138-
public fun <init> (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;)V
5139-
public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
5140-
public final fun component1 ()Lkotlinx/serialization/json/JsonObject;
5141-
public final fun component2 ()Ljava/util/List;
5142-
public final fun component3 ()Lkotlinx/serialization/json/JsonObject;
5143-
public final fun copy (Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
5144-
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;
5138+
public fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;)V
5139+
public synthetic fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
5140+
public final fun component1 ()Ljava/lang/String;
5141+
public final fun component2 ()Lkotlinx/serialization/json/JsonObject;
5142+
public final fun component3 ()Ljava/util/List;
5143+
public final fun component4 ()Lkotlinx/serialization/json/JsonObject;
5144+
public final fun copy (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
5145+
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
51455146
public fun equals (Ljava/lang/Object;)Z
51465147
public final fun getDefs ()Lkotlinx/serialization/json/JsonObject;
51475148
public final fun getProperties ()Lkotlinx/serialization/json/JsonObject;
51485149
public final fun getRequired ()Ljava/util/List;
5150+
public final fun getSchema ()Ljava/lang/String;
51495151
public final fun getType ()Ljava/lang/String;
51505152
public fun hashCode ()I
51515153
public fun toString ()Ljava/lang/String;

kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/tools.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ public fun CallToolResult.Companion.error(content: String, meta: JsonObject? = n
3939
* if both [title] and [annotations].[title] are not provided.
4040
* @property inputSchema A JSON Schema object defining the expected parameters for the tool.
4141
* Must be an object type schema. Defines what arguments the tool accepts.
42+
* Defaults to the JSON Schema 2020-12 dialect when no explicit `$schema` is provided.
4243
* @property description A human-readable description of the tool and when to use it.
4344
* Clients can use this to improve the LLM's understanding of available tools.
4445
* It can be thought of like a "hint" to the model.
4546
* @property outputSchema An optional JSON Schema object defining the structure of the tool's output
4647
* returned in the [structuredContent][CallToolResult.structuredContent] field of a [CallToolResult].
4748
* Must be an object type schema if provided.
49+
* Defaults to the JSON Schema 2020-12 dialect when no explicit `$schema` is provided.
4850
* @property title Optional human-readable display name for this tool.
4951
* Intended for UI and end-user contexts, optimized to be easily understood
5052
* even by those unfamiliar with domain-specific terminology.
@@ -77,14 +79,20 @@ public data class Tool(
7779
* A JSON Schema for tool input or output parameters.
7880
*
7981
* This is a simplified schema structure that must be of type "object".
82+
* Defaults to the JSON Schema 2020-12 dialect when no explicit [schema] (`$schema`) is provided.
8083
*
84+
* @property schema Optional URI identifying the JSON Schema dialect (e.g.,
85+
* `https://json-schema.org/draft/2020-12/schema`). Serialized as `$schema`.
86+
* When absent, JSON Schema 2020-12 is assumed by default.
8187
* @property type Always "object" for tool schemas.
8288
* @property properties Optional map of property names to their schema definitions.
8389
* @property required Optional list of property names that are required.
8490
* @property defs Optional schema definitions available to references in [properties]. Serialized as `$defs`.
8591
*/
8692
@Serializable
8793
public data class ToolSchema(
94+
@SerialName("\$schema")
95+
val schema: String? = null,
8896
val properties: JsonObject? = null,
8997
val required: List<String>? = null,
9098
@SerialName("\$defs")

kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ToolsTest.kt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,61 @@ class ToolsTest {
158158
assertEquals("language", tool.meta?.get("category")?.jsonPrimitive?.content)
159159
}
160160

161+
@Test
162+
fun `should serialize ToolSchema with schema field`() {
163+
val tool = Tool(
164+
name = "typed-tool",
165+
inputSchema = ToolSchema(
166+
schema = "https://json-schema.org/draft/2020-12/schema",
167+
properties = buildJsonObject {
168+
put("name", buildJsonObject { put("type", "string") })
169+
},
170+
),
171+
)
172+
173+
verifySerialization(
174+
tool,
175+
McpJson,
176+
$$"""
177+
{
178+
"name": "typed-tool",
179+
"inputSchema": {
180+
"$schema": "https://json-schema.org/draft/2020-12/schema",
181+
"type": "object",
182+
"properties": {
183+
"name": {
184+
"type": "string"
185+
}
186+
}
187+
}
188+
}
189+
""".trimIndent(),
190+
)
191+
}
192+
193+
@Test
194+
fun `should deserialize ToolSchema with schema field`() {
195+
val json = $$"""
196+
{
197+
"name": "typed-tool",
198+
"inputSchema": {
199+
"$schema": "https://json-schema.org/draft/2020-12/schema",
200+
"type": "object",
201+
"properties": {
202+
"name": {
203+
"type": "string"
204+
}
205+
}
206+
}
207+
}
208+
""".trimIndent()
209+
210+
val tool = verifyDeserialization<Tool>(McpJson, json)
211+
212+
assertEquals("https://json-schema.org/draft/2020-12/schema", tool.inputSchema.schema)
213+
assertNotNull(tool.inputSchema.properties)
214+
}
215+
161216
@Test
162217
fun `should serialize ToolSchema with defs`() {
163218
val tool = toolWithDefs()

0 commit comments

Comments
 (0)