fix: Update/Fix build workflow (#474)

# Update/Fix build workflow

- `macos-latest-xlarge` is no longer available. Switch to cheaper
runner: `macos-latest-xlarge` -> `macos-latest`
- Refactor build to run matrix job under Linux and macOS
- Tune caching GH caching
- Add junit and logger properties
- Downgrade Junit to 5.14.2
- Extract `ProcessBuilder` creation logic into helper functions
- Disable `StdioClientTransportTest` on windows temporary

## How Has This Been Tested?
CI

## Breaking Changes
Functionally - no. Outdated/broken TypeScript tests were disabled

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [x] Bug fix (non-breaking change which fixes an issue)
- [x] CI Update

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [ ] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [ ] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed

## Additional context
GitHub actions workflows were blocked because the selected
"macos-latest-xlarge" runner, which is not available for the free
open-source plan. With "macos-latest" workflow works.
This commit is contained in:
Konstantin Pavlov 2026-01-09 22:48:31 +02:00 • committed by GitHub
commit 288d46cdde
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 268 additions and 541 deletions

View file

@ -26,6 +26,7 @@ kotlin {
jvmTest {
dependencies {
implementation(libs.awaitility)
implementation(libs.junit.jupiter.params)
runtimeOnly(libs.slf4j.simple)
}
}

View file

@ -37,7 +37,7 @@ abstract class BaseTransportTest {
fail("Unexpected error: $error")
}
val messages = listOf<JSONRPCMessage>(
val messages = listOf(
PingRequest().toJSON(),
InitializedNotification().toJSON(),
)

View file

@ -12,6 +12,8 @@ import kotlinx.io.buffered
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Timeout
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.condition.DisabledOnOs
import org.junit.jupiter.api.condition.OS
import java.util.concurrent.TimeUnit
import kotlin.concurrent.atomics.AtomicBoolean
import kotlin.concurrent.atomics.ExperimentalAtomicApi
@ -22,15 +24,12 @@ import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@Timeout(30, unit = TimeUnit.SECONDS)
@DisabledOnOs(OS.WINDOWS) // TODO: fix running on windows
class StdioClientTransportTest : BaseTransportTest() {
@Test
fun `handle stdio error`(): Unit = runBlocking {
val processBuilder = if (System.getProperty("os.name").lowercase().contains("win")) {
ProcessBuilder("cmd", "/c", "pause 1 && echo simulated error 1>&2 && exit 1")
} else {
ProcessBuilder("sh", "-c", "sleep 1 && echo 'simulated error' >&2 && exit 1")
}
val processBuilder = createSleepyProcessBuilder()
val process = processBuilder.start()
@ -65,8 +64,8 @@ class StdioClientTransportTest : BaseTransportTest() {
@OptIn(ExperimentalAtomicApi::class)
@Test
fun `should start then close cleanly`() = runTest {
// Run process "/usr/bin/tee"
val processBuilder = ProcessBuilder("/usr/bin/tee")
// Run loopback process
val processBuilder = createTeeProcessBuilder()
val process = processBuilder.start()
val input = process.inputStream.asSource().buffered()
@ -102,7 +101,7 @@ class StdioClientTransportTest : BaseTransportTest() {
@Test
fun `should read messages`() = runTest {
val processBuilder = ProcessBuilder("/usr/bin/tee")
val processBuilder = createTeeProcessBuilder()
val process = processBuilder.start()
val input = process.inputStream.asSource().buffered()
@ -121,7 +120,7 @@ class StdioClientTransportTest : BaseTransportTest() {
@Test
fun `should ignore first output messages`() = runTest {
val processBuilder = ProcessBuilder("/usr/bin/tee")
val processBuilder = createTeeProcessBuilder()
val process = processBuilder.start()
process.outputStream.write("Stdio server started".toByteArray())

View file

@ -0,0 +1,15 @@
package io.modelcontextprotocol.kotlin.sdk.client
private val isWindows = System.getProperty("os.name").lowercase().contains("win")
fun createTeeProcessBuilder(): ProcessBuilder = if (isWindows) {
ProcessBuilder("cmd", "/c", "findstr", "^")
} else {
ProcessBuilder("tee")
}
fun createSleepyProcessBuilder(): ProcessBuilder = if (isWindows) {
ProcessBuilder("cmd", "/c", "ping -n 2 127.0.0.1 > nul && echo simulated error 1>&2 && exit 1")
} else {
ProcessBuilder("sh", "-c", "sleep 1 && echo 'simulated error' >&2 && exit 1")
}

View file

@ -1,6 +1,7 @@
package io.modelcontextprotocol.kotlin.sdk.integration.typescript
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import io.modelcontextprotocol.kotlin.sdk.types.TextContent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
@ -11,6 +12,7 @@ import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@DisabledOnCI
abstract class AbstractKotlinClientTsServerTest : TsTestBase() {
protected abstract suspend fun <T> useClient(block: suspend (Client) -> T): T

View file

@ -1,11 +1,13 @@
package io.modelcontextprotocol.kotlin.sdk.integration.typescript
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Timeout
import java.util.concurrent.TimeUnit
import kotlin.test.assertTrue
@DisabledOnCI
abstract class AbstractTsClientKotlinServerTest : TsTestBase() {
protected open fun beforeServer() {}

View file

@ -11,7 +11,7 @@ import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
abstract class OldSchemaAbstractKotlinClientTsServerTest : OldSchemaTsTestBase() {
abstract class OldSchemaAbstractKotlinClientTsServerTest : TsTestBase() {
protected abstract suspend fun <T> useClient(block: suspend (Client) -> T): T
@Test

View file

@ -1,455 +0,0 @@
package io.modelcontextprotocol.kotlin.sdk.integration.typescript
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.sse.SSE
import io.modelcontextprotocol.kotlin.sdk.Implementation
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.client.StdioClientTransport
import io.modelcontextprotocol.kotlin.sdk.client.mcpStreamableHttp
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.sse.KotlinServerForTsClient
import io.modelcontextprotocol.kotlin.sdk.integration.utils.Retry
import io.modelcontextprotocol.kotlin.sdk.server.Server
import io.modelcontextprotocol.kotlin.sdk.server.StdioServerTransport
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import kotlinx.io.Sink
import kotlinx.io.Source
import kotlinx.io.asSink
import kotlinx.io.asSource
import kotlinx.io.buffered
import org.awaitility.kotlin.await
import org.junit.jupiter.api.BeforeAll
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
import java.net.ServerSocket
import java.net.Socket
import java.util.concurrent.TimeUnit
import kotlin.io.path.createTempDirectory
import kotlin.time.Duration.Companion.seconds
enum class OldSchemaTransportKind { SSE, STDIO, DEFAULT }
@Retry(times = 3)
abstract class OldSchemaTsTestBase {
protected open val transportKind: OldSchemaTransportKind = OldSchemaTransportKind.DEFAULT
protected val projectRoot: File get() = File(System.getProperty("user.dir"))
protected val tsClientDir: File
get() {
val base = File(
projectRoot,
"src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/typescript",
)
// Allow override via system property for CI: -Dts.transport=stdio|sse
val fromProp = System.getProperty("ts.transport")?.lowercase()
val overrideSubDir = when (fromProp) {
"stdio" -> "stdio"
"sse" -> "sse"
else -> null
}
val subDirName = overrideSubDir ?: when (transportKind) {
OldSchemaTransportKind.STDIO -> "stdio"
OldSchemaTransportKind.SSE -> "sse"
OldSchemaTransportKind.DEFAULT -> null
}
if (subDirName != null) {
val sub = File(base, subDirName)
if (sub.exists()) return sub
}
return base
}
companion object {
@JvmStatic
private val tempRootDir: File = createTempDirectory("typescript-sdk-").toFile().apply { deleteOnExit() }
@JvmStatic
protected val sdkDir: File = File(tempRootDir, "typescript-sdk")
@JvmStatic
@BeforeAll
fun setupTypeScriptSdk() {
println("Cloning TypeScript SDK repository")
if (!sdkDir.exists()) {
val process = ProcessBuilder(
"git",
"clone",
"--depth",
"1",
"https://github.com/modelcontextprotocol/typescript-sdk.git",
sdkDir.absolutePath,
)
.redirectErrorStream(true)
.start()
val exitCode = process.waitFor()
if (exitCode != 0) {
throw RuntimeException("Failed to clone TypeScript SDK repository: exit code $exitCode")
}
}
println("Installing TypeScript SDK dependencies")
executeCommand("npm install", sdkDir, allowFailure = false, timeoutSeconds = null)
}
@JvmStatic
protected fun killProcessOnPort(port: Int) {
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
val killCommand = if (isWindows) {
"netstat -ano | findstr :$port | for /f \"tokens=5\" %a in ('more')" +
" do taskkill /F /PID %a 2>nul || echo No process found"
} else {
"lsof -ti:$port | xargs kill -9 2>/dev/null || true"
}
executeCommand(killCommand, File("."), allowFailure = true, timeoutSeconds = null)
}
@JvmStatic
protected fun findFreePort(): Int {
ServerSocket(0).use { socket ->
return socket.localPort
}
}
@JvmStatic
protected fun executeCommand(
command: String,
workingDir: File,
allowFailure: Boolean = false,
timeoutSeconds: Long? = null,
): String {
if (!workingDir.exists()) {
if (!workingDir.mkdirs()) {
throw RuntimeException("Failed to create working directory: ${workingDir.absolutePath}")
}
}
if (!workingDir.isDirectory || !workingDir.canRead()) {
throw RuntimeException("Working directory is not accessible: ${workingDir.absolutePath}")
}
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
val processBuilder = if (isWindows) {
ProcessBuilder()
.command("cmd.exe", "/c", "set TYPESCRIPT_SDK_DIR=${sdkDir.absolutePath} && $command")
} else {
ProcessBuilder()
.command("bash", "-c", "TYPESCRIPT_SDK_DIR='${sdkDir.absolutePath}' $command")
}
val process = processBuilder
.directory(workingDir)
.redirectErrorStream(true)
.start()
val output = StringBuilder()
BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
var line: String?
while (reader.readLine().also { line = it } != null) {
println(line)
output.append(line).append("\n")
}
}
if (timeoutSeconds == null) {
val exitCode = process.waitFor()
if (!allowFailure && exitCode != 0) {
throw RuntimeException(
"Command execution failed with exit code $exitCode: $command\n" +
"Working dir: ${workingDir.absolutePath}\nOutput:\n$output",
)
}
} else {
process.waitFor(timeoutSeconds, TimeUnit.SECONDS)
}
return output.toString()
}
}
private fun waitForProcessTermination(process: Process, timeoutSeconds: Long): Boolean {
if (process.isAlive && !process.waitFor(timeoutSeconds, TimeUnit.SECONDS)) {
process.destroyForcibly()
process.waitFor(2, TimeUnit.SECONDS)
return false
}
return true
}
private fun createProcessOutputReader(process: Process, prefix: String = "TS-SERVER"): Thread {
val outputReader = Thread {
try {
process.inputStream.bufferedReader().useLines { lines ->
for (line in lines) {
println("[$prefix] $line")
}
}
} catch (e: Exception) {
println("Warning: Error reading process output: ${e.message}")
}
}
outputReader.isDaemon = true
return outputReader
}
private fun createProcessErrorReader(process: Process, prefix: String = "TS-SERVER"): Thread {
val errorReader = Thread {
try {
process.errorStream.bufferedReader().useLines { lines ->
for (line in lines) {
println("[$prefix][err] $line")
}
}
} catch (e: Exception) {
println("Warning: Error reading process error stream: ${e.message}")
}
}
errorReader.isDaemon = true
return errorReader
}
protected fun waitForPort(host: String = "localhost", port: Int, timeoutSeconds: Long = 10): Boolean = try {
await.atMost(timeoutSeconds, TimeUnit.SECONDS)
.pollDelay(200, TimeUnit.MILLISECONDS)
.pollInterval(100, TimeUnit.MILLISECONDS)
.until {
try {
Socket(host, port).use { true }
} catch (_: Exception) {
false
}
}
true
} catch (_: Exception) {
false
}
protected fun executeCommandAllowingFailure(command: String, workingDir: File, timeoutSeconds: Long = 20): String =
executeCommand(command, workingDir, allowFailure = true, timeoutSeconds = timeoutSeconds)
protected fun startTypeScriptServer(port: Int): Process {
killProcessOnPort(port)
if (!sdkDir.exists() || !sdkDir.isDirectory) {
throw IllegalStateException(
"TypeScript SDK directory does not exist or is not accessible: ${sdkDir.absolutePath}",
)
}
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
val localServerPath = File(tsClientDir, "simpleStreamableHttp.ts").absolutePath
val processBuilder = if (isWindows) {
ProcessBuilder()
.command(
"cmd.exe",
"/c",
"set MCP_PORT=$port && set NODE_PATH=${sdkDir.absolutePath}\\node_modules && npx --prefix \"${sdkDir.absolutePath}\" tsx \"$localServerPath\"",
)
} else {
ProcessBuilder()
.command(
"bash",
"-c",
"MCP_PORT=$port NODE_PATH='${sdkDir.absolutePath}/node_modules' npx --prefix '${sdkDir.absolutePath}' tsx \"$localServerPath\"",
)
}
processBuilder.environment()["TYPESCRIPT_SDK_DIR"] = sdkDir.absolutePath
val process = processBuilder
.directory(tsClientDir)
.redirectErrorStream(true)
.start()
createProcessOutputReader(process).start()
if (!waitForPort(port = port, timeoutSeconds = 20)) {
throw IllegalStateException("TypeScript server did not become ready on localhost:$port within timeout")
}
return process
}
protected fun stopProcess(process: Process, waitSeconds: Long = 3, name: String = "TypeScript server") {
process.destroy()
if (waitForProcessTermination(process, waitSeconds)) {
println("$name stopped gracefully")
} else {
println("$name did not stop gracefully, forced termination")
}
}
// ===== SSE client helpers =====
protected suspend fun newClient(serverUrl: String): Client =
HttpClient(CIO) { install(SSE) }.mcpStreamableHttp(serverUrl)
protected suspend fun <T> withClient(serverUrl: String, block: suspend (Client) -> T): T {
val client = newClient(serverUrl)
return try {
withTimeout(20.seconds) { block(client) }
} finally {
try {
withTimeout(3.seconds) { client.close() }
} catch (_: Exception) {
// ignore errors
}
}
}
// ===== STDIO client + server helpers =====
protected fun startTypeScriptServerStdio(): Process {
if (!sdkDir.exists() || !sdkDir.isDirectory) {
throw IllegalStateException(
"TypeScript SDK directory does not exist or is not accessible: ${sdkDir.absolutePath}",
)
}
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
val localServerPath = File(tsClientDir, "simpleStdio.ts").absolutePath
val processBuilder = if (isWindows) {
ProcessBuilder()
.command(
"cmd.exe",
"/c",
"set NODE_PATH=${sdkDir.absolutePath}\\node_modules && npx --prefix \"${sdkDir.absolutePath}\" tsx \"$localServerPath\"",
)
} else {
ProcessBuilder()
.command(
"bash",
"-c",
"NODE_PATH='${sdkDir.absolutePath}/node_modules' npx --prefix '${sdkDir.absolutePath}' tsx \"$localServerPath\"",
)
}
processBuilder.environment()["TYPESCRIPT_SDK_DIR"] = sdkDir.absolutePath
val process = processBuilder
.directory(tsClientDir)
.redirectErrorStream(false)
.start()
// For stdio transports, do NOT read from stdout (it's used for protocol). Read stderr for logs only.
createProcessErrorReader(process, prefix = "TS-SERVER-STDIO").start()
// Give the process a moment to start
await.atMost(2, TimeUnit.SECONDS)
.pollDelay(200, TimeUnit.MILLISECONDS)
.pollInterval(100, TimeUnit.MILLISECONDS)
.until { process.isAlive }
return process
}
protected suspend fun newClientStdio(process: Process): Client {
val input: Source = process.inputStream.asSource().buffered()
val output: Sink = process.outputStream.asSink().buffered()
val transport = StdioClientTransport(input = input, output = output)
val client = Client(Implementation("test", "1.0"))
client.connect(transport)
return client
}
protected suspend fun <T> withClientStdio(block: suspend (Client, Process) -> T): T {
val proc = startTypeScriptServerStdio()
val client = newClientStdio(proc)
return try {
withTimeout(20.seconds) { block(client, proc) }
} finally {
try {
withTimeout(3.seconds) { client.close() }
} catch (_: Exception) {
}
try {
stopProcess(proc, name = "TypeScript stdio server")
} catch (_: Exception) {
}
}
}
// ===== Helpers to run TypeScript client over STDIO against Kotlin server over STDIO =====
protected fun runStdioClient(vararg args: String): String {
// Start Node stdio client (it will speak MCP over its stdout/stdin)
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
val clientPath = File(tsClientDir, "myClient.ts").absolutePath
val process = if (isWindows) {
ProcessBuilder()
.command(
"cmd.exe",
"/c",
(
"set TYPESCRIPT_SDK_DIR=${sdkDir.absolutePath} && " +
"set NODE_PATH=${sdkDir.absolutePath}\\node_modules && " +
"npx --prefix \"${sdkDir.absolutePath}\" tsx \"$clientPath\" " +
args.joinToString(" ")
),
)
.directory(tsClientDir)
.redirectErrorStream(false)
.start()
} else {
ProcessBuilder()
.command(
"bash",
"-c",
(
"TYPESCRIPT_SDK_DIR='${sdkDir.absolutePath}' " +
"NODE_PATH='${sdkDir.absolutePath}/node_modules' " +
"npx --prefix '${sdkDir.absolutePath}' tsx \"$clientPath\" " +
args.joinToString(" ")
),
)
.directory(tsClientDir)
.redirectErrorStream(false)
.start()
}
// Create Kotlin server and attach stdio transport to the process streams
val server: Server = KotlinServerForTsClient().createMcpServer()
val transport = StdioServerTransport(
inputStream = process.inputStream.asSource().buffered(),
outputStream = process.outputStream.asSink().buffered(),
)
// Connect server in a background thread to avoid blocking
val serverThread = Thread {
try {
runBlocking { server.createSession(transport) }
} catch (e: Exception) {
println("[STDIO-SERVER] Error connecting: ${e.message}")
}
}
serverThread.isDaemon = true
serverThread.start()
// Read ONLY stderr from client for human-readable output
val output = StringBuilder()
val errReader = Thread {
try {
process.errorStream.bufferedReader().useLines { lines ->
lines.forEach { line ->
println("[TS-CLIENT-STDIO][err] $line")
output.append(line).append('\n')
}
}
} catch (e: Exception) {
println("Warning: Error reading stdio client stderr: ${e.message}")
}
}
errReader.isDaemon = true
errReader.start()
// Wait up to 25s for client to exit
val finished = process.waitFor(25, TimeUnit.SECONDS)
if (!finished) {
println("Stdio client did not finish in time; destroying")
process.destroyForcibly()
}
try {
runBlocking { transport.close() }
} catch (_: Exception) {
}
return output.toString()
}
}

View file

@ -3,6 +3,7 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.sse
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import io.modelcontextprotocol.kotlin.sdk.types.TextContent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@ -22,6 +23,7 @@ import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlin.time.Duration.Companion.seconds
@DisabledOnCI
class KotlinClientTsServerEdgeCasesTestSse : TsTestBase() {
override val transportKind = TransportKind.SSE

View file

@ -3,11 +3,13 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.sse
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.AbstractKotlinClientTsServerTest
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import kotlinx.coroutines.withTimeout
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import kotlin.time.Duration.Companion.seconds
@DisabledOnCI
class KotlinClientTsServerTestSse : AbstractKotlinClientTsServerTest() {
override val transportKind = TransportKind.SSE

View file

@ -2,8 +2,9 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.sse
import io.modelcontextprotocol.kotlin.sdk.TextContent
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaTransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaTsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -22,9 +23,10 @@ import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlin.time.Duration.Companion.seconds
class OldSchemaKotlinClientTsServerEdgeCasesTestSse : OldSchemaTsTestBase() {
@DisabledOnCI
class OldSchemaKotlinClientTsServerEdgeCasesTestSse : TsTestBase() {
override val transportKind = OldSchemaTransportKind.SSE
override val transportKind = TransportKind.SSE
private var port: Int = 0
private val host = "localhost"

View file

@ -2,15 +2,17 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.sse
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaAbstractKotlinClientTsServerTest
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaTransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import kotlinx.coroutines.withTimeout
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import kotlin.time.Duration.Companion.seconds
@DisabledOnCI
class OldSchemaKotlinClientTsServerTestSse : OldSchemaAbstractKotlinClientTsServerTest() {
override val transportKind = OldSchemaTransportKind.SSE
override val transportKind = TransportKind.SSE
private var port: Int = 0
private val host = "localhost"

View file

@ -2,9 +2,11 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.sse
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.AbstractTsClientKotlinServerTest
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
@DisabledOnCI
class TsClientKotlinServerTestSse : AbstractTsClientKotlinServerTest() {
override val transportKind = TransportKind.SSE

View file

@ -2,6 +2,7 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.sse
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
@ -18,6 +19,7 @@ import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
@DisabledOnCI
class TsEdgeCasesTestSse : TsTestBase() {
override val transportKind = TransportKind.SSE

View file

@ -3,6 +3,7 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.stdio
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import io.modelcontextprotocol.kotlin.sdk.types.TextContent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@ -18,6 +19,7 @@ import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@DisabledOnCI
class KotlinClientTsServerEdgeCasesTestStdio : TsTestBase() {
override val transportKind = TransportKind.STDIO

View file

@ -3,7 +3,9 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.stdio
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.AbstractKotlinClientTsServerTest
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
@DisabledOnCI
class KotlinClientTsServerTestStdio : AbstractKotlinClientTsServerTest() {
override val transportKind = TransportKind.STDIO

View file

@ -2,8 +2,9 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.stdio
import io.modelcontextprotocol.kotlin.sdk.TextContent
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaTransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaTsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -18,9 +19,10 @@ import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class OldSchemaKotlinClientTsServerEdgeCasesTestStdio : OldSchemaTsTestBase() {
@DisabledOnCI
class OldSchemaKotlinClientTsServerEdgeCasesTestStdio : TsTestBase() {
override val transportKind = OldSchemaTransportKind.STDIO
override val transportKind = TransportKind.STDIO
@Test
@Timeout(30, unit = TimeUnit.SECONDS)

View file

@ -2,11 +2,13 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.stdio
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaAbstractKotlinClientTsServerTest
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.OldSchemaTransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
@DisabledOnCI
class OldSchemaKotlinClientTsServerTestStdio : OldSchemaAbstractKotlinClientTsServerTest() {
override val transportKind = OldSchemaTransportKind.STDIO
override val transportKind = TransportKind.STDIO
override suspend fun <T> useClient(block: suspend (Client) -> T): T = withClientStdio { client, proc ->
try {

View file

@ -2,7 +2,9 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.stdio
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.AbstractTsClientKotlinServerTest
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
@DisabledOnCI
class TsClientKotlinServerTestStdio : AbstractTsClientKotlinServerTest() {
override val transportKind = TransportKind.STDIO
override fun runClient(vararg args: String): String = runStdioClient(*args)

View file

@ -2,6 +2,7 @@ package io.modelcontextprotocol.kotlin.sdk.integration.typescript.stdio
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TransportKind
import io.modelcontextprotocol.kotlin.sdk.integration.typescript.TsTestBase
import io.modelcontextprotocol.kotlin.sdk.integration.utils.DisabledOnCI
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Timeout
import org.junit.jupiter.api.condition.EnabledOnOs
@ -11,6 +12,7 @@ import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@DisabledOnCI
class TsEdgeCasesTestStdio : TsTestBase() {
override val transportKind: TransportKind = TransportKind.STDIO

Some files were not shown because too many files have changed in this diff Show more