From ab07a7019acc66a62230bec3d645ec08839d5e1e Mon Sep 17 00:00:00 2001 From: devcrocod Date: Mon, 19 Oct 2026 21:33:55 +0200 Subject: [PATCH] Refactor deprecated methods and constructors to enforce stricter deprecation levels, standardize parameter naming for consistency (`inputStream` to `input`, `outputStream` to `output`), and remove obsolete APIs. --- README.md | 15 +++++----- .../client/StreamableHttpClientTransport.kt | 1 + .../StreamableHttpMcpKtorClientExtensions.kt | 2 ++ .../kotlin/sdk/types/capabilities.kt | 2 +- .../kotlin/sdk/types/elicitation.dsl.kt | 2 +- .../kotlin/sdk/types/elicitation.kt | 4 +-- .../kotlin/sdk/types/ElicitationTest.kt | 2 +- kotlin-sdk-server/api/kotlin-sdk-server.api | 4 +-- .../api/kotlin-sdk-server.klib.api | 1 - .../kotlin/sdk/server/KtorServer.kt | 30 ------------------- .../kotlin/sdk/server/StdioServerTransport.kt | 2 +- .../server/StreamableHttpServerTransport.kt | 10 ++++--- .../sample/server/server.kt | 4 +-- .../sample/server/McpWeatherServer.kt | 4 +-- 14 files changed, 27 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index a08b8016d..b81aeb7aa 100644 --- a/README.md +++ b/README.md @@ -498,8 +498,8 @@ val server = Server( val session = server.createSession( StdioServerTransport( - inputStream = System.`in`.asSource().buffered(), - outputStream = System.out.asSink().buffered() + input = System.`in`.asSource().buffered(), + output = System.out.asSink().buffered() ) ) @@ -561,8 +561,8 @@ val server = Server( val session = server.createSession( StdioServerTransport( - inputStream = System.`in`.asSource().buffered(), - outputStream = System.out.asSink().buffered() + input = System.`in`.asSource().buffered(), + output = System.out.asSink().buffered() ) ) @@ -620,8 +620,8 @@ val server = Server( val session = server.createSession( StdioServerTransport( - inputStream = System.`in`.asSource().buffered(), - outputStream = System.out.asSink().buffered() + input = System.`in`.asSource().buffered(), + output = System.out.asSink().buffered() ) ) @@ -713,7 +713,6 @@ import io.modelcontextprotocol.kotlin.sdk.types.Method import io.modelcontextprotocol.kotlin.sdk.types.Role import io.modelcontextprotocol.kotlin.sdk.types.TextContent import kotlinx.serialization.json.buildJsonObject -import kotlinx.serialization.json.putJsonObject fun main() { --> @@ -723,7 +722,7 @@ val client = Client( clientInfo = Implementation("demo-client", "1.0.0"), options = ClientOptions( capabilities = ClientCapabilities( - sampling = buildJsonObject { putJsonObject("tools") { } }, // drop tools if you don't support tool use + sampling = ClientCapabilities.Sampling(tools = buildJsonObject { }), // drop tools if you don't support tool use ), ), ) diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport.kt index af2813401..0ba803ee7 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport.kt @@ -121,6 +121,7 @@ public class StreamableHttpClientTransport( "kotlin.time.Duration.Companion.seconds", "io.modelcontextprotocol.kotlin.sdk.client.ReconnectionOptions", ), + level = DeprecationLevel.ERROR, ) public constructor( client: HttpClient, diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpMcpKtorClientExtensions.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpMcpKtorClientExtensions.kt index a618f1823..d403641b2 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpMcpKtorClientExtensions.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpMcpKtorClientExtensions.kt @@ -37,6 +37,7 @@ public fun HttpClient.mcpStreamableHttpTransport( "mcpStreamableHttpTransport(url, " + "ReconnectionOptions(initialReconnectionDelay = reconnectionTime ?: 1.seconds), requestBuilder)", ), + level = DeprecationLevel.ERROR, ) public fun HttpClient.mcpStreamableHttpTransport( url: String, @@ -82,6 +83,7 @@ public suspend fun HttpClient.mcpStreamableHttp( "mcpStreamableHttp(url, " + "ReconnectionOptions(initialReconnectionDelay = reconnectionTime ?: 1.seconds), requestBuilder)", ), + level = DeprecationLevel.ERROR, ) public suspend fun HttpClient.mcpStreamableHttp( url: String, diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.kt index ecb8c4851..e4c68cd35 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.kt @@ -82,7 +82,7 @@ public data class ClientCapabilities( "experimental = experimental, " + "extensions = extensions)", ), - level = DeprecationLevel.WARNING, + level = DeprecationLevel.ERROR, ) public constructor( sampling: JsonObject?, diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.dsl.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.dsl.kt index 12309fad7..fe79384c3 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.dsl.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.dsl.kt @@ -153,7 +153,7 @@ public class ElicitRequestBuilder @PublishedApi internal constructor() : Request "Missing required field 'requestedSchema'. Use requestedSchema { properties { ... } }" } - val params = ElicitRequestParams(message = message, requestedSchema = requestedSchema, meta = meta) + val params = ElicitRequestFormParams(message = message, requestedSchema = requestedSchema, meta = meta) return ElicitRequest(params) } } diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.kt index 1bb73e6ea..a77ea2afa 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/elicitation.kt @@ -30,7 +30,7 @@ public data class ElicitRequest(override val params: ElicitRequestParams) : Serv @Deprecated( "Use (params as ElicitRequestFormParams).requestedSchema", ReplaceWith("(params as ElicitRequestFormParams).requestedSchema"), - DeprecationLevel.WARNING, + DeprecationLevel.ERROR, ) public val requestedSchema: ElicitRequestParams.RequestedSchema? get() = (params as? ElicitRequestFormParams)?.requestedSchema @@ -88,7 +88,7 @@ public sealed interface ElicitRequestParams : RequestParams { @Deprecated( "Use ElicitRequestFormParams instead", ReplaceWith("ElicitRequestFormParams(message, requestedSchema = requestedSchema, meta = meta)"), - DeprecationLevel.WARNING, + DeprecationLevel.ERROR, ) @Suppress("FunctionName") public fun ElicitRequestParams( diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ElicitationTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ElicitationTest.kt index 2b4aa9908..1020c5ba8 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ElicitationTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ElicitationTest.kt @@ -133,7 +133,7 @@ class ElicitationTest { } } - @Suppress("DEPRECATION") + @Suppress("DEPRECATION_ERROR") @Test fun `deprecated requestedSchema should return schema only for form mode`() { val schema = ElicitRequestParams.RequestedSchema( diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.api b/kotlin-sdk-server/api/kotlin-sdk-server.api index acfe1ae39..2f48c5d80 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.api @@ -57,9 +57,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/KtorServerKt { public static synthetic fun mcp$default (Lio/ktor/server/application/Application;ZLjava/util/List;Ljava/util/List;JLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V public static synthetic fun mcp$default (Lio/ktor/server/routing/Route;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;JLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V public static synthetic fun mcp$default (Lio/ktor/server/routing/Route;ZLjava/util/List;Ljava/util/List;JLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V - public static final fun mcpStatelessStreamableHttp (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/server/EventStore;Lkotlin/jvm/functions/Function1;)V public static final fun mcpStatelessStreamableHttp (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V - public static synthetic fun mcpStatelessStreamableHttp$default (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/server/EventStore;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V public static synthetic fun mcpStatelessStreamableHttp$default (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V public static final fun mcpStreamableHttp-u4uj9nY (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/server/EventStore;Lkotlin/jvm/functions/Function1;JILkotlin/jvm/functions/Function1;)V public static synthetic fun mcpStreamableHttp-u4uj9nY$default (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/server/EventStore;Lkotlin/jvm/functions/Function1;JILkotlin/jvm/functions/Function1;ILjava/lang/Object;)V @@ -222,7 +220,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/SseServerTransport } public final class io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransport : io/modelcontextprotocol/kotlin/sdk/shared/AbstractTransport { - public fun (Lkotlinx/io/Source;Lkotlinx/io/Sink;)V + public synthetic fun (Lkotlinx/io/Source;Lkotlinx/io/Sink;)V public fun (Lkotlinx/io/Source;Lkotlinx/io/Sink;Lkotlin/jvm/functions/Function1;)V public synthetic fun (Lkotlinx/io/Source;Lkotlinx/io/Sink;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.klib.api b/kotlin-sdk-server/api/kotlin-sdk-server.klib.api index 7d64dd05d..04ef9023e 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.klib.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.klib.api @@ -284,7 +284,6 @@ final val io.modelcontextprotocol.kotlin.sdk.server/DnsRebindingProtection // io final fun (): io.ktor.server.application/RouteScopedPlugin // io.modelcontextprotocol.kotlin.sdk.server/DnsRebindingProtection.|(){}[0] final fun (io.ktor.server.application/Application).io.modelcontextprotocol.kotlin.sdk.server/mcp(kotlin/Boolean = ..., kotlin.collections/List? = ..., kotlin.collections/List? = ..., kotlin/Long = ..., kotlin/Function1) // io.modelcontextprotocol.kotlin.sdk.server/mcp|mcp@io.ktor.server.application.Application(kotlin.Boolean;kotlin.collections.List?;kotlin.collections.List?;kotlin.Long;kotlin.Function1){}[0] -final fun (io.ktor.server.application/Application).io.modelcontextprotocol.kotlin.sdk.server/mcpStatelessStreamableHttp(kotlin/String = ..., kotlin/Boolean = ..., kotlin.collections/List? = ..., kotlin.collections/List? = ..., io.modelcontextprotocol.kotlin.sdk.server/EventStore?, kotlin/Function1) // io.modelcontextprotocol.kotlin.sdk.server/mcpStatelessStreamableHttp|mcpStatelessStreamableHttp@io.ktor.server.application.Application(kotlin.String;kotlin.Boolean;kotlin.collections.List?;kotlin.collections.List?;io.modelcontextprotocol.kotlin.sdk.server.EventStore?;kotlin.Function1){}[0] final fun (io.ktor.server.application/Application).io.modelcontextprotocol.kotlin.sdk.server/mcpStatelessStreamableHttp(kotlin/String = ..., kotlin/Boolean = ..., kotlin.collections/List? = ..., kotlin.collections/List? = ..., kotlin/Function1) // io.modelcontextprotocol.kotlin.sdk.server/mcpStatelessStreamableHttp|mcpStatelessStreamableHttp@io.ktor.server.application.Application(kotlin.String;kotlin.Boolean;kotlin.collections.List?;kotlin.collections.List?;kotlin.Function1){}[0] final fun (io.ktor.server.application/Application).io.modelcontextprotocol.kotlin.sdk.server/mcpStreamableHttp(kotlin/String = ..., kotlin/Boolean = ..., kotlin.collections/List? = ..., kotlin.collections/List? = ..., io.modelcontextprotocol.kotlin.sdk.server/EventStore? = ..., kotlin/Function1? = ..., kotlin.time/Duration = ..., kotlin/Int = ..., kotlin/Function1) // io.modelcontextprotocol.kotlin.sdk.server/mcpStreamableHttp|mcpStreamableHttp@io.ktor.server.application.Application(kotlin.String;kotlin.Boolean;kotlin.collections.List?;kotlin.collections.List?;io.modelcontextprotocol.kotlin.sdk.server.EventStore?;kotlin.Function1?;kotlin.time.Duration;kotlin.Int;kotlin.Function1){}[0] final fun (io.ktor.server.application/Application).io.modelcontextprotocol.kotlin.sdk.server/mcpWebSocket(kotlin/Function0) // io.modelcontextprotocol.kotlin.sdk.server/mcpWebSocket|mcpWebSocket@io.ktor.server.application.Application(kotlin.Function0){}[0] diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorServer.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorServer.kt index f03daa4b7..f2d6cd589 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorServer.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorServer.kt @@ -367,36 +367,6 @@ public fun Application.mcpStatelessStreamableHttp( ) } -/** - * Retained only so that existing call sites get a migration hint instead of an unresolved parameter name. - * - * @param eventStore never consulted by a stateless endpoint. Resumption is driven by a `GET` carrying - * `Last-Event-ID`, and this endpoint answers `GET` with `405 Method Not Allowed`, so no stream - * exists to store events on or replay them to. Use [mcpStreamableHttp] when you need resumability. - */ -@Deprecated( - "Use mcpStatelessStreamableHttp without eventStore.", - ReplaceWith("mcpStatelessStreamableHttp(path, enableDnsRebindingProtection, allowedHosts, allowedOrigins, block)"), - DeprecationLevel.ERROR, -) -@Suppress("UnusedParameter") -public fun Application.mcpStatelessStreamableHttp( - path: String = "/mcp", - enableDnsRebindingProtection: Boolean = true, - allowedHosts: List? = null, - allowedOrigins: List? = null, - eventStore: EventStore?, - block: RoutingContext.() -> Server, -) { - mcpStatelessStreamableHttp( - path = path, - enableDnsRebindingProtection = enableDnsRebindingProtection, - allowedHosts = allowedHosts, - allowedOrigins = allowedOrigins, - block = block, - ) -} - private suspend fun ServerSSESession.mcpSseEndpoint( postEndpoint: String, transportManager: TransportManager, diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransport.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransport.kt index 9261be257..c816c1e72 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransport.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransport.kt @@ -112,7 +112,7 @@ public class StdioServerTransport private constructor( @Deprecated( message = "Use StdioServerTransport(input, output) { ... } instead.", replaceWith = ReplaceWith("StdioServerTransport(input = inputStream, output = outputStream)"), - level = DeprecationLevel.WARNING, + level = DeprecationLevel.HIDDEN, ) public constructor(inputStream: Source, outputStream: Sink) : this( input = inputStream, diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport.kt index b59d1f781..13c39438a 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport.kt @@ -95,7 +95,7 @@ private sealed interface PostRefusal { @OptIn(ExperimentalUuidApi::class, ExperimentalAtomicApi::class) public class StreamableHttpServerTransport(private val configuration: Configuration) : AbstractTransport() { - @Deprecated("Use default constructor with explicit Configuration()") + @Deprecated("Use default constructor with explicit Configuration()", level = DeprecationLevel.ERROR) public constructor() : this(configuration = Configuration()) /** @@ -120,6 +120,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat replaceWith = ReplaceWith( "StreamableHttpServerTransport(Configuration(enableJsonResponse = enableJsonResponse, enableDnsRebindingProtection = enableDnsRebindingProtection, allowedHosts = allowedHosts, allowedOrigins = allowedOrigins, eventStore = eventStore, retryIntervalMillis = retryIntervalMillis))", ), + level = DeprecationLevel.ERROR, ) public constructor( enableJsonResponse: Boolean = false, @@ -155,17 +156,17 @@ public class StreamableHttpServerTransport(private val configuration: Configurat public val enableJsonResponse: Boolean = false, @Deprecated( message = "Use install(DnsRebindingProtection) on your Ktor route instead", - level = DeprecationLevel.WARNING, + level = DeprecationLevel.ERROR, ) public val enableDnsRebindingProtection: Boolean = false, @Deprecated( message = "Use install(DnsRebindingProtection) on your Ktor route instead", - level = DeprecationLevel.WARNING, + level = DeprecationLevel.ERROR, ) public val allowedHosts: List? = null, @Deprecated( message = "Use install(DnsRebindingProtection) on your Ktor route instead", - level = DeprecationLevel.WARNING, + level = DeprecationLevel.ERROR, ) public val allowedOrigins: List? = null, public val eventStore: EventStore? = null, @@ -821,6 +822,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } } + @Suppress("DEPRECATION_ERROR") private fun validateHeaders(call: ApplicationCall): String? { if (!configuration.enableDnsRebindingProtection) return null diff --git a/samples/kotlin-mcp-server/src/main/kotlin/io/modelcontextprotocol/sample/server/server.kt b/samples/kotlin-mcp-server/src/main/kotlin/io/modelcontextprotocol/sample/server/server.kt index 2a85c74a5..56552db95 100644 --- a/samples/kotlin-mcp-server/src/main/kotlin/io/modelcontextprotocol/sample/server/server.kt +++ b/samples/kotlin-mcp-server/src/main/kotlin/io/modelcontextprotocol/sample/server/server.kt @@ -194,8 +194,8 @@ private fun Application.installCors() { fun runMcpServerUsingStdio() { val server = configureServer() val transport = StdioServerTransport( - inputStream = System.`in`.asSource().buffered(), - outputStream = System.out.asSink().buffered(), + input = System.`in`.asSource().buffered(), + output = System.out.asSink().buffered(), ) runBlocking { diff --git a/samples/weather-stdio-server/src/main/kotlin/io/modelcontextprotocol/sample/server/McpWeatherServer.kt b/samples/weather-stdio-server/src/main/kotlin/io/modelcontextprotocol/sample/server/McpWeatherServer.kt index 1dee706f7..23af2a401 100644 --- a/samples/weather-stdio-server/src/main/kotlin/io/modelcontextprotocol/sample/server/McpWeatherServer.kt +++ b/samples/weather-stdio-server/src/main/kotlin/io/modelcontextprotocol/sample/server/McpWeatherServer.kt @@ -48,8 +48,8 @@ fun runMcpServer() { server.registerTools(httpClient) val transport = StdioServerTransport( - System.`in`.asInput(), - System.out.asSink().buffered(), + input = System.`in`.asInput(), + output = System.out.asSink().buffered(), ) runBlocking {