diff --git a/build.gradle.kts b/build.gradle.kts index 96fd3041..c203c4f6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -219,6 +219,7 @@ kotlin { implementation(libs.ktor.server.test.host) implementation(libs.kotlinx.coroutines.test) implementation(libs.kotlinx.coroutines.debug) + implementation(libs.kotest.assertions.json) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57d552cd..2265caea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,6 +13,7 @@ logging = "7.0.0" jreleaser = "1.15.0" binaryCompatibilityValidatorPlugin = "0.17.0" slf4j = "2.0.16" +kotest = "5.9.1" [libraries] # Kotlinx libraries @@ -32,8 +33,7 @@ kotlinx-coroutines-debug = { group = "org.jetbrains.kotlinx", name = "kotlinx-co ktor-server-test-host = { group = "io.ktor", name = "ktor-server-test-host", version.ref = "ktor" } mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" } - - +kotest-assertions-json = { group = "io.kotest", name = "kotest-assertions-json", version.ref = "kotest" } [plugins] kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } diff --git a/src/commonTest/kotlin/ToolSerializationTest.kt b/src/commonTest/kotlin/ToolSerializationTest.kt new file mode 100644 index 00000000..90c5c109 --- /dev/null +++ b/src/commonTest/kotlin/ToolSerializationTest.kt @@ -0,0 +1,57 @@ +package io.modelcontextprotocol.kotlin.sdk + +import io.kotest.assertions.json.shouldEqualJson +import io.modelcontextprotocol.kotlin.sdk.shared.McpJson +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.buildJsonObject +import kotlin.test.Test +import kotlin.test.assertEquals + +class ToolSerializationTest { + + // see https://docs.anthropic.com/en/docs/build-with-claude/tool-use + /* language=json */ + private val getWeatherToolJson = """ + { + "name": "get_weather", + "description": "Get the current weather in a given location", + "inputSchema": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA" + } + }, + "required": ["location"] + } + } + """.trimIndent() + + val getWeatherTool = Tool( + name = "get_weather", + description = "Get the current weather in a given location", + inputSchema = Tool.Input( + properties = buildJsonObject { + put("location", buildJsonObject { + put("type", JsonPrimitive("string")) + put("description", JsonPrimitive("The city and state, e.g. San Francisco, CA")) + }) + }, + required = listOf("location") + ) + ) + + @Test + fun `should serialize get_weather tool`() { + McpJson.encodeToString(getWeatherTool) shouldEqualJson getWeatherToolJson + } + + @Test + fun `should deserialize get_weather tool`() { + val tool = McpJson.decodeFromString(getWeatherToolJson) + assertEquals(expected = getWeatherTool, actual = tool) + } + +} \ No newline at end of file