Skip to content

Commit 0ed9ccc

Browse files
committed
Refactor server setup and integration tests to support multiple server configurations
1 parent 27aff26 commit 0ed9ccc

File tree

4 files changed

+41
-18
lines changed

4 files changed

+41
-18
lines changed

samples/kotlin-mcp-server/src/main/kotlin/io/modelcontextprotocol/sample/server/server.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ fun configureServer(): Server {
103103
return server
104104
}
105105

106-
fun runSseMcpServerWithPlainConfiguration(port: Int, wait: Boolean = true) {
106+
fun runSseMcpServerWithPlainConfiguration(port: Int, wait: Boolean = true): EmbeddedServer<*, *> {
107107
printBanner(port = port, path = "/sse")
108108
val serverSessions = ConcurrentMap<String, ServerSession>()
109109

110110
val server = configureServer()
111111

112-
embeddedServer(CIO, host = "127.0.0.1", port = port) {
112+
val ktorServer = embeddedServer(CIO, host = "127.0.0.1", port = port) {
113113
installCors()
114114
install(SSE)
115115
routing {
@@ -141,6 +141,8 @@ fun runSseMcpServerWithPlainConfiguration(port: Int, wait: Boolean = true) {
141141
}
142142
}
143143
}.start(wait = wait)
144+
145+
return ktorServer
144146
}
145147

146148
/**
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import io.ktor.server.engine.EmbeddedServer
2+
import io.modelcontextprotocol.sample.server.runSseMcpServerUsingKtorPlugin
3+
import io.modelcontextprotocol.sample.server.runSseMcpServerWithPlainConfiguration
4+
5+
enum class McpServerType(
6+
val sseEndpoint: String,
7+
val serverFactory: (port: Int) -> EmbeddedServer<*, *>
8+
) {
9+
KTOR_PLUGIN(
10+
sseEndpoint = "",
11+
serverFactory = { port -> runSseMcpServerUsingKtorPlugin(port, wait = false) }
12+
),
13+
PLAIN_CONFIGURATION(
14+
sseEndpoint = "/sse",
15+
serverFactory = { port -> runSseMcpServerWithPlainConfiguration(port, wait = false) }
16+
)
17+
}

samples/kotlin-mcp-server/src/test/kotlin/SseServerIntegrationTest.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import kotlin.test.assertNotNull
1111
import kotlin.test.assertNull
1212
import kotlin.test.assertTrue
1313

14-
class SseServerIntegrationTest {
14+
abstract class SseServerIntegrationTestBase {
1515

16-
private val client: Client = TestEnvironment.client
16+
abstract val client: Client
1717

1818
@Test
1919
fun `should list tools`(): Unit = runBlocking {
@@ -88,3 +88,13 @@ class SseServerIntegrationTest {
8888
assertEquals(expected = "text", actual = "${content.type}".lowercase())
8989
}
9090
}
91+
92+
class SseServerKtorPluginIntegrationTest : SseServerIntegrationTestBase() {
93+
private val testEnvironment = TestEnvironment(McpServerType.KTOR_PLUGIN)
94+
override val client: Client = testEnvironment.client
95+
}
96+
97+
class SseServerPlainConfigurationIntegrationTest : SseServerIntegrationTestBase() {
98+
private val testEnvironment = TestEnvironment(McpServerType.PLAIN_CONFIGURATION)
99+
override val client: Client = testEnvironment.client
100+
}

samples/kotlin-mcp-server/src/test/kotlin/TestEnvironment.kt

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
import io.ktor.client.HttpClient
22
import io.ktor.client.engine.cio.CIO
33
import io.ktor.client.plugins.sse.SSE
4-
import io.modelcontextprotocol.kotlin.sdk.Implementation
4+
import io.ktor.server.engine.EmbeddedServer
55
import io.modelcontextprotocol.kotlin.sdk.client.Client
66
import io.modelcontextprotocol.kotlin.sdk.client.mcpSseTransport
7-
import io.modelcontextprotocol.sample.server.runSseMcpServerUsingKtorPlugin
7+
import io.modelcontextprotocol.kotlin.sdk.types.Implementation
88
import kotlinx.coroutines.runBlocking
99
import java.util.concurrent.TimeUnit
1010

11-
object TestEnvironment {
11+
class TestEnvironment(private val serverConfig: McpServerType) {
1212

13-
val server = runSseMcpServerUsingKtorPlugin(0, wait = false)
13+
val server: EmbeddedServer<*, *> = serverConfig.serverFactory(0)
1414
val client: Client
1515

1616
init {
1717
client = runBlocking {
1818
val port = server.engine.resolvedConnectors().single().port
19-
initClient(port)
19+
initClient(port, serverConfig)
2020
}
2121

2222
Runtime.getRuntime().addShutdownHook(
2323
Thread {
24-
println("🏁 Shutting down server")
24+
println("🏁 Shutting down server (${serverConfig.name})")
2525
server.stop(500, 700, TimeUnit.MILLISECONDS)
2626
println("☑️ Shutdown complete")
2727
},
2828
)
2929
}
3030

31-
private suspend fun initClient(port: Int): Client {
31+
private suspend fun initClient(port: Int, config: McpServerType): Client {
3232
val client = Client(
3333
Implementation(name = "test-client", version = "0.1.0"),
3434
)
@@ -37,13 +37,7 @@ object TestEnvironment {
3737
install(SSE)
3838
}
3939

40-
// Create a transport wrapper that captures the session ID and received messages
41-
val transport = httpClient.mcpSseTransport {
42-
url {
43-
this.host = "127.0.0.1"
44-
this.port = port
45-
}
46-
}
40+
val transport = httpClient.mcpSseTransport("http://127.0.0.1:$port/${config.sseEndpoint}")
4741
client.connect(transport)
4842
return client
4943
}

0 commit comments

Comments
 (0)