Skip to content

Commit 21aec46

Browse files
nomisReve5l
andauthored
FEAT: Support all Tier 1, 2 and 3 targets by Kotlin & remove dependency on Kotest Json due to not supporting all targets (#151)
Co-authored-by: Leonid Stashevsky <[email protected]>
1 parent 058bba1 commit 21aec46

File tree

5 files changed

+93
-56
lines changed

5 files changed

+93
-56
lines changed

build.gradle.kts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,6 @@ kotlin {
220220
}
221221
}
222222

223-
iosArm64()
224-
iosX64()
225-
iosSimulatorArm64()
226-
227223
js(IR) {
228224
nodejs {
229225
testTask {
@@ -238,6 +234,31 @@ kotlin {
238234
nodejs()
239235
}
240236

237+
// Tier 1
238+
macosX64()
239+
macosArm64()
240+
iosArm64()
241+
iosX64()
242+
iosSimulatorArm64()
243+
244+
// Tier 2
245+
linuxX64()
246+
linuxArm64()
247+
watchosSimulatorArm64()
248+
watchosX64()
249+
// watchosArm32() not supported by libs.kotlin.logging
250+
watchosArm64()
251+
tvosSimulatorArm64()
252+
tvosX64()
253+
tvosArm64()
254+
255+
// Tier 3
256+
androidNativeArm32()
257+
androidNativeArm64()
258+
androidNativeX86()
259+
androidNativeX64()
260+
mingwX64()
261+
241262
explicitApi = ExplicitApiMode.Strict
242263

243264
jvmToolchain(21)
@@ -262,7 +283,6 @@ kotlin {
262283
implementation(libs.kotlin.test)
263284
implementation(libs.ktor.server.test.host)
264285
implementation(libs.kotlinx.coroutines.test)
265-
implementation(libs.kotest.assertions.json)
266286
}
267287
}
268288

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
package io.modelcontextprotocol.kotlin.sdk
22

3-
import io.kotest.assertions.json.shouldEqualJson
43
import io.modelcontextprotocol.kotlin.sdk.shared.McpJson
5-
import kotlinx.serialization.encodeToString
4+
import kotlinx.serialization.json.buildJsonObject
5+
import kotlinx.serialization.json.decodeFromJsonElement
6+
import kotlinx.serialization.json.encodeToJsonElement
7+
import kotlinx.serialization.json.put
68
import kotlin.test.Test
79
import kotlin.test.assertEquals
810

911
class AudioContentSerializationTest {
1012

11-
private val audioContentJson = """
12-
{
13-
"data": "base64-encoded-audio-data",
14-
"mimeType": "audio/wav",
15-
"type": "audio"
16-
}
17-
""".trimIndent()
13+
private val audioContentJson = buildJsonObject {
14+
put("data", "base64-encoded-audio-data")
15+
put("mimeType", "audio/wav")
16+
put("type", "audio")
17+
}
1818

1919
private val audioContent = AudioContent(
2020
data = "base64-encoded-audio-data",
@@ -23,12 +23,17 @@ class AudioContentSerializationTest {
2323

2424
@Test
2525
fun `should serialize audio content`() {
26-
McpJson.encodeToString(audioContent) shouldEqualJson audioContentJson
26+
val actual = McpJson.encodeToJsonElement(audioContent)
27+
assertEquals(
28+
audioContentJson,
29+
actual,
30+
"Expected $actual to be equal to $audioContentJson"
31+
)
2732
}
2833

2934
@Test
3035
fun `should deserialize audio content`() {
31-
val content = McpJson.decodeFromString<AudioContent>(audioContentJson)
36+
val content = McpJson.decodeFromJsonElement<AudioContent>(audioContentJson)
3237
assertEquals(expected = audioContent, actual = content)
3338
}
3439
}
Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,53 @@
11
package io.modelcontextprotocol.kotlin.sdk
22

3-
import io.kotest.assertions.json.shouldEqualJson
43
import io.modelcontextprotocol.kotlin.sdk.shared.McpJson
54
import kotlinx.serialization.json.Json
5+
import kotlinx.serialization.json.JsonArray
66
import kotlinx.serialization.json.JsonPrimitive
77
import kotlinx.serialization.json.buildJsonObject
8+
import kotlinx.serialization.json.decodeFromJsonElement
9+
import kotlinx.serialization.json.encodeToJsonElement
810
import kotlin.test.Test
911
import kotlin.test.assertEquals
1012

1113
class ToolSerializationTest {
1214

1315
// see https://docs.anthropic.com/en/docs/build-with-claude/tool-use
14-
/* language=json */
15-
private val getWeatherToolJson = """
16-
{
17-
"name": "get_weather",
18-
"description": "Get the current weather in a given location",
19-
"inputSchema": {
20-
"type": "object",
21-
"properties": {
22-
"location": {
23-
"type": "string",
24-
"description": "The city and state, e.g. San Francisco, CA"
25-
}
26-
},
27-
"required": ["location"]
28-
},
29-
"outputSchema": {
30-
"type": "object",
31-
"properties": {
32-
"temperature": {
33-
"type": "number",
34-
"description": "Temperature in celsius"
35-
},
36-
"conditions": {
37-
"type": "string",
38-
"description": "Weather conditions description"
39-
},
40-
"humidity": {
41-
"type": "number",
42-
"description": "Humidity percentage"
43-
}
44-
},
45-
"required": ["temperature", "conditions", "humidity"]
46-
}
47-
}
48-
""".trimIndent()
16+
private val getWeatherToolJson = buildJsonObject {
17+
put("name", JsonPrimitive("get_weather"))
18+
put("description", JsonPrimitive("Get the current weather in a given location"))
19+
put("inputSchema", buildJsonObject {
20+
put("properties", buildJsonObject {
21+
put("location", buildJsonObject {
22+
put("type", JsonPrimitive("string"))
23+
put("description", JsonPrimitive("The city and state, e.g. San Francisco, CA"))
24+
})
25+
})
26+
put("required", JsonArray(listOf(JsonPrimitive("location"))))
27+
put("type", JsonPrimitive("object"))
28+
})
29+
put("outputSchema", buildJsonObject {
30+
put("type", JsonPrimitive("object"))
31+
put("properties", buildJsonObject {
32+
put("temperature", buildJsonObject {
33+
put("type", JsonPrimitive("number"))
34+
put("description", JsonPrimitive("Temperature in celsius"))
35+
})
36+
put("conditions", buildJsonObject {
37+
put("type", JsonPrimitive("string"))
38+
put("description", JsonPrimitive("Weather conditions description"))
39+
})
40+
put("humidity", buildJsonObject {
41+
put("type", JsonPrimitive("number"))
42+
put("description", JsonPrimitive("Humidity percentage"))
43+
})
44+
})
45+
put(
46+
"required",
47+
JsonArray(listOf(JsonPrimitive("temperature"), JsonPrimitive("conditions"), JsonPrimitive("humidity")))
48+
)
49+
})
50+
}
4951

5052
val getWeatherTool = Tool(
5153
name = "get_weather",
@@ -81,12 +83,18 @@ class ToolSerializationTest {
8183

8284
@Test
8385
fun `should serialize get_weather tool`() {
84-
McpJson.encodeToString(getWeatherTool) shouldEqualJson getWeatherToolJson
86+
val actual = McpJson.encodeToJsonElement(getWeatherTool)
87+
88+
assertEquals(
89+
getWeatherToolJson,
90+
actual,
91+
"Expected $actual to be equal to $getWeatherToolJson"
92+
)
8593
}
8694

8795
@Test
8896
fun `should deserialize get_weather tool`() {
89-
val tool = McpJson.decodeFromString<Tool>(getWeatherToolJson)
97+
val tool = McpJson.decodeFromJsonElement<Tool>(getWeatherToolJson)
9098
assertEquals(expected = getWeatherTool, actual = tool)
9199
}
92100

@@ -95,6 +103,11 @@ class ToolSerializationTest {
95103
val json = Json(from = McpJson) {
96104
encodeDefaults = false
97105
}
98-
json.encodeToString(getWeatherTool) shouldEqualJson getWeatherToolJson
106+
val actual = json.encodeToJsonElement(getWeatherTool)
107+
assertEquals(
108+
getWeatherToolJson,
109+
actual,
110+
"Expected $actual to be equal to $getWeatherToolJson"
111+
)
99112
}
100113
}

src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBufferTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import io.ktor.utils.io.charsets.Charsets
44
import io.ktor.utils.io.core.toByteArray
55
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
66
import io.modelcontextprotocol.kotlin.sdk.JSONRPCNotification
7-
import kotlinx.serialization.encodeToString
87
import kotlinx.serialization.json.Json
98
import kotlin.test.Test
109
import kotlin.test.assertEquals

0 commit comments

Comments
 (0)