Skip to content

Commit 9bb851a

Browse files
authored
Fix deserialization in read buffer (#225)
* Add deserialization error processing * Add test
1 parent ad82052 commit 9bb851a

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBuffer.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.modelcontextprotocol.kotlin.sdk.shared
22

3+
import io.github.oshai.kotlinlogging.KotlinLogging
34
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
45
import kotlinx.io.Buffer
56
import kotlinx.io.indexOf
@@ -9,6 +10,9 @@ import kotlinx.io.readString
910
* Buffers a continuous stdio stream into discrete JSON-RPC messages.
1011
*/
1112
public class ReadBuffer {
13+
14+
private val logger = KotlinLogging.logger { }
15+
1216
private val buffer: Buffer = Buffer()
1317

1418
public fun append(chunk: ByteArray) {
@@ -37,7 +41,13 @@ public class ReadBuffer {
3741
string
3842
}
3943
}
40-
return deserializeMessage(line)
44+
try {
45+
return deserializeMessage(line)
46+
} catch (e: Exception) {
47+
logger.error(e) { "Failed to deserialize message from line: $line\nSkipping..." }
48+
}
49+
50+
return null
4151
}
4252

4353
public fun clear() {

kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransportTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,24 @@ class StdioClientTransportTest : BaseTransportTest() {
4545
process.waitFor()
4646
process.destroy()
4747
}
48+
49+
@Test
50+
fun `should ignore first output messages`() = runTest {
51+
val processBuilder = ProcessBuilder("/usr/bin/tee")
52+
val process = processBuilder.start()
53+
process.outputStream.write("Stdio server started".toByteArray())
54+
55+
val input = process.inputStream.asSource().buffered()
56+
val output = process.outputStream.asSink().buffered()
57+
58+
val client = StdioClientTransport(
59+
input = input,
60+
output = output,
61+
)
62+
63+
testClientRead(client)
64+
65+
process.waitFor()
66+
process.destroy()
67+
}
4868
}

0 commit comments

Comments
 (0)