Skip to content

Commit be4f9c3

Browse files
authored
Test and fix #52 (#53)
* Add test to reproduce #52 * Solve issue #52 by improving url handling in SseClientTransport * Remove unnecessary url processing --------- Co-authored-by: Abdullatif.Ghajar <[email protected]>
1 parent b0532d9 commit be4f9c3

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/SSEClientTransport.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class SseClientTransport(
3939
private var job: Job? = null
4040

4141
private val baseUrl by lazy {
42-
session.call.request.url.toString().removeSuffix("/")
42+
session.call.request.url.toString().removeSuffix("/sse")
4343
}
4444

4545
override suspend fun start() {
@@ -52,7 +52,7 @@ public class SseClientTransport(
5252

5353
session = urlString?.let {
5454
client.sseSession(
55-
urlString = it,
55+
urlString = "$it/sse",
5656
reconnectionTime = reconnectionTime,
5757
block = requestBuilder,
5858
)
@@ -79,7 +79,7 @@ public class SseClientTransport(
7979
val eventData = event.data ?: ""
8080

8181
// check url correctness
82-
val maybeEndpoint = Url("$baseUrl/$eventData")
82+
val maybeEndpoint = Url(baseUrl + eventData)
8383

8484
endpoint.complete(maybeEndpoint.toString())
8585
} catch (e: Exception) {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package integration
2+
3+
import io.ktor.client.*
4+
import io.ktor.client.plugins.sse.*
5+
import io.ktor.server.cio.*
6+
import io.ktor.server.engine.*
7+
import io.modelcontextprotocol.kotlin.sdk.Implementation
8+
import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities
9+
import io.modelcontextprotocol.kotlin.sdk.client.Client
10+
import io.modelcontextprotocol.kotlin.sdk.client.mcpSse
11+
import io.modelcontextprotocol.kotlin.sdk.server.Server
12+
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
13+
import io.modelcontextprotocol.kotlin.sdk.server.mcp
14+
import kotlinx.coroutines.runBlocking
15+
import org.junit.jupiter.api.Test
16+
import org.junit.jupiter.api.assertDoesNotThrow
17+
import io.ktor.client.engine.cio.CIO as ClientCIO
18+
import io.ktor.server.cio.CIO as ServerCIO
19+
20+
class SseIntegrationTest {
21+
@Test
22+
fun `client should be able to connect to sse server`() { // runTest will cause network timeout issues
23+
runBlocking {
24+
val serverEngine = initServer()
25+
try {
26+
assertDoesNotThrow { initClient() }
27+
} finally {
28+
// Make sure to stop the server
29+
serverEngine.stop(1000, 2000)
30+
}
31+
}
32+
}
33+
34+
private suspend fun initClient(): Client {
35+
return HttpClient(ClientCIO) { install(SSE) }.mcpSse("http://$URL:$PORT")
36+
}
37+
38+
private fun initServer(): EmbeddedServer<CIOApplicationEngine, CIOApplicationEngine.Configuration> {
39+
val server = Server(
40+
Implementation(name = "sse-e2e-test", version = "1.0.0"),
41+
ServerOptions(capabilities = ServerCapabilities()),
42+
)
43+
44+
return embeddedServer(ServerCIO, host = URL, port = PORT) { mcp { server } }.start(wait = false)
45+
}
46+
47+
companion object {
48+
private const val PORT = 3001
49+
private const val URL = "localhost"
50+
}
51+
}

0 commit comments

Comments
 (0)