From 5cb3c1de1219e36abdb409856a4d6edaf3e8b779 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 5 May 2026 11:05:59 +0200 Subject: [PATCH 001/178] fix: enable DNS rebinding protection by default (#659) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `DnsRebindingProtection` Ktor route-scoped plugin and enable it by default across all http transports ## Motivation and Context DNS rebinding protection was disabled by default (`enableDnsRebindingProtection = false`), and sse endpoints (`Route.mcp()`) had zero protection. Same vulnerability as typescript sdk [GHSA-w48q-cv73-mx4w](https://github.com/modelcontextprotocol/typescript-sdk/security/advisories/GHSA-w48q-cv73-mx4w) ## How Has This Been Tested? all tests pass ## Breaking Changes - `Route.mcp()`, `Application.mcp()` signatures changed (new `enableDnsRebindingProtection`, `allowedHosts`, `allowedOrigins` params), binary incompatible on JVM - `enableDnsRebindingProtection` default changed from `false` to `true` on `mcpStreamableHttp`/`mcpStatelessStreamableHttp` - Default allowed hosts: `localhost`, `127.0.0.1`, `[::1]` — opt out with `enableDnsRebindingProtection = false` - Host validation is now port-agnostic (matches ts sdk) - Origin validation now allows missing `Origin` header (non-browser clients) - `Configuration.enableDnsRebindingProtection`, `.allowedHosts`, `.allowedOrigins` deprecated in favor of the plugin ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../sdk/conformance/ConformanceServer.kt | 2 - kotlin-sdk-server/api/kotlin-sdk-server.api | 21 +- .../kotlin/sdk/server/HostValidation.kt | 185 +++++++++ .../kotlin/sdk/server/KtorServer.kt | 99 ++++- .../server/StreamableHttpServerTransport.kt | 31 +- .../sdk/server/DnsRebindingProtectionTest.kt | 382 ++++++++++++++++++ .../server/KtorApplicationExtensionsTest.kt | 4 +- .../sdk/server/KtorRouteExtensionsTest.kt | 6 +- .../StreamableHttpServerTransportTest.kt | 8 + 9 files changed, 703 insertions(+), 35 deletions(-) create mode 100644 kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt create mode 100644 kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/DnsRebindingProtectionTest.kt diff --git a/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceServer.kt b/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceServer.kt index 03d5ee3..8a18957 100644 --- a/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceServer.kt +++ b/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceServer.kt @@ -12,8 +12,6 @@ fun main() { val port = System.getenv("MCP_PORT")?.toIntOrNull() ?: 3001 embeddedServer(CIO, port = port) { mcpStreamableHttp( - enableDnsRebindingProtection = true, - allowedHosts = listOf("localhost", "127.0.0.1", "localhost:$port", "127.0.0.1:$port"), eventStore = InMemoryEventStore(), ) { createConformanceServer() diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.api b/kotlin-sdk-server/api/kotlin-sdk-server.api index 80da5b5..f400e80 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.api @@ -32,16 +32,31 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/ClientConnection$De public static synthetic fun ping$default (Lio/modelcontextprotocol/kotlin/sdk/server/ClientConnection;Lio/modelcontextprotocol/kotlin/sdk/types/PingRequest;Lio/modelcontextprotocol/kotlin/sdk/shared/RequestOptions;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } +public final class io/modelcontextprotocol/kotlin/sdk/server/DnsRebindingProtectionConfig { + public fun ()V + public final fun getAllowedHosts ()Ljava/util/List; + public final fun getAllowedOrigins ()Ljava/util/List; + public final fun setAllowedHosts (Ljava/util/List;)V + public final fun setAllowedOrigins (Ljava/util/List;)V +} + public abstract interface class io/modelcontextprotocol/kotlin/sdk/server/EventStore { public abstract fun getStreamIdForEventId (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun replayEventsAfter (Ljava/lang/String;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun storeEvent (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/JSONRPCMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } +public final class io/modelcontextprotocol/kotlin/sdk/server/HostValidationKt { + public static final fun getDnsRebindingProtection ()Lio/ktor/server/application/RouteScopedPlugin; +} + public final class io/modelcontextprotocol/kotlin/sdk/server/KtorServerKt { - public static final fun mcp (Lio/ktor/server/application/Application;Lkotlin/jvm/functions/Function1;)V - public static final fun mcp (Lio/ktor/server/routing/Route;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V - public static final fun mcp (Lio/ktor/server/routing/Route;Lkotlin/jvm/functions/Function1;)V + public static final fun mcp (Lio/ktor/server/application/Application;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V + public static final fun mcp (Lio/ktor/server/routing/Route;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V + public static final fun mcp (Lio/ktor/server/routing/Route;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun mcp$default (Lio/ktor/server/application/Application;ZLjava/util/List;Ljava/util/List;Lkotlin/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;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public static synthetic fun mcp$default (Lio/ktor/server/routing/Route;ZLjava/util/List;Ljava/util/List;Lkotlin/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 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 final fun mcpStreamableHttp (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 diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt new file mode 100644 index 0000000..88b56bc --- /dev/null +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt @@ -0,0 +1,185 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.ktor.http.ContentType +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpStatusCode +import io.ktor.http.parseUrl +import io.ktor.server.application.ApplicationCall +import io.ktor.server.application.RouteScopedPlugin +import io.ktor.server.application.createRouteScopedPlugin +import io.ktor.server.request.header +import io.ktor.server.response.respondText +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCError +import io.modelcontextprotocol.kotlin.sdk.types.McpJson +import io.modelcontextprotocol.kotlin.sdk.types.RPCError + +/** + * Default list of hostnames allowed for localhost DNS rebinding protection. + * Matches the TypeScript SDK's `localhostAllowedHostnames()`. + */ +internal val LOCALHOST_ALLOWED_HOSTS: List = listOf("localhost", "127.0.0.1", "[::1]") + +/** + * Characters that are valid in a URL but must not appear in an HTTP `Host` header. + * Rejecting them prevents the parser from accepting malformed values + * (e.g. `evil.com@localhost`, `host/path`) that a generic URL parser would silently allow. + */ +private val FORBIDDEN_HOST_CHARS: CharArray = charArrayOf('/', '@', '?', '#') + +/** + * Extracts the hostname from a Host header value, stripping the port. + * + * Only accepts the strict `host [ ":" port ]` / `"[" ipv6 "]" [ ":" port ]` + * format defined by RFC 7230. Values containing URL-only characters + * (`/`, `@`, `?`, `#`) or whitespace are rejected. + * + * Examples: + * - `"localhost:3000"` → `"localhost"` + * - `"127.0.0.1:8080"` → `"127.0.0.1"` + * - `"[::1]:3000"` → `"[::1]"` + * - `"example.com"` → `"example.com"` + * - `"evil.com@localhost"` → `null` + * + * @return the hostname, or `null` if the value is blank, malformed, or contains forbidden characters. + */ +internal fun extractHostname(hostHeader: String): String? = when { + hostHeader.isBlank() -> null + + hostHeader.any { it in FORBIDDEN_HOST_CHARS || it.isWhitespace() } -> null + + hostHeader.startsWith("[") -> { + val end = hostHeader.indexOf(']') + when { + end <= 1 -> null + isValidPortSuffix(hostHeader.substring(end + 1)) -> hostHeader.substring(0, end + 1) + else -> null + } + } + + else -> { + val colon = hostHeader.indexOf(':') + when { + colon < 0 -> hostHeader + colon == 0 -> null + isValidPortSuffix(hostHeader.substring(colon)) -> hostHeader.substring(0, colon) + else -> null + } + } +} + +/** + * Checks that [tail] is either empty (no port part) or `":"` followed by zero or more digits, + * matching RFC 7230 §3.2.3 where `port = *DIGIT`. Non-empty non-digit characters are rejected. + */ +private fun isValidPortSuffix(tail: String): Boolean = when { + tail.isEmpty() -> true + tail[0] != ':' -> false + else -> tail.substring(1).all { it.isDigit() } +} + +/** + * Extracts the hostname from an `Origin` header value. + * + * Uses Ktor's [parseUrl] to avoid reimplementing RFC 6454 parsing. + * Scheme, port, userinfo, and path are discarded — only the host matters for + * DNS-rebinding protection. The result is **not** normalized to lower-case; + * callers should apply [String.lowercase] if they need case-insensitive comparison. + * + * @return the hostname, or `null` if [origin] cannot be parsed or has no host part. + */ +internal fun extractOriginHost(origin: String): String? = parseUrl(origin)?.host?.takeIf(String::isNotEmpty) + +/** + * Configuration for the [DnsRebindingProtection] Ktor route-scoped plugin. + * + * @property allowedHosts List of hostnames allowed in the `Host` header. + * Comparison is port-agnostic and case-insensitive. + * Defaults to `localhost`, `127.0.0.1`, `[::1]`. + * An empty list will reject **all** requests. + * @property allowedOrigins Optional list of allowed `Origin` values. Entries are parsed as URLs + * (via [parseUrl]) and compared by **hostname only** — scheme and port are ignored. + * If `null`, origin validation is disabled. + * If configured, requests **with** an `Origin` header whose hostname is not in the list + * are rejected, but requests **without** an `Origin` header are allowed (non-browser clients). + */ +public class DnsRebindingProtectionConfig { + public var allowedHosts: List = LOCALHOST_ALLOWED_HOSTS + public var allowedOrigins: List? = null +} + +/** + * Ktor route-scoped plugin that validates `Host` and `Origin` headers + * to protect against DNS rebinding attacks. + * + * Install on a route to intercept all requests **before** handlers: + * ```kotlin + * route("/mcp") { + * install(DnsRebindingProtection) { + * allowedHosts = listOf("myapp.com", "localhost") + * } + * // handlers... + * } + * ``` + */ +public val DnsRebindingProtection: RouteScopedPlugin = + createRouteScopedPlugin( + "MCP-DnsRebindingProtection", + ::DnsRebindingProtectionConfig, + ) { + val hosts: Set = pluginConfig.allowedHosts.mapTo(mutableSetOf()) { + extractHostname(it)?.lowercase() + ?: error("Invalid host in DnsRebindingProtection.allowedHosts: '$it'") + } + val originHosts: Set? = pluginConfig.allowedOrigins?.mapTo(mutableSetOf()) { + extractOriginHost(it)?.lowercase() + ?: error("Invalid origin in DnsRebindingProtection.allowedOrigins: '$it'") + } + + onCall { call -> + val hostHeader = call.request.header(HttpHeaders.Host) + val hostname = hostHeader?.let { extractHostname(it) }?.lowercase() + + if (hostname == null) { + call.rejectDnsValidation("Invalid Host header: (malformed or missing)") + return@onCall + } + if (hostname !in hosts) { + call.rejectDnsValidation("Invalid Host: $hostname") + return@onCall + } + + if (originHosts != null) { + val originHeader = call.request.header(HttpHeaders.Origin) + // Allow requests without Origin (non-browser clients cannot perform DNS rebinding) + if (originHeader != null) { + val originHost = extractOriginHost(originHeader)?.lowercase() + if (originHost == null) { + call.rejectDnsValidation("Invalid Origin header: (unparseable)") + return@onCall + } + if (originHost !in originHosts) { + call.rejectDnsValidation("Invalid Origin host: $originHost") + return@onCall + } + } + } + } + } + +/** + * Responds with a 403 Forbidden JSON-RPC error without requiring ContentNegotiation. + */ +private suspend fun ApplicationCall.rejectDnsValidation(message: String) { + val error = JSONRPCError( + id = null, + error = RPCError( + code = -32_000, + message = message, + ), + ) + respondText( + McpJson.encodeToString(error), + ContentType.Application.Json, + HttpStatusCode.Forbidden, + ) +} 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 3f03a7a..d6191df 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 @@ -37,14 +37,26 @@ private val logger = KotlinLogging.logger {} * Use [Application.mcp] if you want SSE to be installed automatically. * * @param path the URL path to register the SSE endpoint. + * @param enableDnsRebindingProtection whether to install [DnsRebindingProtection] on this route. Defaults to `true`. + * @param allowedHosts hostnames allowed in the `Host` header. Defaults to `localhost`, `127.0.0.1`, `[::1]`. + * @param allowedOrigins origins allowed in the `Origin` header, compared by hostname only + * (scheme and port are ignored). Requests without an `Origin` header are allowed. + * Pass `null` to skip origin validation. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. * @throws IllegalStateException if the [SSE] plugin is not installed. */ @KtorDsl -public fun Route.mcp(path: String, block: ServerSSESession.() -> Server) { +@Suppress("LongParameterList") +public fun Route.mcp( + path: String, + enableDnsRebindingProtection: Boolean = true, + allowedHosts: List? = null, + allowedOrigins: List? = null, + block: ServerSSESession.() -> Server, +) { route(path) { - mcp(block) + mcp(enableDnsRebindingProtection, allowedHosts, allowedOrigins, block) } } @@ -55,12 +67,22 @@ public fun Route.mcp(path: String, block: ServerSSESession.() -> Server) { * **Precondition:** the [SSE] plugin must be installed on the application before calling this function. * Use [Application.mcp] if you want SSE to be installed automatically. * + * @param enableDnsRebindingProtection whether to install [DnsRebindingProtection] on this route. Defaults to `true`. + * @param allowedHosts hostnames allowed in the `Host` header. Defaults to `localhost`, `127.0.0.1`, `[::1]`. + * @param allowedOrigins origins allowed in the `Origin` header, compared by hostname only + * (scheme and port are ignored). Requests without an `Origin` header are allowed. + * Pass `null` to skip origin validation. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. * @throws IllegalStateException if the [SSE] plugin is not installed. */ @KtorDsl -public fun Route.mcp(block: ServerSSESession.() -> Server) { +public fun Route.mcp( + enableDnsRebindingProtection: Boolean = true, + allowedHosts: List? = null, + allowedOrigins: List? = null, + block: ServerSSESession.() -> Server, +) { try { plugin(SSE) } catch (e: MissingApplicationPluginException) { @@ -72,6 +94,8 @@ public fun Route.mcp(block: ServerSSESession.() -> Server) { ) } + installDnsRebindingProtection(enableDnsRebindingProtection, allowedHosts, allowedOrigins) + val transportManager = TransportManager() sse { @@ -91,21 +115,35 @@ public fun Route.mcp(block: ServerSSESession.() -> Server) { * Automatically installs [ContentNegotiation][io.ktor.server.plugins.contentnegotiation.ContentNegotiation] * with [McpJson][io.modelcontextprotocol.kotlin.sdk.types.McpJson] and [SSE]. * + * @param enableDnsRebindingProtection whether to install [DnsRebindingProtection] on this route. Defaults to `true`. + * @param allowedHosts hostnames allowed in the `Host` header. Defaults to `localhost`, `127.0.0.1`, `[::1]`. + * @param allowedOrigins origins allowed in the `Origin` header, compared by hostname only + * (scheme and port are ignored). Requests without an `Origin` header are allowed. + * Pass `null` to skip origin validation. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. */ @KtorDsl -public fun Application.mcp(block: ServerSSESession.() -> Server) { +public fun Application.mcp( + enableDnsRebindingProtection: Boolean = true, + allowedHosts: List? = null, + allowedOrigins: List? = null, + block: ServerSSESession.() -> Server, +) { installMcpContentNegotiation() install(SSE) routing { - mcp(block) + mcp(enableDnsRebindingProtection, allowedHosts, allowedOrigins, block) } } +@Suppress("LongParameterList") private fun Application.mcpStreamableHttp( path: String = "/mcp", + enableDnsRebindingProtection: Boolean, + allowedHosts: List?, + allowedOrigins: List?, configuration: StreamableHttpServerTransport.Configuration, block: RoutingContext.() -> Server, ) { @@ -116,6 +154,8 @@ private fun Application.mcpStreamableHttp( routing { route(path) { + installDnsRebindingProtection(enableDnsRebindingProtection, allowedHosts, allowedOrigins) + // Set Mcp-Session-Id on GET responses before Ktor's sse {} commits headers. intercept(ApplicationCallPipeline.Plugins) { if (context.request.httpMethod == HttpMethod.Get) { @@ -160,10 +200,12 @@ private fun Application.mcpStreamableHttp( * with [McpJson][io.modelcontextprotocol.kotlin.sdk.types.McpJson] and [SSE]. * * @param path The base path for the MCP Streamable HTTP endpoint. Defaults to "/mcp". - * @param enableDnsRebindingProtection Enables DNS rebinding attack protection for the endpoint. Defaults to false. - * @param allowedHosts A list of hostnames allowed to access the endpoint. If `null`, no restrictions are applied. - * @param allowedOrigins A list of origins allowed to perform cross-origin requests (CORS). - * If `null`, no restrictions are applied. + * @param enableDnsRebindingProtection Enables DNS rebinding attack protection for the endpoint. Defaults to `true`. + * @param allowedHosts A list of hostnames allowed to access the endpoint. + * If `null` and DNS rebinding protection is enabled, defaults to `localhost`, `127.0.0.1`, `[::1]`. + * @param allowedOrigins A list of allowed `Origin` header values, compared by hostname only + * (scheme and port are ignored). Requests without an `Origin` header are allowed. + * If `null`, origin validation is disabled. * @param eventStore An optional [EventStore] instance to enable resumable event stream functionality. * Allows storing and replaying events. * @param block factory block with access to the [RoutingContext] (for reading request headers) @@ -172,7 +214,7 @@ private fun Application.mcpStreamableHttp( @KtorDsl public fun Application.mcpStreamableHttp( path: String = "/mcp", - enableDnsRebindingProtection: Boolean = false, + enableDnsRebindingProtection: Boolean = true, allowedHosts: List? = null, allowedOrigins: List? = null, eventStore: EventStore? = null, @@ -180,10 +222,10 @@ public fun Application.mcpStreamableHttp( ) { mcpStreamableHttp( path = path, + enableDnsRebindingProtection = enableDnsRebindingProtection, + allowedHosts = allowedHosts, + allowedOrigins = allowedOrigins, configuration = StreamableHttpServerTransport.Configuration( - enableDnsRebindingProtection = enableDnsRebindingProtection, - allowedHosts = allowedHosts, - allowedOrigins = allowedOrigins, eventStore = eventStore, enableJsonResponse = true, ), @@ -191,8 +233,12 @@ public fun Application.mcpStreamableHttp( ) } +@Suppress("LongParameterList") private fun Application.mcpStatelessStreamableHttp( path: String = "/mcp", + enableDnsRebindingProtection: Boolean, + allowedHosts: List?, + allowedOrigins: List?, configuration: StreamableHttpServerTransport.Configuration, block: RoutingContext.() -> Server, ) { @@ -201,6 +247,8 @@ private fun Application.mcpStatelessStreamableHttp( routing { route(path) { + installDnsRebindingProtection(enableDnsRebindingProtection, allowedHosts, allowedOrigins) + post { mcpStatelessStreamableHttpEndpoint( configuration = configuration, @@ -236,9 +284,12 @@ private fun Application.mcpStatelessStreamableHttp( * with [McpJson][io.modelcontextprotocol.kotlin.sdk.types.McpJson] and [SSE]. * * @param path The URL path where the server listens for incoming JSON-RPC requests. Defaults to "/mcp". - * @param enableDnsRebindingProtection Determines whether DNS rebinding protection is enabled. Defaults to `false`. - * @param allowedHosts A list of allowed hostnames. If null, host filtering is disabled. - * @param allowedOrigins A list of allowed origins for CORS. If null, origin filtering is disabled. + * @param enableDnsRebindingProtection Determines whether DNS rebinding protection is enabled. Defaults to `true`. + * @param allowedHosts A list of allowed hostnames. If `null` and DNS rebinding protection is enabled, + * defaults to `localhost`, `127.0.0.1`, `[::1]`. + * @param allowedOrigins A list of allowed `Origin` header values, compared by hostname only + * (scheme and port are ignored). Requests without an `Origin` header are allowed. + * If `null`, origin validation is disabled. * @param eventStore An optional [EventStore] implementation to provide resumability and event replay support. * @param block factory block with access to the [RoutingContext] (for reading request headers) * that creates and returns the [Server] to handle the connection. @@ -246,7 +297,7 @@ private fun Application.mcpStatelessStreamableHttp( @KtorDsl public fun Application.mcpStatelessStreamableHttp( path: String = "/mcp", - enableDnsRebindingProtection: Boolean = false, + enableDnsRebindingProtection: Boolean = true, allowedHosts: List? = null, allowedOrigins: List? = null, eventStore: EventStore? = null, @@ -254,10 +305,10 @@ public fun Application.mcpStatelessStreamableHttp( ) { mcpStatelessStreamableHttp( path = path, + enableDnsRebindingProtection = enableDnsRebindingProtection, + allowedHosts = allowedHosts, + allowedOrigins = allowedOrigins, configuration = StreamableHttpServerTransport.Configuration( - enableDnsRebindingProtection = enableDnsRebindingProtection, - allowedHosts = allowedHosts, - allowedOrigins = allowedOrigins, eventStore = eventStore, enableJsonResponse = true, ), @@ -395,3 +446,11 @@ private suspend fun RoutingContext.streamableTransport( return transport } + +private fun Route.installDnsRebindingProtection(enabled: Boolean, hosts: List?, origins: List?) { + if (!enabled) return + install(DnsRebindingProtection) { + allowedHosts = hosts ?: LOCALHOST_ALLOWED_HOSTS + origins?.let { allowedOrigins = it } + } +} 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 870a92c..ae8a39d 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 @@ -136,8 +136,20 @@ public class StreamableHttpServerTransport(private val configuration: Configurat */ public class Configuration( public val enableJsonResponse: Boolean = false, + @Deprecated( + message = "Use install(DnsRebindingProtection) on your Ktor route instead", + level = DeprecationLevel.WARNING, + ) public val enableDnsRebindingProtection: Boolean = false, + @Deprecated( + message = "Use install(DnsRebindingProtection) on your Ktor route instead", + level = DeprecationLevel.WARNING, + ) public val allowedHosts: List? = null, + @Deprecated( + message = "Use install(DnsRebindingProtection) on your Ktor route instead", + level = DeprecationLevel.WARNING, + ) public val allowedOrigins: List? = null, public val eventStore: EventStore? = null, public val retryInterval: Duration? = null, @@ -300,7 +312,12 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } /** - * Handles an incoming HTTP request, whether GET, POST or DELETE + * Handles an incoming HTTP request, whether GET, POST or DELETE. + * + * **Note:** this method does not perform DNS rebinding protection on its own. + * When using this transport outside the [mcpStreamableHttp] / [mcpStatelessStreamableHttp] + * DSL, install the [DnsRebindingProtection] plugin on your Ktor route + * (or apply equivalent middleware) to validate `Host` / `Origin` headers. */ public suspend fun handleRequest(session: ServerSSESession?, call: ApplicationCall) { validateHeaders(call)?.let { reason -> @@ -651,10 +668,13 @@ public class StreamableHttpServerTransport(private val configuration: Configurat if (!configuration.enableDnsRebindingProtection) return null configuration.allowedHosts?.let { hosts -> - val hostHeader = call.request.headers[HttpHeaders.Host]?.lowercase() - val allowedHostsLowercase = hosts.map { it.lowercase() } + val hostHeader = call.request.headers[HttpHeaders.Host] + val hostname = hostHeader?.let { extractHostname(it) }?.lowercase() + val allowedHostsLowercase = hosts.map { + extractHostname(it)?.lowercase() ?: it.lowercase() + } - if (hostHeader == null || hostHeader !in allowedHostsLowercase) { + if (hostname == null || hostname !in allowedHostsLowercase) { return "Invalid Host header: $hostHeader" } } @@ -663,7 +683,8 @@ public class StreamableHttpServerTransport(private val configuration: Configurat val originHeader = call.request.headers[HttpHeaders.Origin]?.lowercase() val allowedOriginsLowercase = origins.map { it.lowercase() } - if (originHeader == null || originHeader !in allowedOriginsLowercase) { + // Allow requests without Origin (non-browser clients cannot perform DNS rebinding) + if (originHeader != null && originHeader !in allowedOriginsLowercase) { return "Invalid Origin header: $originHeader" } } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/DnsRebindingProtectionTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/DnsRebindingProtectionTest.kt new file mode 100644 index 0000000..96c44ef --- /dev/null +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/DnsRebindingProtectionTest.kt @@ -0,0 +1,382 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.kotest.assertions.ktor.client.shouldHaveStatus +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.string.shouldNotContain +import io.ktor.client.request.header +import io.ktor.client.request.post +import io.ktor.client.statement.bodyAsText +import io.ktor.http.ContentType +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpStatusCode +import io.ktor.http.contentType +import io.ktor.server.application.install +import io.ktor.server.response.respondText +import io.ktor.server.routing.post +import io.ktor.server.routing.route +import io.ktor.server.routing.routing +import io.ktor.server.sse.SSE +import io.ktor.server.testing.ApplicationTestBuilder +import io.ktor.server.testing.testApplication +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource +import org.junit.jupiter.params.provider.ValueSource +import kotlin.test.Test + +class DnsRebindingProtectionTest { + + companion object { + @JvmStatic + fun invalidHostCases(): List = listOf( + Arguments.of("", "Invalid Host header: (malformed or missing)"), + Arguments.of("evil.com", "Invalid Host: evil.com"), + ) + + @JvmStatic + fun extractHostnameAcceptCases(): List = listOf( + Arguments.of("localhost", "localhost"), + Arguments.of("localhost:3000", "localhost"), + Arguments.of("127.0.0.1:8080", "127.0.0.1"), + Arguments.of("[::1]", "[::1]"), + Arguments.of("[::1]:3000", "[::1]"), + Arguments.of("localhost:", "localhost"), + Arguments.of("[::1]:", "[::1]"), + ) + + @JvmStatic + fun extractHostnameRejectCases(): List = listOf( + "", // empty + "evil.com@localhost", // userinfo + "evil.com/path", // path + "evil.com?q=1", // query + "evil.com#frag", // fragment + "[::1", // malformed IPv6 + "[]", // empty brackets + "[]:3000", // empty brackets + port + " localhost", // leading whitespace + "localhost ", // trailing whitespace + "localhost\t:80", // embedded tab + "localhost:abc", // non-numeric port + "localhost:-1", // negative port + "[::1]:abc", // non-numeric IPv6 port + ":80", // leading colon + ) + + @JvmStatic + fun extractOriginHostAcceptCases(): List = listOf( + Arguments.of("http://example.com", "example.com"), + Arguments.of("http://example.com:8080", "example.com"), + Arguments.of("https://Example.COM", "Example.COM"), + Arguments.of("https://example.com", "example.com"), + ) + + @JvmStatic + fun extractOriginHostRejectCases(): List = listOf( + "example.com", // no scheme + "not-a-url", // unparseable + "", // empty + ) + } + + private fun testWithPlugin( + config: DnsRebindingProtectionConfig.() -> Unit = {}, + test: suspend ApplicationTestBuilder.() -> Unit, + ): Unit = testApplication { + application { + install(SSE) + routing { + route("/mcp") { + install(DnsRebindingProtection, config) + post { call.respondText("ok") } + } + } + } + test() + } + + @ParameterizedTest + @ValueSource(strings = ["localhost", "127.0.0.1", "[::1]", "localhost:3000", "[::1]:8080"]) + fun `plugin accepts valid Host header`(hostHeader: String) = testWithPlugin { + val response = client.post("/mcp") { + header(HttpHeaders.Host, hostHeader) + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @ParameterizedTest + @MethodSource("invalidHostCases") + fun `plugin rejects invalid Host header`(hostHeader: String, expectedBody: String) = testWithPlugin { + val response = client.post("/mcp") { + header(HttpHeaders.Host, hostHeader) + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + response.bodyAsText() shouldContain expectedBody + } + + @Test + fun `plugin does not echo raw malformed Host in rejection`() = testWithPlugin { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "evil.com@localhost") + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + response.bodyAsText() shouldNotContain "evil.com@localhost" + response.bodyAsText() shouldContain "malformed or missing" + } + + @Test + fun `plugin allows request without Origin header`() = testWithPlugin( + config = { allowedOrigins = listOf("http://localhost:3000") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @Test + fun `plugin rejects disallowed Origin`() = testWithPlugin( + config = { allowedOrigins = listOf("http://localhost:3000") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Origin, "http://evil.com") + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + response.bodyAsText() shouldContain "Invalid Origin host: evil.com" + } + + @Test + fun `plugin allows matching Origin`() = testWithPlugin( + config = { allowedOrigins = listOf("http://localhost:3000") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Origin, "http://localhost:3000") + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @Test + fun `plugin allows Origin with different port but same hostname`() = testWithPlugin( + config = { allowedOrigins = listOf("http://localhost:3000") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Origin, "http://localhost:9999") + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @Test + fun `plugin allows Origin with different scheme but same hostname`() = testWithPlugin( + config = { allowedOrigins = listOf("http://localhost:3000") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Origin, "https://localhost:3000") + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @Test + fun `plugin rejects unparseable Origin header`() = testWithPlugin( + config = { allowedOrigins = listOf("http://localhost:3000") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Origin, "not-a-url") + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + response.bodyAsText() shouldContain "Invalid Origin header: (unparseable)" + } + + @Test + fun `plugin with custom allowedHosts accepts matching host`() = testWithPlugin( + config = { allowedHosts = listOf("myapp.com") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "myapp.com:443") + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @Test + fun `plugin with custom allowedHosts rejects non-matching host`() = testWithPlugin( + config = { allowedHosts = listOf("myapp.com") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + } + + @Test + fun `host validation is case insensitive`() = testWithPlugin( + config = { allowedHosts = listOf("MyApp.COM") }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "myapp.com") + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @Test + fun `origin validation is case insensitive`() = testWithPlugin( + config = { + allowedHosts = listOf("localhost") + allowedOrigins = listOf("https://MyApp.COM") + }, + ) { + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Origin, "https://myapp.com") + } + response.shouldHaveStatus(HttpStatusCode.OK) + response.bodyAsText() shouldBe "ok" + } + + @Test + fun `plugin with empty allowedHosts rejects all requests`() = testWithPlugin( + config = { allowedHosts = emptyList() }, + ) { + val localhostResponse = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + } + localhostResponse.shouldHaveStatus(HttpStatusCode.Forbidden) + localhostResponse.bodyAsText() shouldContain "Invalid Host: localhost" + + val otherResponse = client.post("/mcp") { + header(HttpHeaders.Host, "myapp.com") + } + otherResponse.shouldHaveStatus(HttpStatusCode.Forbidden) + otherResponse.bodyAsText() shouldContain "Invalid Host: myapp.com" + } + + @Test + fun `plugin fails to install when allowedHosts contains an invalid host`() { + val ex = shouldThrow { + testWithPlugin( + config = { allowedHosts = listOf("https://example.com") }, + ) { + client.post("/mcp") { header(HttpHeaders.Host, "example.com") } + } + } + ex.message shouldContain "https://example.com" + } + + @Test + fun `plugin fails to install when allowedOrigins contains an invalid origin`() { + val ex = shouldThrow { + testWithPlugin( + config = { allowedOrigins = listOf("not-a-url") }, + ) { + client.post("/mcp") { header(HttpHeaders.Host, "localhost") } + } + } + ex.message shouldContain "not-a-url" + } + + @Test + fun `Route mcp with DNS protection enabled rejects non-localhost`() = testApplication { + application { + install(SSE) + routing { + mcp { testServer() } + } + } + + val response = client.post("/") { + header(HttpHeaders.Host, "evil.com") + contentType(ContentType.Application.Json) + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + } + + @Test + fun `Route mcp with DNS protection disabled allows any host`() = testApplication { + application { + install(SSE) + routing { + mcp(enableDnsRebindingProtection = false) { testServer() } + } + } + + val response = client.post("/") { + header(HttpHeaders.Host, "evil.com") + contentType(ContentType.Application.Json) + } + // Not 403 — the request reaches the handler (may get 400 for missing sessionId, etc.) + response.shouldHaveStatus(HttpStatusCode.BadRequest) + } + + @Test + fun `mcpStreamableHttp rejects non-localhost Host by default`() = testApplication { + application { + mcpStreamableHttp { testServer() } + } + + val response = client.post("/mcp") { + header(HttpHeaders.Host, "evil.com") + contentType(ContentType.Application.Json) + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + } + + @Test + fun `mcpStatelessStreamableHttp rejects non-localhost Host by default`() = testApplication { + application { + mcpStatelessStreamableHttp { testServer() } + } + + val response = client.post("/mcp") { + header(HttpHeaders.Host, "evil.com") + contentType(ContentType.Application.Json) + } + response.shouldHaveStatus(HttpStatusCode.Forbidden) + } + + // -- extractHostname unit tests -- + + @ParameterizedTest + @MethodSource("extractHostnameAcceptCases") + fun `extractHostname accepts valid host`(input: String, expected: String) { + extractHostname(input) shouldBe expected + } + + @ParameterizedTest + @MethodSource("extractHostnameRejectCases") + fun `extractHostname rejects invalid host`(input: String) { + extractHostname(input) shouldBe null + } + + // -- extractOriginHost unit tests -- + + @ParameterizedTest + @MethodSource("extractOriginHostAcceptCases") + fun `extractOriginHost extracts hostname`(input: String, expected: String) { + extractOriginHost(input) shouldBe expected + } + + @ParameterizedTest + @MethodSource("extractOriginHostRejectCases") + fun `extractOriginHost returns null for invalid origin`(input: String) { + extractOriginHost(input) shouldBe null + } + + private fun testServer(): Server = Server( + serverInfo = Implementation(name = "test-server", version = "1.0.0"), + options = ServerOptions(capabilities = ServerCapabilities()), + ) +} diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorApplicationExtensionsTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorApplicationExtensionsTest.kt index 05200e5..9888867 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorApplicationExtensionsTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorApplicationExtensionsTest.kt @@ -24,9 +24,9 @@ class KtorApplicationExtensionsTest : AbstractKtorExtensionsTest() { * added to the same application. */ @Test - fun `Application mcp should installs SSE and coexist with other routes`() = testApplication { + fun `Application mcp should install SSE and coexist with other routes`() = testApplication { application { - mcp { testServer() } + mcp(enableDnsRebindingProtection = false) { testServer() } routing { get("/health") { call.respondText("healthy") } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorRouteExtensionsTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorRouteExtensionsTest.kt index 5ba4448..d6b95b4 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorRouteExtensionsTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorRouteExtensionsTest.kt @@ -61,7 +61,7 @@ class KtorRouteExtensionsTest : AbstractKtorExtensionsTest() { route("/api/mcp") { get("/test") { call.respondText("test-endpoint") } - mcp { testServer() } + mcp(enableDnsRebindingProtection = false) { testServer() } } } } @@ -91,7 +91,7 @@ class KtorRouteExtensionsTest : AbstractKtorExtensionsTest() { route("/v1") { route("/services") { route("/mcp") { - mcp { testServer() } + mcp(enableDnsRebindingProtection = false) { testServer() } } } } @@ -112,7 +112,7 @@ class KtorRouteExtensionsTest : AbstractKtorExtensionsTest() { routing { route("/api") { - mcp("/mcp-endpoint") { testServer() } + mcp("/mcp-endpoint", enableDnsRebindingProtection = false) { testServer() } } } } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt index 8b413d8..f6dda15 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt @@ -477,6 +477,7 @@ class StreamableHttpServerTransportTest { // Step 1: Initialize session via POST val initResponse = client.post(mcpPath) { + header(HttpHeaders.Host, "localhost") addStreamableHeaders() setBody(buildInitializeRequestPayload()) } @@ -485,6 +486,7 @@ class StreamableHttpServerTransportTest { // Step 2: Open first GET SSE stream client.prepareGet(mcpPath) { + header(HttpHeaders.Host, "localhost") header(HttpHeaders.Accept, ContentType.Text.EventStream.toString()) header(MCP_SESSION_ID_HEADER, sessionId) header("mcp-protocol-version", LATEST_PROTOCOL_VERSION) @@ -495,6 +497,7 @@ class StreamableHttpServerTransportTest { // Step 3: Open a second GET — the transport closes the old session // and the new stream takes over. client.prepareGet(mcpPath) { + header(HttpHeaders.Host, "localhost") header(HttpHeaders.Accept, ContentType.Text.EventStream.toString()) header(MCP_SESSION_ID_HEADER, sessionId) header("mcp-protocol-version", LATEST_PROTOCOL_VERSION) @@ -528,6 +531,7 @@ class StreamableHttpServerTransportTest { // Step 1: Initialize session via POST val initResponse = client.post(mcpPath) { + header(HttpHeaders.Host, "localhost") addStreamableHeaders() setBody(buildInitializeRequestPayload()) } @@ -536,6 +540,7 @@ class StreamableHttpServerTransportTest { // Step 2: Open and then close a GET SSE stream client.prepareGet(mcpPath) { + header(HttpHeaders.Host, "localhost") header(HttpHeaders.Accept, ContentType.Text.EventStream.toString()) header(MCP_SESSION_ID_HEADER, sessionId) header("mcp-protocol-version", LATEST_PROTOCOL_VERSION) @@ -547,6 +552,7 @@ class StreamableHttpServerTransportTest { // Step 3: Immediately reconnect — the transport should close the stale // stream and allow the new one. client.prepareGet(mcpPath) { + header(HttpHeaders.Host, "localhost") header(HttpHeaders.Accept, ContentType.Text.EventStream.toString()) header(MCP_SESSION_ID_HEADER, sessionId) header("mcp-protocol-version", LATEST_PROTOCOL_VERSION) @@ -578,6 +584,7 @@ class StreamableHttpServerTransportTest { // Step 1: Initialize session via POST val initResponse = client.post(mcpPath) { + header(HttpHeaders.Host, "localhost") addStreamableHeaders() setBody(buildInitializeRequestPayload()) } @@ -586,6 +593,7 @@ class StreamableHttpServerTransportTest { // Step 2: Open GET SSE stream with session ID client.prepareGet(mcpPath) { + header(HttpHeaders.Host, "localhost") header(HttpHeaders.Accept, ContentType.Text.EventStream.toString()) header(MCP_SESSION_ID_HEADER, sessionId) header("mcp-protocol-version", LATEST_PROTOCOL_VERSION) From 49e1072c66a34d4af9100264abb728881bd41aac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 11:34:35 +0200 Subject: [PATCH 002/178] chore(deps): bump the infrastructure group across 1 directory with 2 updates (#752) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the infrastructure group with 2 updates in the / directory: [io.github.oshai:kotlin-logging](https://github.com/oshai/kotlin-logging) and [io.netty:netty-bom](https://github.com/netty/netty). Updates `io.github.oshai:kotlin-logging` from 8.0.01 to 8.0.02
Release notes

Sourced from io.github.oshai:kotlin-logging's releases.

8.0.02

What's Changed

Full Changelog: https://github.com/oshai/kotlin-logging/compare/8.0.01...8.0.02

Commits
  • accd3ca bump version to 8.0.03
  • 2bd058a bump version to 8.0.02
  • 8ab1a8a Fix GraalVM native build error caused by stale substitution target in v8.x (#...
  • See full diff in compare view

Updates `io.netty:netty-bom` from 4.2.12.Final to 4.2.13.Final
Release notes

Sourced from io.netty:netty-bom's releases.

netty-4.2.13.Final

CVEs Fixed

  • CVE-2026-42586 (netty-codec-redis)
  • CVE-2026-42578 (netty-handler-proxy)
  • CVE-2026-42577 (netty-transport-native-epoll)
  • CVE-2026-42587 (netty-codec-http, netty-codec-http2)
  • CVE-2026-41417 (netty-codec-http)
  • CVE-2026-42581 (netty-codec-http)
  • CVE-2026-42580 (netty-codec-http)
  • CVE-2026-42585 (netty-codec-http)
  • CVE-2026-42579 (netty-codec-dns)
  • CVE-2026-42582 (netty-codec-http3)
  • CVE-2026-42583 (netty-codec, netty-codec-compression)
  • CVE-2026-42584 (netty-codec-http)
  • CVE-2026-XXXXX (netty-codec-mqtt)

What's Changed

... (truncated)

Commits
  • b3844c8 [maven-release-plugin] prepare release netty-4.2.13.Final
  • 82f47fa Merge commit from fork
  • ada0999 Merge commit from fork
  • b4051e2 Fix BrotliDecoder not forwarding all decompressed chunks
  • 67207c1 Merge commit from fork
  • 541ca7c Merge commit from fork
  • 943edb3 Fix codec-dns tests
  • 6459a28 Merge commit from fork
  • b4ba61b Fix checkstyle in HttpObjectDecoder
  • 977661f Merge commit from fork
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 360a468..63a75c5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kover = "0.9.8" ktlint = "14.2.0" knit = "0.5.1" mavenPublish = "0.36.0" -netty = "4.2.12.Final" +netty = "4.2.13.Final" # libraries version awaitility = "4.3.0" @@ -18,7 +18,7 @@ coroutines = "1.10.2" kotest = "6.1.11" kotlinx-io = "0.9.0" ktor = "3.3.3" -logging = "8.0.01" +logging = "8.0.02" mockk = "1.14.9" mokksy = "0.8.1" serialization = "1.11.0" From c1210009a5d3b9d5c89d21684f7d5cfd3ebbb17e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 11:53:25 +0200 Subject: [PATCH 003/178] chore(deps): bump io.modelcontextprotocol:kotlin-sdk-client from 0.11.1 to 0.12.0 in /samples/kotlin-mcp-client (#743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.modelcontextprotocol:kotlin-sdk-client](https://github.com/modelcontextprotocol/kotlin-sdk) from 0.11.1 to 0.12.0.
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 69ebdde..dd1ec3f 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -2,7 +2,7 @@ anthropic = "2.27.0" kotlin = "2.3.21" ktor = "3.3.3" -mcp-kotlin = "0.11.1" +mcp-kotlin = "0.12.0" shadow = "9.4.1" slf4j = "2.0.17" From 9561624ba999dae728d38aaf4f4076e21e218557 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 10:13:00 +0000 Subject: [PATCH 004/178] chore(deps): bump mcp-kotlin from 0.11.1 to 0.12.0 in /samples/kotlin-mcp-server (#744) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.11.1 to 0.12.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index a6c07dc..2eccae2 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.3.21" ktor = "3.3.3" -mcp-kotlin = "0.11.1" +mcp-kotlin = "0.12.0" slf4j = "2.0.17" shadow = "9.4.1" From 22e48089be89524dd6301fca30eec31775668711 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 10:27:26 +0000 Subject: [PATCH 005/178] chore(deps): bump mcp-kotlin from 0.11.1 to 0.12.0 in /samples/weather-stdio-server (#750) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.11.1 to 0.12.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 19874f4..b294c80 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ coroutines = "1.10.2" kotlin = "2.3.21" ktor = "3.3.3" logging = "8.0.01" -mcp-kotlin = "0.11.1" +mcp-kotlin = "0.12.0" shadow = "9.4.1" slf4j = "2.0.17" From 3e4a5e0c1d4f508c660cff0094a30b2033eb0810 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 14:18:24 +0200 Subject: [PATCH 006/178] chore(deps): bump kotlin from 2.3.20 to 2.3.21 in /samples/kotlinlang-mcp-server (#748) Bumps `kotlin` from 2.3.20 to 2.3.21. Updates `org.jetbrains.kotlin.jvm` from 2.3.20 to 2.3.21
Release notes

Sourced from org.jetbrains.kotlin.jvm's releases.

Kotlin 2.3.21

Changelog

Backend. Wasm

  • KT-84610 [Wasm] Failed to compile klibs in IC mode

Compiler

  • KT-84566 Prevent launching Default dispatcher threads from IJ SDK in kotlin compiler
  • KT-85358 Native: roll back the workaround for KT-84678 once MapLibre has been properly fixed
  • KT-85626 @JvmRecord in commonMain breaks compileCommonMainKotlinMetadata with "Cannot access 'java.lang.Record'"
  • KT-85405 Postpone/Revert DontIgnoreUpperBoundViolatedOnImplicitArguments
  • KT-84678 K/N: Undefined symbol from SPM-added ObjC frameworks when linking iOS target
  • KT-85021 False positive SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC error in multi-module project

JavaScript

  • KT-82395 Support top-level declarations from compiler plugins in JS incremental compilation
  • KT-84475 K/JS: false-positive exportability warnings in multi-module project
  • KT-84633 Kotlin/JS: "Serializer for class not found" error when IR output granularity is whole-program
  • KT-85047 Kotlin/JS: @JsStatic on suspend fun of class companion generates incorrect d.ts
  • KT-84517 K/JS: bad mappings data in outputted Kotlin stdlib source map

Libraries

  • KT-71848 Kotlinx.metadata: Add CompilerPluginData into Km API

Native. C and ObjC Import

  • KT-85399 Kotlin/Native: TypeCastException when casting ObjC Protocol MetaClass with genericSafeCasts enabled
  • KT-85508 K/N: TypeCastException when using nw_parameters_create_secure_tcp block parameter on 2.3.20

Tools. Gradle

  • KT-84729 Update Gradle plugin-publish version to enable configuration cache badge on Gradle plugins portal

Tools. Gradle. Compiler plugins

  • KT-85257 AGP/Compose: MergeMappingFileTask clears R8 artifacts due to @OutputDirectory annotation on AGP 9.1+

Tools. Scripts

  • KT-85105 Scripts: JVM backend internal error (IR lowering) when scratch file contains anonymous object
  • KT-85103 Exception while generating code when explain destructuring decls
  • KT-84842 scriptCompilationClasspathFromContext behavior changed from 2.3.10 to 2.3.20
  • KT-85029 Kotlin Scripting: ScriptDiagnostic reports "at null" instead of error location

Tools. Statistics (FUS)

... (truncated)

Changelog

Sourced from org.jetbrains.kotlin.jvm's changelog.

2.3.21

Backend. Wasm

  • KT-84610 [Wasm] Failed to compile klibs in IC mode

Compiler

  • KT-84566 Prevent launching Default dispatcher threads from IJ SDK in kotlin compiler
  • KT-85358 Native: roll back the workaround for KT-84678 once MapLibre has been properly fixed
  • KT-85626 @JvmRecord in commonMain breaks compileCommonMainKotlinMetadata with "Cannot access 'java.lang.Record'"
  • KT-85405 Postpone/Revert DontIgnoreUpperBoundViolatedOnImplicitArguments
  • KT-84678 K/N: Undefined symbol from SPM-added ObjC frameworks when linking iOS target
  • KT-85021 False positive SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC error in multi-module project

JavaScript

  • KT-82395 Support top-level declarations from compiler plugins in JS incremental compilation
  • KT-84475 K/JS: false-positive exportability warnings in multi-module project
  • KT-84633 Kotlin/JS: "Serializer for class not found" error when IR output granularity is whole-program
  • KT-85047 Kotlin/JS: @JsStatic on suspend fun of class companion generates incorrect d.ts
  • KT-84517 K/JS: bad mappings data in outputted Kotlin stdlib source map

Libraries

  • KT-71848 Kotlinx.metadata: Add CompilerPluginData into Km API

Native. C and ObjC Import

  • KT-85399 Kotlin/Native: TypeCastException when casting ObjC Protocol MetaClass with genericSafeCasts enabled
  • KT-85508 K/N: TypeCastException when using nw_parameters_create_secure_tcp block parameter on 2.3.20

Tools. Gradle

  • KT-84729 Update Gradle plugin-publish version to enable configuration cache badge on Gradle plugins portal

Tools. Gradle. Compiler plugins

  • KT-85257 AGP/Compose: MergeMappingFileTask clears R8 artifacts due to @OutputDirectory annotation on AGP 9.1+

Tools. Scripts

  • KT-85105 Scripts: JVM backend internal error (IR lowering) when scratch file contains anonymous object
  • KT-85103 Exception while generating code when explain destructuring decls
  • KT-84842 scriptCompilationClasspathFromContext behavior changed from 2.3.10 to 2.3.20
  • KT-85029 Kotlin Scripting: ScriptDiagnostic reports "at null" instead of error location

Tools. Statistics (FUS)

  • KT-85628 KGP: composite build FUS metrics fail on access of 'configurationTimeMetrics'
Commits
  • fea1ad8 Add ChangeLog for 2.3.21-RC2
  • 09c341e disable swift export execution tests in order to update macos
  • 67a0868 Avoid accessing KotlinNativeLink taskProvider when task was not executed
  • f89e5db [K/N] Disable TSAN in runtime tests
  • 45d6c85 [K/N] Don't generate generic safe casts for Objective-C types
  • 9261a6f [K/N][tests] Add a reproducer for KT-85508
  • c9ab9db [K/N][tests] Add a reproducer for KT-85399
  • 502e844 Explain: fix for destructuring declarations
  • 0c26485 Explain: fix for object literals
  • 68a9e3f [minor] fix testdata name in explain test
  • Additional commits viewable in compare view

Updates `org.jetbrains.kotlin.plugin.serialization` from 2.3.20 to 2.3.21
Release notes

Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

Kotlin 2.3.21

Changelog

Backend. Wasm

  • KT-84610 [Wasm] Failed to compile klibs in IC mode

Compiler

  • KT-84566 Prevent launching Default dispatcher threads from IJ SDK in kotlin compiler
  • KT-85358 Native: roll back the workaround for KT-84678 once MapLibre has been properly fixed
  • KT-85626 @JvmRecord in commonMain breaks compileCommonMainKotlinMetadata with "Cannot access 'java.lang.Record'"
  • KT-85405 Postpone/Revert DontIgnoreUpperBoundViolatedOnImplicitArguments
  • KT-84678 K/N: Undefined symbol from SPM-added ObjC frameworks when linking iOS target
  • KT-85021 False positive SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC error in multi-module project

JavaScript

  • KT-82395 Support top-level declarations from compiler plugins in JS incremental compilation
  • KT-84475 K/JS: false-positive exportability warnings in multi-module project
  • KT-84633 Kotlin/JS: "Serializer for class not found" error when IR output granularity is whole-program
  • KT-85047 Kotlin/JS: @JsStatic on suspend fun of class companion generates incorrect d.ts
  • KT-84517 K/JS: bad mappings data in outputted Kotlin stdlib source map

Libraries

  • KT-71848 Kotlinx.metadata: Add CompilerPluginData into Km API

Native. C and ObjC Import

  • KT-85399 Kotlin/Native: TypeCastException when casting ObjC Protocol MetaClass with genericSafeCasts enabled
  • KT-85508 K/N: TypeCastException when using nw_parameters_create_secure_tcp block parameter on 2.3.20

Tools. Gradle

  • KT-84729 Update Gradle plugin-publish version to enable configuration cache badge on Gradle plugins portal

Tools. Gradle. Compiler plugins

  • KT-85257 AGP/Compose: MergeMappingFileTask clears R8 artifacts due to @OutputDirectory annotation on AGP 9.1+

Tools. Scripts

  • KT-85105 Scripts: JVM backend internal error (IR lowering) when scratch file contains anonymous object
  • KT-85103 Exception while generating code when explain destructuring decls
  • KT-84842 scriptCompilationClasspathFromContext behavior changed from 2.3.10 to 2.3.20
  • KT-85029 Kotlin Scripting: ScriptDiagnostic reports "at null" instead of error location

Tools. Statistics (FUS)

... (truncated)

Changelog

Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

2.3.21

Backend. Wasm

  • KT-84610 [Wasm] Failed to compile klibs in IC mode

Compiler

  • KT-84566 Prevent launching Default dispatcher threads from IJ SDK in kotlin compiler
  • KT-85358 Native: roll back the workaround for KT-84678 once MapLibre has been properly fixed
  • KT-85626 @JvmRecord in commonMain breaks compileCommonMainKotlinMetadata with "Cannot access 'java.lang.Record'"
  • KT-85405 Postpone/Revert DontIgnoreUpperBoundViolatedOnImplicitArguments
  • KT-84678 K/N: Undefined symbol from SPM-added ObjC frameworks when linking iOS target
  • KT-85021 False positive SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC error in multi-module project

JavaScript

  • KT-82395 Support top-level declarations from compiler plugins in JS incremental compilation
  • KT-84475 K/JS: false-positive exportability warnings in multi-module project
  • KT-84633 Kotlin/JS: "Serializer for class not found" error when IR output granularity is whole-program
  • KT-85047 Kotlin/JS: @JsStatic on suspend fun of class companion generates incorrect d.ts
  • KT-84517 K/JS: bad mappings data in outputted Kotlin stdlib source map

Libraries

  • KT-71848 Kotlinx.metadata: Add CompilerPluginData into Km API

Native. C and ObjC Import

  • KT-85399 Kotlin/Native: TypeCastException when casting ObjC Protocol MetaClass with genericSafeCasts enabled
  • KT-85508 K/N: TypeCastException when using nw_parameters_create_secure_tcp block parameter on 2.3.20

Tools. Gradle

  • KT-84729 Update Gradle plugin-publish version to enable configuration cache badge on Gradle plugins portal

Tools. Gradle. Compiler plugins

  • KT-85257 AGP/Compose: MergeMappingFileTask clears R8 artifacts due to @OutputDirectory annotation on AGP 9.1+

Tools. Scripts

  • KT-85105 Scripts: JVM backend internal error (IR lowering) when scratch file contains anonymous object
  • KT-85103 Exception while generating code when explain destructuring decls
  • KT-84842 scriptCompilationClasspathFromContext behavior changed from 2.3.10 to 2.3.20
  • KT-85029 Kotlin Scripting: ScriptDiagnostic reports "at null" instead of error location

Tools. Statistics (FUS)

  • KT-85628 KGP: composite build FUS metrics fail on access of 'configurationTimeMetrics'
Commits
  • fea1ad8 Add ChangeLog for 2.3.21-RC2
  • 09c341e disable swift export execution tests in order to update macos
  • 67a0868 Avoid accessing KotlinNativeLink taskProvider when task was not executed
  • f89e5db [K/N] Disable TSAN in runtime tests
  • 45d6c85 [K/N] Don't generate generic safe casts for Objective-C types
  • 9261a6f [K/N][tests] Add a reproducer for KT-85508
  • c9ab9db [K/N][tests] Add a reproducer for KT-85399
  • 502e844 Explain: fix for destructuring declarations
  • 0c26485 Explain: fix for object literals
  • 68a9e3f [minor] fix testdata name in explain test
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 20dff78..967e7ff 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.3.20" +kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.11.1" serialization = "1.10.0" From b0093523566e8c4facd3dbde46a7a7cb1997c325 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 15:04:13 +0200 Subject: [PATCH 007/178] chore(deps): bump org.jetbrains.kotlinx:kotlinx-serialization-json from 1.10.0 to 1.11.0 in /samples/kotlinlang-mcp-server (#746) Bumps [org.jetbrains.kotlinx:kotlinx-serialization-json](https://github.com/Kotlin/kotlinx.serialization) from 1.10.0 to 1.11.0.
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-serialization-json's releases.

1.11.0

This release is based on Kotlin 2.3.20 and provides a new Json exceptions API and some bugfixes and improvements.

Expose Json exceptions structure

To make working with exceptions easier and providing proper error codes in e.g., REST APIs, classes JsonException, JsonDecodingException, and JsonEncodingException are now public. They have relevant public properties, such as shortMessage, path, offset, and others. This API is currently experimental, and we're going to improve it further in the subsequent releases. See the linked issues for the details: #1930, #1877.

Ability to hide user input from exception messages for security/privacy reasons.

Historically, exception messages in kotlinx.serialization often included the input Json itself for debuggability reason. Such behavior may pose additional challenges for logging, analytics, and other systems, since a system is not always allowed to store user data due to privacy/security reasons, which imposes additional sanitation logic. To address this issue, a new property exceptionsWithDebugInfo is added to JsonConfiguration. Disable it to hide user input from exception messages. IMPORTANT: This behavior will be enabled by default when this property becomes stable. See #2590 for more details.

Bugfixes and improvements

  • CBOR: Relax value range check when decoding numbers (#3167)
  • Use a specialized writeDecimalLong method for IO stream integrations in Json (#3152)
Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-serialization-json's changelog.

1.11.0 / 2026-04-10

This release is based on Kotlin 2.3.20 and provides new Json exceptions API and some bugfixes and improvements.

Expose Json exceptions structure

To make working with exceptions easier and providing proper error codes in e.g., REST APIs, classes JsonException, JsonDecodingException, and JsonEncodingException are now public. They have relevant public properties, such as shortMessage, path, offset, and others. This API is currently experimental, and we're going to improve it further in the subsequent releases. See the linked issues for the details: #1930, #1877.

Ability to hide user input from exception messages for security/privacy reasons.

Historically, exception messages in kotlinx.serialization often included the input Json itself for debuggability reason. Such behavior may pose additional challenges for logging, analytics, and other systems, since a system is not always allowed to store user data due to privacy/security reasons, which imposes additional sanitation logic. To address this issue, a new property exceptionsWithDebugInfo is added to JsonConfiguration. Disable it to hide user input from exception messages. IMPORTANT: This behavior will be enabled by default when this property becomes stable. See #2590 for more details.

Bugfixes and improvements

  • CBOR: Relax value range check when decoding numbers (#3167)
  • Use a specialized writeDecimalLong method for IO stream integrations in Json (#3152)
Commits
  • 6956af2 Prepare 1.11 release
  • 390d84c Merge remote-tracking branch 'origin/master' into dev
  • 431fe2d Use local repo for publishing (#3171)
  • 05c12b6 Add usage attribute to "testRepositories" configuration
  • a4e1f08 Bump Kover version to 0.9.8 release (#3174)
  • 304e858 Expose Json exceptions structure (#3145)
  • 4a0338e Included G Play SDK verification file for core-jvm (#3169)
  • 421f64c CBOR: Relax value range check when decoding numbers (#3167)
  • 85a4f12 KT-84955: mark apple x64 tagets as deprecated error
  • bd38b0e Remove dead code
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 967e7ff..2150c10 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.11.1" -serialization = "1.10.0" +serialization = "1.11.0" coroutines = "1.10.2" logback = "1.5.32" shadow = "9.4.1" From 93e5ed2c06a1e88b9981b92713557fc5f16acb4d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 16:03:42 +0200 Subject: [PATCH 008/178] chore(deps): bump the other-dependencies group across 5 directories with 3 updates (#753) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-client directory: [gradle-wrapper](https://github.com/gradle/gradle) and [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/kotlinlang-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 2 updates in the /samples/weather-stdio-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and [io.github.oshai:kotlin-logging-jvm](https://github.com/oshai/kotlin-logging). Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `com.anthropic:anthropic-java` from 2.27.0 to 2.28.0
Release notes

Sourced from com.anthropic:anthropic-java's releases.

v2.28.0

2.28.0 (2026-05-04)

Full Changelog: v2.27.0...v2.28.0

Features

  • api: improve Managed Agents APIs (8453f3e)
  • client: add Workload Identity Federation, interactive OAuth, and auth profiles (b5f1d02)
  • client: more robust error parsing (d523547)
  • support setting headers via env (03bb766)

Chores

Documentation

  • clarify forwards compat behavior (f48cfb4)
Changelog

Sourced from com.anthropic:anthropic-java's changelog.

2.28.0 (2026-05-04)

Full Changelog: v2.27.0...v2.28.0

Features

  • api: improve Managed Agents APIs (8453f3e)
  • client: add Workload Identity Federation, interactive OAuth, and auth profiles (b5f1d02)
  • client: more robust error parsing (d523547)
  • support setting headers via env (03bb766)

Chores

Documentation

  • clarify forwards compat behavior (f48cfb4)
Commits
  • e448de8 chore: release main
  • b1899db feat(client): more robust error parsing
  • 959647a codegen metadata
  • c8cc791 feat(client): add Workload Identity Federation, interactive OAuth, and auth p...
  • 14e9142 docs: clarify forwards compat behavior
  • ac01a78 codegen metadata
  • 5dda387 codegen metadata
  • 84b5f41 codegen metadata
  • af86b69 codegen metadata
  • 8194aad ci: pin trigger-release-please github action
  • Additional commits viewable in compare view

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Updates `gradle-wrapper` from 9.4.1 to 9.5.0
Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Van... _Description has been truncated_ Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 +- samples/kotlin-mcp-client/gradlew | 2 +- samples/kotlin-mcp-client/gradlew.bat | 31 +--- .../gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 +- samples/kotlin-mcp-server/gradlew | 2 +- samples/kotlin-mcp-server/gradlew.bat | 31 +--- .../gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 +- samples/kotlinlang-mcp-server/gradlew | 2 +- samples/kotlinlang-mcp-server/gradlew.bat | 175 ++++++++---------- .../gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 +- samples/simple-streamable-server/gradlew | 2 +- samples/simple-streamable-server/gradlew.bat | 31 +--- .../gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 +- samples/weather-stdio-server/gradlew | 2 +- samples/weather-stdio-server/gradlew.bat | 31 +--- 22 files changed, 144 insertions(+), 189 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index dd1ec3f..2959a9a 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.27.0" +anthropic = "2.28.0" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" diff --git a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.jar b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 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 delta 40115 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 e{Sg5G5zENPNVU~b5#<2@M#Os+0czL&{q{eZe&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.jar b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 z;U1F#i!+m#VJLq=6g@+M-F~20QBYKLRVWGDjiO0|!~~_lLk*_2CO$R8?(KHzer0yI zh8X!F{tIJ*MiYO4KgxKwXpG{6FEew`oOAEFcjnvo&tCyNz_P%*CG{>f^#UBFoW{~#f+`h2kcG9g+E+%j*^rD4HpH^#Qmg40?W0tPFBxC z6>XrrFZ8O4@>i*n{vW z9C!d83gLqA!LmR9zwNK@k52%&fT@7@?e;!@l`GU6@`YSVUCNo%P2F0Doo&3Tn}V1J za)gn1SYcGUBE5-y9p$n_7ilJ2qiSrG9d{6&UoJ3bZOH%qW$zq=SfM%_CEi$16s&(Y zOa}^)Z!yp3i+QdJ8sysqgn;Qo(+5r0){%hICYa0wEF5Le0o#^BcJtdl{dKo!{n3>k z|4w07z~LGP%p7`?-L2N7yA<{Xr1V0%?|5NyeDcU(4^kLIuw?=VV+9H49Y}rvP)i30 zE7W3A_W%F@ECB!jP)h>@6aWYa2mq4}Wk`Qnd3;p$wLfRJJGmJJCj=N48AFuGGKr!h zCL#tBATkNa0CCvj&CE?QGBY>M5{L^`tG4!8^|iJ&*7_{9ja9m6VJ4UgQd_E4yJ$D7 zeRi{}-8Ze3^!vMaCYebl0pDMbPe|_l{mwbRvoF8<+=(ZS5YYvu)0pntw{O$(>neY` zl;CbP7OH5d2zFQ0Rs^+ZUpS&9!&=N6)j}%P<7z}z5-K)(m4r9gs|I%`Qqe?3L$?x1 zsI?V+J>IC&=M4)Qs=D;T^Ofa*jW5sPcc&r|EF^jr?|A|w))S7YYCIh4!D_!6Pv9)9 zFRwelZn-z4_E+3sCuWlUS}Gn?*Mxr~DpREv@2T&JE1`&5zbCHr^{Mgtwfbv^@z$n< zV-i`IW?rrIEAFTs>uNQal*qp=lDuYHs4W{DZ2#(ur-zkjCewduIA}GL zWk}4lVA2ueyCCkQGMUbxSxj@Mf|6)9Qz^*$w4iQGC?-cVrY7sRZ1RE7Tyn`YhvqRk z@^>U!z+_EoTQ;>$LTd%unY2izh2$G;UiIqF)N3fuWbia(%CXCrgLDG zZWz~2o&u{Ga1vEB+0<)N@G*a;a*uDKSsSaiIjEMrGSyHWY-Ml~*6Ib#`i)Am7e+jn z$qa_zKb}G%ax&$^gSDk}zD(!Q1x(J#`w}e!OG(Y}$T7VDM63XNIbB>z7f}PaDdJ`l zU6S(#eYsuJJ*`>oUZbUAp_X`Di%WEAPN`Y45?#h52}cA64q9dCZZ&@xxg;D5Coi3# zn=zMmPz$Y*sfpGyo!%E$`;>StRG2mv3xh&ws(hysag|NFD?|2Hx?CnJt!Juv7l;zI zK{|CW95@M`nmvN?4YaY8+UW|WdE-oOO2v}lsM@kOsP-9{ex^%TE3ufCbcfWW8jm8Y zxPwBaeNdIVTZ_B1$Gd+oSK{vOxE6H>5g=X2W$q*ABy9AX^Ba}A6Y_X(+ z6k+!!>N0$xU5Tm=3K?tAn{7wk)k?h5PCW?vy1uvup_5@XVW)pE+zG~yC?b)@6A*KG z5iyH6P%$ZYQ$$D^Wm!^cf{`%NSTw4{LOvK2 z2niKokrI?P%G6JL5M4?nqV3rd+a1&P#5U+!1r-;lNVt+0X;?@2`={N{l^SnQ0v zWA!uulJBGUm(Xo=JD9)5PXC1zd`&8>Chhb=tTfx{E*Lj4kVvXguQ0Kl{u`mKlSw7R zk$PV^fm-)rrbfS-Ot=;I6NP6?@rU_6}Fk+Ya9e2nfDybk6vx6VORJgy8N>wX*>RuY0Arn5a$$IuwtAovM- zK&JcYeWp-{O>g$a#d_NThC`w|^uTI-p{aSiOoi4c>No8>1XQ<{czWl*t3;YBMbh(Av+ z$aIXp$z<|+?euLX?@0w|>IS>noFvhUA^=WR=iim-CHfv@^m@1NTCuanPCvj4Y7^S2 zgoA%x7Tna(k5CvAsjfuUy~{nVMRWD5^kV`2zsS2p2Bp3c2_t{Ys|S>DQpT^Y1wVi$om4;&> zb?=65_zaZS>Yz91_d-{H5Wd_xl{)_mM>u|$hCWm7rRs$!n=Zn^y{{Y`NDcN7Vo zTfwZ(>pzjbDp4CmF^4-fhZ7?HLJoS%D0BZps?K6~cM61m=OzN3pQapUwzWJV)2Jw) zr9llHNjR2RuMRjcXrYCEgiTCyCW^8u6^?{ZeHmjFd+ltK*(%x_o9L=yAz&62e+qvx zjSenh86>zA`6HhOTv}5k)JhI=DfqTt2Ug;_kWq`ZYuVnw!SjTMkMVp&zfLD-j+R)+!3#xSag5ItsT|t5 zPt=R1hbiP`hGW;PWgPkKse2XD4&Le`AsKZ#I)E`I8IE_ z9I|Ku83U82$k4EHjHDp34qA%{XS~E1%>8<2GY-SFXu_HKWl694d?~M#c?ExCqH=mB zY#QvW5>kob3JPk9L>!!5S~J#3)`?ECPVXdn9gJLTFfCSqmh$C-(E7qrSC>KJHqqJX zcMW=%=HLzJw7H!(B6}CGDe)#_oJ$}+#ya1LEskg_9K4ygl)w|WBG_^P@8By%v_HfF zkp&Yi(LQn5c0?IhGsY52B7A=>;%gVe2n(H)s!N_Uih#g4vM8@XK-<%!MD(;aKJGB` z#C(HQH;T7Anu;XD2xPa>VAa{VTV_?Hl|@;okftWwVyx>``c=0Q8!$itiD_oZl+)!F z7-k*p;?uO+Hg&Gs(AMJMC>noQj&RJlCCO=i zfiFp z1Fz>B1f6~8af(4me51@a2~TwuQISvU=@G&6UQzV68P0yI%(w7uOjmR?ZEA0AU+Zq| ziJ`R&xr3=h62r2gR=0m}c(-tPcO-k4gfTkS9qvg9*l=tTT!Y)r??)>R(VDsvS_GrL zetE$k&<9q=WMhtK$owCqHG+jZ#YN9vRF(#XeB2r{85L)#60+clVFhmwf zdr8rBGf{_z*dLYo9{w24G^AiEdexCVYIRmp#Ypcw$oG{19TR`f{31xrm`5X;5|a26 z#XYqcRf#e5oE}q?d$joO&Ecr3iR8>EXP@N#CHx>`teFE|`ys{Tq*vpaLe^qq4}Y3J zBl81{v1h5LnAC=wG#0^aHI(;Rf&R!$LS~v1QKDTTrLypHsq$Q=JB!kuV7$g+S5VWi zG>y6&iy42c3T%IM@aOpRGFkZxGi;18tYZA!aI9b3t=9W=N!rw;(yau++knK6BQZqB z7nq*UPYhW+VDxGsqcSBbjl@%=)J=sbt^)pVo5qpT<5o@HU9ChS{;+5|`5+&X`AeLJ zN-|7O{J*l;yS#ebz=xegjH$FXyYC+FM%?21R=@5WuPc9gvOzidGSj>wN43ThNhnI< zBZZd{V|@vdndq&fU3x$A)a1@%k_RGkz9RE6ewu0Lw1GFR&Q8Wl_9RsEql}4I4#riK z;%5CG=HlrrT$tr1-fQzS{H!4PoXFeZE;~Pu*a%}BiK}{SIQW}J*8Uc9X^}%#X<8EF zs?sOSrq6$NNE7Et{2iHJ6v?|J0uIGdNM}`rnv5w?@c}3)WZOQGt?%;p#HruUO)lB5 z7y5OY4+;~;`JuRCbZ5V2_#FI-_~NmcUqx#(;Q}s)fr)w6SbLebBQAOJLn?0zy!?cJ zD)VdnGY2Wg(=UW9+Y3LqOo44!?UypY%)csV4>y1J!hk3yzd@f6OvT03sj)Qin!{KH z8^7Z>Wd1Gx9^xg$C#6^tQ*?n4^E^{?!GGjG33N=kXTpwk*^W1&q+-EdbiGCl3M<K9MiT<**i}DJO4vy=bv^ABKiflk+7I9JIU?4K_H)GTQ45mxi%@MP50$ZoASD+P*~jPbfxtE%J@2AlF+P)PkJyv!X~&Ib$GM5 z0YGmh=EwF_v`dX=S7we!nJ#I9z!^y-{+WNNgzWgwrV_lpfORwe2A$S4%}7&un&zkJ ztbi{~OPp0{svo54nqj)|Ff}syhRE45LQR3Tnlv?MXkD#OZ2Arp29d``Xmh~wBuRnw z<{H0qYxOW~%h2|t>&1F?hORnFCLDA+1!yPDr%LkBN-~*b@dcVJqj)t*v_hiA#1en4 z90j29-b6G?GH}Hf9%lmq5Iaq!IyJ#OjEDVIc$USdCqp#J1tCG*a-g~<$8!+>yPdtx ztJ4(A&^2jF8b7`f>JRML(Vn5bmP2&C^+~D;1kBETev9))f0}M_)*PY_YZY> zBe!xlRz4(F0?vB?==|s*x^I{s9HD>xfdE~(sO@no4^Z@pMr|;K^{h2G$^v7iaupFR&F+j_$maBjCr`OW- z4}r7?NN?&$Zh>SO2X#rdaj=b#)7$saTmZkL1KWnEbc99&XdjMxfdeh#VA>>Q-BoTLUHC!TR( zy}ZF{U1l%0yQDO`_MbTDvX+0_EmsLq%k8?X4R)Qby^yZX4v+!kvNwRj(C86Z>iPn9 z1@WO1%G8`?Ayx{MG%pa(=esO|twkgBNT5B#Zs*-;UVM-}X|93stcI;=t$4~=+E&Ki zG@lz-Cf!fa4PKX~d0EHM=u3Dhms~b;xg-R!S*{Xhwsji2hlFR>l<|M^3^xvQQ-f6; z8Sr+xtQl@j^V%|QO|#E9;W#<)>aq><6&)^1z_|}=;H%>xcewDdZIJvfcxzLG&AAWj z@IIa8otB%00~s$@Sw2N`TsHm9oaP`XBMl6ZI>Kt8jC(TNd(?QmT0B0^S_jS?=7fHJ zx!|?|!T`r5HNa=QWt@K+=Dkzw&d^tEpn|2`t|6>0X9Fw_sUfN^=XJ+PvJ8>MEH)cT zTy|GUP7nGDV$SL+F&2jTJ;FpckMJ#lcAUS81 zPxD>1Y5ve4HIDE-K&(bI2Wm(7CiwqHGJNkrzJL7)KM-j1Rv&-lhj7*~Kirw&M{8ZS znkRUK=!<#DvesY5Pv){EvYDO}`7T;8O8ZGNa-jaxFVTL9j!E=1(Z6Y#L^X>pIA@fc zBCC%gJ=%-H0!)Bc;_oP}Edum<4rmk!vt%k7EcTm8o@(Ft5kPaM076PO0M43@(@`oV z+t@Z4n__u>-m-s0kLVkq`3}_!?%t$@LM7}UrHw)#vZxu85ZF(27641J^bS=S8<+7Y z1@jfnw+L4Cx^tc~P%Q9)Ocjn)Bf8!GE=Xt586$010H z9JH5CqkB=PK29^}C7MaE&>5xya++?UGSh7|%XB-Hn_hpV*`_yWj_GZhYo1Lm^L(0T zUPSZFwY0!|F)cK&p)<|9XpuQYZu7NtmU$mln2*z9^Pj2GGKr55Bh_2(q;oCzKn7V1!A6;6JNUK<*+%$ipt=)Yd@QhD zB(MyB)mwj^;jhD))BKI~BK`tx)n)tw!cTYpD#XCI2dM%mF9zB&{1V=O5NJD2Gi#4n z9wfQeytHiylXhF}aq^Gw%Yhy10r8_W|F{jVzc2vLA7xv=DXSaK08xeM6n?`!-hjoEMFq|d0-FZ_2|Xi23zhEB;^88J~m`E|L- zi)-65HN2-1mG2A8Fa0(64=-N|l$Mq+9XOb%pp2@65sZ#v2sH;4j1|?Cz~BMD5^CI( z`DX^WVv4I;!EhEF4#s(%;cgBk4xqYnb@hVD)o0Wj&zOD!`e>O9u$Q4wrdp z0RRB!0h0km9FyyeEq|?A31FMmk)C-veo0mmCyqiCFcCSxhisEToS;A;b`oM@I}j(N zf87%;Q9Kw)!WgJAbdge#@$VTGShh?>19? ziz18S{fokj;_1PmL^763q*G0U={^(v88d0dvL*%xV%etnfEnMN%@1Z5MfzjOtQlT3 zw5w?_Hq?|58K${>#aXdc;LWTm&hO7Bljz6}#F~}~OKMjlWty2pY8QI)sVmfF>_x%X-_o-@eJC;zGkN;bdsE4DtdFU-65~31 z7_2jfV!45}*{nI(n-sx|D)C=j&Vxw{%zg1>KAYI1H-ED>9yhbuu2?FjRXeX-LL!wj zGpSgzr5}tf$#i@-tkkl8+UXGPJ~xp{eriEJ*D z=*^3NZhuLqb4;7+I`!En(k-&g>dpyI=*fwbt*)=MKiheh*tA`|8rJle%Q9#Y>}&4B znpwU7%lx#2milNhoj%Fstc47!V+!bA=$CA1PbZV`L};2dsDa6A4i4ppJ0Xo}PF;QH z1gG?^_EVUeeAGzIU`?V&RKU8k>*_C`yhT5qNq@^ki{(tSri>YMHdD=n=(U+lOs{EB ztB+R7!Br))>k=7gmd*_O=^SfA5o|ElhZ_*6>zsO*R?EiErSoJy9Bt-g#SOZE$w*|^ z%kKQtMoX(`EwwXUb)hzSsITnILT4<^o)PLxo7qq*oeRa&sa!0P3dK^xV6${enAzsg z`hR^xXqbJWTsqXBNcDxxeX)2hIUHJ6;u~)E(0ZIte>yW5gGtY+JO1b|udtWnx%_k? zZS+w+bugXrKlBxYHZd)JW8c$Prprg2)Xn6~CayKLCw2JgV!A{OwFNhKT0`0P$-)fj z(BMC6rL9rn0)JmJ(d(hh#3P_@eFbB*;nqRT*iaV~>&eA3 zxcN(#8FYn@t`zU8pKOytbOWybp;ov{4jrB_0emmsElj*GKr*}xgx{hvvoIY(_tb~Z#=BIbkZ6f4fnNFH| zJZdba@}W-$!@Q2Y&>R0R7|! z{Is7gk$`h2y2P(j*!U@R?Z?ly6@ieu=^oMLLrhK6yVEo??~|Dy2GGf+i@MIOtElSz z^bz6xsN}tC^1yd~8j-+XPahWp0tx0|(@$DC<5NgKaP+mk*>p0WGsQ>z^q@#sO#jBp zeW~2RL|lW(P`ba;Z4LFu;D1Sdr!7q_O+|tCD)J1*hC>6fJ!YuaG*h8mY!Gn>L2qv& zH_*H^)t*lECo+Sf+(0ac4>NQ|`Q)B~7;bG(e(;RYP$rFux#18($FQtrMYbk8vNhY| zh^!%T?@%I(NRyE;iu}|kQ$n!}RI_6W45pW}r-%A8=|O~~Tqd8Dkbj)j=(SlkRt{Q1 z+cL>WXlWL`wwzFB+A@*VU5e>NpdHb1aA|67Jck1*>kioimnO1_TxcMd8_Gsn>~P&I zk=q9D6Og?{qNf!Zwd$n-Ih}Mr&MJWw%FTx))6s8Pt5+NO%=7a#^wVo&+2a@qhRrAn=5*ZONx{i9r+K(6mF-!&6Ylq}+MPM~~2>K;A$nJ^7)b z3<9Nz>oUK5M(OJ7NuxC8qnqh5;3&&u0e1vPO^);Rmmv})H5v<)AlBsD@Hu*1eEA5% zOoefSKJTZ)^jRMe>K71j@~LYRLre=Rf`ZbjmrlZnn9*`sVt>d&n@?6yQrqCmK6;A2 zf&gfya+3L(f|Ky$`c!_<%xEWq)=$&dg#YW47Aj*g=$p8>sO7rS8FPKo9E4Qd^KT1q z`xbo%Q7vWe%h>}{BSi@_JVW0T_U|Jv9k-qJP;=OzA3|fqhi*UsKmAzZ!jI@##II=! z2Z{f`m220BD0W1 zeQ~hKmC9O}y8=YqZc!bWcjaxrte@=Im63L(nFbw$1C&P^*ul27nQPg$rDL_9iP=lz ztdQeiqV{AgD|ly;=ju+dI@yH^mfgi-&lX~^$8uMl#@GjUWiMAja*Ky&;8I{ZY~N?@ z+uT1*ynpKO^DM4LvgFxJp*Je34F<08X7jySJ>Aa%feH0I4@)+Cc)kF>j*5VS1H3>u zPX-b_L0xZfEp{X~XIloC^whe^MysD{!-X93@u_?oVr?$Hwx_+LqsP{4v1N=Us1Lf< zt?)3aU)Q#+8=6*mxX!Y8+i*_8(!5G$0oLLMZhsVw!#2JX2*=GpU))mkL)35sEp3Ti zMR>)_a9`^>EaqxH%g4+4Yyl|mmv618zsp^s4S5b#btPl1;&a3`aQ&+<+_H9E=lY%7 zde(2*xp8yXdJmr~cS@UYTh`2MOiOf`Ii*bDHGIC8=dzT!7jM~o(fanS9&Up;q&NwN z6Mw}tud_JUPtneDsS7PdHbM+;s%Y%zi>$s)R-eV!W%YGe)A!)R$=G0TUu?<5ty^*? zQ~ZQEX7a)Qqc_ygm+%(kHtw0_Vw8~8byFCs8M$oHgvAr7J?Y(MOQ%-2%gn|4W7;eR zqp++RoakVBy4+9fd6+Sf?%N2cg|cKxXMZ}qJ3myR7@Kb5*5M)Z9~-omJn`K6<444ne3<(Nek-Q(KjU&EBa2Xp!qd%@aZI|AZ}RcA z{4cq#1$qyAkjuD#~}1xm8kta(PuzC=eQ z8h*0;DPwb)A`igy6N>1W*nh~s!Q`?@52FeSPWwP_@Wb->mPWEYgp!9JVO${3795Av zg&rQY+|Pa`^7CVYrf=rYpc`h5n;Xnrd_cVNM3F?^PH<^7uN+8uidve5r5noL>plDw9JU#OCg)+4J^poNCAWv4p7I1T?Za-lTYg>K@*5M? zSt+_6S8nmP-Bv`9tkQ(b$Qz?N34x(PtyUZk;#!wyj7%27dveHlu}ojP)y^8~ zWDAq;T!sB~9>;IrpvreB?bXob!?d`JlyoCuTs5{s;;E$P9d8h>HobhcUUokulUFXda!6vwnn<_-q<#Ir8CQ1Him7VtyXx|S*lgP*>{%8g;(RM-k!cO{DBB z;8ATw6n~>^(4(V;`e(bG>~e=sT_KO`PJem-^r)Ro=l-vL%bP4ue$G=dh*Z6R zTazUY#7&kWLQj8lcx=(gT8;{9>+A zwttdpTM$wz9YRh{^o0a($XK&S-ElZ*=m=_|L+d z8XhBDp8Zto{2Uq4O^(K%IU5?r=%P)BsWZwAqqO-TSP(6o_m=Z)o66&OjG~I3pnt{a zTpW#dHO#quly*SP{Ztp$E1woVOjn9(JJIfqb{(Zz;m4i#kvHsEK0;1@vRr=O6#4S4 zf#sXP1+@>KG4hYY{tAEViN;|VWzb@~Q6-HPx^awV7_^c(IF9pj2sfI-!@^@|o<)nt zY3;=P3-IMtIz8*$FArq6mJuAoy6Cqx7D~TV0M;cfcKR9iZl>fPed}*))Fr z7=17rF$#1SEL#gaXBJ=MvL{Q%?H5!H}Z^A zaMIxQ2EZzYUeoPy+&Nci6cXPpr#zFKWizyMvVc*^z*sExKZiDvfvp}ARb{?gM#>dZdtf@Wa0EHTBmq(m(4SyPfIHw(B^u;^L z<#^ym2dw`S@IUYX=Cig3RysxjgZ`cQY$fv4oa&%&9Kd@p*Ot2AuTkALt*m`)>iS?`OM9}>Mv z^T!d?omv3;Z5f6vadSziQ^JeA2xK`YMs=i`;%`3qSsy0c3OXC!{JP}z*XQ=B7d&NC}fQBq5?0CxNGHS|WgU(X*XO~r7u3s>t-S{BwR zZibcOa0DTVla>}WeDx^rMqn+@D;(i2?jGapT+R*F@SdAuE1ev12i;FnkKH@ZdB@$f z;V|!uMt|j4uE$>ZEd_p?9Q)g&UC5C^cheZ(ia)dIshh_5-6Q1N6m)luP$~=(L9%!l zw>=hgAEh(HO+k0VWBgv0-Mt@kWc6DckfjgGP+1>$9Vse~9oO&&^^W%x_^ukhN9<-y z+DAj!R-!a3=)r#P)%(T74^Oa`7>sEcbY`jHkAF6d^2d+R9NcLS&p z=@zv^(<@a>)40lOx=-CM)QTf~9|gt{vJeswE5;4>8ax;2ge4&OUZc4@j+;7lROg%5 zX@AH=AJh4%nmosI=s_KEE+Fsm!x;0>-|Wmat6V@arCA&@e3M2)TGlDxVLrL7<|7Dq#5knfj}y-uo~ZLpyvvt(XH6a zcJ%JV>{}r7V+gsQ0!Vxax&MdAQ$IzD_&Kb5jH(%Mp6h82FGs1h0tdU50z5$T_-Q(c ze@F9GHw976El_vT$?7?*H(OpvY;cgn8UpRNHipOeQx8SE8={BkOoyd)U~@NtdrY|baB1iW_Jy24Zhp`P56B}M476s;+mWS#T7%vBVUhOQyCfXB z9BTqj{mnC*UukvLHeiK_tA>w6+=8|vhNIPU4^`Fh=Of+`LZwhU#!p7P^5Ju7JQ%5R z1id}Zps%NfzZ|Rr7L0fUKnfDRqkjPp#?S@*0B>$u>Eejf*=hug+WYB=#)ha4s6Zxm zKy56Kr(d0jrvRY#&UN(pnixkXr*9U`QY)yHzoVmVb)!tcmLkp(0lAR=z3mTSP1#(~ zSsO4!eUIJ1}gkJNv<;F#!P9XX8G zQ259l@s&9r>U6M-+GjDL097}ogGRq+&`EjvZQ!$`LLpZlpXjI!d>WBik-K!O(l z362sR=3vnEF#jruu9ph@vK(X3d5HfQaXVTKcdMsS&-Db1{j>n!85rd+tw{f`wt5?z z0!9F*`C3?)zBsuSffXCWQu{^>UHtx5@Wje!#4F`*tIyF|6{rgM4u8=7f0#O0`04&gz zV#Rq8Oh?xUd9g(R_@MVlDRM!_8WqN-tqWNpTItk2HCzGMU7dAU6kY$u=|;L2X+*la zkp>CrmPWdpB}77`hL+BSmF|!Z0qK+uk&==W5q>N0^Lu@H_Mf?~ozHcj@0^)EJ2Tfg z_pLyE41wmCXXBh~1iNlm_aRUqxka0LL>ayNDg%9WsQt7ra=i{+sm+J{ z;!?0&y#;hBP_I00gLY0{Bj$UI@T=)?u~G7wiA{uO+F8L6v4U6bQsuLuEN7Y1G<|q zwgl0mq_^tWI`j)JR66Mm6w%4Q@|BSjjeBO8s5#G^IeN4f9~E8N`;ja|cL#Q*RBO` zPAWZAr-E6-Os-TOPQW(pYGRPZKQp7n@?jfe^|;*zbvr7ZxP90LY!ax}7_RgyV$XM( znEAjIlImdysRI`TRl?BU;ArwW$2?n+GSJNAETJQ&R2eAiLfCN2X}9 zHdTj ze`0C@zU`}?7qv-J6Xo9)YiEeKz5Koq*2v|SaxboPC7F_cBj?qxEfMrdUIL zf|3akmgbP6p$j$=v%C@*_H*8;%aJHQ#Ag<#`gJIMMC{@iw#2f|sw?w}a}fFlm2&_y zeiISDVng_cJKf0Ih$b)4IKg^Lt$rdViIP(&^on2x?)Rv+uBPNco^R}P;lb+UZz3zt zqy~uUI$epfzVGz-Db*#YF#df}2VQSb z$0%Atg74F=W=q;Cwu5kS(KFJY(reCgRlXQzTA&L@JSS<0{5ixTi zALgENDz#f_p*3ZYTpY0%T zwj01k!AF*4C&4&YXx=dW>QojCzsdbIht?(!+9rUkvrzN?y(0m;>7#lDp%TrN^?n=v z1!1)tWBZr!FHlaGX0XM>5fHZ`ajq@&!FgsOT2VObz}>t0jqk6V1;=&&Q;w>ZVzV?HCt zQK@A4dSv@pF6wf5#)RMLbdf|FPrGg3TlAV4L)i3z)m&|Gys8qS6mGaF1s_+x?Tvo3 zy7iV?zf=Jy1T8-jQ%Zx-$cr&qaUgp)Pb4aGN2)Cx6VJ#84u@g(nUR8&=gfYkiBw=9 zH~?Y3KeTiB^wjEVhtJAG-fnpDJikHrk`}O38qVe}%}FD!c2Wd9dUGguZy+)gS^G~$ z7af%kActV9>YPuXb(>KqW}nNv`MhxK+`c@QfjpORYaLrytrYb^$wCL!lJdx0Y{}N) zb@W_?KXcb~g@5;alvPkzItZJ=%{i5fNM@Vf z-{o7YtWg>18nSn^R8Qys3ZEaEjV)vqx)cz%&28`Ie50p7+Aoe4a|G2oe}t5xb31j{ zIztiCJ+!Ba45Tp^M7~01P*E|%;vq@`L-j)@=-QEAEfM~_r8DB{(`K`|A_4&rm+WmP zJmg1aeg_v9lvDf8keOA^OAM@u?(zKpEIE^Qa2+#)O_~__&!maqd<`&rLmhb@iD6+V zwmLfT3l1M{Aw?8Mo=u}%)_SP;72N`A;CK5RY5Un4oc5oG&c^~*=1VqB^hQP*^^80= zrtN`3t1BIMzlST~*e$}=2YVuvzc^dSR+MAb626bI+tTAM*5@-6Xeu$ZF0)QX8l-%Q zc8H;=)BJw2Oxn=_-_41MAYFBzpTg za@{KL4nTow0^Fxd+2)aT`$Q0|<(5`J$0p!=5E9-Q1Z|VPM{?MEfg3AYrM?-%k4!q> z+TZZ?Cl}!$K?S5h!GaCmYqD$DDzt2jQO$X1OR4`{Sk)!1U<3_OnBW-aeD->#9c++u zN2+}4qbet&Wd>fmZi#+rWVXZ2YGN)p$NlOQ$6-}cn>w%q@$0Ivlf#HI%SP8 zHYrs&&nRbDn!0mw4M}kkBW}JW|LRy()Ev~ z-gBF&=4WUNtt1<5BvfwS-Q}D3rnf|q+F-Ks!?S?i8&$RYQ_QB`bB|i)&yY-PP5Fc0 zLNO_JuPegUZ&O9Etf6Jnk|l--{zLSir@?1;lEh%G8(}PT4FKF*)ytLOHbB@xv7(c= zPC@&N_rR3As!g6HyQPKIaYxv#E{NpDKtnL(^~DytdCd*p0d9UoSCI_)av^-s^J&*T z^rUT4pV>~cy!gd_C^i3(Wusq)ZXD>9THS~NJZrDyhrsBh5vP_CQ z92Dai*pbra^_4a6>V-cGe>iaz8Hbq_K)l;T%sv-3 z)Lo7?Z!a~wZy(;CUQ~9#FLgcc;c#9_ik8rS(&on8R#tDV{R)<|V#jX~J1kSOyG1cl z2BuyjsaOliHOoT%sbsA6Jj{!(YWCFX; zd)rXx)3AxYE|RUflYWf2@b-9Pa!8ZQl*ndwOvVhW)UEbFx7Pw@nwehgOyZEEYpmgO zaH^wx6@En5`sM6Z?D9n`-;)G0Qvbd&A8;4UC39ZFmx1{uei)YA47&8Hke%}5o=;Ax zTTxXm>I=>CWh+-GlxZ{{{S!(-L(#u{SASHEa(=-~-Vg9ScWPcXQ@Gu!%U79v+eBBl zxnB&v&YHp<@%q&1Me3C8I#>Eb-Qk>G_}Do5al$+aQgm?dSXKes9~gz$F!$C_}9+V6vcm`5+Z_>tJ%Y&_F%AL}pn(MB6-1-8d~iXKt0>pM&E%eM7+k5Eto zj84o~R7$k|^sT^r;T#1cC4*v45@A}K){nHznhHL15zu17d~AP;T$#OHZVT9p)};uMMtIBGGIiUuO;B9?mVl~I;=7sfZ$(s|$@j@CndxNv)W8n4z<5{a;OznR zoyga*UVIGK3f_tdD$-2TowbH&4hx3Z_m*2GbK7^FXU;G`QytGAb_^ZRhntlfk+AJ_)TpiAj<>b*t6!A)DlY7aTd- zKiJ9xo)0#j{}5sTe-Ja2%Q}c^=ObePM^nBNE%~~-mi|2Z?boyJ@l$e?+xrFKJC}5~ ziZG8r1K5vD76iO169j`P`iSmg8T`X*1gp(~R-$}d!xUCG^F;LwL3kC1CwfB6Pk28R zCA6I=K@TgwBPlh-rMxG`fbR}0DW77jp}|dMF%r8UHPt%VmTaeWo5Ja`B(eq zFYA@h0uli}k2?JV23&6DtGf6Cctyc%5Ct z?D(lMQk8*M)fBgWVY8g=_`b+7X?IY%vwf%=;W^H7*y|n~gejQ@tuN z^sBtbVzu#{40BM3>2)=R)J7*~y%vKg5e@4Zkjz5LUf-0m@SJma$({_W{D3l$=z232 za%@ecyTJ^vry7jq?PX6qCX~1;YbBYEM?{H+Igo|5tS!_E+7*g06dGZ&IrN*2z@&Bk zq4sRtgq8@5tikN28C{!1T2W#6dM{F$YpaQ1QDk13tIwsL%2=?V`4KqwzR%oUEhM26&jv6-2!C<^(+mQh?fjWgXfq7=>FZ?Va%NaZyJr~XBk;pKQ#!pC2nft00mr76pVD%OB1kdr{ z&ASun*$DABMYSqpAIeDMFTA;oe$_IOWkdjmNKeAP4rR~HJSN*S5q{dZ|5K2UgdN(L zQCu_@muGnTPRaf1wYVQ%3y=C2X z5|W_?#?&W;q_AUh>pfGMN>!iR`0WpB;*7u-jD7XABBK5brh$M#ia1{_Rb zi4_S2%<5~dN3u^uhjwB|HB=*Sc3vSKi z$z3XhS{EMy@GELa=sOdR9#IEMCBFu{!xD4BT^V*nILb2MB;PTUz-J5oNf%Dx4V3bU zq8y8Rn@Jj0FRS9+Bdg2KpODdtS$8QQyB8A>vhnEcO?3?w;j0*0^EX{9`Fp0~sLd^D z*GOaBN@oc=8t9Ldb`0a3jkK@s<=ohu=t^XFxnr&8h_m?1vAP>k6w5I=XKn_GhLezj zQ?vvISB%=%a8vB{kvX(8OqwH( zL!Jol03zlcj{m{JhM$KwS9QZ;npliOf{%jw3AZH+1X0 z^awT+8Kh~?49~DqGP`Pc^fY?6#x}!TXkCxjq$c00tn13wU6SDCt=3P-$U0zo$iJO8 z>OGgRUy2qI;^JI2nSM7(=T<^W{uJr&r?y zY_rCmc*s^Rit7_uD3M$^u+l$tTkFHT{+m?EymN{S=SE04e47sNalIxa-&w9Fp7IGb zA(=Y-bS$CNjEzmA=%79h8E=hx>a&56f^U<@EwV%7B+3gjC?$xx9aZqb2Up5P`?N*^ zCAOkMs(zRX{#?5X1#D&{if3rqYH07lB~ShOld&F467(TDVCD4JbUwqo6UN~KrJ0$S z+em+v#ANZ}kA8+9nBDnoi6Rzt)I*aWNXulj4BPKVoPBdQ6_>;KsYKz8oL_ws2w6Gd z7sRN-Q9wGxHecfqr)5lO0lc2*<=*7JML3GlNhmHP6ozNg+kTST7L)2?{F-1Fshb5M z=ODBD=P^yxZ#6bA_=6$qAFNf4Nmagy6n1UT)h85H==pue3hdIoY26;bONi1QnD}J< zVp6TolPv19bs=_k%3I6v{ghL(gs;f>!(^5D3hD1H5Je>r{!H=r3`gDQJ3@hj8wOOX zi;y=__Z4V>%W4bca^KMGcYtXP5kfjHP*n>8zKak6Ypu8-#5D6>0|Yp@2H34C4;(to zY2^PuVFWOc4!Edc0XfL8O=`maW&u<DS+30t19$ZaiWSAS|G= zRv+|=rd(MW)>100rH3LbH1{I%b-c&~QpCwKKyV!qLMHwFmuvJ4_jR^T`4Qy7p2GuS z3W5*Rx1Rh1q5zysb~+5ShSmJ=pw6HE7cQu00R1cCLHE(h zFkk>yxWoe}iTxgOX%GPYPXZ|%;{zyw3kJ~wTMbkcf7Acq{snadRE^T0znOI~!6b+!#ECBj%TmX#XctE{Y0YW|!0sSifIfs9J z&i`GR&+~imKN$lY_vi4h{WBaK?*mm4&Hus~E!?2L4p4A#G!HUMxm5u4cl8n+9P#t_&?(eHXIz& e10@T{J;Yvu3XpYBJ)(u9g^Pee)s=t7mHz`sLc5g! delta 40115 zcmXV%Q+QqN*Y%q=&W^QX+qP|^v2A-dHg{~BZLG#@Y};vUetrJ$cd`!F*}CSOW8U}p zjWzl5b?D=3y%REMd38|-8Qy^Zu()|mV!mA+wfMNA46Czj#TqxuEX}M1)`V!F<%-^p@5zZ#zK3v1!%Twk#AfK(j(D~g%G)1wvnIq8OF~L7?k0+oGmA81 zTNa^TfZQ1UR18{GD#XxwYlDgr@y$#z*v;V_$-=XmV<%aevua^h4}Kt39J%8 z01n7S1|v};gKz6GLFQ^}is&jB`r*w0`*1k~iK`%P11mW>35O<%ZWJbRi5Lo$7^X6| z@RJ_5(u@qW*u>9iqAQJ9>FI%|bI&LA?g(FK8#ynYS61J;rm0oSfcN)@Z$12}IGaTH z{7l^{HhLTAsinyn?oy*Pl^a&Ll#hV5F)lj=!wPMF8DAXEDK zEW%lnet{1f$Ong_!u|Xs$?aU5BrOZJCX1tCW@A98mQnx=V1JAImQg>m=j2PuG!& z+x>zNl!Fl@KPf6~ZxqNyH?Y zgzvFL#QEOI`NKFF03>De3R@Hoe2uXUZ~YMJc8;M58@pq<0bDZYQaGmWP#rFI8__>v z%IOj*27usU$K5DrT!U!tq$8w@5kHKAB&m1tKX9Cb=*jR#RbQoutpHHBp&tcHQW`Jlro>kEh7FGfGGAU;z<0vB|C+GeBXqf5CW1{Jko72_Lr`~dxDw1OR zYFy0;ZPw}@$9BT_b>YkaBZQxHJ8*>XE{on)I_}0Gj=oeP+$xTXP?J$B-qNY8(zUqj z{Pw=TDd8a+gQfvB2i|6|XX~AEx+DZz@CAA&3GPbe2`-6Ut$vPeR;wmcPu%cB`HoNw z=8=}QRKP#NJWx{3Yv@qpt_Wv=m#)@nG_we`q6LRbHi^nv6COJSVch+*!m?U+68vbm zlE5U;B3wu>bspSw;96NULIncfV#|JNGe`p@mT2RyGTFMCW0bCmekexPOg z)pLM`G7s%(Zm==0+U9|8=eF|+MsuOZl_rTZVyHrj?MG1ph`^{ldYpC`}`&LK2r^$xC> zPG>xZp_<}2HY@zeM|*{C;u+>*^6slSSBxypdd~!8t!bQbC9-gEFUnrCzr`2Ms*b)W zt1qhQ!$EOttzzGr6zgJ)JM{-7$LrwlqqGD9WpHU@H+jioEn*tEPk56WEv&erfnm~S zl&&eusI$+G=}%D)Tr!`bgwzT@5pkpZFP=-C8jf^}Az704gjm!@2~0>oIXy$h4S9Kf zHO3{#d)yfIE)dczjb~13L^wz2K3{74x%SPB^2z%Ik)MSSiJmk4*Jz7!B(l0-VJth4 zt>c_Fia^W6VvX~Otv5q`aVfh!8kaDM0$ys#-y79&v5=Z%(m;powSoEg5sy`Uk|(08 z45BY+c3N)Ueqy^)41CRM_HslQ*k~(}Qvz(BlYiE)(?DDPUz{Mga18i;J?gH+Yn=SQ zFKf8VE~L#@SMq80Gq*W%H(T&%h_upy^-2cK?LYQ(y;aB7$O=qWSE(#G(Y$#7NT1 zjB4v!hI*W1aNvMI^Sq9Y#tYAFW6HWbMCC^m=KDL8*1v#gxLv za4W1r5E51)-unT7gTZMh$Rc%nr*;S%One^p3q6u|SaP8dlD2o|W5vZ&r9;hf5zcJ% z*OBOuKDLzp%aj``JQvRj?Gynb!D)#NAp-~~wx)62TJDD!6T7V6A+mV}``+tzs;D~w zgxq(i5NQ?!98koJx<}a( z&eEl-bX1hYbqiqaSX1n1Dy6XdJSA$kD!JkpyKFH}a0)c8PXU|Bby*|@o6Td6&f_p~ zEJnUz?ZtM}PhS_K8ar3M?jzk0oo~Q1qz2Jon9J{?^%oFyiWf4C1BdHgaRgjDFuXE% z%-;YjE_V;KN&~No6uF=jmf$TQ+AsDiYu=g6Zh4r$f_0F;I;fbtHyUaC5K-@D_`$~< z13s@o*OH&BJ^!AMws&qAfA64@-FR-XHZsm}eGJH+?h4XsBkqxT6Y{shPuu~?jxg2z zj??eZR6ju??;!;@HB&&P@aYlPyE-!c(z1p>MR&N9T{^>FJZ9H~*yFB$bt*ul?_2@j z`%~i2(&4_}>Trs6R@L<#*Ukw&mkKyuu7mOc13JBl&^nh6pC~@lQyQGqfp3VR9t6w zI4h?2@LD~r#O`wZ6!u*qO5jvD_LW2%A;zA|%5d$zWw>m~y-kbXdL{c|s;zu=nnGu( zn}-~CeC?d52)Pz?Jp(f02DYf;^v~<}%Sx$giY7Q9s2#^`@1$Rd@0yYdUYMyV*4wLd z5uhSjBqb*2Mgmob#mI*52d>fgn{*LwioVa0_u|Zvg|}gz6enW!an8!9Qic4T#yY8) zkjl~}gJVJUD?p3-`uQWJX>XUM9|K-d+v6vN^%9J34fWw8 zw~-^`VoG|OXY5B+hiIr$Zz4yi+=#t${&zy}o)m4&M)6A(CB=OG-mvViP`#fdnP3u6 zcfSm6(E+wZYP4eMP_kZHD+4^8L|3$x5C@CUA|u_qLcxL-GyQ(MlSX@gS{v?Kvt#Dj zFkjW)rZD&Ru4Yh`t#7lSCvG^#6Rsi`l6Co@rjWXwT75}~A*}~Bwc`lO;;Tw{4(^4R z0w!&}t{6q-{wV}vfcm(GaBx_x3+8-1T-Je&5Z#=t=jy1PY_UF+K4KeerVsB*60*pi z&m5{YodqqfcD&E#>9%^9OdSpDy8UU~TrEjRDJ?r`wGn9UW+%a%T%DawI=F$YjGdo4 zL&r(G*PpJSihFE5>s-b255j^qBJxga9@!q`qYr6s63s&^XumL`<8SN{2Y(DF&a4NM z@Ex%!{P!$m&T2M%T){waK-dcyKJ$X{yL4~GxN~B>$`JwKL4L)t=JZSkQiS?Y4m^e^ zFnvBpcnH)?851H6DapW>aM>Lpvk|Db2aQDFgv6n>i(x97nmp+zq({1?lma_q!-yEa z2Zu8{M`xm4j$23X`*tj<-aB*Au?=~DzXSWq;5ca3 zsoX5vG79|{KNAajig)6m(E1|R!ldkPM^e0Gd*f1!FUD{!M3-p=_lD<|M;mm>%k!Jn zH*-T7J8VMC^DS9B88F3Vo8R?gR3yHNuHqdS(W)@eF59QnYP8xkb0$~kMFZ1heNUApov~(>x<{0N z?_iiCr}cgxC48go)`)f7UdtYhyUw1zio*Zt{^WpJYvO6_X02ljKME|*=^Z^Kc3 zhF}#TZPW2eSBP-%66mX2Tn!g?OW=*&73QM(<53{`8h&(`~To4Eb{EPnOjr|Oj*L)?7j z8{I*cT)X{gMD4L7`pn)rcct6 z@h2go%-&5L@y)?RE~jd1q?);MxIv3@GbDn3SFioUuk9xLt8;s=-w0zR#>GJ2n&LS& z`oOox?`o01KKgK)(snq1<0(HlLVE59)Y|TleI1Ilq#Zjcif^6VHX~d@v4;PIiE_3- zI{e@PD2nO!DATjYFHamXIC`fg zZiaIJ%6}ibj9qQdW24QnK|}_S<8{ui)i?zoR!pe?`2oW1$Qg6KbB(Bs=Q}Ky7={_ zZ@){1ohh+`E8A4(&6ZqGdFhbM?&R-f8TO~*ldFq>(gCRG=G!>Vh13G6k8*)}q2eG5 zX4qH0s_C^o!)l5tXkTBS5uz5CCTD%wx zJA3ax&0hJ*B?zI^ZWrXockqMQ|L7ZEgz7WRYkIcgMO7{~AjW$Fs1{q-YF(?kMVIqg zwlCfE)9`l~xg2Ixq}LKfA>$fHJD7qJOcH-LxLH;hYnvGQ=6y3AX?b%nilU061D*yL zEuH_+tu4=}RnvVGh?lF9k)85Ji8A`gKo28tTZvQy0hencq(pnE#qL4U4qL@B^kR!j z>cG@2DVJ9WWSVN!&s?&cW5NEY0JOjxtp4(k#?BH_WDaB~bXpf6(J+t_CyEfXh6RaO zIKe(;-Sr%Hd7C+2qHinVY`-+N28j9~rpJ>@!B<4TG>izc4)WqJ%nhTpP#)W(pJb7L zx?y_$OL8OjHMd&3B_1@T>Xdlcp9cB2m9+4=wc=CiuHRWhZ%B_Y%}HX=TQ4HIngzqJ zZD+jKQ3zLaVJ}o>w%GdIM^uuw)|4d9J2*4ZOvp$u6-!J~3HP^ROPDdMhof6pGpxZ) zGaa+Ugx2u|>*@^sv_s5;H-=Tsv^6wNOacRa_oQEc#h4a`5Sd;;=`lk|K2Oj9afvGL zT>ts7c%7_mD!p7|1(3!o6@$%;3hQ_Na{q#CQ@CxO>V!9aas7$9D}R`V&ooQ|E7qs5 z$zKdn*}9jE2JryMjIIBA%{G`lU;gWtFKJ-oTmo=2xgIFGxlvBU;efOljh%cMjTr4s zthA&5XMG37FWnHJH%eYFkxeUk=F=C!&u-TYw%?y`Pf$h}u7JGw zIL)6#3#3b)p|<5}mE9$!8eRM6-#H&^lB#$p#84PR8Ct1ES|9^cM5V_$;5M*li?l;5VWgmc zWs*EBC?OgF5*JjzpYAr9BZNgJv9p!#hcU3W+nXQC#r5l(Mkc4W-G#(pKLlmF618>; zYx-XxKs5nQDkqotPjPVXKQW-)Pr`b5Hd;y9CX_*!j=BbZ$4Cz~P7uCBE)1a59fd;P zE}y6U4r)>>KoQa-&;~sk0!2a&65d3GoftoT6{v$BppBtken*FBdMr)<_sT!Fq0QDp z^L<;d6nu%3Jdm9>53PpSsuaLQ1K%FG>y&rc8@&s`OLi>6)Kt5FD0flvRMjz1rRjIi zUk>{2zi_HGJ?x}}|CDr8{M{qu%vW8T!fmDHTwYN&pw-O#!wrKrH|!eHIjorv7Cx6H zq}6!+SiYc@%q@=>UE=E~Y_93HheZpmN9Hb`a~Zeemx!_o>#{`sdGhD$8Ay@+RB93@J*2t80Vp91R- z4G9VJjbq_G#a|y4IoJ#sPEJ)SE2NwP4*#GBN7!5-@3eQXpS%voorY?Sewo)(Xn-n? zg>_Atao7 zf(&*o;#DwI$NsJB8D`5oe2CBiu~Y7<59$$K-)J2yj! z>vzDn9$znt?bDkZ-A^eLQx`>EM2{ddjA|&E#5C0ca46C(Da9coji?-b+)UVLdXlT| z0p~IZr{HHJR`U0BQykgL1{_D@_NIxp($Bg8b(+Bt0@J53vDu7yammw|6*!!65X+V! zsAUsbEfW&^mKd@zT*4gfg%lIcOE;Z<3{Vf@*}6au)$0-PIl{d%jkGo z1>y8->ZDUpqG*nU)HM!8EtCSp1hT5!qlz%7W{vOr4{xveFsw$X`3{&aFem$4hnm#` z%SA$WhY}@v{mfs)3;Vs_&>r4lqOR5{V2`hYo-m#pfE>e~i(mpioHqYP&szSzlRL6n zdQ2VzP5*doCZm}wd`)lpL!hZdXB>3=i4uB9Ugjk>zJNJKOzcA5)zj*koPk05XdMpS zk;M%<6M`4d?KW43hY@P&xCK@Gl#zGTl)%(?j_#v;kN?%{Ufc4f5PU&n22w&7!4Q~R zbg0mkL(qo8)K^}ewKr9_>v*Oe3loFM26iEt?`uo;YCH*e_M3Y@WT7pn%pOrmvA$8Is*S*jXVf! z+$)H5V#NL1bK``_?nP8Fp#J*Hu+rVfrF4KxR0zdOCoEnys{= zWW=!QJZTg!GhdIpbmJ0ULaxbq51D42H4SIfP<{+O)x`dJ3`QdziGYwXK-&nBIrAS) zTQINmi4RiRr_KADh}K8~^DZmA;fhMUv4f~>(-Q4rL&C6zo@x1;?`N?iUugoo!yA== zckcv0mUFcHwurDRNMun7o}g%QfJ>d;m?yQh#stfiMaS6at`=9!0!$fHFdb=i-0Xdo zhvqkxa{-Ag=hm{A2AH>vt%7A2LxvZFo zo9@urLefPA&me!23+SAX)4%_(VH*9d6iEN=FAMMwbOLZDy$EPa4o?JS*fLgzJu_3& zKF^QGPg-`esBs~GSF9umMLp(edu@GV|7Uv(-UA~9>buw*(~J65uTYPWEH7S>2CSD8 zpHTO&ypreeaQ9elzjI~mtMVn^lghPvNC?r;8UFNWk;&ossldbHA3(U>jo0%xXb z0u*>>U$!1J2T^8pfw6je04Npsl4JAjKs3XG!D7{3%czTsj$D?-FZ_bl+aE z4?noO4)-~q8#?h+t1P!Vz%*utIQXhiEEn9ldFfjg) z9%Pi8Csl)E8G}JjP?#}rNx)b{pbB7MVEw`%HFTq6VuQgZhCgCz8(9IK^5Z`yxMxSR zN-Wc#m(#}fn9alX>v8FlNC;wmkiP%u{T=%t-X}%3Lv-~e$ieS}iwZy?`?GF*ffmM`J=A93`@f_N@8j#>q{lsq+_fxk5#`Qby> z)>|c{{y!^FcKgQ)Y*ae++SO?BnwRHmhImlPXe}OxqL>5T|U`7D7mwq-gw1WAK8D` z77!h=Nt0EP1a})0GZ%~Ww=Lt%Ob2f+x;s=&BBFGA0>__WiZXy zMC})*Hz~Q$3iTPS$`wwPOe|f>CXV+IG2q-(o10A?DHV=l5#B<}DLu|6=hIvEasWTY z^=5nnU?Vfz;2XW+O%Lez3@-i+_!(oTbt6aT35Q;z*PJ4UiR64>OD7OoWq(o&J{kRe z?5&DlGz^c2hZrMhn@|Yt&@B*h-5z)i>@nh`ATK94&0Y@6%onGJjr^a#84nvJ<@!%C zhX0*->Hm>cOmI63Do9rgT?@D|3`sShO_9%zWu9pR7nne6fYLb_k@6J|ZCJ+7SmheJ9;%lZ-W* z68hxt9hwb$?`(Q45}utpvKn3-C2jbYrBg2V=RAEn{%5b2HtmYg9e>oQtZ8GCEMSeT zB_pd{`+lC#|9rf^d$=o6XTb*He>H{0{*ze}ahAylG@GL>k;Bq*Pt{=8)kX^fz<`LZcybrpRAi6Jh+qd3>(dH&gg9A}rxXrYi-OfmGa@5 zaawD$Zd+o$_h)n6d=Q3pVY7?5GO|FT<+PA-{|GjgwgQ=0t@e@>@Wf!TOQ7_ANV0D; ziyeQ}-=N~I_nxa(oRp1V!Pg9}`7Sz9&1dM;s`jgE??UnlVzrMus0cNrVXDN=(n@Z< zf)b91MLM8e`G;y`qC%RVJv6Up3U?6t6L-ws zaRhOQ9e|}|t{N%+4F_@P9^rrNGw{x^1_^Lq3Oh?n{@mMSsA(!s(Eb!%+JTptDa}mg zQzh86tt_GnvBl`anIruKPA(in59Ap;z{OnAOzV4%$ zQUh`8{~p~@343@;Rlv2MW$0ay_>ReztVJ7mqdwt2tI{{&*zMvkXeo(bLS2qJ>;a=Hv027+05D{i@6JD^Y#z|SLL?UGS*_alLv&N zfR%>oADp^-#fn4$5r*N8gj>_FjV9SXYRD0cr#yU0gr0}Cl z@BJ3>=iqi-LR5dCc0CG#e65ic4jJgT{jVdBhIso`s;I%4TFiC*q4%Y2IqF!qcRbV5T$3FJERMVE+eu{>z%2 zaZ>(I4KY5D;1q#hGpVC=WMfDZ5NHa4ZOdN=3(1XQQzTE!lX&31fiv7J`eqk2w6s1Y z-oJJ4>R>c}xA#94)A|%9dS!c=E`8k(k^wJpBD+4EucSHVz5mTI{CN40`l6*`@h=bk3pUEQ{BTBA9TvK9AF;!&I{E7=P1q@FVQV$#WCAo-ehJhn1jYnthmZMA@DN=Un#XvK=oLt%W zncf}Wqxky%>_WMwRY_UAzcrZBAZT{06FaH`*q<4+Q*X!%R{Cz2vn{M96~g9B2}t9G zjGSU)g|2qF{aDGLaQy7KDYBDTKwo}i6W-nB<5{j&Q>TagVx5Ge!|CcfWnk*$II*v+ z`o<3jfrA|)Mf4K7ApsqK=p^SXFGo!1806Pcn|E&lnI=)H0u6fggxdq4HCV*fmg{VY zG4(~b$*(xM34>~>nrk<_uqBPaf1J!09Ir<1p zs~Qzi84Ng!m3n7blW4_Cp&gc&nncP*#5ZY8*Pdt}DsL#(3MQw&Eg% zwZ%PNeFCNIolzGe3JA1k6Vda;P_svvA+y>ga;E5f_6SpnEWLB4LGxw3I+Z=g5dyf( z@>KaZ_z=oe{3CEKp2CLu?7FPn?6`vzs|x^sn(z-KtBG~&&L8pZBr~6(S>!rgfa-NcRueDRhUUHkBnuk#P3~!eZ2jL5HpU4J&Gq;m~sZ707=Uhi_!O z=Y8;q9TF%~cEqfQ`KKV-Nv2W#is~y`sZ90sEc$Q4-frGE$8vn^oKa<*@skCyb(g8G zKKn4U;yCLYzv4vJYkKuA|Jo2aSLU!##3;l``s zOM?ndvqGLvUx|Rlm+aW?{J-2X9C%HWjfljU8XDT;<=n_0SmdQ{mXQ-?vutaX#|RYN zrBpxM?kEITs<00G%buzUtwO)L&+rfy+L9)$EV&g`2^H}*YC$V?NTh3MaUV>Dk9?x6 z2@wQde5>kF0&YV7ti-^chg$ldM+sDjK?(k+QmX$aQXPDJpmEuLVGIG&`FWkKcK5_k zD{DaEVj-z?Z)|8((DVU&n?jjl5-S)({7&o*0b5o1>f0Ojb@TS*#6jobddBm|^V3(S z5QV^{w6wJ$@KVaow~|E9(@=rB!_e=n>N?;ltO@$K0K!ysuaUJeB3rgI!xS%87&_(*??mOgkRotrNk#cqmck!Vc#znl>@K;2k z!o)|tAQb8?^H8`GS!=ZAQF;6UNy*G0<*IE-TsajsIkXH(h6`I{DlHEdx_aIOG90Un zA(0Ngd}dD;CT5|ec4E5vh0GU;S~n-_e{w{VmFK*zqgO)v8^y`v@q&)pv;lyP85j$? zVN4y@7AXlr!@^7 z06ZE-W3&oVR-2d+7p9S3M>uHNhK&mJH=}8EP)lFHsyS&T{OsEZF+hDu*9FzJCkCQ% z>7&Nak44hfQ2-(v>ZXUI{a;5HPx2m_78Jmc4xv;Ya~j&_{b+qG)vPkZp?j+INsm;I zfK`fB29vd@*GW{3;xHX!xF(jr;QgiKGCwhlc*<#t8LxY2uehMV6xuk3- zjK+Va=;0o}xl2_xuSP4q8%U|wMRa1HG0rS3E)RE|Zf46a;D9Y!2C zUvA{KYVXU*ZdJujWkiyVao1*I;Y_fU9b~(MUfPR0iUS&i8r#$Lf%X@IElZXxZg4dU zX2ks2`V~iGXd{^2+6spVE>_}VWWr8Ra{C{U?D~;>qR4D0muRTY3Qydk@k3As8F9#l z>faKKaW)e_3tSmPxY0!V6p|_|$KB+Xd6c828RnCW@`fF(U%&R-7#cnT*xcuxpUf7W zDq?(b`jq%+kBg*IL7`L#8O>*@N7y9jqC!Y+CPL7_)uN2=tl>e+;r;56!9Fq;MyLcr zdKQX`ZUzH#v+u`#^Hg{6v&po$F(l3l2s@CP9=qI%s?^bt0NcW7HmwuFoyUBwo;n0^*`S0=v1|*g_JEpLD7J-v{`;lu0MtN{FC)N z)f^Tp=&6))MGSY#KT1WB3%4J?)GbhRizziqSWX1a%*j#9#Ygdn1+|jTqjE^ms+oDGcuu93~NAn)Y~3vDOsE5@;!N^~k`rRF&{n-fpURc^>DP zPMxDDwFPVuE!UHsOmIqpIVzV-%`zfbrkzHNfqcDwf4kiMCVF>XEkKgZZhteZ z>(Jmn-r^S$f1oQ!vWOn0(MY9-nWySnX5BRRwP1027~1{|&F~N|(N~B9KAt zi3V%)6a?bW?rlC7IR8U*LD&_H*>It*^sOt{v!Sw#&mD%#bfc&{pNl9@vNBNM`5f?Y z0OL#aL-T<>j=zT`j9%Z+qBSFIj%jlQyW-*-*P;f~& z03L>X;xO;}3d-C5;{w#l5nAJ!^?Rs0x3}aC0D^zcjo#U17yl;tEv<}2a=q&L;j&== zSD-ed-Q#9BAL3;}UNX}$zQk}l2t^ImTw%;xSOnXD4vxKHj03X`!iP6Z-}=-XupfV&wn%)1{NC8&WaT3%NNc6+eWXV`k<0^f19Fq ztU^SUXxajJMRnMyG4HNi?zQTr)TOv`ly{VXAFfKUNccQgDm}}zyFG*!o}0e67VNLL zOD&gQkgk=t=O!kyPQr;(ZA3WX;=XYpJbX*B4CVYe+lKgypJYgmm7IWuCyi0vRTV+Y zl94-CX3t89dX^b1QH~d1ifI|$$}*apk<%FtY8BHWSADHgYFb#R5VrKZbcx`&g8^MJqX5lscuU#9 zd_MZNm4BLgCNIVp#gA0vMwX{XHz}e&g9X;nk1Hq%Owixm?TpCl?;T+Y)1oZK37a9? zEjwu;J_~oZxYGvLh9JrAyfP1~h1vU^{d!g+9D6+--=NM~YVzYr-uQf6q#R>FJw%{E z|G=r^?hf<%aZ;kSH{4a@!1$Cc{4YB!Lq=ux3(w#FtJ6y9_(2Z%Lfjg3LTUZOPnniT zBSv~oVK%~Vp;_J9o`uprq0uNxhche7ZEeC~*)ECz+Ta~;z_N_VzZ?lNVP>ad^6B!a zcu#w3qZng#J7LOqO5o^i@;S$K>f`#7={E#7O!Q9g`|DEJrDSwedta=o8+m1FQDnJ| zrfp{Ja;7zTl|>|YeV129>oglFE!js^fA>_jOQl9iYAnj&DAKAXshYN_n9?ts$v{~a zn=z@Dqtn#T;g}chR8IB=VBe-P1DIr(C{J)p(RJ@5eZHDrDcCWKtdqR-?ghSi|1z%d z(*ZL|VuKvCWow3NWTMkrjcqZKAi2bxzJJ$HZ8uR@ZQEtlvWMFM5Uv%Q;q~%7T z;+S(QtDk1_8Xjq`QfC1+Ofw5s_5j}+-cMgCf|qdg8hXzl?zVprp&>zUhfcvD2SGgP zRx$UBtm$<0{jExsF) z%ll?9{a-fwRD@of?1n?XWpZdp9HA*Px7HoFxH3umog~|B4e<%y?U9Sc+gnWVspFgy zgv~X)uM+eYc`5zKGdW)K<(-+nLu>gL5M|eyVBVLADQNi?Tq8OX03cRu!cZ_t1}5dG zKY}7xr7;xI#QG$ncEqc{=`zvfqDB$1dfESSA93PdWEpnlW^!X<#{bN#lm(W?mGs;< z>3Zrhq(`}s_Wg-!WSM}W?M7ezCx1LGl@><(5re$OjJeuTM2*(!wHq|Kso6qr{3?lL_ z#h`t1YEjl}>pamLiPXD+d$k-f&i<+rMV8DF$h_lj!QM;s9-Ogb6sVXbcviI2^MmLr z1&Zbs51MQgj!tZvjOiqDlyKNZ$&)wJ#g1r`-?#IH$vS|2o@*JB9A!xsPpg}?{xjd{ zrhV&UXi;ZqdjmTakda+jsR~WFlS_I9*UGWl4x~{EBdKO?OQSW};jJ;zf)hRj@*x7h zyk|D@Az^m~in$bA0mFCWQDpf=_d!$xDMjV|8GCY$TuS^0RJ8xGNJGZDVVI@dvQ$7UdWcw!04UEq^f6N8j94i+> zT%c4aN4}fWV}|FKdvjd)nfQdom=sKBJhdBtY!FUAoYxQbk5JC;R!Vp$1a;kriCbYi zdnEZ1I4p(P?m;CXUrZZvOK`;!TQIMMaVtE-MVPt-@|%wco;_o#7HlWoUU+@L)!K7s zhYY}4uhbK^j>11FVnLeqyCw_aIQC+9=YEIr9AMjFB5*Ede&y?o*|$vUO{DCmjrpv9 zFB6V#eaUL2Ab#Cw$yBz?0|jDBuDjf@q{g+giF+vr!25WhnVMY~XN0VqaG_&IZwu^Z zd1NVeNyH%}e4z3p*^!+)@d^_eW$n7lT{S)oG@?-KB=vY|1l0kVomX3aeP;Qba6Ti0 zi>PxBVC$q`u>NMu5$Zd=!~7>|vT%anwSQNkQ`rBD24Q@G1@p@qf>ibY$4kjV2Y(X7 z4_?;Ymsq7OlrJmq1q0F1VZ)+I84z@#DCbs_?8R7eVLB z$XRDQTKApGd4BmjXZa-_1=eqUYpeD*@+#{l*&N(rP%GYi5cgk8S-CP*^oKbl76%#d zpGah1R^&axLEmRkejbdieuZl#)OWN8bF50z;k}2-^J+ok+M2xMj&C(MBfhMDJtP_8 zIHXnbea8uQlTE<7I)1&1Z~|OtqEZsbu?aULQ=bZUxOufK@yHYcg_#~20-C)M+=?Pk zO$(eAY+6svCK!o5KFzwaFgCV9F&U!(EhO{e5}Cr92gX6rWPfsxDnDgT68w6d13rQ} zF6IIr-tPkit-B3vLa{Kt#$WH1B-@`jzSIcv0veKSmS0m&h3*{vpVApjpj-fogi#@1g!AxM=sUMxzsxF`rst&?C-(&+#_KVf_vHJ=Zu9@kS1(NvV^ z7omcEWu4}>hCh?bdec07OdXI!cSH{`GDEjdrr%@>c&aTFZxPh$MO$3FGx^5g6}R{* zZ9PtYRl*BO-zLQnK)VEP1oy*M!RxAJs_7(5%xM+ToS_)&8#_j3(&~HZ&|+^EMoueh z3vn!hLdxLjaxSv4GFw-~Ls9|Kwza{1?~^NAFW_H7d|}4US>OxZ(D$Ggo1MR8e%bF3g@S^wd9XX#F%}y{K3g<>j#`kTVG^^TRCwRP@G_GP<9iB_s zrPRveS^~Y@MQkIujiJN3>$qvHV#%(*4_fD_AOo~{w4`3l|B5oog_;o$c2;x-DLA4_ z0Ry0Ye_eZkxyi$XAsw1SRw?5Oe(ViRi;5-U11d}~%qq|bF5{N6sy#Q}of0ZtPGZHB z^o|Pz9%AN0B4nr4=&iulWx9$30X#LXBF!r!8M^p`^+gw?uIo;HaOH~&TTr-u0=e8?rOqd=P( z+M{g>##}1bxm)c((>=0P>@JYoLC^H;1;up9ELE!jLI+AI(QE>%7hqZriuX*M&i=L9Xii!AOfmpjt>YT0QM!FMr7+v~YPJ}i`L9`0$s>bH zsGp9MZu2`L#9?tn;h#>Bm?si|YLRC>Cw{7zh#jvT1~^PEplaxDSe&yNM|t`@OO!k` ze5sq2my{0=0q;<;XF7=`s4HSI$_pc$PT(}S9+=#BYU6CWuZlN1%=}TQu;e|j<{Tq> z|4blb&mM(H;N4lZ!+l78;l;b@D=2hbht)z#Qx^pWoF;TMXrHN~g-SL&8!GBcK}aB8 z77aM<$8uC@=U+$<6g4VgKjerFLNZ*N)AOs%Kf<(T*Lx3RVwjHR zmy~r5Q9(*+)hQ18#XlSJMXluFDBkI69;tK%38}<``Ib4+PnGgI=nY2l7^ZvF@&Xjk zBrCKt?Pz7$RL$YZ1e(elI$vz5So39mV9r}uU+ePF@cw~&ZQ(M8T%PO#|2)TIj$G#9 zOvz`c5g@`-cD}pL0RKcbRQn#I({TrTU-sPgip)%T0>h+__LvG-?0%qQEqPmK6bz7d zpWG#1Etge6>jZn%)Hy6KagW1Fo9yPZt8_X@1sSI{9H)|T zJFrQf=ioS7HUB@;uT?eOQtsbxC}>dsBNG~`3ZNP+_0BDtG(S_jXwb1d?Ikym8FmugA5`GKe6NFiDN@xjJW@k}?*!|coK+Z?v7^GhMa-``pz zti!m*$A7hH`6Omdh1#AJwe!@Kxy@Cn+lRw6AC=POQj9Q$lC?68d_N3WrAN4JGpu@g zIR^22`X$a*mAHj!&3UBnss8&-O{_m8rETKrIddF{74nzn6xLW>8IO712?V`jobu^_6rxfguvz(GnCXYTh0&44wLqZ%*gyqDM0OG;+vVUck}`k5H@-;a`n&>Di-(WBul*-ESRkGV zF@5eI{R(C$@D=RmG5f`hzB`te+V&IgG?0gXqhnD^ zCVjQh(zfM*5b@i6NCp?P<4hcEm-)}Q?s)DSq}x$Z0;<#EVWkLAunN$xJxHA3WRqUt zl=~B^jq|O?YG+d^hFn)fOGjAk_w))M=RM*Qg1QN*M62#4n6C9UAodwU0J*>(QwdeY zihYNuDk6|(UOytD`X2Kc0qMV;vyTuBg8nxaBL6oQgBnaAEjTZ{1=No`GFx*A89N?0 zZtSR0?&5G$3M~)*(Q6LHLI$VPt`R$OIHwyzvt38 zJ+1ohWpiWWUAL7r0%GguS_=Migj|IX$cOKC^G_Dn?Np~XvJmL8>&s#UR^VFQ?|`*- z+tb(ieL|3e(n8B3)$3W-8Ca4tZL-{Bb(-uuSxKU!4UR$+yCPDhCOJ!=qr7tKrzrjCsxyw#*)retb{_Qo0Rok;G$$4P#lxj9iSr&ycbj zJpb1PtxDeoE6D|z!n6nd3JQBD0|>_}sk$Z3)tT7KeZ`)q2>iRyOH z38XAvZL9d1)-6uQ{{weGh`&T{og^+*T0{KKa)yF-TC)V^bvZWX?Q|yEt>(CBuCCep z40BIUI;$CZe_KFw2%M5Mbb7^(Pf^g+P^RI;L|bDSdy8rfy2@*&Fck#plJnDg+P+X= zRzu_V0On(XAGKI0Fn>DT3QiU9X}WC=#WfmO(@?${S#1Fk?ZkP5h z48Vt~e=1aBLjVEHkzbbxwEZ7YSFlN7*-YlRDBI%4W^@GL$85Q4X8?0CPkwa^EFt3i z(*t=^qxStn>+|*?5tmLnRVaWey!I`J3Bh3WCBHdw{?{KRU!of<+Oqx zfhtBS&gzwAsJ6@a^;Muj?+TZ~ z{Yfn+-K-!Zu;_$>ZFxo@tCh{`OrlLHt8pr18=;(PT3U#De8>reXFgWXplR$=`!ZV5 ze<0Hj11xBB2W>mol9NI2wKUU*{Dd0fl&pP>!hkG2tENeuY13o~SI@?NT*Hbh^;_i| zTqn>n6WS*OP}ZMUur4)Bs@?86Ug^gTcoi$#xML@YzJ}MBrP;+CVg$-yJ7KA#@O5~- zAFst5SZ38!YGN7)G){tiIn~u}=sHi&e}&XEq4v9OVIhAD{cUPj<z@DOvY;`Ik^O)sjO<;EKq-fo!0jnd$eemn(a%e-I}fTt4W@U74{b9LiPkh z;F0njigJ_~G*VksoiVXibQ#8;d~RlZPY~=G%4sid(%o`q*~Y1}?P?|y=fy^_f4v*G z`tdH@HqVRO1u6-r3=i2d1utcEe_nSY72Q<)pqlsMeL*&6?oghY0e$>6A=|kFrn}bD)O@(|tI=Hlr*-9D~z3?_yoe zM0dDL+f6Mck;(Q?!6yhS-ldyae;AAE1$zI7Dt8i>OndEq5})$pPJCKm^$Xg;&C<_G znS-VBH~oGJ?jlf&u5e4mVaB4!*s59<`?Qn~1@>o?x7mNarmO zc|qA!l;`BsSpu8kaf2a-$zT{p` zrNsd}BGZ30t*GhE3ja?s>=@S5q!;$HayBpVaNJyv5wg0P_IQBLtA=! zwuXH8#w5`R5&4$1``g^mmY`#Koi5nl#rLWhxbG998#L9_%uo@cKNP4tX}h7|$JDz) z`oo8x2xLPO>uAVeZyi$ge^6Stv?N=OP;%Tk@?J|7Z-NkoLYti(Lgg9R658s#hNPG! zlPHuQKX$yuhoAAf;-e#gpUYD|hF>r`(gMRwU+oy+!!OxK6i?*ClL0*79`rZ#x??xF zzbo~S4qD08)~-?T2i_(O-9|mhhm|QoQeIZvRV#|Kbl{)xXFvXkf4>MUcfpW0qRByd zZ`<@TE1znn+FhD?{1n~R+p}pm+t)>1Q`Q&PQS0CFbQS)Ff4Gg$h9O(NOvc->X+#=# zvf2C>o{?~QR^Zf=S*+kVONr(XJ>w1d!iJq2rmY3fW6Y1|_+&!(gvRxKj1+Gg+2Y63 z*<42J$Y%4lY(3nLe_vEgsvRfqz$H?J$1i4yO8($X`9tRfd8Td54$T@bcmYu*i_9_M zFCEWOwBEAhBg)V>nkJh85nw^+D3;QYCV8!)UOr!P+>T9E@DPIm0`i4dc3hEMSQws@r#U1^0HR$6V&e`DFF zPw*kLTVNy3^7G;2V zcoemX&S9KVz|s+%F3{C9f<}Sca2`J*0{0`DNOX_jEP(>n#zt_SV6pXy?gN<9>`-KP zha=4eT(slB*n{DNR4YUie_P-gLl6}TY8Ad;@f^Ymf1(Q7#%PPj<&xq*m|9g#g88_( zXy6$%SQ@w@oY=K%80(vkpuPDBHjZL*qO)ljF9{z(*U}@16>!-h$iFIVL%b+`3n}TA zi$>9#kQxfOyi;@)u(P{>-4_4r9;3&QTbN;8o#a z*!MX~e`fQcoTV3QoH2+6&bSbD&bS!MoH2ycopB}3az@t$0f;e@^oT-UjeG?bO^h=F zf@4$oFg6DFj^Nq~`nATPu6L+os2Rl#3CS78tB>N1@|+cpS}!V=Jc~J^ncsd?U`IIfipbF_NgO+&zrD3%IwswSX@~_))+Y zV^UA6ClY*+d)!Z$bIqYTPwW6f)cKV}thiOHM?~aSV^4}!&w;VWBM-rIh$}7+esy;N ze_y{HYa_J2y;E+~75wHfzH=BqI0k?4M_dji_|sNTxT%h@yf^r`yK@0gM1sHSbe1ia zVv*g!U%PVdg02GyM-Jn+$8fQn4*s5#NAXw5x(oj-;NJxyiYuE(#Vmq9+%zn_1)=a9 z%?07(P!O{Zjfy#mS}|`}1n(P**vGioI4OUyAWm+RWf7^|Fh&i^r)HcK23T*w>`5(E)~;Cv!$C$;1W zfSU+`TPb}PtHYyAiYEw{r-%sb$BaDR(T973m7e=KnD z$a8l(ZTv{SqJq~@^I9*xoy9Y{wo9t@!&Z-s5?`5#bA2M9B) z4G&NY0012p002-+0|XQR2nYxOll^5+e^C%Umjb)}K(V5r_{FMF61E$oVuQp4rNBcC zq_rkKHMhId?b7|q-Q5~u6=lk%9nU9$l}NdktEA(T^;*d|CS~o8-F8B1FAAs;MT0EXFexy5D2LMW zW$0S_-9xfd4buV(+x4BTcH>27f48}{-Kclkt$MSwxBt8@P;UHYw9=8X#{&AM?R%k@ zJ`u=OR$mIt|DE(S^L&SthLXVa<~X;6b0`)tgYyFUjHOlktWC#-KUB4jl9U1s7X^wg zr3WhFdD0_+<;qzlt7oASF5z+kbC~DGqh*ASfcanCpPISE6$WC%9I=!N&=V54iIl7}IimP9XOKP)i30t*d8B*#Q6mvXhZ69g`1550l@d z2$NuFI)4x_s@=G-6G8$B&Ti_q+0wL1+Jc1GgYYOEcmN&>;eznN^8eYt?XT~TPXM@p zset$G_C9@;8R`wWTrQ<9(hUK(Ob(PRH)8ak}HiP@_)vaOb7CTZ!u5j=krwMG|0CJ2m#ZF zruUj|j3oi5jW3hZV{R#V_Sm-Mlhv<$`ct=P+|jij|Bhi-z~LGPOf0%Gxy#n1yBPKb z#PmYC?|5N!eDcU(4`LWYuw?=VV+9fC9f*DaP)i30LH+M{_y7O^ECB!jP)h>@6aWYa z2$NlY5tFECIDcAsd{ouF|NYJ^cXBg8NC+@2GD47SlL#te5HVp5BmoIahef=Zxk*N5 ziL(UaLe*-mt=nsDD{A|!wM}d7W^oct743rB+EriezP#>>-B+vTeb2dfl9^-z`rbc} zPr|+ToZs(ve%tvi=j2PTJ@y0A zNYqG267fJR5jHWNG^3`GGBMd}qynK{Gju4GiKP}dbsN!?S--fiClE9G0uf2$ysni- zc;)$kO|Ht}cW0te45WIEz;b+=@t#QBG?S5d4@UdVWD09xd{x6a4XXlSvw!h59%3fF zGm%M#%zurMsL527NcJ@LB#m&?Y&@Ja`ufad<0kdF$NFkFB5{qJOl6lF{YGQdi1##Z z>$=Fvox8brY2`h-Pe zadnMFBV~p%$w+#jaU#rWFL`O2PNg)R>5NmuYJXJ5Gz|-_gR(4%nHEf1Vtf|F%c(-A znKX-O?o?13&1NbE*|tPT854@h5sjPa#$7wwKxi)cbeco+n7sKj8ZBUQr4ze$v`#{6 z1=<<3NT-G5FGOqAXfaa>*6f6j#30739BRI{y;Ma@by`Aa!7AM_u7|1%tY*P!RLkTx zuYbtE$CxUs+a{WIbHr{#1mQ~Bh1jaGuCbi(q;F}(mpjsSZVT~JErQxmu;;$|9MnDYiT+>ub8w%+XC zn8?J#8w^1O7y}KizBkw}0$z_g9+@Jq`ZA`q+S+T@xGVH=-G{2HWA?SRrhtLdl4& zpYmdE@Lsx0@_8&5wbkm)$)quWh&=V!-e&R?QdRshMtvhUxL5JjDao_D<#w0Y!5G*Jwg0A`if3Z(N~#7AmE{| zGX+j7NOL#Xwd0XS-;^8R_3Hcuot~%vf{cN{zDw5}sPoW^_0efgdl{kH#t0mc2(RS20mV;q4%03xU(;z+rq0q(0@X+)p4w^- zc+q5`e14Dx)0~N-v}7XDFfuQrrQ(2x-8#EuY2%g^RewAT%%b8?L1wj=OIQa9E=BxE zC#*>?PeTcVL9|KJQ5_&G=G5!uGWsGk!!woEp~k)_iaak@DDyIUA9oa;WV%;HgH|uk z<~gtu&xMSMct^sn3%oo}YWOLhkKM26A&c5s@nd{e2`}Ykx!$G_K;s&nYh{4tH6E^?B9KW3=LV^l zMkey`a%ihBGqDP^Bju@U-CQ{3bNF28H0L3GS`y|LoP0jhlIp@%Vv53$W%BdG&-zi=7rJm29k_ zpyp`Q%l6R5u`04bR*?;=isa2Oa9~qLF0B=)v0p^Rj7G+8>(#X z;O&Us1#D`(!)oPH*dJq6@5B;EmK9#!$-7G6iMz4cavR>uZ<4$H0S?M2nA#BQlZ)-c zE`Q@%MoZ#MMXtpDx)j?80|zH%mpo|<34vB*QC@+7vZu$0s<1ZR>M-KOe2Y~-lD9vW ziKZji$bPH9YVdHk&ZZ12i)^TH!c6&POV?}kn|>ocV1WV>oy@W+JIh@#%x2i7Es;2s zfu;^27_Q&2v3Xb9&V!qFG_P;laBx@WhJPIgH*ag-;N=(!SdMbsIw8qveu6yTf8HS@elw%1SzJU4`|x0cIx9d*<99)18MK!b4L1{Y zXo>wEo$uuLVogg5rlQ9j_EPI?Nq-G1yz?=>y9DUyaOM|5T8~~dnlQo|zpuEb7Ne>$ znx5%#GkrLbJhU?sGZQj6Gt$`y`2G^UkI~l50k8d#Vsg-{tDZvEVr>t9h(E0J`x$M| zit1ugTW+$t2yUyTypKxs2g?YNX-?FLb%l+p!h@x%vzcxyN_&FwRu?;dI)4RAr%?Cm zV#XiK0=vEZasGr(F8<^UH=_+(Jicxu-k&&RHnu5A+Re1lZG^zvfW{9aFvP|On4ZfI z3^pDxdJ|zQGo`Amz*8jEO@%0r0seQB){>{jt(iQ#&WJ`kBeLk^l8pJzI7%8hqQot=&sdnIJ^6O4}78;-~>u`6Ts zebXl#;qx>6tPC&ciMi3k&%xoNMk?KEHAi0ls#P?84b#xoH&8L8jDK!(R}xA1j44ji z$4EcVFUUZFW_DUS(cHPNwKZ4mzo-tc`P;|=?d#9;@ON`3rDGQu?Pe-v^qA`-J*F&i zzi(w|Wt6zQ7+F4bhAvJ6{QQuAr1KB>$4stWJ2wVac^Dn42V`3Y(lUz9E=F@-iM7 z-A)hxdjh1DYG1V=UjyWokv@ejNR0`$#uS`zSYv4L=9x!A(SJ-T(ywmYnnNL|u-%A5 zizso{UDA=D+3K%cpA>_#ip zYsBMbG^Mn<&ic^AS-Ja`Ng!?DM-$adB6-*&YIU(xwtsE9RF(zCbY^wljao7KP+mYZ z09Bw9)zZlUNmNFYsqo}Hkd})Tx>zR8VOsrva6?VVc2%AJt&1j7<|XoAJvuPH`LVj1 z$X&yT^TjG%tP~d%^lUqOVYRR(RwELmqNdp=H}@6^zD8W6iwnitT(e$yv7?D*K!)I% zUa^jzm4Dv09$K(3*1cjQZP!JO*d&YNNS8;nqA)Gu!7YhI8k^ndlQ~cwl%eLr#@VWi zHW@WaqKE}jcKB~i;ZBMhF{zcbOceVj+*^tcu}wPY_S`X$eGROfz75$&>Tid5$G^0Cv1}(#+wiv$9na=8F^wpX@757Q{ZK<*r$u2*zYC7db?E0vaj&w zdJ1f7Ghe2QPGKPXARoxhWf^Va>99451w$e%Er-ojnUc5g@T?>00(R$BPraV#5xo*! zCPrAS!9FO68ku;g*Gx88rHizeM;wwC0;U~dmY$~D%*C9Th)X>rJmj(N1g$!c>EhE| zSbtgs@<}GmZh1RlSBjvW6e*obMY`bZun;6NM^1G+dY z(D}MTa<6&C)za@f#WhSD#v`NZG);9|Wp|f3ZThz~@5pO9^E01)p)1~u;A{6$^2*C2 zu9JUFQRG}V?_g5A1zA_zz|`o6Phg?2|9`L%Ndrhlu;J!C?GUMBD8ad*Pi;Qe!``(xI?F% z0XK+v~Eleuy^L zx5>%2M`;Jsr$=aK(D^uN!L5$E&hp*0!?bsZ_MO-&$7_e^vJ-?#g{D)G4$yq6qH0=8 zLfk3;WQm-k_!Jtg(P#;=Mr%g_Xn%b-6OED%Tsei;*+2lq0r74{O)?MH#e56ib@{gn zmS~y}Lh3}$hidC`JcsbxUEW)Md6wcsbVZiZ)=%3A^#}Lw?--&Z&PV8K*W*+d3_8k> zb~?+i?aa~*<#mtH+jFD0VDvUQx+gbs2S(m0M}p;d0!2bl(WwAAf9ej?e?a zz;XIWmOe2=pB|#)Ba{s`xdJ}t5Iy=RonUHm``nMx(@e+sS)WV3f0^k?kZ#hl^tEIB z5uaB64P}a%BlJ9QCF-{ZN1wy^x3l!UW8?#x1_S=cryb1FPqXyvCfDHTLzw@qns1Qv zWoxqZhm{hr5}<#!Kr3C&%YW3{kFxZ4iF6o9|5QkRiR2sy^=a;Lu^MfVBrUv;@m3bFX*ZQfs1gNrqt7+MuAr~vU8Q7r)Al9|7*v6u7668^D-%FrANuy z)4=Kn9G@(*z2Gqffw6R~N7=i4VSJOwE}Mu~wpFd4YUC$LEx6EgGQ*gB?Tc zFTW$pOOA7Omg`_Vmt||(B;RtDc2{s9%V!5yYWEU!gU=ONUb$y*^m%+#YCgB4Qj>zX zotH^7yAN8kk4Vq1tAF5CL%e#Jo10v6$zb51&o#vBv%IN-TeI9|t#FdO`1HAl`I0?8 zXR!Pz#=zH}uY!<1*(5X^zjWz8qN&fil9t zAekd<1}nH{hp0)Lb%fs^Y<~~b9_I(J)-ZqM;1GYT-si4+j7Nw*l@~1QJ1h9{T(m?qQ!$Zmrv;;Q zKWSDBR6qS1-LKJ88hxJV6)khH?Jw;&wCc&%l9HmV~fPS6>8b!b? znTiI>`SqkvHE;b$pgB_jAtYM>XP%1FQ7R?(*fd#_a({S!-mpdwstM41l^P{?|D=Ud zCEPhm+oe8qnKLFKa3|5304&AOt5jo6T+E{s%2zbsAX!y;=OUS3)VoSICuunn4T@a+ zzXVeaU^ zR+=SlrhiKDeVQ$PM{~r#X|7{7`5g0Uo?{Wschu7Y#|5;|v60SjTuO@^Ve&h!q%$2y zX|dxZEphybs+_ZEsdE9H<*cD)&Hz^A$}U}9Be<%Uk-L4?W%1%ER)r~BMZ+8|9E3tn1%5LAZwTUq{2lc$2eH_Sg#8?}NF zMt_;*-;VH02(r$V*lK^O^kB>UwX7=3f46tx5dQ=FPp$4fXzj!%O-3xwaef(u5KL5> z)PH@>rV`XDK8(B~N5maIS5ry7j0locy`*%UN5_cC$StXO=+qk3GFjEGW13gCGHwe>?{dRADqRB)?IBWXLmND--9k`S}T zurVEM&x$#B({d~9Osmg|d5ST=3?ve__J3f7Sdbs1WHjM+?id#SS>nuCg;;W-h%HhWDL{=Sz<=WU z5z!WG9}?~Oz9iUwlFI6zaNb9Hy<sdh|b{tt$^5>6?@tdH5UdEG>653 ztN^=R!=k%3D=x1P(X8mhY$;-D`I^oOaRr7mV-+dm>#99jadf;;ZFAHD?Akgz_Dy=fOWW|jY;wEX{l79kS*VfyL8pHDGu!)s7fcTDa&@q6LDF9T>Tp@0+ z9TM+6fdJn}{f>8tTWNr9QqNoI9{J=K`G?{HB#W2$uj=_Szbc=CMTvTr2(PHYbGn$R zp0mXw^;{xq)U!owav-paP2v&--zj#>r-L1(>N(9(rk>@FD)n6ESSz1)ihuek%^gMM z?a}yz44!-+D)d~qmHFaj(qExjEYnJH7!~kerMQQNRCbz<%rOO=0#PA(HKKPO5RHN0 z#lvnpiA*L%`A`z%X4yt4k_%+U0+lt0^`ca!4|`&k%!hJ96H7I*43nCuapq<(M%0%W z%kaAt#6-&|M#eB|au`d;Fn>JA7i7`0;bqG*f&TdNyJQPw@%4&g_FvQ~^Q(J|hy=F? z&6K^4J(?#$9XT;QHX&`H1SA_sDa$W$Cl1LjOWdl`UOz3Qc}RPUkoKy;@GEB2C497Ec3A?>vy?cIVkh3f9`zjzOxUSb}GZ$8AI=7;_VP)i30OlKHPf*1e* z?J|>r6C42|lhLFWe@Sk0bYX04Brz^yY+-YARa6B40RR910F74*d|PD||9?r_dz)sj zmTt=!qm&K0u4%_$Wds>-V550cZy#S6;?Fu(s zeDTIL@2>B)Vi(w{czvWk)>q$DA9Is~PQvmWHx*90ahvODJ7HTHo0|hxCL9~EV;5wy z$xMBu&q`$MruxDDaMBtKJHlgiZ>tq=J(jfTHO2FN*+ha1nE@+&6j3|X@1$%y?WFp- zy4_A^D2wZBf0~bOUK5Vn+w0$JLMa5g+-y2#Z*UT}!eTew-_oD9;t9KDN7@=3w9_r^ zsf=eO5=)OVP^K_1?z?G1SjQqYZcNB z6ZM`7E2=jW%eSoK@^gZihw4g{qc(^Ds^n`y5W)OcD2Q2@Enf!*F$Z(y>ktKhgPg0u zp#d1Ee^V%<>*>FP8kToVjv=iJmKtGTslu#&+dJEmK<1-0w|KB@dnv-T1k7d26=Ka3!_<>wb0YzgH&80-0()iH=ZqsB8#K2 zN~9f4;# z{S7l_(3@E?!{Ma`*d~RBzH7(Z0yrIKC>;3~4;eU<+U5yQcawC$S(1>QID0~w=(;H5 zf7wX`8|gVa&3j#YK<%@srAJ+DD@hGDVRI$Aa1QTypXDU7Y5Pq2!RlwqR8N&K??6LK10j7MVogDNo z>fi~+qUZ@tDQk4ZyYZd?-i7y)G{F@SPp8dmSiWU)&3GT)FY-RXOEPKCzz2(=f7Gnk zrPG#{Y2ZTvTqZ@tZ^h%2Vp*tQawV_8hlTD+CeTC$4SbZrbUd3eaG8PgCz#M)Sf_Fy z!^f*|6|Sb0Z`?Os%DQ?+YDYf6i9iq**nb6tPyPUxenG>c<=mTc(;2z}Uf8a37>UhA& zpoK%msXJr#VE)eCneRXOQaqZs<8H1sXY}PWaW9dy&4Rt1)uw*>wo|-JL3{`I3zzTG z8%3>7$@cZxX*<5rwsht82J7aVbeY7p#UDl4;0Eb zZ`u%EW8y~&jpKwRJf`hxe~$#PA3v6ocHmfErNaJC0@#b6^1_fyyn{nz5RZ$?_TmYO zjV0U+SAHgQ#a{fpcw@Dg5|96K!p5e7w7Vle3jT^tX>+rQcwNf%>iVQ|)$vXZ)UlE= z=YPXXGexEsQ_a9{8L5obXKzlkkS=MMRO2Q`=^6Y!fZyTSNwY+;e`w4&OFSnx?~e+q z*~Fje4mv60rXp1GFVgpHuh5=?_^Y_**Z3P%b2H5;PB|w2&apvKF6~l(k2Um&w=~R9 z@;~r$fPL_v#hRZlV{#+tzJDwDHg_H9h$VYG`5(MmiC6GniuT+NcL#e9Ulik_OR1+6 z{Xe`Oz=as2Av>H@f85=XF%{nkCdX^fa#Aem2bWsWHejW@>YJKY^qjr(|C_dX5-Q;7*vO`o?U^bCPz6Ehh!k$iWoy5;(rkuX8fgr;aa6Ctk;PqW79jf3=>0YU6X8N_2UA(VuAzZW2v7 z%t)c^%qDy7v|izZt(=n~ZASUrdGcrj2!jR42b+d`u4%~U9RMHcYj6;slDq%v#!)Pbb~FxQ zVGhejf3YIk*fWeKjjqh$nCe#k%i*|ToG^q%Ih?!;t5@XEwhPTXGoQaj(Hu66pd)(b z5Z)f`+=q(Y{y8h|KsT9e$-&AY-rX3DZY4D-7IqF{aiomLBIQF^5{*YwU%PIf~1ok-#u6 zzqhr@-x{n9)>eHUhlb4B;Hqe3mR7nd6bSL_Bi)w<)$XyULxG4HGVjDS3i*#uD(u41 z^0iB`Z7(A~>VLC1BoyeW{_HSrp_zGKW7E%=rA73;mL@Z!!JT+#Mq5aaad(Y7Vc|`7A-P*s-LDs zBltrOf2w}|fLXbwpM;d9baqS@OpPK1^8R6ncZHJ z2&zi9qmeQRaP>$O?d!qgt z73?ajQM0?sTPt#EUTsBB*RVP$rxr48a%#ygWW*7j;)aM3;!=I}!#(ubqalNie;8Fu zNjI#P(Vb6{U>_Pn6*cO}h*@?IjA*3NA2Pb=?#i56!C*esxf^r&TO^ED@?(B@M78D= zjen7t85S7chr>c;MK_iA)TrYpWkyruikw>8tuIiV;O(8^+eg*OQMnDnYTbSEosVse zYSU-`RHIHU1eg0*g=_d;cn9vnf6bh{1>VMSTHp{zRDs{cehnYO!y5jA1Cc-(VFdn> zLx#Xt*_H{}a0437VjmMIokn22I!?nA)kY1IYEV6mr__b&3JtGRS7~^)x>3WM)QE<6 zt4B3_R6VAi1=JJj=Nf-jJulFAmG650Y}KM+K!trb`97y{fr8)S`;x{5e+qu9Z;!?W z3O?c+)wn>x@AciUae;zA;M=Ehfr3Bi`<2E83jVb3IgJYx`~}}j8W$+|%f44ME>Q6Q z`YSXpkhs6vzd&#eiNmK(W7)kNb^pUT29_DaaM8!Sicc`!mw;8JCHTX#-&K#%VR)Go<*wT%b@r|<5e+_YYe&ZD!HpUKJ z#y(vjrkcE zBdGc@OC>Sew-$4Jn=sdR9_IOCsP^@v#&<5=K#u+X1C$Ums%`1RP~ z|36Sm2MA9re$T`V1ONcC7?bg3Gn2S{F@HVXc()3kx-R0WsCXlYf+8pgUZ%U#Z8Uoz z+13lu2k|Yu5Wx!{z=slNt0E!;nVCP|{0YhX$Lkw_4a^8UK0KT^?%bvfZYT-e9XDvX zbvH=kOlg^`H1XmzB-RaSl9qV0Ev*-{DY&tn*t$C{sV&vrEb?NRd8+W(Y;MVLYk!+r z)A*Thb+l%|wxzemEhUjkh>S`iR=Z>@pT&A(b$zwrh17NLhadzh7iq@?bf`25ETks# zBO^mi{;iQ&M#eu*Y%aB)|IP=+#meXx7{8WX>1&xp{#o;yg1n4D_WK$?N@MmLJLxeh z^$Y)97Fts2j-gYsRz^%rocy|6d%;Z0(xkvXHohDP)i30lnTR?YLiWVPJg9X3w&GEdH+uIxRR_qY{yAN0=cncVoR2t zgvJgEFUJYsSb1RQfk;ZYmagqfBwe9<700{=YuGy2*3q)HNmpQW%xq;{vw<9%LSXBF zveB-4cVl!L?H(;%JGO3v4ZQz%?v*V&GIU*j`RUy6obP<+JKy*J9>=e|_r>Rk=zl}v zPC=*dzI$-%9nHg9`k0>2G$)$VBh4MnX){+avYKs}`FPIE=$J3+SzWVqERJbbJUynT zk6ERh)tng7vXtwHSA}%V51oKatLsEaSM;t2dq2Eo--y*W@WzR&O@)wqDF@*{%^Vc7J8f^f6qx zYv+R7A>4n3kvHtC1bw*eee``_4Qnm#)9kTc%hGehS!{1VD9F>+elSc+XjzC9su#5F z|Dm@+jUif2^3Q-+@T?BV(a@YEe8#f9Xt$9J$q1%$unTFZL zhq;t=?U2o=+1CC(o7cNzAAiG?eLJe#eOb-21U0s`SILr-+ro4Stz|2yg2L6uD%1>z z=qC)zwxq#s3e$RO4N(hSItOl!P71XNYLc@h+sJnHnb|B*2xMCdMFj=*T*015LYkn4 ziXM`a=b%Oh#X}UMPOxS%!z$q1`nLANbFC4kjkJli*eq!2yfp=ZO@EEEqI-))O`fSx zcZhn}({+Zm!ze;Cvp5l^%bg1)a6v5t^f$F7=f}}DzW5b%CGQ6^m&{dMp=$&whP9J# z7pCphT1UOqC+L>zq<7Q|n2N@5i7laSXtg$|8B@2^ylJaxGjD4~Ue)pwU~_abbgNU{ zd7=P9Pkju`ojs(+u*(sp)2-892D(HWqf@Xv@@%xN&`*)Fr zwNt;K4L>5R6dDlJ()NKcl`*zEL`m8s$ZHw5>k>)*VcJJGu%QMK>I)jmwT}fem}>6F zwbFhZi4b7l_P1YXkuV*kL#)b;;L94r0lJA10e#zR7-PF>+J8_}E9{11L$+2#s#w2C zp$~`XW=2>0T$|*z9Onz0vrY{d-@+$pf_8l{R`__W$XA^~jap+D?wc000yV`LnW*H% zKDS^A+EN20AM8W`eCYb#_~tF$0UAXqkt~*;E)@-XqH8yD8q(knV^rsGFc4xew?s=m z4S#Q{ai;5s+J7=&nq!m=(X9lHS5|A+pD&bbh|sm1LMA7Nxyn0uyDdZoLNQu&c)LP& zB_Dui&i3N~B)$;yzP7{L8ImVxB1GeKJEE#o$Y?fnSFqII&tmVSyI7;UE8^sB_Ky|K zac!7$PC^#j9;W-~r+-+;Pgky0Ws>bBBb(t`@-rd2 zpOI8Q%h8X5B&j7+reh*!dM1xn z8ry`-J+1lPv<-(;O{?z0LBld^b0(UR1VV@=u8N`;aTL4QvPTk1c~vY5{T@OMubtgyQQw)>bC8P2{C#e3zDzG759Rd} zw!1Jtwr48q%k&jye+3ok0(*_n=UQ>8l*cuhQ3$aTe^yIp+5lHGh6J zX-+f3nepprUM+1zW(1Zc=+Yl4XF;<9xnt-aaM!js6bZr7WE@tAe`PlC@1& zxy;z9#ZeT{j+P3)GS&;Vx3rzoQfA$ZwXZa+1aT_v;A|$C=1C!)QC&P1~wO-oejWh zx|BuBcEHk$y`zvA7EvGs%P}B?XXA1@AmWu|bb(MsbU~D*+k;~@NbDDfu)(mndoC7B1#~!JkwQ|( z%1u7vf6It)68eTw1c=4Yc|Cu@pRwjg_4*z9h*rwl6?)&i?SDA`W^t6=e9PRwEB#*u zDPkDqxzhaMv1ymAzA;=>myecRyBI7Pp@&3Tj3Bqpw0Gm0r5dxh?hJ@As6&W(3W#G! zt3~-R-EW3PjysSRfyk?`PHnQY3Kd4&t7B!lEH&^F`6s7;5Pv;KJ*ngrZGG-4Pq(+pd+}p* zakR<1IhF90Y1=6Z#Ul8)`p`+Qn4EqiHV}P=b_hB}s`pt^QUjijp@wUtXKB~KIZCFI zB05ETC+U;m0<^u4RI?qpfUOYqJVU8P^gOj-z9p4PMjH-K(Ge(nirQlG{B^N&bTcb> z6!dT^`F|oUjXmdml!7tO=1KC3m#UA*TyVrrPI{Qbc;h@gRi$~?KFI| z2s24|WxDT^q5Oy5i`WVDMjM+)>y?+5sRFqBM#uubRx|i-= zx}}??JER0bO1fE)6eL$Vqy&`i5)_v15)f%bx};XhZ{>Tx=Xv>d&wcjn%x|ulxoh{H zGxNW&Q#2W?jQn#8PQNCk4+NH2?{jTl<`l_sti^+q4L-l=BvyelJoWiT{lWDQYz99O zE(yNlzwKdK1iy3m#TyWDdlw+N&OJTIA546G)PKhw@MZeI=~wT&z&GL>;LhP)$E(Bo zGb@g;QM|5IZ-S$`c)P0^`k4M1NGV?K84`izk(F3t@x|MnT0L#{G>+*FneRlZksT@G zDaQeY^2_r{)wTn)v@hWCF>~&dP*X22Xi}*aVpkJ8+X_U9BucCD-gz`o|{g zKg_rqpSAMe^7L=31B+NsASdX^Yv(Us;L)PJ?HN8(e!eqqmvr09ZaQ@Fr(7O7ZJAvR zqdxIGqx9^|v%v>XiZFJvUtROx%6FR`<)T+=O;2GpbV`Wb=K2lwPG`fV#e&CWh*>-Q zJBu_{Bw*58$)j>DLq3iTn;zz>AA#8)3=&*sxci59IK&Q%Ej%=)AWy{}PZ5aG6cm9( zlcQ=@-QQ@4rEMdL{W|i&%+ea14AV|?uZfU99iFNjuhZi7^!QRQK>ll#i}Q>_nJ*)Y zLQd5Jq`HF2mv`v&!|qq0y&6n~1)4Wu{cXS^iUlP>dLe&0kH_nTaG zWzOU|?6SwcB=1WQzJXj5-{P-@1DxPmH(o6(ZX4+Ch9#Hgvv8fWnGsG&0rf3+awNi# zACJ)`2KeSU@^>SR;5i!|c&f@te(j7|DJH&jhNQAve$T?{Fl4QYFeGf4b!nu3WpR_hqU->4IhaK zy6tZo?Eva6Rv9{}2dE_#;geNkl;JhDC2badMG08N{NpF zf=KKHFR~*(Lga$vm-T+4Sx?kCmL(W!u-Rnlq4kl}CKOR(<|_(28n0>7ma0`~ZIlOe zEddBrTbTru;>-cdvnhF9A8v;*G=>2Q%e-_7|u>H z_$ppV#I`S~IvfT|I!JshrJw6~yddTL=5&tEkuiNKaBG0UaGdw~2gFpVyj34*Tos52 zozW7;sk92sTRvV9o&CqZZg~F=o+L1PRpJr=0AqCb5u(Pkg&;^na_nzCh`89QVqL6F zv@39hSfU~#il5rxDs_UJVLsMw`>3{WZtz1QDJx&oB39rsoQI#_aLYBM=I+~HGkH;)B;_zj}Y2H%Qlqc?J#tOx|qG+W3mP6IO$YhsrJN zS4M$ry&qjm^bxYxzWBH|Wj8wu7Cf3lzAU`~%b zETk$$EUVJ0!pps4!sF=eUe-wsuvIba5C!#=AY3ddctPF*tKMeY)yRj}3=^Drj_H|Dv~?)cO(^A>P5sau_v@TB6A%^J0Ol2p7O9NB#{jp$YU$@<`qy$5s zt!+MkV=ryJFZBc3CCakEhkcOYwZ_<&kbDz5Y#9eOPYuHv<{qXcr?;n>TNp9T9&E@c zAobi(T%&$1RXU?pTrl16j*VSCI@=|h;mQH9!5wYA1Cp3iIOI({Qpoi`%k%ruZj|g| zv-8K+rk5===iiJ&;EAUe&#LE-Qq8Pm@ zObP~T*_A-^Xxmub>3`BKcc-p)Kk{R%Rr0bHn%M}x{g`!k6YvKRYCBJGT=#SZU5j6# zF`p}i=!3lnn?WAwg4Ku95%trU3^V?S1USF!)`y6hZf-qRRsq3;sJfUAVr(rVh=gW0 zpVEfj*utt?NRwbxnEHgoGj&8rJ%;l7jGfqujphvWq9UDD#fFq|7kp%Kyx&tCZL?7* z`&+^nwsFbyeN>>PcXr=egvjE~eAv&`~@EFT@W$pG_-%lwbd(W-t^TNmIb*~@bg z?J(T3;QMvcjIkd^84;6bUO;t1sG$=1IuN-E7srUF&dFH9GR(#r9jk*sm?$zv-gt)9 z%~V}<(M~?uwza$_UZ^v?Ud=wbLxY6#_60|&Blo;FapL#9*!-S;dT@Ka!fT1t65}1k zibum`9}+{-(!?@ietPh3mcI?Y=TLs?{)$$~6Fy;dcU zq8*f`O41v!Uy4s2o>d>DOw{Zp59;AA&Eb*wYI-H}L8sC_aT|A0GPaeDqTN z90gu^H~FsvdR>lKfr=vDN2d4}t|-qz`GvI4DXy{wa)ew~hW!&(4N%<%9ikyvIOZ#c zd@-Il)KR^0IL|4Sz;|H>5;21yd7OShn1>?D(cqVGa+ZCiDuKmHZFa164y9+hxlT3$ zte;?;DKSITin^~#$lD&55f^_jXk!H)nmmT>JnF1(_dpg+#Dl>BWaI$}yCmi|+A)=< z>z!m>c3zQu2{;B$DWRsH5Mx{l1l>7biW}PHDEvshL&*c?eU#Oj=3ZJvzDlI%K73Nz zC)eU18Z7Y>>j}MhJB_cTugN7x4-~GWF<5K{*Y6dyCtrSf`>H)#&N8UU?(w^|riL-y zYTPUiOpTF@cqLmRONyk{7wxZv) zxvok|jTE7_)^6rm0shl-@r8@jf|&Bt3ASRB@v)#H4`CJR#>*{`X(2%yrQD9?At<9V z77HoYRq>D=3ex*C`R5VDMEk@E#H3(wM*t(_X0S6O{!F!OSg;nza7}z*Nm-Ml%$e8L z#^kasj+h|7b^AhAG%Vs`lh3B^hTs6dFuLnKj9gsx(M?v_S`QK1_~fNC)$Q*fA8a>Q zTadI!)(C48e&yN{3O%H0L&fZskU5B~_W{InHm$Z%WrQjjy2Vmb>S% zo$WB8kxf?d7x0_(E85p#2|6huvayuEhPC!SGv{q&KmS&W!Hju(F5GY;z>?tj2YC{GGHgIf@&&h zYpQCR9E(`Dz_I%^t58>cvQgiFmoG;oW2kHpWDF^=|7dL8D^UMb=zS``0a%#v>ks|Z zSzWC0TK$0uU3-c~rP8VKUerq8=GT&0tbe*g^hx$9J218q=t6Ucm@5+h+@1n-%(r}CjEywT@gO7td z9o_5@PScQWX1ce;)BJDca`!MIe9SoFO?GY<$2fEkPH-hbVFQPsHT>g_TJ$cXOi7So z2YSD;axI5`>=_{6U8;?a^+=gfb(4&HZ|qm<+662z$oOEq5iI-owyd{lf$)HeLn#sC ztcpF$Mv8udS__B)LV?L1!@!F}af?^8hZlp8kPr#qUmizaeE>?R7~Sztw!`?4Z(TpY z??wQNq%t+(zNi@AmZgx;oV5t)a2PHRvGK!X52ffpR{TzTx;s7a&4m*%YJTD#6a{T_ zIG`OMe-dHDhYsdFd3p0u*!`tYqs8PH@M7N~`ohf&WxIL2J(S^;lHjTIkHp0b)X@t_ z77h0Sw4Yd+Oa~6L5 zqGPw{B}*~EiL2b(S|wg8ib~+X|6C#wyhcxzD>p| ziS5WMxx0=hb>dF;?zFGpB50Y&((8oTEoib=AP*i9#~Zjo#FKa4!)kGpEb?S$owH^) zOe@%@+vymNMbmrO0w?m@4eK|*p{NL4)3iN#y55Z4_P-Vr&5B5RM+l2bWNkF4b(ucI zm&kzl?kUtqE=ESKoU4#8w!v|#W)`bO2DP%`Jt3(caSjXb&cvWbPG$oaG6zpt%TZYi z_F+D#l5Slr4~BQAe8;dX0u@xv4iIH!bvq2aY#;VrX+OHXJ?fPPRP?>WVNC>noAqYn zXDU^0Nqb!pUtFJT%v8CB9m`=BTh$9W4Tzfl)MdbvokJRJCy+<;bBCZlLxj<(zV5{@ zatxY*|0^wO4@1e}Gc9pqpj*WUngZG%8#tGGQ$xdR58;jZvz|jN`7?Y*o%GcVD zMVxtSMai%yAT)?BFQsFriH?}Of{4fK9Qx<_dE^2=@u3Q zXi|wjR%{ZQMPHmWFc-YmAi>EM4H;i1p@$)yjuU(gCC)_HosUIAOb@Op6+_ziwk4GZXf@0Ipq?AzZQr)?td`+XF*^CQ`VH`(A0g8aZ5Y-OO@0Vn-8}mw% zTKq3duS)DI>@v6=JSe1PBpWpG-23vKGA$DWQBE7qe`Zfx@HfoxaTB)CQYo-el`?_o z%wSI>K~hMFqV^(T=%tWA&$&SJazx;p7v+Q2{+n52&-jkyd10^EOIVE_ZTlX$*|l7^ zu~FoNL6uQhzYnB}6_p>jmPu?E1NE^~U+^qeF7xa%6R+j#zKl!ru%#?^tbcLENA|~$ zWSQCRh-rCK!RJIC>gOxIvHn3pcIt3zHpBI=<*PZb=@`KQCLJW&8Zj>7XBODg6YwTx z#32!Vbce1$;r-WqZ2d560+VI-ay6wU_**@~Q2H^5fJPV3ZG^(TO4$Ef z;v?jcq$audDA^aK{#^&UTFIG1-A#q|IvECg%H%dn0Xm}*LQ7b2kBNC2J6^t5j;@c& z!{ar3!LxU~wvz>!Ju)=wuAiB&YfDbAyvnxsJ(}4oyps)hJbvwt!wXXQ1KD$-6+Ywh zkGYEd{w49+otT$zQGdxZph0eufh+x#@ac!MBoB3ug6b=G~QFt{S6^p@eR)OAB<~64D z^$FvcZlv-aIsU*Q-#IlEto3e4jSFx#UD}Oa5a0&!tin0W43#$ZR+Keh-PMaleX(lSWU* zSB{B>_Cs>r@sx6OdS#zWMr@4132)<)WhLL4O}vcnLBotElrqeSfc>#TswHPXRgCKB z;jURF)GWSQu$^@OL{ooK6%XBVko1o{vxi;;O}WRTbyX#A6O6pW7nUwz50FU3IaDH| zbl88B*WW$CPW8@Gk&aTl_fyZfNirul*YXq_p(f-!K&~`p*@6GePQp$qp}HEsuFHJ` z$teu~R#5hdBER62UcnDG^VmgYR8MCK0xSih_``&P@{-~u*#(9QZ7=ujvoy>g+9ggI zBGF42lcrzR!9L5JUhU%xqwWQ}{Ug2F_y`w|n#8v?s3}yApOhyiHJyuR1F8!h3of1a zIVeSKpQq<2FlMW%)4HHUr_Spenyz9#Wek5>THLQt_$SGDEC5q+2xv&T`upCj-~?pT zT7U)sC_t;K-=nTxX(%v2jcaUCtt%oA5};pdNRYGep#*h6=xGfza8{jO%?$Bd*MyjR zBmlttyV&ACuSg;U#0WL2sF!Ugj+5VfTvYI`WOPJb^%&2TS-su<BS9`;y3a_gM}yMW z^8(L}pZ_XEJk|yyR74-tu*doz5Cr_kl^)UNhn>1%|3^)ngXC|Uf%pFB2*ojkBL4%$ z7_NKxGZ*DO_>XfnqVduXz+9etaGHnp9{k7F72y)X@&JtDLx2nj$7{U%-Sw}t;{ON7 zprMU&zs%nE|TU%t7_n2x9@E){jto@&HnT#x|P*?>!k1`80@p z-Us=q8qk7P5-3TF5X#@!@=(ndQsh|8`?RO67|`$*Y2d%XwE+OZ2Zh19|A5ym{J{T? z1W5k?>@@ff$O`-?a2%p3+z%joYXqbM{O_o04?A3BivXygbZvZ8|1MJk05~3~Jc8!8 z0uc;0bi(oea035#65roBd;kE$1NLX|-)3R{v%Cq)S5FJPpM8edS6hhfVFMq<-S?s; zi1Gf&{5#SL0MI?qoqTf-Dz~!$??=cGT{T6VowN@ip}c!2ubmnA&!7;Z%7&-{BR zH4k`S<^3}tLdhO+G4ni7voE{{b@T5pRN(*pSJp<{a2|Hzwgg)6Nd@@N-3S)|V0)mX e{Sg5G5zENPNVU~b5#<2@M#Os+0czL&{q{eZe&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.jar b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 zcmXVX<6|9e({vi+geNu|+iq;Lv2FW=CpH_~Zfx7O8#Gqq^zH9{-Y?fbaLvr_?9PsS zLe9KG);pnsnwo2xi7~sprey3}qgMu0B@znDa&>Nqe=c%xjWdlqpbrT}IPS~b>_I&% zA287HK|$@#zWWDsgCP2NFW9`+?JUNDy*MsmOutN-aJpvAEnMxz3)pei86*w_@iD*1 z=tZH8Q%z{l*zX;Nv3z+G&`QMeF0R6huq-N&9y?D4?S4vF1JI3W3l}F2QamCI_$4mz z{qyyQs6+NiBUSb8Pqg!J!+Xh*NXmmPdRL$trm+cBH#T2jQ(0-(f|f>yj$a@?K$R>QdLJo90QU}F(J zzWCPDO4K7t%Frz{75JB{KyoPgIM(049+s=sh_wSYs1( zeNPcVCM!L$@cL2j(4Nz~+{l3FQH;33g{>mX|0P%T5bFDwc|#AN^PJWcTl@Td{#B)j%DojhmcFSQk57S&@3V8y=r3UM3#7}g`5)7Js2J=0%)v7G5TbOQ~| zOXx^|cQTbWd#19gg5aeSg%CebRPLlL@3cvctTY~y6kynrE(@iFVNbKmHc>jz$=PVw+vi_x9E4M|G-+~9h@7R8~`*2 zEh=LMFcGA46bK14e%$P`$i>&@T9NRqMXsE=Dw`|55 zFQJCE-o*By?hZTgWDCwEXcMU@msdzws*D@V%uI}F3c42rB;ozI4>kEE47Xd4&>?s< zWk)m)zJ+Gq4%Un}{!EvM=05!zG)osYj2JdQ@sLnCDe~o3p1;&&i#>J|*Lo|aKv#6E9N9E=B zB!J}h3F6%os(87wCahsW-SKO-80b5aEeBLR)MM{R9Nh&OuTs{B`1rR*gGn%8XB^24 zIT=ux-qO?koB6SNOi`}PU49>gm}5%H4e7m*W!dfX3_8QJctu!o3L&H4k&3FLEBl3n z7v>g_vrsekC|f0a8xlnzNsqTRaEa+)0yZv$`xerlu-D@60Krw|I}l|B!Im+c9oN|= z1=TFs8e`0X-7tSwCE9(Up=6W|mM!X>87so0V3z5LV$hVd()C^xNUFJQmivSS*b=rQx)o>P?i z3=gD?qst_L+(f<7ps}2GJ#qr8)n}cY{877wriZC+@a_52BA1#@BXPN9oG_E zjuF6R+`6Nq%_1Y%c*EJYJ#(_EbnL7&QP+(jdUM(Q&Mm7m*C`xlDDx0w^YL93^m9Qc zJ;5j=vblR1{$a+^r8O+Y?+OWl2tX9DeFFv=DW@N9VMhAT*CYRB8+>f=dJT|-*YdoL zI())(E385?{H8*B7z#k3#_J%;B6s_saR4tj{Ce{XIgxi*b)gcLw!bB1BPLL#NAGm` zmf2*gBhe{+YAH>`oa-A@%4`k*?O}?sIS?QivOe(a8|)0^B?7@gW6q1*Q(G8Mzv;VF z)NeR@&IU+(%uo628TR?Xe==|IBt7ALs$2|Dg-XsKiuVYU*k(*l$9Reaq@QyO4@%GM zK27R2XG)3oiJ^2gSc2zC8!-p%>`b24uFs~N!N6CkPqItz`YcSdgv&w@$^!0?F;>(g z+U~bbUFu3lMM-?O0JglA98X&XxwX$_VYhkNeN3_IPc~_uS(c>z}@7=DOUnJc)L!vozIW}~&Y}`D3f$J|r?RJx>{yP^0{qdQ$)Bo+o zqL1$bdRxiq>l@~8dO*6C0Yx54K|}cIu1JTx67a|F;%0_lSBQll@2xOXier;)$>)y; zcD;=eC1%fhw8pe%JFu4)N%*{enJ?|zEtQ35D%e&X&_o^hpy9b%h_rdRzZ~dusp%)@ZzDuj{Y%m4*iVa6J~h{^ebF^8V}a=@WjB2OF!) z=jHB4%SlL)kDqEWM*klpKL!vk%1Djb28;V@y=r1{Dq8X80A>e;7f%6y;&W((65o$v zpdHDgf>db8*{!syk`$mqETRaNaB*|YwiWAWl&w@In7u$MPC9L=EfHgYOZBi=5n;1{ zabZ&@uDMA9!-Vcx6blpPQ-t1hbl4P3iz#5XepqwZlFK4tyTzg7TMaT(RiY|fa?@!g zGA21y_`X;X)C8Sd1nB6XSAWJN)YobY)hmIVz8edv9jeUd^hx(|fh0ntb4A32{u^$k z2;Snn#WF!apA|2ZP9VpMgRaUq_qURmkug*2_<kc z!J;(Y6#|SF0r%;j*IH2R_4>$`HNNJat-vxzbpgueyK;km{|ZJx#acyv7whQSo|K@6 zbsJpsa(N#yvPOAY=Nref3WetvWPGl1edR$5yTneYYI*u)^LWc7@?UhP4pS0yOKOKT zFK8V097I8nCZ&amkL4#dDAUD19yZ7a1xv4Zi10l2j)E=a(CMik@X_`hf=4m)oeD$r?87dr=FI>0MDT$R#PSvu9gemd5OcvUV zFXya&|p~1?a9;=ns9pFY$xu-o#bOVi%<^)MQiQM*D41Zc-o)^)S7nz<@zUk20 zcEl!$s6NO`>;H5&F5r)7X_gC%CD7(z@Cq0uYtchj)ddCc9*6 zHG`wK;0LIhoXQeEr#``e-+pDv5UVAau^pa&n;k}7H~I>()V@$j378Ts&q*lnOj^UM z=^Uvs%0SPfZevqTW$lGB`^FkFt7;~g9k%ZE!nMh(5EnJuFkt7*YPwdqEBknlSGbR) z`gU?FL0n?LUq9m_o85ecjEHbD`5fhTU3F39_YK71r@xSSQy8p3Pj04l+sKe8UN~tM zhmRkP`A54{M*Z$JS@2oGuL^dzua!5M=#aNyAB)%Q{C3+$uRnL-;SZ%N&MGQq_UU9s zZGT0_7P+F4&e}ok=vutCDVW}FyE$W*C=CC;I(uUA?6&H;A@mME%lNWADvu4r4}Rjd za35sJqZYDy>-w5VZtVVxiTW|UjqYVfSy|9Q_s0V~zvf`G9wDf?)U8YVb0fZ$DvE9; z-m{lgqScyN&!@NF@xu$V*Yv_Zv8fby#`8%3fotcH?pqQDRM?TZD?(24NmrGhpkE1F zVz$z)Oxi_)5FJUju9^R%Wm3_=ADZ%CVa1@kOTB&~62z_L3CrNtyTrX3KXNbnJWOJ0 ziin!`ouge9SuH0)%%~h;!=6B*=<@hSCL>QPlqarPV@EHPH*(jt-My^AeoqLcMKZ#f z$zJI*w%QZX?-!HgcT90TL5I`#R#_7EG-)MC-fnSIhlvEyr*Vn4j&;|lUL4qrsK}rd z!4*HC5>x)Q64eYWqUDkSSodAC@M0JKYQ%SIwOPEv`{s$n3*pR>z1yAq#+r_u z*rR?(-TP~!q(*S9zxZv_s|&tbveIYQfg)%xFfc9c@lzZ0yceI_nGuL#sKyGn||%zP!^ z-X-~Zja=v*Deu2exVT_Qu^-&wL1HZD2ommm@EpiXe}kd>OOQ&UH+}gB0+0F?-%it#F!fdbTOCF#I~k0I3c-V-g+W=etAMi@!~jv3hnMHrK#`0 zk5~TA|MQiHcJN{v!J}*(v2E;X>YL)Zg4d7ix_W-g^{l!E@*VQ1^NVSQmi@f7I8^O$ z5)*16Nx}0*k@ea1{_nGz?I+4FpfCRw;cq@8y#{a)5PYZ*5Xy2;(3r{a5?IOaWU`=S zd!>JtYxHk=e@7}gi^LFhQ?LiBIbt~yZY+j^JX#DpuD9pvj(h4K4{Lr5)1#1QJimg- znIW722;r35CO24Q1ktRAt=!Mq>+D?Lt69Tc5QH{({KnYvTH-Kg=U^o+p{1u#*S@<{ zH)z*gkhn95k zQO_FT_#_Zds1lyliV^9iM=O3R8{XAP9z%okLVzTPguIB|`T7Ql8?piLDWJ-2%Qb2P zhAM6&v|mPc{Azz}?t5x)T8(_j4o`$X$!%8=ADebieI1;$9udGs1moFAjexGQ7|3T6 zP*o8J?_Lud-VjjHG-*F`>9?PS2K5gq1Mjd0>u;O7N<_j+Mf)?rkWmsbM%l&#Cyu(o z#l~GfmU+#qd-prLuAI-7vYZz-m+!bjOavk(jzyaT7crme#QQO2{D>EGCGksDRGqO; za7Q3ta01@Y-pLS@R;q^&r9iZ8()Z}nNgjgei+)=ipA>KXUHD9#kGfD;6*>QBN<~EuC$iK?WmH zl`-ec^w@NwYMxywt;Eho@@p=cN!*3@FQl)pZ8|lN&X;N<*@J#xv;MWT;+mI(xY85l z?}?Nb@}k9BZ>bHK!l7G^|6$FBtVT}mpT|o7KabT(sRt6#-6+v3(F;`%21Cn1i3fwm z-1zNqJX*~>qR}W&57?i@kkiG1Bz@s*x%MKHRA&y2>~A^OekW{}0e@d^k@_gH@r3fS ztILEcd26qcsOx4bUu!d!9}E4Bbhg-|<1BFQgPmv@`t?OdAU!#|Ngw=M%{qTyFtzF> zDx(6Xk3n#mXSVRHLY)0-L#Y+?f47s&(f6?1xQ^8b2i-ywN=?yxXo}?;;FV(KV~U%) zc+`bCgIGhkqNpmOS4*jIOQRR0@smy%6PFm-+tr)wua2~2XeUePkM=f#@?2k`($mMl zqk;wbxnwGfFPTylVn09g2J&ln&}bI#HP~DMu^@wfH#n(lqg}+4pC<~V57@Xn;jE+@A2QAcOeC-^rji$Un0& zFd!)YV!!qj_XaEhMUVF{FQ4&rpm3~|vJ37B-l>C`+zi=Bk~N8HWV^ag2vK|I(lm{O zdSaVi9iihR)X6MmmZ(ut9PheE$%fkH6&%n?~gB*dZXhhtGRQ8K^Dm;&k z2MPHO*cb_#jH1D^5wa?}=u1$o<5y;fE9d&_JLRepAo#z*Y9++aU*5~3oZ)R8;Yr>{ zuBQcNr|LGd@*r;Ta}k~c+#h*+0ADk*lNCd{Nq@k0il`oysGph@40cIJdW%KPVMMbx z8M74~ZE3b6gZ`A3GhD)&V;^gS7ktr>cL1!%dceOmd784U#+JA}ceH%TnPbv9to+ob zFU-e>pYX56AJSYGD+>RQh` zv@SZntx^5R>-!^=L06!Hql@}4Ae*66VZ`eE9_xp7@QvDi_jFx&OmM^P0scyWm;dDC zxtw>nGm|;3qu2Mo#S*yDi;W-!ZHBBI0iobgB)aq)OhSgiS7L#sayk>N{eHU<#@wl(b0)X*Ow8ZQ2AiqSbsY<`h~RDzk~r!1rSv zWMkO8(z3uYi23+$Aii8&68ZHL0+iz8S#S$AMVZWQc_sKX^W*JfG~E&6s%YkB|M^+s zzGh{AB+;pJqs8K(DbvC$&T(C!NkGf9tCrLNQTOKCoOvEx2WTE=M1{o((!O)_^4k)} z?h?_}xn?ohP&b@zmrO&WckV918W*}q-nnNH+G>*?S@EyTA(SvcIri=Jt7dnF=diMG zI;`nfQ&$kj5O5M3&_O*7ruAOMMjmXz@60`PYVDMgooxq%>g_%i7@6+6-D2?kr{J)_R{+kN0r;WMaVylPq55VgBF}yc!LI zD(w+jSS{z+f`{vm!yt3dFm#L2aEbBT{FlhkbfppV}RxRCxys(W-+mtVm_xtu&Pqm{TO%K8Ys{8#ZctXj5kL zbMkqZ26E6RNK`WCmW9uhoX_wtzfaYCh$o_{jalY=iz*(aM-Qh8_+JzCrGo&UEIEk5 z1T?Eiz=}398cNBLfRW!9IawKAJkfZN*A!d{hn7kw5hy(zw0Uu5W_q)c=m|v7_$A^M zolE!F2X&*2b%>^uK;E$6Gji|$xlSzn{^5!W(OJ*5clGCw!27-gu3@rbmp}8Bw>>l0 z`Zqd;;`smzjDrp;i40)0|I|mD(yhDD6v)M~H=M4lgqpE zz+KxYhh+w?AGfYZAWtwknt1`yi|m~FoO00WH!j{!+>tz=Lsm)xJLc>B($)ObG(C2@ zW`H-tB`DBS1pX!u_nP60aSvS2oQ=j0NRthUZ9u7aJ4kH(eX|S+vtHBU2wk0H&GtIT z0r$93ja)`&Ov1^$fWdd>GVbgyUY0~|o*DV0j%1i>1>9`*M?r>x=l+bN1GefIeUi^h zWs=z!l0{y|TOOzqssFgY@+l`-^^f~A|8c*S$pi$CPmc?vWW^`=w^N9SY~Su?Kzf_s z+AbU!3wZ{7&J`OSp#Im5%rHveQ(8a&WcRd~`N8h`^!a&zj}zFLVgB6M`?v93rq0Dy z3%aEzUsu;hrB$@|*hj!)uE#*Aobca}1~ z8R%#l0n0am1#r%57djl-3U(^)lLWlt|YBB6J{WVXo|nKsz!V+0qlBQA_pfQDKk z^Y!0t+@-W{O#;-!zOdsRsT5CYmwFDdH z)cO%BD*!TvX_{nr18uGxi9hm&Aj7XEQ7_L$Xt-i+Rx6AWdW&xTq*^}(;lq;FN6RwQ6w?YBnk>bjWMC9 z95nicqa-knC3I$S**_R6i+lR)s5%sP5M5&}lWOUr<6a`1-+hz+N)h_HKrp6=2U`U9 zO>Y7P{AXxe&TzX%aO$^Y_p6nSX-Z~K`UT3qKe$ETEa~P;$Wa**3{5KTw%hosMZK?9 zB*p1axN-J3Eod^1&KWmQvOrH8z!InyyXG4C6V(+hZ}_AlKLlYm>$^dZ zCA&aE!s|e~ZGa{95NyoHrlqltqkHwcsng71a!b3F=4x&({fLv%ympl?yD`{CGZCu; zMT;hiYq@wU_4l2@qP{W0~3w_ug*fKbacUYSwSrHY`QZ{v^7fNOa}kgUw4T^np)u13-LmbXlQ{^8d-;{K4fZ)_-=HU zwi|g{{2%{0mQgg0u|6l7`R@A}bamr4o@5=(8pV3~5XgXk`wnHnz+Wpo)@W1no)N~v z?qcR~I_JfkvlU?-Dif;rcURs~Fy^Q){88Jj7AA*`)xNhQPf0}mEnqgilP;?r5V z?wLeS$KNcbPfX%$d9WKB zn)6^mj7&;-h$<_IzAP&YD(Y!|X>Bi4hB;w*yWJ!XB>`k8V&6T(|I`ng2g>UV8UkVg z9wHf1g5Y2N1ehGxik=MMMhEGu0WC2D3^3N}p*d7An^SNlNJ)wV7skS|X|Soj*j97M z3a1?@Xs=zAb`nUIsg*5)RQ?9G@`#CKS)Xe#^L;>dU(B9LWaWA$8!eb^9GmR^w45Dv z-MP1)O~3`Kv83Qc9ENfii8%!vD4(I?qf zuYt#ZOS9U_BFoaFMztSt<_L58Akm1Ggpp>roX*5a$lG2vGPwq??(IZ2QxefuH&PKE zC|LJ9JF7C6`jVKNaYEwt`FY7pAoG`Rf1SX;wd(}U54-@mWgf9UmivaT3NudPNh_O+ zS`!_CPBTozs9XhQ0R)f(IGKMU7h@4qkVJQPV;@gf6lV~jh-RVzJFnO-F?C;kfR$mr z5?fcL`m$Ix+x(P1bL*g^+kn%NQ_fj8<42d##qCAIcM_0Y)>0W(ZhKF#VPGE|N(-j{ zE0Nf7$%(gk-~#$309ri%EQLH5yd{r2XPcgs2ewxVB(X?wV#%qC`ZYBNYbtEAIqsEO zo%#ZHm}SA!I1d*@V#|1631k}U&Cy5M{v;JxA4z3o6>5AzAD;PCYt>e5W++qaVmAG* zehD(&Z?cvvT7Suhqc036N(_YajHr-pkd_M~Hjfd&qH1^W z?hsIio(X#8P*%Xg#cPp->@bFF6p(^wJS0AXZr{xJ#GY;e{1Xc2NDodi$BEKjC>{1E z80Nhq2k8gU{@2JAWEr6b?TX+q}pdO*Vh2+4pt=jNC*w>$W2Vv{t$N})!` zgkyo#v`N5-e_)X7)fgEzSFTn7NCX#`!w02bqo0ruK3!Z621HJ3oH>NZD0q90eNol_ z7d+uS{{xWPkZmA1!1%O9zhxmUX_N7lN&Gi0aF#Uuy((OLH{axg1d)t^SYw{^sq4=6 z6of`{Nn+YgS^vD3R6j+?f(77n#5m4*5@z|fYt3ZiWpT!~?KVQw{{`02#Pks&{Y;wB zC?d{m6*XZY%eGc|f=JO_QuWjAfl6rI6Y+ju%}*1lNi>M>ln`m26MbyTwqt%dZys-h zIizfxe5#T@`|d>S2o#!=7bo%*tg%P!hy!^>GYsS2_sIR9P}Tl084dm?RI2d*o9B%2 z^Me%R2EU>C+b%EZ2>%{k7DFj4VYR{vjv@`lLBfJ57`10pXx*kX=cbKVBRS~3Aq@@| z?jxa6MB3>BIPUn~TX^<>gnA$dP388?+1inEw`u|5DUw$e1b?=`1Qz4c)<3Ek9+Mcz zkCCmD(zGw+&cpl>!&{`QeK(RfR0oNM4M5~lxtSJdL^&MheFnhy=_kaRANBrcM2d{o z)vDx03mNOIc$1wOs3@6mK{)ek{!C)<>Q_GpLfvXO5H2jf{xPMXPzWeb1<}WroYKi* z{E%dvv5hZP@?c@E7fLWav;8p=(8-_A;#p5q&y&_cN?*U7c_vZY1hS6tv!l(*YcSr| zE1~N}qq)2kR#)kFfkCN+%=-IGRIOPLw!t!IU^M>18T3N`$!xR5<7e6*(Ts<&$WfcM zb(uc|zgF(K({LBrJTuL|a_+e11!HlAvC5nBfBw0A$rNAhp9`!0zeHjl5H967=8 zUeWlGYsC#!S-qp&_T9s$kE^GN*}nl#P=VWR(=6_XBWItsi7K`62vul!5vRk_0)?BY zmBuc!^)=$dOz=tk1DIP_#SE_81?gcz$15N@2ebS!1+5{9W!1ugDg-eT_y*TmrX8gg z#lP9028&Eer%8bZu}p2ML5u;`Y7CjtutQabq$g@msy84ED{*^mFe|jH$MpO#!XPF9 z;a`s}i^7~iZmyl{#NbdGRVl;xw9@5x8)80@NrUsr!xDt~Hx-3vr2+ePsXl(i zgPh;FCu11ABkhd5+UAq)o5)Fl6io7Bl z<9_r*^_H-^|FP|`eGsf=p}if&;thJ-^FC`%?2=TsdQje-s#jwxLL>+1*Ot44`?gS+ zCK>aE;?y@o>DI^Q9z;}*yHAW~TJdd@!;y*4)0+64D!DVyUm25Ns&vp$*?`z z{cu3wN3ub$c+tVQh+ZSJ_hhSnc;uXAQIjGJSF%7(pJ>Y>d#^4E?tU0cx&fJyEqYAf zy_1`Xo{oMhUJOEr`Eo2$y0SzF@`y{Yl&71)V$a=)&-P!tW*{!(lk$rdbBOAUz#F`WUZ!3JKdIX{Zzk=q`y1r23efs#r*xP} z=o-uKvyO{{kH?>!d1<9#LpWUsE{M?{s3g(QuYHUO*@$f2o9X zclF>YCz@4hU2{+ctFzud;Qw$FR8jdhS(Lo-oMNgKcBlY$Le3HC3h_Lt{(zm@;7fP) z3!(E*^Z3rwsV$|xGYEPkYKugLpa1#uPpH#E(|Dd;d)Nx&?j5>Nn&V5Twi2#pf3A~; zpX_u_>9QhHsE!y3!O=3ipSr`@ukRZdV$BofPJRgX`&7!OsNu%ldVvqil9p&WlrPys ztqqu8l0J#5OouT)+u~C_(W1h%RvQ8kdxr-Iey?$a<(ceHe~yBR@a)ESM*qAQTqSmD zW1lNNF3od$q0;+wsChcmuLvF>z24ng7yn*Mot-gK3aGy(vocpYyb&WbA6t0D0`qH= zl+~@`1q}6s^NcG?IXoL2I(Nmf-*fRF%Xi#`?7O-jmDL+A*uCSS8YZlcTz`&ks;&9e z-P&H9&Rop$reNz@qx@|t%(=b zuhx#O^C*Bl4&DF>s@JfIn+!KP8(haUSp0P~NX@W1p+3sTx99pe-Tm2erd^X?+<}Hm zfwO`)B>$DCcHCY_QWyvb&HpP;@M8KPQDabZg2L?kC*dJPl)*2Z+nZ6kDCu-9Emm}9{5BO zHrSUEm1A=DW+g}jC&MYYo@UZMCN50=)yKuyJv07p9LXb#2I>~hOq1H&#NzRwT*9%G zW~L8a;i_2UzFG74`ouMPUGg&fk<+B?6N8wtH@G)zffDlvXJk<$C(R|rc{zLOy*8)s zNxZzADOS3PKNl$3OEJ{SVRWgOnNlmd4O(DkQ^~KDN>cIKA@qZ$k=j!t6RZ6M+etNG zw6V1PD{E?V5!^gHX2Z3`K!Fe-s2~-ly02~~h)Rw&3aRZFYdhY{nWyB|2)wLrUA{91 zfA=6fp?xZ4!q>z>Le`{kGa1(?Iv84a_O-^Hy##>pIWe#&%)I;QrE3JYWDORAMkEx5^C(mE^>j9JqP z9rf$TS;%X~d&|8dejZ-?1$+s?F(^vzBcM@gqEVl#uOBEVFI`Vtt~1x!yZ=I@B!55e z2m*iB;}Q${dAUCXG?kaPwyQ+NNi4f?pleLqC@f;>vd5Y&GdL&d>Yd1H=Pd3wsw!1Z z>UHZos-Mp{G#0LUlj~GbR>?9}AdqC|33*E5QR&;dE%t29xnnG)rykK3n5c7vxXQ89 zQFc$(@EIrixgAZ7Sv3w_OOkl?lyxYfz9)Bg@_vn%N{zK?1-<%j&D){N9o!Fi+m^YqPNW13jp0 z*ZUeUe!~f?W%sNDvCVTD9xC?5YyZAK#0cVZg>K4etVNT_^)1R=b?p!0-~d6pqfGYJ zB(fM53`lmm2?qzv{|mT9pX?MW(&(k2rGD@rZD&&%VhrK9UryrB({eWOWjeF6&=r9i zcT3B){e=<3Gdt;W(`z(5`PA~XWxCoso=&WLkOgIwQ8LTqS!9Xig3jqT-!D&3^_^QKzQpW{atjUc{Ho3bSFZWm z8D_DsEAE;0e^8rEUUQt%T^4u%Jrk3voqT1reivh`rxsIC8s?ek=mq0}=RD#V;oQW8 zL7T2s8@c?(Ff5U?AJPc%&Nsuj1~T1|o$)uopv5ejk9vshlY zTG4e>6hw~3STeuX9BXw~I%{y<#pOoLOb2o|L8~$qxegUiM(f$Wh~lw?IzaF{{)KC- zO`>ibG+Cw>hM;4Il|)g3CK)UI*)9}58vIwl~kadow~}Jn-D_LU-C8XZ;WS_m+(D?7>qZqKo|I5lmJ>PlLuHP0X#9>Gr=(^ zs7v@BE@hw)8h*C7Q0kUS$hLIK4c`(J9ZFiDR47MzkTaxC;1_gvTKKo&nQtaJWYTzc zA)e<3w~-J8qx6SX)cI9N>W}XOXhI3SK!0dm=4#Zb^IzJ;j_hR*o@8G0#039Bo?LpPR5Gnx(u_@x*49E?0B=a==b*Viav=_$Onyoi@ zr{W2QN1b5)Hmhh7GbPB7oS=JQabSY(_swt7VY#Ap%o%+_IC!)GIh05-{1nPgxyu0| zcO^FiyO2^3>+ zZ)psQJPli*M6>vcVnWfG862d+r(8jmEKAhI&Ne$PpcTeh$xZ{e%jv@|*UqL(s1A+& zbfgTcQ|f$E`BN$peK&C2uc0=AX zPEuRx9y^*z0UiHv5T@Xq3^43Mwt77Ru;gzy`A76RyZx`>Pb9TpgG)@8HarO^^!Nsr z(H)4nP)0B81DL+~S!S??yQbKD-v^Wi{L6;H!8_fV`zOcBTY)%7zGWvs*CN63-}zuc zF3^eaLPx5hVWjbpGUYh?3eH?z*jU)1MEJq)Cde_7I{&+~qYgcy>MRa8O(6K%}~=kqZV!ZN0d9grVy&c>E`3*%46C-2dvN zBp#Jo-HUk0Jr|UsPF*@~6!88K$Tr_`(F$T?MkISrN&1j9aW(ys)6iazAUuo-cCZhpEa&(szLj>azv|aQ8Uxi4( zuA{7zFukZ{$-Y81&@nKR#Hq1irbCxycPnm1TP@7K5(+X6OEvhb0B65tLm?`KSj@R9 zvTuC-;P`j`ERVQouIsq`ucq;n&scGOd#XmeS=*BX55?-hh_I=?F1a0@I2BByPuS(o zUs3+H@Jp_i`l9+*J&!1+6*Hc&th;n>XmcIj>&Y7Wa_H4RJ$rw!>Wi=TuIld6#(Nx{@ov4oc`*p|Lph)FJ2{($Mb3yo@ zHFi~Cp=O~VR^;E}zamO=+>>=ph2@&I?BLg46^>tZ<_ z9N=f!umL~qr*KPmFL{~bL4>>Xp8j&m0%)~+1^L4$sFM~_83e{#$gyEuo?@(~4;L=! zPZMzhViAj$Ctj)bB9E7!9v2;$@cdnVvZ4Z;x1sQav!zys&}7akU3~o9x{SJoj(+U$ zBl(;kJS@W+qgVh=;d*+HK1MBdE~uUJ$b6Ue-3PrqT`A^huK4X!(B-?u-ewT|AQ&h) z01S%a5c9}+@*e(`tN-0V7ssO5B+$6;(OwrCkQ|GO#*s9PKbSAUSnn+!srQU_^VdRD z>hc<<@cP;L8HJ);n%Tt2ed46+kazwB5ROD5Q{Fa_K!>U24xp$K87_|#F=JC^DHR)} zUYI~Kb4S4fatv!V+{mkJDmc-K+;eK7jWf`J@F#d=D8q*1^A+Wm2nV%; zo!({rUncz39*#nkozwRB-fHL@aCr3_Y(EGGhpx69+#x~iyl>4qdDi77K~1?tL*7Ji zPRbNP($^2<-B@6nF>sAN?z|G)f;jCq^t|# z3UW!SF6o~jfd$MjBeFI8N)1m#*dy!Me@a?dZYdM})W6=szEi`V!u3pB5`P5xmgF^D z^XhzOv{ewC5`GwEZNJt3eT5Q3ByY+26Xc12wsa= zXXAFwPu&FE4>FP5@FWYWN5|hV0zxZy0v#`w42e7w*M^moM4##2b$Ek?9LZGGz zdnLf>uwGYRv@`t}*-)x&h=7Fl555RP#&s^dE`fMM6jH?*m(YZ?WQy~S1mb0KUpm$d z>EWLy`XD@5Q)Qg3B#z-?b0lymz3X`P(RW=+Zc1kCFnPr`g1E~&yWMQJJjb}y_bw;D z$)g^6tR;3g!C&VBXYj(`4{gmNyg*sG%!rsWKm6pp0QQTW&q0g_8g>ijM04qOu~BG~h!d>PwPgA?}#XIPl-uq}ZD0 zQy)GPj66Wk!m1)EELbE71oJ3rT3yZGd8eKcpt0?r47P3Ck$<{{ovuzx4bB48_;R46 zV8B*{6njJ$oCve2I)#5d?>rMoH&wk;0Q*q9^3)gu4(Y%Nr81wU0`ZH!9X(Yhn92AX z^XPE87c<&IO&{JAdbGPo%idOAd^9df^uYv*Jj*w#H|0dguPeyoBTGJj*P#6Ec zK^FV*pn<{v9W{*M)F8q6SVBtNwicj3{oo<@egmcXGPw0+SV zIj(*57*d&r!NCR==yfz0{1csy7MP@3musxOrUIpn((zZsVq}GdF0PGQT~XM^$ju}V z+OrOe>*mc3`|ZP3!A=ML&Jw(eC*j>xyO%H1d^bwFo-HWby$@LAIrH-cV{F>%g)&WzrI^gVF|I9l_2Op3stxl3>ai*<>4mYNTe96afQlV#OvNtN zN6gAVVEJWtr=zx6Foh*+`R2T zJY6g=SdbWA@tP1I?kIQmqo8H`{{e15k-r0njJTsw1ye=J92zn#&`0KA5K)VpL7cVB zA7-LKpxH`1sT`WP~tZezqxYh-U5-2|B(GwO(c&gAQ2 z!FL_4_mM^$uovX}^iL?-DOv|q(j_YMReYAtR{N$r5IknqQ z3uvLtb}=o3#}6ila+U$^$40j1oMCueGOn_apLUCjmeU@%fvpc3eO6MPsBVb>YU|tE zRn%7zWb&878uc<&!ctLWuQW`xPwdx6fBV4_*qx^B_$lV%?sjo|Ow08)$b69AAuIP3 zR&;0BPxrdJb=L##%o!G3DDEN?OjST`xAdVjF5;&_7Y~2RHq3UXw}R>V<;Yy!C*|-% zNP?w0iH>9({n)l+aU&~g)+ohv-4uhpIanZVl&ohEMB8;_<3!LggIV3OjUf1Ve<{n< zboFcX4qN6?eIR8N1hRZ&5)zs>QSd6J8)g{Pg_35QQdC^ zPiypHrfW;(oWA-I$+9!AFIs!pM-S1jFx5@1mQogWeauG>(#NL0?(s4n0cFyTr!oAG(5_*c#iA4PI19U zWAqY&Kr(X%;kFDnoVB^Y3&#HveOV~J0-FQ}O$%`zkw|!%DKys^SLO6I;q==xDCa11 zvnjtWl$YdZgOBnee_)QBqR}^zJ|?XYHPO!&O5W%u?S;t8D>2D;5eUJXOoaA3M z5sY8VrBO$Ba(3r1e^?nxraSHsC-?#VgOuQZEH-*GvWG_hjJ-!Kv}-7HxJQ=?fq$hR z`siQi-;i~R9YFA?ZU>W7(zJT%-c5<9_-tamSz1f8)G(%Cr#? zKa&c7j^2=?-Vl4E9jz&z2d4-QT4oyl_jAO3a8T8taL{p0e;jP^qHm^oX}i(OW#T6& zEDMGai>+DdCM2hLxqMo4D!njkAR3aM_Qqe}n8p5!E7@1YUamq=3xB)xfcZ?VS8JnY zb~b2ic_FS-+R{s>rs9=rd|b`7r5SJr=^{iXa#Eo=LuoI`$J4e7Ltety_;@j2JMB^6 zUdz__I_S$ne=1E{Mvs~4!E4RW%h>1RrF?xg`xaKRe}su7Lfh9)UJg<$$t=?MioPz;-ioq7g3wO2+=^KdSE^~Pr!Ved%R z_~jPeBd<=|ID55IPo<&=Avnt_zR|}kdG*2y#xtcHf9{aNC0l3Ny96H0WmMg0+g_M} zO%pfQBE0c}S(re}Z6ybCveIXzyxjT=UlVf}YSNpR@ftDlP44qoRZuwTkz_*Lc^w*v zf)DrNVi_;vtClk+s7pDbRiYhxYdhDw*p& z#+x|of8%!EEVb@AncY(CcIW1z@ojLw!Uf#`-U7c!@Sv_4#k-h=?)LL;-s7Xq zd?$+E{;hj^x_Wj5`)tXHs#*1NRQ04V5t7MVf2!%@eU(rMo;v;x1I@A(EEqHf!VVGH z%Lka!!Rakt(3H+t&mhy=2FjJR!^OTv`u}3J34$oNL-|Co)InQ=d(>AWA+yD&g1Jel zqpedRg~FflBf?l%(VY)+km~WmaH~o7ZcMca;yC-j^a<-B)e4qOu>=<$6i_PRSbqGBevOON!M8(EN23Qbo`ZTsYX5F^*-y53jEHRMrUE zXkHAs#|N(v5bE#``}hPui13p2)+1gX%=iR9DUN|xkVjq(h!(hJ{4fmID^`=QiOG!7lS>aEL%W#j z4%2kR&RMre*;Ipfm4*h9fl#s|%@?SV=`q@bNr>rXYKz5oU7)p$#_Q&u3$%&pRYGPvL-Sh{1oW<^ zP)nX}+ka-_m8KWKmiZa{wvuOpYN<@4fJUo`-lQgt+BDic0a-jQ77+f3e_jU)jVryq zAmAFRPy()OiXA*SN?V)HQ)kP0+BQx*V%^Q7bVt*9id=u5dh&GVS=A#~${W5weF~7M z<+gF^iwTE3-PO&JJRR7Tr~X^>G!XXW$q1L{X*gWb)ZB7?ou{t6u40r9ztBBSW~}zU zrcrV(DkfF5j?&O#jT&odf3X^uP@Ni=(sDHh>1}FUMQhdQs=!Y?0T3F|fUBV#9dSjR z_chl}{6I4__pUs>dw=bFdpPXjaQPU$KTjWug)7GC!B|)ur-x!Kqx8{H`b3^S1!FX| z;D1c$K9i>>YoF@R)32QqO?*N9{>E47`NwES%ggk9o?eV?siAK?e?=8%Xu~+=W8*Xy zTiPEQrSUvnto>@9Ua70d)2n&<#wh*H#YmkN_MD;D3gfAkSf2hcTwc>aU-CkGe{xG@ zN99IuU3qh!{vvj>uk5oF8>8>%>F-X{_9fmGi+v{!cIX?uEA)dMi|Fsul_#H|swLiK zCr+NGMNKP!GCIyte`MK-CEh&!Q=Qg4Z?P{=KLX`OZ^xO5FNlD({~?0ZX?5jI=cu#x zKlAi@p8h9Km(NDd(E3R64x{vD?L<-f05hgd>h>1{JP!aa)I7?bizRF>5hMq%I*-g? z|I5u6X@wY&L-d*&8)2yx)S_S+1#Y1>Itf_DhXJppJ_XAtfAC$@uV5JkK1BB^SVn;@ z{0c0iz>m|@3YJmeXX$eamQmo((-##iqrflXwIr~N0$-%BD_BN>zeC?uu#5u#h<>bK z83q0cmnm3Azk7)ED(FAlN3#8J? zIT9rN`gbQVe=ETkwqxbB$rTN+>FKN%s|Ag|&7Mg-0{${>;OYsY*90~w$S z7YSIf6f;54whxh-=O)5y^qT1Mlfr{ zSR)_T+#||1L6{2IDBCO?Vq?5~|4VRHiuE)HxNVHr?ho*K8Ib1!d~;}wx5UC8b!dC6 zr_RHpeCruHir_r}e1JRL9p!bH-!Ai>OSC0)iP|N=>dN~OV~C{caGrOB+>q)KPGL_d zz+E`!e`S=fe(rAGEm%(vezO7?xz}!VOgzS z7Q|-pD35rPi=05w@VHS{M69NHZcS7n^Exe4E^#Yrcr9FF4P4?jc-p<-azEVRQ8>ht zf1n;i_5U_}@`rGqH>rxzDRCFvsh1Y80ooe*2wU*fr^%=4+9@fF$~zxc-idp6EAXR5 zFrvVZ7r|W${A3aAQQ*lU81^Xm(Mh3PraaOc^R e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 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 delta 40115 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 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel + +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.jar b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 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 delta 40115 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 e{Sg5G5zENPNVU~b5#<2@M#Os+0czL&{q{eZe&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index b294c80..1fc2e6a 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ coroutines = "1.10.2" kotlin = "2.3.21" ktor = "3.3.3" -logging = "8.0.01" +logging = "8.0.02" mcp-kotlin = "0.12.0" shadow = "9.4.1" slf4j = "2.0.17" diff --git a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.jar b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 z;U1F#i!+m#VJLq=6g@+M-F~20QBYKLRVWGDjiO0|!~~_lLk*_2CO$R8?(KHzer0yI zh8X!F{tIJ*MiYO4KgxKwXpG{6FEew`oOAEFcjnvo&tCyNz_P%*CG{>f^#UBFoW{~#f+`h2kcG9g+E+%j*^rD4HpH^#Qmg40?W0tPFBxC z6>XrrFZ8O4@>i*n{vW z9C!d83gLqA!LmR9zwNK@k52%&fT@7@?e;!@l`GU6@`YSVUCNo%P2F0Doo&3Tn}V1J za)gn1SYcGUBE5-y9p$n_7ilJ2qiSrG9d{6&UoJ3bZOH%qW$zq=SfM%_CEi$16s&(Y zOa}^)Z!yp3i+QdJ8sysqgn;Qo(+5r0){%hICYa0wEF5Le0o#^BcJtdl{dKo!{n3>k z|4w07z~LGP%p7`?-L2N7yA<{Xr1V0%?|5NyeDcU(4^kLIuw?=VV+9H49Y}rvP)i30 zE7W3A_W%F@ECB!jP)h>@6aWYa2mq4}Wk`Qnd3;p$wLfRJJGmJJCj=N48AFuGGKr!h zCL#tBATkNa0CCvj&CE?QGBY>M5{L^`tG4!8^|iJ&*7_{9ja9m6VJ4UgQd_E4yJ$D7 zeRi{}-8Ze3^!vMaCYebl0pDMbPe|_l{mwbRvoF8<+=(ZS5YYvu)0pntw{O$(>neY` zl;CbP7OH5d2zFQ0Rs^+ZUpS&9!&=N6)j}%P<7z}z5-K)(m4r9gs|I%`Qqe?3L$?x1 zsI?V+J>IC&=M4)Qs=D;T^Ofa*jW5sPcc&r|EF^jr?|A|w))S7YYCIh4!D_!6Pv9)9 zFRwelZn-z4_E+3sCuWlUS}Gn?*Mxr~DpREv@2T&JE1`&5zbCHr^{Mgtwfbv^@z$n< zV-i`IW?rrIEAFTs>uNQal*qp=lDuYHs4W{DZ2#(ur-zkjCewduIA}GL zWk}4lVA2ueyCCkQGMUbxSxj@Mf|6)9Qz^*$w4iQGC?-cVrY7sRZ1RE7Tyn`YhvqRk z@^>U!z+_EoTQ;>$LTd%unY2izh2$G;UiIqF)N3fuWbia(%CXCrgLDG zZWz~2o&u{Ga1vEB+0<)N@G*a;a*uDKSsSaiIjEMrGSyHWY-Ml~*6Ib#`i)Am7e+jn z$qa_zKb}G%ax&$^gSDk}zD(!Q1x(J#`w}e!OG(Y}$T7VDM63XNIbB>z7f}PaDdJ`l zU6S(#eYsuJJ*`>oUZbUAp_X`Di%WEAPN`Y45?#h52}cA64q9dCZZ&@xxg;D5Coi3# zn=zMmPz$Y*sfpGyo!%E$`;>StRG2mv3xh&ws(hysag|NFD?|2Hx?CnJt!Juv7l;zI zK{|CW95@M`nmvN?4YaY8+UW|WdE-oOO2v}lsM@kOsP-9{ex^%TE3ufCbcfWW8jm8Y zxPwBaeNdIVTZ_B1$Gd+oSK{vOxE6H>5g=X2W$q*ABy9AX^Ba}A6Y_X(+ z6k+!!>N0$xU5Tm=3K?tAn{7wk)k?h5PCW?vy1uvup_5@XVW)pE+zG~yC?b)@6A*KG z5iyH6P%$ZYQ$$D^Wm!^cf{`%NSTw4{LOvK2 z2niKokrI?P%G6JL5M4?nqV3rd+a1&P#5U+!1r-;lNVt+0X;?@2`={N{l^SnQ0v zWA!uulJBGUm(Xo=JD9)5PXC1zd`&8>Chhb=tTfx{E*Lj4kVvXguQ0Kl{u`mKlSw7R zk$PV^fm-)rrbfS-Ot=;I6NP6?@rU_6}Fk+Ya9e2nfDybk6vx6VORJgy8N>wX*>RuY0Arn5a$$IuwtAovM- zK&JcYeWp-{O>g$a#d_NThC`w|^uTI-p{aSiOoi4c>No8>1XQ<{czWl*t3;YBMbh(Av+ z$aIXp$z<|+?euLX?@0w|>IS>noFvhUA^=WR=iim-CHfv@^m@1NTCuanPCvj4Y7^S2 zgoA%x7Tna(k5CvAsjfuUy~{nVMRWD5^kV`2zsS2p2Bp3c2_t{Ys|S>DQpT^Y1wVi$om4;&> zb?=65_zaZS>Yz91_d-{H5Wd_xl{)_mM>u|$hCWm7rRs$!n=Zn^y{{Y`NDcN7Vo zTfwZ(>pzjbDp4CmF^4-fhZ7?HLJoS%D0BZps?K6~cM61m=OzN3pQapUwzWJV)2Jw) zr9llHNjR2RuMRjcXrYCEgiTCyCW^8u6^?{ZeHmjFd+ltK*(%x_o9L=yAz&62e+qvx zjSenh86>zA`6HhOTv}5k)JhI=DfqTt2Ug;_kWq`ZYuVnw!SjTMkMVp&zfLD-j+R)+!3#xSag5ItsT|t5 zPt=R1hbiP`hGW;PWgPkKse2XD4&Le`AsKZ#I)E`I8IE_ z9I|Ku83U82$k4EHjHDp34qA%{XS~E1%>8<2GY-SFXu_HKWl694d?~M#c?ExCqH=mB zY#QvW5>kob3JPk9L>!!5S~J#3)`?ECPVXdn9gJLTFfCSqmh$C-(E7qrSC>KJHqqJX zcMW=%=HLzJw7H!(B6}CGDe)#_oJ$}+#ya1LEskg_9K4ygl)w|WBG_^P@8By%v_HfF zkp&Yi(LQn5c0?IhGsY52B7A=>;%gVe2n(H)s!N_Uih#g4vM8@XK-<%!MD(;aKJGB` z#C(HQH;T7Anu;XD2xPa>VAa{VTV_?Hl|@;okftWwVyx>``c=0Q8!$itiD_oZl+)!F z7-k*p;?uO+Hg&Gs(AMJMC>noQj&RJlCCO=i zfiFp z1Fz>B1f6~8af(4me51@a2~TwuQISvU=@G&6UQzV68P0yI%(w7uOjmR?ZEA0AU+Zq| ziJ`R&xr3=h62r2gR=0m}c(-tPcO-k4gfTkS9qvg9*l=tTT!Y)r??)>R(VDsvS_GrL zetE$k&<9q=WMhtK$owCqHG+jZ#YN9vRF(#XeB2r{85L)#60+clVFhmwf zdr8rBGf{_z*dLYo9{w24G^AiEdexCVYIRmp#Ypcw$oG{19TR`f{31xrm`5X;5|a26 z#XYqcRf#e5oE}q?d$joO&Ecr3iR8>EXP@N#CHx>`teFE|`ys{Tq*vpaLe^qq4}Y3J zBl81{v1h5LnAC=wG#0^aHI(;Rf&R!$LS~v1QKDTTrLypHsq$Q=JB!kuV7$g+S5VWi zG>y6&iy42c3T%IM@aOpRGFkZxGi;18tYZA!aI9b3t=9W=N!rw;(yau++knK6BQZqB z7nq*UPYhW+VDxGsqcSBbjl@%=)J=sbt^)pVo5qpT<5o@HU9ChS{;+5|`5+&X`AeLJ zN-|7O{J*l;yS#ebz=xegjH$FXyYC+FM%?21R=@5WuPc9gvOzidGSj>wN43ThNhnI< zBZZd{V|@vdndq&fU3x$A)a1@%k_RGkz9RE6ewu0Lw1GFR&Q8Wl_9RsEql}4I4#riK z;%5CG=HlrrT$tr1-fQzS{H!4PoXFeZE;~Pu*a%}BiK}{SIQW}J*8Uc9X^}%#X<8EF zs?sOSrq6$NNE7Et{2iHJ6v?|J0uIGdNM}`rnv5w?@c}3)WZOQGt?%;p#HruUO)lB5 z7y5OY4+;~;`JuRCbZ5V2_#FI-_~NmcUqx#(;Q}s)fr)w6SbLebBQAOJLn?0zy!?cJ zD)VdnGY2Wg(=UW9+Y3LqOo44!?UypY%)csV4>y1J!hk3yzd@f6OvT03sj)Qin!{KH z8^7Z>Wd1Gx9^xg$C#6^tQ*?n4^E^{?!GGjG33N=kXTpwk*^W1&q+-EdbiGCl3M<K9MiT<**i}DJO4vy=bv^ABKiflk+7I9JIU?4K_H)GTQ45mxi%@MP50$ZoASD+P*~jPbfxtE%J@2AlF+P)PkJyv!X~&Ib$GM5 z0YGmh=EwF_v`dX=S7we!nJ#I9z!^y-{+WNNgzWgwrV_lpfORwe2A$S4%}7&un&zkJ ztbi{~OPp0{svo54nqj)|Ff}syhRE45LQR3Tnlv?MXkD#OZ2Arp29d``Xmh~wBuRnw z<{H0qYxOW~%h2|t>&1F?hORnFCLDA+1!yPDr%LkBN-~*b@dcVJqj)t*v_hiA#1en4 z90j29-b6G?GH}Hf9%lmq5Iaq!IyJ#OjEDVIc$USdCqp#J1tCG*a-g~<$8!+>yPdtx ztJ4(A&^2jF8b7`f>JRML(Vn5bmP2&C^+~D;1kBETev9))f0}M_)*PY_YZY> zBe!xlRz4(F0?vB?==|s*x^I{s9HD>xfdE~(sO@no4^Z@pMr|;K^{h2G$^v7iaupFR&F+j_$maBjCr`OW- z4}r7?NN?&$Zh>SO2X#rdaj=b#)7$saTmZkL1KWnEbc99&XdjMxfdeh#VA>>Q-BoTLUHC!TR( zy}ZF{U1l%0yQDO`_MbTDvX+0_EmsLq%k8?X4R)Qby^yZX4v+!kvNwRj(C86Z>iPn9 z1@WO1%G8`?Ayx{MG%pa(=esO|twkgBNT5B#Zs*-;UVM-}X|93stcI;=t$4~=+E&Ki zG@lz-Cf!fa4PKX~d0EHM=u3Dhms~b;xg-R!S*{Xhwsji2hlFR>l<|M^3^xvQQ-f6; z8Sr+xtQl@j^V%|QO|#E9;W#<)>aq><6&)^1z_|}=;H%>xcewDdZIJvfcxzLG&AAWj z@IIa8otB%00~s$@Sw2N`TsHm9oaP`XBMl6ZI>Kt8jC(TNd(?QmT0B0^S_jS?=7fHJ zx!|?|!T`r5HNa=QWt@K+=Dkzw&d^tEpn|2`t|6>0X9Fw_sUfN^=XJ+PvJ8>MEH)cT zTy|GUP7nGDV$SL+F&2jTJ;FpckMJ#lcAUS81 zPxD>1Y5ve4HIDE-K&(bI2Wm(7CiwqHGJNkrzJL7)KM-j1Rv&-lhj7*~Kirw&M{8ZS znkRUK=!<#DvesY5Pv){EvYDO}`7T;8O8ZGNa-jaxFVTL9j!E=1(Z6Y#L^X>pIA@fc zBCC%gJ=%-H0!)Bc;_oP}Edum<4rmk!vt%k7EcTm8o@(Ft5kPaM076PO0M43@(@`oV z+t@Z4n__u>-m-s0kLVkq`3}_!?%t$@LM7}UrHw)#vZxu85ZF(27641J^bS=S8<+7Y z1@jfnw+L4Cx^tc~P%Q9)Ocjn)Bf8!GE=Xt586$010H z9JH5CqkB=PK29^}C7MaE&>5xya++?UGSh7|%XB-Hn_hpV*`_yWj_GZhYo1Lm^L(0T zUPSZFwY0!|F)cK&p)<|9XpuQYZu7NtmU$mln2*z9^Pj2GGKr55Bh_2(q;oCzKn7V1!A6;6JNUK<*+%$ipt=)Yd@QhD zB(MyB)mwj^;jhD))BKI~BK`tx)n)tw!cTYpD#XCI2dM%mF9zB&{1V=O5NJD2Gi#4n z9wfQeytHiylXhF}aq^Gw%Yhy10r8_W|F{jVzc2vLA7xv=DXSaK08xeM6n?`!-hjoEMFq|d0-FZ_2|Xi23zhEB;^88J~m`E|L- zi)-65HN2-1mG2A8Fa0(64=-N|l$Mq+9XOb%pp2@65sZ#v2sH;4j1|?Cz~BMD5^CI( z`DX^WVv4I;!EhEF4#s(%;cgBk4xqYnb@hVD)o0Wj&zOD!`e>O9u$Q4wrdp z0RRB!0h0km9FyyeEq|?A31FMmk)C-veo0mmCyqiCFcCSxhisEToS;A;b`oM@I}j(N zf87%;Q9Kw)!WgJAbdge#@$VTGShh?>19? ziz18S{fokj;_1PmL^763q*G0U={^(v88d0dvL*%xV%etnfEnMN%@1Z5MfzjOtQlT3 zw5w?_Hq?|58K${>#aXdc;LWTm&hO7Bljz6}#F~}~OKMjlWty2pY8QI)sVmfF>_x%X-_o-@eJC;zGkN;bdsE4DtdFU-65~31 z7_2jfV!45}*{nI(n-sx|D)C=j&Vxw{%zg1>KAYI1H-ED>9yhbuu2?FjRXeX-LL!wj zGpSgzr5}tf$#i@-tkkl8+UXGPJ~xp{eriEJ*D z=*^3NZhuLqb4;7+I`!En(k-&g>dpyI=*fwbt*)=MKiheh*tA`|8rJle%Q9#Y>}&4B znpwU7%lx#2milNhoj%Fstc47!V+!bA=$CA1PbZV`L};2dsDa6A4i4ppJ0Xo}PF;QH z1gG?^_EVUeeAGzIU`?V&RKU8k>*_C`yhT5qNq@^ki{(tSri>YMHdD=n=(U+lOs{EB ztB+R7!Br))>k=7gmd*_O=^SfA5o|ElhZ_*6>zsO*R?EiErSoJy9Bt-g#SOZE$w*|^ z%kKQtMoX(`EwwXUb)hzSsITnILT4<^o)PLxo7qq*oeRa&sa!0P3dK^xV6${enAzsg z`hR^xXqbJWTsqXBNcDxxeX)2hIUHJ6;u~)E(0ZIte>yW5gGtY+JO1b|udtWnx%_k? zZS+w+bugXrKlBxYHZd)JW8c$Prprg2)Xn6~CayKLCw2JgV!A{OwFNhKT0`0P$-)fj z(BMC6rL9rn0)JmJ(d(hh#3P_@eFbB*;nqRT*iaV~>&eA3 zxcN(#8FYn@t`zU8pKOytbOWybp;ov{4jrB_0emmsElj*GKr*}xgx{hvvoIY(_tb~Z#=BIbkZ6f4fnNFH| zJZdba@}W-$!@Q2Y&>R0R7|! z{Is7gk$`h2y2P(j*!U@R?Z?ly6@ieu=^oMLLrhK6yVEo??~|Dy2GGf+i@MIOtElSz z^bz6xsN}tC^1yd~8j-+XPahWp0tx0|(@$DC<5NgKaP+mk*>p0WGsQ>z^q@#sO#jBp zeW~2RL|lW(P`ba;Z4LFu;D1Sdr!7q_O+|tCD)J1*hC>6fJ!YuaG*h8mY!Gn>L2qv& zH_*H^)t*lECo+Sf+(0ac4>NQ|`Q)B~7;bG(e(;RYP$rFux#18($FQtrMYbk8vNhY| zh^!%T?@%I(NRyE;iu}|kQ$n!}RI_6W45pW}r-%A8=|O~~Tqd8Dkbj)j=(SlkRt{Q1 z+cL>WXlWL`wwzFB+A@*VU5e>NpdHb1aA|67Jck1*>kioimnO1_TxcMd8_Gsn>~P&I zk=q9D6Og?{qNf!Zwd$n-Ih}Mr&MJWw%FTx))6s8Pt5+NO%=7a#^wVo&+2a@qhRrAn=5*ZONx{i9r+K(6mF-!&6Ylq}+MPM~~2>K;A$nJ^7)b z3<9Nz>oUK5M(OJ7NuxC8qnqh5;3&&u0e1vPO^);Rmmv})H5v<)AlBsD@Hu*1eEA5% zOoefSKJTZ)^jRMe>K71j@~LYRLre=Rf`ZbjmrlZnn9*`sVt>d&n@?6yQrqCmK6;A2 zf&gfya+3L(f|Ky$`c!_<%xEWq)=$&dg#YW47Aj*g=$p8>sO7rS8FPKo9E4Qd^KT1q z`xbo%Q7vWe%h>}{BSi@_JVW0T_U|Jv9k-qJP;=OzA3|fqhi*UsKmAzZ!jI@##II=! z2Z{f`m220BD0W1 zeQ~hKmC9O}y8=YqZc!bWcjaxrte@=Im63L(nFbw$1C&P^*ul27nQPg$rDL_9iP=lz ztdQeiqV{AgD|ly;=ju+dI@yH^mfgi-&lX~^$8uMl#@GjUWiMAja*Ky&;8I{ZY~N?@ z+uT1*ynpKO^DM4LvgFxJp*Je34F<08X7jySJ>Aa%feH0I4@)+Cc)kF>j*5VS1H3>u zPX-b_L0xZfEp{X~XIloC^whe^MysD{!-X93@u_?oVr?$Hwx_+LqsP{4v1N=Us1Lf< zt?)3aU)Q#+8=6*mxX!Y8+i*_8(!5G$0oLLMZhsVw!#2JX2*=GpU))mkL)35sEp3Ti zMR>)_a9`^>EaqxH%g4+4Yyl|mmv618zsp^s4S5b#btPl1;&a3`aQ&+<+_H9E=lY%7 zde(2*xp8yXdJmr~cS@UYTh`2MOiOf`Ii*bDHGIC8=dzT!7jM~o(fanS9&Up;q&NwN z6Mw}tud_JUPtneDsS7PdHbM+;s%Y%zi>$s)R-eV!W%YGe)A!)R$=G0TUu?<5ty^*? zQ~ZQEX7a)Qqc_ygm+%(kHtw0_Vw8~8byFCs8M$oHgvAr7J?Y(MOQ%-2%gn|4W7;eR zqp++RoakVBy4+9fd6+Sf?%N2cg|cKxXMZ}qJ3myR7@Kb5*5M)Z9~-omJn`K6<444ne3<(Nek-Q(KjU&EBa2Xp!qd%@aZI|AZ}RcA z{4cq#1$qyAkjuD#~}1xm8kta(PuzC=eQ z8h*0;DPwb)A`igy6N>1W*nh~s!Q`?@52FeSPWwP_@Wb->mPWEYgp!9JVO${3795Av zg&rQY+|Pa`^7CVYrf=rYpc`h5n;Xnrd_cVNM3F?^PH<^7uN+8uidve5r5noL>plDw9JU#OCg)+4J^poNCAWv4p7I1T?Za-lTYg>K@*5M? zSt+_6S8nmP-Bv`9tkQ(b$Qz?N34x(PtyUZk;#!wyj7%27dveHlu}ojP)y^8~ zWDAq;T!sB~9>;IrpvreB?bXob!?d`JlyoCuTs5{s;;E$P9d8h>HobhcUUokulUFXda!6vwnn<_-q<#Ir8CQ1Him7VtyXx|S*lgP*>{%8g;(RM-k!cO{DBB z;8ATw6n~>^(4(V;`e(bG>~e=sT_KO`PJem-^r)Ro=l-vL%bP4ue$G=dh*Z6R zTazUY#7&kWLQj8lcx=(gT8;{9>+A zwttdpTM$wz9YRh{^o0a($XK&S-ElZ*=m=_|L+d z8XhBDp8Zto{2Uq4O^(K%IU5?r=%P)BsWZwAqqO-TSP(6o_m=Z)o66&OjG~I3pnt{a zTpW#dHO#quly*SP{Ztp$E1woVOjn9(JJIfqb{(Zz;m4i#kvHsEK0;1@vRr=O6#4S4 zf#sXP1+@>KG4hYY{tAEViN;|VWzb@~Q6-HPx^awV7_^c(IF9pj2sfI-!@^@|o<)nt zY3;=P3-IMtIz8*$FArq6mJuAoy6Cqx7D~TV0M;cfcKR9iZl>fPed}*))Fr z7=17rF$#1SEL#gaXBJ=MvL{Q%?H5!H}Z^A zaMIxQ2EZzYUeoPy+&Nci6cXPpr#zFKWizyMvVc*^z*sExKZiDvfvp}ARb{?gM#>dZdtf@Wa0EHTBmq(m(4SyPfIHw(B^u;^L z<#^ym2dw`S@IUYX=Cig3RysxjgZ`cQY$fv4oa&%&9Kd@p*Ot2AuTkALt*m`)>iS?`OM9}>Mv z^T!d?omv3;Z5f6vadSziQ^JeA2xK`YMs=i`;%`3qSsy0c3OXC!{JP}z*XQ=B7d&NC}fQBq5?0CxNGHS|WgU(X*XO~r7u3s>t-S{BwR zZibcOa0DTVla>}WeDx^rMqn+@D;(i2?jGapT+R*F@SdAuE1ev12i;FnkKH@ZdB@$f z;V|!uMt|j4uE$>ZEd_p?9Q)g&UC5C^cheZ(ia)dIshh_5-6Q1N6m)luP$~=(L9%!l zw>=hgAEh(HO+k0VWBgv0-Mt@kWc6DckfjgGP+1>$9Vse~9oO&&^^W%x_^ukhN9<-y z+DAj!R-!a3=)r#P)%(T74^Oa`7>sEcbY`jHkAF6d^2d+R9NcLS&p z=@zv^(<@a>)40lOx=-CM)QTf~9|gt{vJeswE5;4>8ax;2ge4&OUZc4@j+;7lROg%5 zX@AH=AJh4%nmosI=s_KEE+Fsm!x;0>-|Wmat6V@arCA&@e3M2)TGlDxVLrL7<|7Dq#5knfj}y-uo~ZLpyvvt(XH6a zcJ%JV>{}r7V+gsQ0!Vxax&MdAQ$IzD_&Kb5jH(%Mp6h82FGs1h0tdU50z5$T_-Q(c ze@F9GHw976El_vT$?7?*H(OpvY;cgn8UpRNHipOeQx8SE8={BkOoyd)U~@NtdrY|baB1iW_Jy24Zhp`P56B}M476s;+mWS#T7%vBVUhOQyCfXB z9BTqj{mnC*UukvLHeiK_tA>w6+=8|vhNIPU4^`Fh=Of+`LZwhU#!p7P^5Ju7JQ%5R z1id}Zps%NfzZ|Rr7L0fUKnfDRqkjPp#?S@*0B>$u>Eejf*=hug+WYB=#)ha4s6Zxm zKy56Kr(d0jrvRY#&UN(pnixkXr*9U`QY)yHzoVmVb)!tcmLkp(0lAR=z3mTSP1#(~ zSsO4!eUIJ1}gkJNv<;F#!P9XX8G zQ259l@s&9r>U6M-+GjDL097}ogGRq+&`EjvZQ!$`LLpZlpXjI!d>WBik-K!O(l z362sR=3vnEF#jruu9ph@vK(X3d5HfQaXVTKcdMsS&-Db1{j>n!85rd+tw{f`wt5?z z0!9F*`C3?)zBsuSffXCWQu{^>UHtx5@Wje!#4F`*tIyF|6{rgM4u8=7f0#O0`04&gz zV#Rq8Oh?xUd9g(R_@MVlDRM!_8WqN-tqWNpTItk2HCzGMU7dAU6kY$u=|;L2X+*la zkp>CrmPWdpB}77`hL+BSmF|!Z0qK+uk&==W5q>N0^Lu@H_Mf?~ozHcj@0^)EJ2Tfg z_pLyE41wmCXXBh~1iNlm_aRUqxka0LL>ayNDg%9WsQt7ra=i{+sm+J{ z;!?0&y#;hBP_I00gLY0{Bj$UI@T=)?u~G7wiA{uO+F8L6v4U6bQsuLuEN7Y1G<|q zwgl0mq_^tWI`j)JR66Mm6w%4Q@|BSjjeBO8s5#G^IeN4f9~E8N`;ja|cL#Q*RBO` zPAWZAr-E6-Os-TOPQW(pYGRPZKQp7n@?jfe^|;*zbvr7ZxP90LY!ax}7_RgyV$XM( znEAjIlImdysRI`TRl?BU;ArwW$2?n+GSJNAETJQ&R2eAiLfCN2X}9 zHdTj ze`0C@zU`}?7qv-J6Xo9)YiEeKz5Koq*2v|SaxboPC7F_cBj?qxEfMrdUIL zf|3akmgbP6p$j$=v%C@*_H*8;%aJHQ#Ag<#`gJIMMC{@iw#2f|sw?w}a}fFlm2&_y zeiISDVng_cJKf0Ih$b)4IKg^Lt$rdViIP(&^on2x?)Rv+uBPNco^R}P;lb+UZz3zt zqy~uUI$epfzVGz-Db*#YF#df}2VQSb z$0%Atg74F=W=q;Cwu5kS(KFJY(reCgRlXQzTA&L@JSS<0{5ixTi zALgENDz#f_p*3ZYTpY0%T zwj01k!AF*4C&4&YXx=dW>QojCzsdbIht?(!+9rUkvrzN?y(0m;>7#lDp%TrN^?n=v z1!1)tWBZr!FHlaGX0XM>5fHZ`ajq@&!FgsOT2VObz}>t0jqk6V1;=&&Q;w>ZVzV?HCt zQK@A4dSv@pF6wf5#)RMLbdf|FPrGg3TlAV4L)i3z)m&|Gys8qS6mGaF1s_+x?Tvo3 zy7iV?zf=Jy1T8-jQ%Zx-$cr&qaUgp)Pb4aGN2)Cx6VJ#84u@g(nUR8&=gfYkiBw=9 zH~?Y3KeTiB^wjEVhtJAG-fnpDJikHrk`}O38qVe}%}FD!c2Wd9dUGguZy+)gS^G~$ z7af%kActV9>YPuXb(>KqW}nNv`MhxK+`c@QfjpORYaLrytrYb^$wCL!lJdx0Y{}N) zb@W_?KXcb~g@5;alvPkzItZJ=%{i5fNM@Vf z-{o7YtWg>18nSn^R8Qys3ZEaEjV)vqx)cz%&28`Ie50p7+Aoe4a|G2oe}t5xb31j{ zIztiCJ+!Ba45Tp^M7~01P*E|%;vq@`L-j)@=-QEAEfM~_r8DB{(`K`|A_4&rm+WmP zJmg1aeg_v9lvDf8keOA^OAM@u?(zKpEIE^Qa2+#)O_~__&!maqd<`&rLmhb@iD6+V zwmLfT3l1M{Aw?8Mo=u}%)_SP;72N`A;CK5RY5Un4oc5oG&c^~*=1VqB^hQP*^^80= zrtN`3t1BIMzlST~*e$}=2YVuvzc^dSR+MAb626bI+tTAM*5@-6Xeu$ZF0)QX8l-%Q zc8H;=)BJw2Oxn=_-_41MAYFBzpTg za@{KL4nTow0^Fxd+2)aT`$Q0|<(5`J$0p!=5E9-Q1Z|VPM{?MEfg3AYrM?-%k4!q> z+TZZ?Cl}!$K?S5h!GaCmYqD$DDzt2jQO$X1OR4`{Sk)!1U<3_OnBW-aeD->#9c++u zN2+}4qbet&Wd>fmZi#+rWVXZ2YGN)p$NlOQ$6-}cn>w%q@$0Ivlf#HI%SP8 zHYrs&&nRbDn!0mw4M}kkBW}JW|LRy()Ev~ z-gBF&=4WUNtt1<5BvfwS-Q}D3rnf|q+F-Ks!?S?i8&$RYQ_QB`bB|i)&yY-PP5Fc0 zLNO_JuPegUZ&O9Etf6Jnk|l--{zLSir@?1;lEh%G8(}PT4FKF*)ytLOHbB@xv7(c= zPC@&N_rR3As!g6HyQPKIaYxv#E{NpDKtnL(^~DytdCd*p0d9UoSCI_)av^-s^J&*T z^rUT4pV>~cy!gd_C^i3(Wusq)ZXD>9THS~NJZrDyhrsBh5vP_CQ z92Dai*pbra^_4a6>V-cGe>iaz8Hbq_K)l;T%sv-3 z)Lo7?Z!a~wZy(;CUQ~9#FLgcc;c#9_ik8rS(&on8R#tDV{R)<|V#jX~J1kSOyG1cl z2BuyjsaOliHOoT%sbsA6Jj{!(YWCFX; zd)rXx)3AxYE|RUflYWf2@b-9Pa!8ZQl*ndwOvVhW)UEbFx7Pw@nwehgOyZEEYpmgO zaH^wx6@En5`sM6Z?D9n`-;)G0Qvbd&A8;4UC39ZFmx1{uei)YA47&8Hke%}5o=;Ax zTTxXm>I=>CWh+-GlxZ{{{S!(-L(#u{SASHEa(=-~-Vg9ScWPcXQ@Gu!%U79v+eBBl zxnB&v&YHp<@%q&1Me3C8I#>Eb-Qk>G_}Do5al$+aQgm?dSXKes9~gz$F!$C_}9+V6vcm`5+Z_>tJ%Y&_F%AL}pn(MB6-1-8d~iXKt0>pM&E%eM7+k5Eto zj84o~R7$k|^sT^r;T#1cC4*v45@A}K){nHznhHL15zu17d~AP;T$#OHZVT9p)};uMMtIBGGIiUuO;B9?mVl~I;=7sfZ$(s|$@j@CndxNv)W8n4z<5{a;OznR zoyga*UVIGK3f_tdD$-2TowbH&4hx3Z_m*2GbK7^FXU;G`QytGAb_^ZRhntlfk+AJ_)TpiAj<>b*t6!A)DlY7aTd- zKiJ9xo)0#j{}5sTe-Ja2%Q}c^=ObePM^nBNE%~~-mi|2Z?boyJ@l$e?+xrFKJC}5~ ziZG8r1K5vD76iO169j`P`iSmg8T`X*1gp(~R-$}d!xUCG^F;LwL3kC1CwfB6Pk28R zCA6I=K@TgwBPlh-rMxG`fbR}0DW77jp}|dMF%r8UHPt%VmTaeWo5Ja`B(eq zFYA@h0uli}k2?JV23&6DtGf6Cctyc%5Ct z?D(lMQk8*M)fBgWVY8g=_`b+7X?IY%vwf%=;W^H7*y|n~gejQ@tuN z^sBtbVzu#{40BM3>2)=R)J7*~y%vKg5e@4Zkjz5LUf-0m@SJma$({_W{D3l$=z232 za%@ecyTJ^vry7jq?PX6qCX~1;YbBYEM?{H+Igo|5tS!_E+7*g06dGZ&IrN*2z@&Bk zq4sRtgq8@5tikN28C{!1T2W#6dM{F$YpaQ1QDk13tIwsL%2=?V`4KqwzR%oUEhM26&jv6-2!C<^(+mQh?fjWgXfq7=>FZ?Va%NaZyJr~XBk;pKQ#!pC2nft00mr76pVD%OB1kdr{ z&ASun*$DABMYSqpAIeDMFTA;oe$_IOWkdjmNKeAP4rR~HJSN*S5q{dZ|5K2UgdN(L zQCu_@muGnTPRaf1wYVQ%3y=C2X z5|W_?#?&W;q_AUh>pfGMN>!iR`0WpB;*7u-jD7XABBK5brh$M#ia1{_Rb zi4_S2%<5~dN3u^uhjwB|HB=*Sc3vSKi z$z3XhS{EMy@GELa=sOdR9#IEMCBFu{!xD4BT^V*nILb2MB;PTUz-J5oNf%Dx4V3bU zq8y8Rn@Jj0FRS9+Bdg2KpODdtS$8QQyB8A>vhnEcO?3?w;j0*0^EX{9`Fp0~sLd^D z*GOaBN@oc=8t9Ldb`0a3jkK@s<=ohu=t^XFxnr&8h_m?1vAP>k6w5I=XKn_GhLezj zQ?vvISB%=%a8vB{kvX(8OqwH( zL!Jol03zlcj{m{JhM$KwS9QZ;npliOf{%jw3AZH+1X0 z^awT+8Kh~?49~DqGP`Pc^fY?6#x}!TXkCxjq$c00tn13wU6SDCt=3P-$U0zo$iJO8 z>OGgRUy2qI;^JI2nSM7(=T<^W{uJr&r?y zY_rCmc*s^Rit7_uD3M$^u+l$tTkFHT{+m?EymN{S=SE04e47sNalIxa-&w9Fp7IGb zA(=Y-bS$CNjEzmA=%79h8E=hx>a&56f^U<@EwV%7B+3gjC?$xx9aZqb2Up5P`?N*^ zCAOkMs(zRX{#?5X1#D&{if3rqYH07lB~ShOld&F467(TDVCD4JbUwqo6UN~KrJ0$S z+em+v#ANZ}kA8+9nBDnoi6Rzt)I*aWNXulj4BPKVoPBdQ6_>;KsYKz8oL_ws2w6Gd z7sRN-Q9wGxHecfqr)5lO0lc2*<=*7JML3GlNhmHP6ozNg+kTST7L)2?{F-1Fshb5M z=ODBD=P^yxZ#6bA_=6$qAFNf4Nmagy6n1UT)h85H==pue3hdIoY26;bONi1QnD}J< zVp6TolPv19bs=_k%3I6v{ghL(gs;f>!(^5D3hD1H5Je>r{!H=r3`gDQJ3@hj8wOOX zi;y=__Z4V>%W4bca^KMGcYtXP5kfjHP*n>8zKak6Ypu8-#5D6>0|Yp@2H34C4;(to zY2^PuVFWOc4!Edc0XfL8O=`maW&u<DS+30t19$ZaiWSAS|G= zRv+|=rd(MW)>100rH3LbH1{I%b-c&~QpCwKKyV!qLMHwFmuvJ4_jR^T`4Qy7p2GuS z3W5*Rx1Rh1q5zysb~+5ShSmJ=pw6HE7cQu00R1cCLHE(h zFkk>yxWoe}iTxgOX%GPYPXZ|%;{zyw3kJ~wTMbkcf7Acq{snadRE^T0znOI~!6b+!#ECBj%TmX#XctE{Y0YW|!0sSifIfs9J z&i`GR&+~imKN$lY_vi4h{WBaK?*mm4&Hus~E!?2L4p4A#G!HUMxm5u4cl8n+9P#t_&?(eHXIz& e10@T{J;Yvu3XpYBJ)(u9g^Pee)s=t7mHz`sLc5g! delta 40115 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 e{Sg5G5zENPNVU~b5#<2@M#Os+0czL&{q{eZe&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From 3c092c65e80c278337afdf2c2f9e193d64f640d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 16:41:55 +0200 Subject: [PATCH 009/178] chore(deps): bump gradle-wrapper from 9.4.1 to 9.5.0 (#747) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.4.1 to 9.5.0.

Release notes

Sourced from gradle-wrapper's releases.

9.5.0

The Gradle team is excited to announce Gradle 9.5.0.

Here are the highlights of this release:

  • Task provenance in reports and failure messages
  • Type-safe accessors for precompiled Kotlin Settings plugins

Read the Release Notes

We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

Upgrade instructions

Switch your build to use Gradle 9.5.0 by updating your wrapper:

./gradlew wrapper --gradle-version=9.5.0 && ./gradlew
wrapper

See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

Reporting problems

If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

9.5.0 RC4

... (truncated)

Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 2 +- gradlew.bat | 175 +++++++++++------------ 4 files changed, 86 insertions(+), 95 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 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 delta 40115 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 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel + +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From b20eec587bf64563704406a26c02dd2a40cc9a5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 07:50:37 +0000 Subject: [PATCH 010/178] chore(deps): bump mcp-kotlin from 0.11.1 to 0.12.0 in /samples/kotlinlang-mcp-server (#745) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.11.1 to 0.12.0. Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Updates `io.modelcontextprotocol:kotlin-sdk-testing` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-testing's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 2150c10..723deb5 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.3.21" ktor = "3.3.3" -mcp-kotlin = "0.11.1" +mcp-kotlin = "0.12.0" serialization = "1.11.0" coroutines = "1.10.2" logback = "1.5.32" From bf2e339908ddc0f5494e1cb8313097b9f54b2313 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 10:16:40 +0200 Subject: [PATCH 011/178] chore(deps): bump mcp-kotlin from 0.11.1 to 0.12.0 in /samples/simple-streamable-server (#749) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.11.1 to 0.12.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.11.1 to 0.12.0
Release notes

Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

0.12.0

Description

Adds sampling-with-tools per SEP-1577, JSON Schema dialect declaration on tool schemas, server-side tool name validation, and capability extensions; fixes SSE reconnect on the same session and stops swallowing CancellationException.

Breaking Changes

Sampling messages can carry tool calls and results (SEP-1577) by @​devcrocod in #718

SamplingMessage.content is now typed as a new SamplingMessageContent supertype, with MediaContent (text/image/audio), ToolUseContent, and ToolResultContent as variants. MediaContent still exists and now extends SamplingMessageContent, so most source code that constructs sampling messages compiles unchanged — but the binary signatures of SamplingMessage, CreateMessageResult, and related types have changed. ClientCapabilities.sampling is also now a typed Sampling object instead of a raw JsonObject. Recompilation is required; consumers reading sampling as JsonObject must migrate to the typed accessors.

watchosX64 and tvosX64 Kotlin/Native targets removed by @​devcrocod in #727

These targets have been deprecated upstream. Migrate to the corresponding ARM/simulator targets (watchosArm64, watchosSimulatorArm64, tvosArm64, tvosSimulatorArm64).

Features

  • Add $schema field to ToolSchema, declaring JSON Schema 2020-12 as the default dialect (SEP-1613) by @​devcrocod in #696
  • Validate tool names at registration time on the server, following the MCP tool naming standard (SEP-986) by @​devcrocod in #695
  • Add extensions field to ClientCapabilities and ServerCapabilities for advertising supported MCP extensions during the initialize handshake by @​eritscher in #678

Fixed

  • Validate the mcp-protocol-version HTTP header on initialization requests and correct DEFAULT_NEGOTIATED_PROTOCOL_VERSION to match the spec by @​devcrocod in #697
  • Propagate CancellationException instead of logging it as an error by @​devcrocod in #706
  • Evict stale GET SSE stream mapping on reconnect so a new GET on the same session is no longer silently rejected by the leftover entry from the previous stream by @​amr in #716

Maintenance

  • Add kotlinlang MCP server sample with search and get_page tools by @​devcrocod in #713
  • Migrate detekt to a buildSrc convention plugin with a fully explicit, version-locked YAML config by @​devcrocod in #729
  • Add Streamable HTTP integration tests for pagination, bad-request handling, and logging by @​jskjw157 in #613
  • Remove unused OpenAPI Generator plugin and configuration by @​devcrocod in #683
  • Remove Codecov configuration in favor of kover by @​devcrocod in #691
  • Remove redundant JUnit XML report configuration by @​devcrocod in #728
  • Remove IDEA files tied to the incompatible detekt IDE plugin by @​devcrocod in #714
  • Add Node.js setup to the release workflow so TypeScript integration tests run on macOS runners by @​devcrocod in #684

Dependencies

  • Kotlin to v2.3.21 in #704, #723
  • kotlinx.serialization-json to v1.11.0 in #687

New Contributors

Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.11.1...0.12.0

Commits
  • c339d8c release: bump version to 0.12.0 (#731)
  • 64804a0 refactor: explicit locked detekt config (#729)
  • a238fc0 fix(server): evict stale GET SSE stream mapping on reconnect (#716)
  • 66d9efb test(streamable-http): add missing integration tests for pagination, bad requ...
  • f434fca feat!: SEP-1577 sampling with tools (#718)
  • 7474a33 chore: drop deprecated watchosX64 and tvosX64 targets (#727)
  • 12ace76 chore: remove redundant JUnit XML report configuration (#728)
  • ec606db chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/weather-stdio-serv...
  • 1d93042 chore(deps): bump kotlin from 2.2.21 to 2.3.21 in /samples/kotlin-mcp-server ...
  • 9817b17 chore(deps): bump org.jetbrains.kotlin.jvm from 2.2.21 to 2.3.21 in /samples/...
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index dc668c0..3296f05 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.3.21" ktor = "3.3.3" junit = "6.0.3" -mcp-kotlin = "0.11.1" +mcp-kotlin = "0.12.0" slf4j = "2.0.17" shadow = "9.4.1" From 8a814292cff713cecb7339ef4a4c8444d6982fb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 08:39:40 +0000 Subject: [PATCH 012/178] chore(deps): bump zod from 4.3.6 to 4.4.3 in /integration-test/src/jvmTest/typescript in the all-dependencies group across 1 directory (#751) Bumps the all-dependencies group with 1 update in the /integration-test/src/jvmTest/typescript directory: [zod](https://github.com/colinhacks/zod). Updates `zod` from 4.3.6 to 4.4.3
Release notes

Sourced from zod's releases.

v4.4.3

Commits:

  • 4c2fa95ce3f3390fbc522324e406b4e9e89b88f9 docs: use Zernio primary wordmark for gold sponsor logo
  • 2aeec83eb135e3a83756e973ef44845fc5a455d2 docs: prune lapsed gold sponsors and rebalance logo sizing
  • 7391be88ac1ee5cd02057f5ccc012a1f5df4efd0 docs: prune lapsed silver/bronze sponsors and add active ones
  • 2c703322a21b4e2b12f33f49ea8430c451a68b4f docs: normalize bronze sponsor logos to github avatar pattern
  • 9195250cab0e7950efe39c3926d6c203b4b0a170 docs: remove Mintlify from bronze sponsors (churned)
  • b8dffe9e62f17e6571e6249d05cc5102b54d94e4 docs: remove Numeric and Speakeasy (2+ missed monthly cycles)
  • 1cab69383fcdeae2a366d5e2a2fc4d8fc765d168 fix(v4): restore catch handling for absent object keys (#5937) (#5939)
  • c2be4f819064eed62c7c350a2d399b5faecd15f8 fix(v4): generalize optin/fallback to transform; restore preprocess on absent keys (#5941)
  • f3c9ec03ba7a28ae72d25cc295f38674bee0f559 4.4.3
  • 1fb56a5c18c27102dbc92260a4007c7732a0ccca docs: document release procedure in AGENTS.md

v4.4.2

Commits:

  • 0c62df0ea19fd05abdf90473e9eef7eea530fab2 Clean up docs navigation and stale labels (#5901)
  • 20cc794895cc8604fe0c87d83a5d1c3f89fad0ac chore: add security policy and refresh tooling deps
  • 6fbe07b0177efdd1bf1c0b05160e70d7a0702337 fix(docs): heading anchor links now include the hash so it doesnt scoll all the way up, follows navbar logic (#5791)
  • 4bbed1b1c73eca4ce9e59b1189ed236aa6c8b5bd Tighten discriminated union option typing
  • bbac3e567e7fccfaaf7cdc97f1ce30c295e2c908 Update PR guidance for agents
  • cf0dc942a32805c292fff59ade20a7ace980735a Merge remote-tracking branch 'origin/main' into fix-discriminated-union-key-constraint
  • 292c894a5fd2aa42e527900b83d8d7a3009a709c docs: add Zernio gold sponsor
  • 1fc9f311c28dcf80d0bb5a36b177086cbc3d8eca docs: document codec inversion
  • 1373c85da9aeff704a9762d27bc58699618aefb7 docs: remove AI disclosure guidance
  • e20d02b473c08e3a4e557bc610b1b5fac079b649 chore: ignore triage notes
  • e58ea4d91b1dfe8194b73508203213cbc7e9c936 docs: test Zod Mini tab code heights
  • 905761a5d127e8d5dd2ebb3bc88c75cb0b8149ff docs: document preprocess input type narrowing
  • bf64bac850d4dee2b7dde7e64909d5d796d32043 chore: tighten test guidance in AGENTS.md
  • 8ec4e73f4c4693b6361ad591be40fb41eb8a9f95 chore: update play.ts scratch
  • 02c2baf7d0d615872fa4528a8020603b71211702 Make z.preprocess defer optionality to inner schema (#5929)
  • 88015df8e25c44fb5385eb3ef28935119cd5edea fix(docs): drop deprecated baseUrl from tsconfig
  • c59d4474e3b4cad1b323462186cf607178ce8267 4.4.2

v4.4.1

Commits:

  • 481f7be4238c83ed58183f921b2646f340a91c6a ci: gate release publishing on full test workflow
  • 95ccab423aec720b2523c3a64cdc7e3204537cc7 test(v3): restore optional undefined expectations
  • cede2c63739a5823d6aa5093d291e9a111da943d fix(v4): reject tuple holes before required defaults (#5900)
  • edd0bf0f5ada4a8dc581c259407d7bbad0a71ea7 release: 4.4.1
  • 180d83d1dbe6a59260710cc8637a3dea2281ee56 docs: remove Jazz featured sponsor

v4.4.0

4.4.0

This is a minor release with a wide set of correctness and soundness fixes. Some fixes intentionally make Zod stricter, so code that depended on previously accepted invalid or ambiguous inputs may need small updates.

Potentially breaking bug fixes

... (truncated)

Commits
  • 1fb56a5 docs: document release procedure in AGENTS.md
  • f3c9ec0 4.4.3
  • c2be4f8 fix(v4): generalize optin/fallback to transform; restore preprocess on absent...
  • 1cab693 fix(v4): restore catch handling for absent object keys (#5937) (#5939)
  • b8dffe9 docs: remove Numeric and Speakeasy (2+ missed monthly cycles)
  • 9195250 docs: remove Mintlify from bronze sponsors (churned)
  • 2c70332 docs: normalize bronze sponsor logos to github avatar pattern
  • 7391be8 docs: prune lapsed silver/bronze sponsors and add active ones
  • 2aeec83 docs: prune lapsed gold sponsors and rebalance logo sizing
  • 4c2fa95 docs: use Zernio primary wordmark for gold sponsor logo
  • Additional commits viewable in compare view
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for zod since your current version.


Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 8 ++++---- integration-test/src/jvmTest/typescript/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 34e6bf4..0d258ed 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "express": "^5.2.1", - "zod": "^4.3.6" + "zod": "^4.4.3" }, "devDependencies": { "@types/cors": "^2.8.19", @@ -1797,9 +1797,9 @@ "license": "ISC" }, "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 030c79c..d648fa9 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -11,7 +11,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "express": "^5.2.1", - "zod": "^4.3.6" + "zod": "^4.4.3" }, "devDependencies": { "@types/cors": "^2.8.19", From 7b474720f46c9e9d416140601960e35d66254815 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 13:49:33 +0200 Subject: [PATCH 013/178] chore(deps): bump hono from 4.12.14 to 4.12.18 in /integration-test/src/jvmTest/typescript (#755) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [hono](https://github.com/honojs/hono) from 4.12.14 to 4.12.18.
Release notes

Sourced from hono's releases.

v4.12.18

Security fixes

This release includes fixes for the following security issues:

Cache Middleware ignores Vary: Authorization / Vary: Cookie leading to cross-user cache leakage

Affects: Cache Middleware. Fixes missing cache-skip handling for Vary: Authorization and Vary: Cookie, where a response cached for one authenticated user could be served to other users. GHSA-p77w-8qqv-26rm

CSS Declaration Injection via Style Object Values in JSX SSR

Affects: hono/jsx. Fixes a missing CSS-context escape for style object values and property names, where untrusted input could inject additional CSS declarations. The impact is limited to CSS and does not allow JavaScript execution. GHSA-qp7p-654g-cw7p

Improper validation of NumericDate claims (exp, nbf, iat) in JWT verify()

Affects: hono/utils/jwt. Fixes improper validation of exp, nbf, and iat claims, where falsy, non-finite, or non-numeric values could silently bypass time-based checks instead of being rejected per RFC 7519. GHSA-hm8q-7f3q-5f36


Users who use the JWT helper, hono/jsx, or the Cache middleware are strongly encouraged to upgrade to this version.

v4.12.17

What's Changed

New Contributors

Full Changelog: https://github.com/honojs/hono/compare/v4.12.16...v4.12.17

v4.12.16

Security fixes

This release includes fixes for the following security issues:

Unvalidated JSX Tag Names in hono/jsx May Allow HTML Injection

Affects: hono/jsx. Fixes missing validation of JSX tag names when using jsx() or createElement(), which could allow HTML injection if untrusted input is used as the tag name. GHSA-69xw-7hcm-h432

bodyLimit() can be bypassed for chunked / unknown-length requests

Affects: Body Limit Middleware. Fixes late enforcement for request bodies without a reliable Content-Length (e.g. chunked requests), where oversized requests could reach handlers and return successful responses before being rejected. GHSA-9vqf-7f2p-gf9v

v4.12.15

What's Changed

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=hono&package-manager=npm_and_yarn&previous-version=4.12.14&new-version=4.12.18)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/modelcontextprotocol/kotlin-sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 0d258ed..b71ef4c 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1197,9 +1197,9 @@ } }, "node_modules/hono": { - "version": "4.12.14", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.14.tgz", - "integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==", + "version": "4.12.18", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz", + "integrity": "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==", "license": "MIT", "engines": { "node": ">=16.9.0" From bab4b0bc606bc193a863b2c428e247e963cc9f8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 12:11:20 +0000 Subject: [PATCH 014/178] chore(deps): bump @types/node from 25.6.0 to 25.6.2 in /integration-test/src/jvmTest/typescript in the all-dependencies group across 1 directory (#762) Bumps the all-dependencies group with 1 update in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 25.6.0 to 25.6.2
Commits

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 8 ++++---- integration-test/src/jvmTest/typescript/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index b71ef4c..d66c9ee 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,7 +15,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.6.0", + "@types/node": "^25.6.2", "cors": "^2.8.6", "tsx": "^4.21.0", "typescript": "^6.0.3" @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", + "version": "25.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.2.tgz", + "integrity": "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index d648fa9..6ec358a 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,7 +16,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.6.0", + "@types/node": "^25.6.2", "cors": "^2.8.6", "tsx": "^4.21.0", "typescript": "^6.0.3" From 6d34e6ce03b87b95570ce67f666c942a5107fcf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 12:48:46 +0000 Subject: [PATCH 015/178] chore(deps): bump fast-uri from 3.1.0 to 3.1.2 in /integration-test/src/jvmTest/typescript (#756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.0 to 3.1.2.
Release notes

Sourced from fast-uri's releases.

v3.1.2

⚠️ Security Release

What's Changed

Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.1...v3.1.2

v3.1.1

⚠️ Security Release

What's Changed

New Contributors

Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.0...v3.1.1

Commits
  • 919dd8e Bumped v3.1.2
  • c65ba57 fixup: linting
  • 6c86c17 Merge commit from fork
  • a95158a Handle malformed fragment decoding without throwing (#171)
  • cea547c Bumped v3.1.1
  • 876ce79 Merge commit from fork
  • dcdf690 ci: add lock-threads workflow (#169)
  • c860e65 build(deps-dev): bump neostandard from 0.12.2 to 0.13.0 (#167)
  • 9b4c6dc build(deps): bump fastify/workflows/.github/workflows/plugins-ci.yml (#166)
  • 85d09a9 build(deps): bump fastify/workflows/.github/workflows/plugins-ci-package-mana...
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index d66c9ee..6aa468d 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1033,9 +1033,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", From 664c0da900297cef8589a418d6517c86b9a51353 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 18:44:47 +0200 Subject: [PATCH 016/178] chore(deps): bump com.anthropic:anthropic-java from 2.28.0 to 2.30.0 in /samples/kotlin-mcp-client in the other-dependencies group across 1 directory (#757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [//]: # (dependabot-start) ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- [//]: # (dependabot-end) Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Updates `com.anthropic:anthropic-java` from 2.28.0 to 2.30.0
Release notes

Sourced from com.anthropic:anthropic-java's releases.

v2.30.0

2.30.0 (2026-05-06)

Full Changelog: v2.29.0...v2.30.0

Features

  • api: add support for Managed Agents multiagents and outcomes, webhooks, vault validation (e641d5f)
  • api: add support for Managed Agents multiagents and outcomes, webhooks, vault validation (6067599)
  • client: support proxy authentication (d91fea2)

Bug Fixes

  • api: Adjust webhook configuration (34ea5b4)

Chores

v2.29.0

2.29.0 (2026-05-05)

Full Changelog: v2.28.0...v2.29.0

Features

  • client: allow targeting a workspace for OIDC federation token exchange (578003a)

Performance Improvements

  • client: create one json mapper (556ef49)

Chores

  • remove duplicated dokka setup (d6b94f4)

Documentation

Changelog

Sourced from com.anthropic:anthropic-java's changelog.

2.30.0 (2026-05-06)

Full Changelog: v2.29.0...v2.30.0

Features

  • api: add support for Managed Agents multiagents and outcomes, webhooks, vault validation (e641d5f)
  • api: add support for Managed Agents multiagents and outcomes, webhooks, vault validation (6067599)
  • client: support proxy authentication (d91fea2)

Bug Fixes

  • api: Adjust webhook configuration (34ea5b4)

Chores

2.29.0 (2026-05-05)

Full Changelog: v2.28.0...v2.29.0

Features

  • client: allow targeting a workspace for OIDC federation token exchange (578003a)

Performance Improvements

  • client: create one json mapper (556ef49)

Chores

  • remove duplicated dokka setup (d6b94f4)

Documentation

Commits
  • 5f413b5 chore: release main
  • 46baee8 fix(api): Adjust webhook configuration
  • 0ce73ea feat(api): add support for Managed Agents multiagents and outcomes, webhooks,...
  • 337eb3b chore: fix merge errors
  • 0a95f16 feat(api): add support for Managed Agents multiagents and outcomes, webhooks,...
  • 93912dd feat(client): support proxy authentication
  • 1fc9ab1 chore: release main
  • 9e4cbbd feat(client): allow targeting a workspace for OIDC federation token exchange
  • e8e5894 perf(client): create one json mapper
  • 726e6f4 chore: remove duplicated dokka setup
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.anthropic:anthropic-java&package-manager=gradle&previous-version=2.28.0&new-version=2.30.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 2959a9a..6d4a979 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.28.0" +anthropic = "2.31.0" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" From 9947353a48e13b3871d5b9ca1c87c7e15a0e92c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 17:04:01 +0000 Subject: [PATCH 017/178] chore(deps): bump coroutines from 1.10.2 to 1.11.0 in /samples/kotlinlang-mcp-server (#758) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `coroutines` from 1.10.2 to 1.11.0. Updates `org.jetbrains.kotlinx:kotlinx-coroutines-core` from 1.10.2 to 1.11.0
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B efore, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

... (truncated)

Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core's changelog.

Version 1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

Version 1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

Version 1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

... (truncated)

Commits
  • 8564f65 Version 1.11.0
  • a4c6af9 Merge remote-tracking branch 'origin/master' into develop
  • ef917b4 KT-84955: mark apple x64 tagets as deprecated error (#4645)
  • 5ebc421 Update the release procedure description (#4670)
  • 95f46a0 Remove old maven repository settings (#4672)
  • b4f4f0a Fix package name of ToMapCollectionSamplesTest. (#4674)
  • 86738dc Added templates to the issue creation wizard (#4654)
  • 330fcc2 Version 1.11.0-rc02
  • e31cef6 Merge remote-tracking branch 'origin/master' into develop
  • dc6e9f6 Restore Promise-related functions on Wasm/JS as HIDDEN (#4661)
  • Additional commits viewable in compare view

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-test` from 1.10.2 to 1.11.0
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-test's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B efore, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

... (truncated)

Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-test's changelog.

Version 1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

Version 1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

Version 1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

... (truncated)

Commits
  • 8564f65 Version 1.11.0
  • a4c6af9 Merge remote-tracking branch 'origin/master' into develop
  • ef917b4 KT-84955: mark apple x64 tagets as deprecated error (#4645)
  • 5ebc421 Update the release procedure description (#4670)
  • 95f46a0 Remove old maven repository settings (#4672)
  • b4f4f0a Fix package name of ToMapCollectionSamplesTest. (#4674)
  • 86738dc Added templates to the issue creation wizard (#4654)
  • 330fcc2 Version 1.11.0-rc02
  • e31cef6 Merge remote-tracking branch 'origin/master' into develop
  • dc6e9f6 Restore Promise-related functions on Wasm/JS as HIDDEN (#4661)
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 723deb5..5b7988e 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" serialization = "1.11.0" -coroutines = "1.10.2" +coroutines = "1.11.0" logback = "1.5.32" shadow = "9.4.1" From a967df1eac5b69df7d4df522612255f38073f69b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 19:29:28 +0200 Subject: [PATCH 018/178] chore(deps): bump org.jetbrains.kotlinx:kotlinx-coroutines-test from 1.10.2 to 1.11.0 in /samples/weather-stdio-server (#759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) from 1.10.2 to 1.11.0.
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-test's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B efore, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

... (truncated)

Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-test's changelog.

Version 1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

Version 1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

Version 1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

... (truncated)

Commits
  • 8564f65 Version 1.11.0
  • a4c6af9 Merge remote-tracking branch 'origin/master' into develop
  • ef917b4 KT-84955: mark apple x64 tagets as deprecated error (#4645)
  • 5ebc421 Update the release procedure description (#4670)
  • 95f46a0 Remove old maven repository settings (#4672)
  • b4f4f0a Fix package name of ToMapCollectionSamplesTest. (#4674)
  • 86738dc Added templates to the issue creation wizard (#4654)
  • 330fcc2 Version 1.11.0-rc02
  • e31cef6 Merge remote-tracking branch 'origin/master' into develop
  • dc6e9f6 Restore Promise-related functions on Wasm/JS as HIDDEN (#4661)
  • Additional commits viewable in compare view

Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 1fc2e6a..8eee298 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -coroutines = "1.10.2" +coroutines = "1.11.0" kotlin = "2.3.21" ktor = "3.3.3" logging = "8.0.02" From d6027fd46d8b17cc4b5587041d5a2128b2f528bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 20:09:56 +0200 Subject: [PATCH 019/178] chore(deps): bump the kotlinx group across 1 directory with 3 updates (#760) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotlinx group with 3 updates in the / directory: [org.jetbrains.kotlinx:kotlinx-coroutines-core](https://github.com/Kotlin/kotlinx.coroutines), [org.jetbrains.kotlinx:kotlinx-coroutines-core-wasm-js](https://github.com/Kotlin/kotlinx.coroutines) and [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines). Updates `org.jetbrains.kotlinx:kotlinx-coroutines-core` from 1.10.2 to 1.11.0
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B efore, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

... (truncated)

Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core's changelog.

Version 1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

Version 1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

Version 1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

... (truncated)

Commits
  • 8564f65 Version 1.11.0
  • a4c6af9 Merge remote-tracking branch 'origin/master' into develop
  • ef917b4 KT-84955: mark apple x64 tagets as deprecated error (#4645)
  • 5ebc421 Update the release procedure description (#4670)
  • 95f46a0 Remove old maven repository settings (#4672)
  • b4f4f0a Fix package name of ToMapCollectionSamplesTest. (#4674)
  • 86738dc Added templates to the issue creation wizard (#4654)
  • 330fcc2 Version 1.11.0-rc02
  • e31cef6 Merge remote-tracking branch 'origin/master' into develop
  • dc6e9f6 Restore Promise-related functions on Wasm/JS as HIDDEN (#4661)
  • Additional commits viewable in compare view

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-core-wasm-js` from 1.10.2 to 1.11.0
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core-wasm-js's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B efore, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

... (truncated)

Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core-wasm-js's changelog.

Version 1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

Version 1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

Version 1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

... (truncated)

Commits
  • 8564f65 Version 1.11.0
  • a4c6af9 Merge remote-tracking branch 'origin/master' into develop
  • ef917b4 KT-84955: mark apple x64 tagets as deprecated error (#4645)
  • 5ebc421 Update the release procedure description (#4670)
  • 95f46a0 Remove old maven repository settings (#4672)
  • b4f4f0a Fix package name of ToMapCollectionSamplesTest. (#4674)
  • 86738dc Added templates to the issue creation wizard (#4654)
  • 330fcc2 Version 1.11.0-rc02
  • e31cef6 Merge remote-tracking branch 'origin/master' into develop
  • dc6e9f6 Restore Promise-related functions on Wasm/JS as HIDDEN (#4661)
  • Additional commits viewable in compare view

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-test` from 1.10.2 to 1.11.0
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-test's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B efore, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

... (truncated)

Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-test's changelog.

Version 1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

Version 1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

Version 1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

... (truncated)

Commits
  • 8564f65 Version 1.11.0
  • a4c6af9 Merge remote-tracking branch 'origin/master' into develop
  • ef917b4 KT-84955: mark apple x64 tagets as deprecated error (#4645)
  • 5ebc421 Update the release procedure description (#4670)
  • 95f46a0 Remove old maven repository settings (#4672)
  • b4f4f0a Fix package name of ToMapCollectionSamplesTest. (#4674)
  • 86738dc Added templates to the issue creation wizard (#4654)
  • 330fcc2 Version 1.11.0-rc02
  • e31cef6 Merge remote-tracking branch 'origin/master' into develop
  • dc6e9f6 Restore Promise-related functions on Wasm/JS as HIDDEN (#4661)
  • Additional commits viewable in compare view

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-core-wasm-js` from 1.10.2 to 1.11.0
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core-wasm-js's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. B efore, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

... (truncated)

Changelog

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-core-wasm-js's changelog.

Version 1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web target. On Wasm/JS, this is a breaking change. Before the change, Promise on Wasm/JS could work with arbitrary Kotlin types, but now, only JsAny subtypes are accepted (#4563).
  • Changed handling of coroutine exceptions that can't be propagated on JS and Wasm/JS. Before, exceptions were logged, but now, they are reported to the JS runtime (#4451, #4631).
  • Deprecated using CoroutineDispatcher as the coroutine context key; now, ContinuationInterceptor has to be used instead (#4333).
  • Advanced the deprecation levels on kotlinx-coroutines-test APIs (#4604).
  • Added lint functions that mark passing a Job to coroutine builders as deprecated (#4435).

Bug fixes and improvements

  • Added a callsInPlace(EXACTLY_ONCE) contract to runBlocking in code shared between JVM and Native (#4368).
  • Added a callsInPlace(EXACTLY_ONCE) contract to suspendCancellableCoroutine (#4574).
  • Fixed flowOn incorrectly handling ThreadContextElement updates (#4403).
  • Fixed exceptions in user-supplied Thread.UncaughtExceptionHandler instances causing the internal coroutines machinery to fail (#4516).
  • Fixed CoroutineDispatcher.asScheduler in the RxJava integration not cancelling outstanding work when a Worker gets cancelled, which led to memory leaks in some scenarios (#4615).
  • Fixed SharedFlow entering an invalid state when a subscriber and an emitter are cancelled simultaneously (#4583).
  • Fixed an R8 optimization leading to shareIn/stateIn coroutines getting garbage-collected (#4646). Thanks, @​solevic!

Small additions

  • Added CompletableDeferred.asDeferred for obtaining a read-only Deferred view (#4408).
  • Added SharedFlow.asFlow for obtaining a Flow view with hidden hot flow semantics (#4530). Thanks, @​g000sha256!
  • Added a StateFlow.collectLatest overload returning Nothing to assist with finding unreachable code (#4454).
  • Added ReceiveChannel.consumeTo for consuming a ReceiveChannel into a MutableCollection (#4520).
  • Added a StateFlow<T>.onSubscription overload returning a StateFlow<T>, similar to SharedFlow<T>.onSubscription returning SharedFlow<T> (#4275). Thanks, @​xit0c!
  • Added terminal Flow operators for collecting a Flow to a Map (#1541).

Changelog relative to version 1.11.0

No changes, only the version is increased.

Version 1.11.0-rc02

Restored binary compatibility with 1.10.2 and older versions on Wasm/JS for usages of Promise-related functions (#4661).

Version 1.11.0-rc01

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

... (truncated)

Commits
  • 8564f65 Version 1.11.0
  • a4c6af9 Merge remote-tracking branch 'origin/master' into develop
  • ef917b4 KT-84955: mark apple x64 tagets as deprecated error (#4645)
  • 5ebc421 Update the release procedure description (#4670)
  • 95f46a0 Remove old maven repository settings (#4672)
  • b4f4f0a Fix package name of ToMapCollectionSamplesTest. (#4674)
  • 86738dc Added templates to the issue creation wizard (#4654)
  • 330fcc2 Version 1.11.0-rc02
  • e31cef6 Merge remote-tracking branch 'origin/master' into develop
  • dc6e9f6 Restore Promise-related functions on Wasm/JS as HIDDEN (#4661)
  • Additional commits viewable in compare view

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-test` from 1.10.2 to 1.11.0
Release notes

Sourced from org.jetbrains.kotlinx:kotlinx-coroutines-test's releases.

1.11.0

Various

  • Kotlin was updated to 2.2.20 (#4545).
  • Improved the published jar files (#3842, #4599).
  • Various documentation improvements, including complete rewrites of structured concurrency and error handling-related KDoc (#4433, #4596).

Breaking changes and deprecations

  • Moved Promise-related functions from JS and Wasm/JS to the new web Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 63a75c5..a1f2cc0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ netty = "4.2.13.Final" # libraries version awaitility = "4.3.0" collections-immutable = "0.4.0" -coroutines = "1.10.2" +coroutines = "1.11.0" kotest = "6.1.11" kotlinx-io = "0.9.0" ktor = "3.3.3" From 44e012e4eefc9ad1128a814c0be09769613367ba Mon Sep 17 00:00:00 2001 From: johny <69754601+jskjw157@users.noreply.github.com> Date: Sat, 16 May 2026 01:44:16 +0900 Subject: [PATCH 020/178] fix(client): invoke onClose when SSE session disconnects (#437) (#738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the SSE client transport so that registered `onClose` callbacks fire when the underlying SSE session ends — whether the server closes the stream gracefully or an error event terminates it. closes #437 ## Motivation and Context `SseClientTransport.collectMessages` already runs `closeResources()` in its `finally` block when `session.incoming` completes, but it never invoked the `onClose` callback chain. As a result, the MCP `Client` (and any user code calling `transport.onClose { ... }`) had no way to detect that the server-side SSE connection had dropped. The other client transports already do this correctly: - `StdioClientTransport` calls `invokeOnCloseCallback()` from its read-loop `finally` (kotlin-sdk-client/src/.../StdioClientTransport.kt:224). - The protected `AbstractTransport.invokeOnCloseCallback()` helper guards against duplicate firing with an `AtomicBoolean`, so it is safe to call from both the read-loop `finally` and the user-initiated `close()` path. The fix mirrors that established pattern in one line. ## How Has This Been Tested? Added `onClose callback fires when the SSE stream is disconnected by the server` to `SseClientTransportTest`. The test: 1. Starts the transport against a mock SSE engine. 2. Closes the SSE byte channel server-side via a new `MockSseClientEngine.disconnectSseStream()` helper. 3. Asserts the registered `onClose` callback fires (using Kotest `eventually`, since the close propagates on a real-time dispatcher). I also verified the test fails before the fix and passes after. ``` ./gradlew :kotlin-sdk-client:jvmTest ./gradlew apiCheck ktlintCheck detekt ``` ## Breaking Changes None. `invokeOnCloseCallback()` is `protected` on `AbstractTransport`; this PR only adds a call site inside `SseClientTransport`. No public API surface changes. ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../kotlin/sdk/client/SseClientTransport.kt | 1 + .../sdk/client/sse/MockSseClientEngine.kt | 8 ++++++ .../sdk/client/sse/SseClientTransportTest.kt | 27 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/SseClientTransport.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/SseClientTransport.kt index a48db60..0295eb9 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/SseClientTransport.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/SseClientTransport.kt @@ -136,6 +136,7 @@ public class SseClientTransport( throw e } finally { closeResources() + invokeOnCloseCallback() } } diff --git a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/MockSseClientEngine.kt b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/MockSseClientEngine.kt index 3627b6c..14af546 100644 --- a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/MockSseClientEngine.kt +++ b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/MockSseClientEngine.kt @@ -53,6 +53,14 @@ internal open class MockSseClientEngine( job.cancel() } + /** + * Closes the SSE byte channel without disposing the engine, simulating a server-side + * disconnect of the SSE stream. + */ + fun disconnectSseStream() { + channel.close() + } + private fun responseContext(): CoroutineContext = dispatcher + Job() private suspend fun respondWithSseEndpointEvent(data: HttpRequestData): HttpResponseData { diff --git a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/SseClientTransportTest.kt b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/SseClientTransportTest.kt index 6cc7f6e..319ba2a 100644 --- a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/SseClientTransportTest.kt +++ b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/sse/SseClientTransportTest.kt @@ -1,5 +1,6 @@ package io.modelcontextprotocol.kotlin.sdk.client.sse +import io.kotest.assertions.nondeterministic.eventually import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.shouldBe import io.ktor.client.HttpClient @@ -9,6 +10,7 @@ import io.modelcontextprotocol.kotlin.sdk.client.SseClientTransport import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification import kotlinx.coroutines.test.runTest import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds class SseClientTransportTest { @@ -90,6 +92,31 @@ class SseClientTransportTest { engine.close() } + @Test + fun `onClose callback fires when the SSE stream is disconnected by the server`() = runTest { + // Given + val sseUrl = "http://example.com/api/mcp/sse" + + // And + val engine = CapturingSseClientEngine(endpoint = "/messages?sessionId=abc") + val transport = sseTransport(sseUrl, engine) + var onCloseFired = false + transport.onClose { onCloseFired = true } + + // When + transport.start() + engine.disconnectSseStream() + + // Then + eventually(2.seconds) { + onCloseFired shouldBe true + } + + // Cleanup + transport.close() + engine.close() + } + private fun sseTransport(sseUrl: String, engine: CapturingSseClientEngine) = SseClientTransport(HttpClient(engine) { install(SSE) }, sseUrl) From 664f51b9cc210466c02699f5146130f86c4be98b Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Mon, 18 May 2026 12:17:26 +0200 Subject: [PATCH 021/178] test: remove mokksy dependency (#754) Drops`dev.mokksy:mokksy` dependency ## Motivation and Context `mokksy` is a niche, single-maintainer library with very limited external adoption, introduced by its own author. Keeping a test-only dependency on it is unnecessary supply-chain exposure given that the two patterns already used in this repo, `MockEngine` for transport-level tests and `embeddedServer` for integration-level tests, cover everything it provided. ## Breaking Changes none ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- gradle/libs.versions.toml | 2 - ...mableHttpClientTransportIntegrationTest.kt | 270 ++++++++++++++++ kotlin-sdk-client/build.gradle.kts | 1 - .../http/StreamableHttpClientTransportTest.kt | 73 +++++ .../AbstractStreamableHttpClientTest.kt | 42 --- .../kotlin/sdk/client/MockMcp.kt | 237 -------------- .../sdk/client/StreamableHttpClientTest.kt | 293 ------------------ 7 files changed, 343 insertions(+), 575 deletions(-) create mode 100644 integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpClientTransportIntegrationTest.kt delete mode 100644 kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/AbstractStreamableHttpClientTest.kt delete mode 100644 kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/MockMcp.kt delete mode 100644 kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTest.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a1f2cc0..5b04ca4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,6 @@ kotlinx-io = "0.9.0" ktor = "3.3.3" logging = "8.0.02" mockk = "1.14.9" -mokksy = "0.8.1" serialization = "1.11.0" slf4j = "2.0.17" logback = "1.5.32" @@ -65,7 +64,6 @@ kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-cor ktor-client-mock = { group = "io.ktor", name = "ktor-client-mock", version.ref = "ktor" } ktor-server-test-host = { group = "io.ktor", name = "ktor-server-test-host", version.ref = "ktor" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } -mokksy = { group = "dev.mokksy", name = "mokksy", version.ref = "mokksy" } netty-bom = { group = "io.netty", name = "netty-bom", version.ref = "netty" } slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" } logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" } diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpClientTransportIntegrationTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpClientTransportIntegrationTest.kt new file mode 100644 index 0000000..598825f --- /dev/null +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpClientTransportIntegrationTest.kt @@ -0,0 +1,270 @@ +package io.modelcontextprotocol.kotlin.sdk.integration.streamablehttp + +import io.kotest.matchers.collections.shouldContain +import io.kotest.matchers.shouldBe +import io.ktor.client.HttpClient +import io.ktor.client.plugins.sse.SSE +import io.ktor.http.ContentType +import io.ktor.http.HttpStatusCode +import io.ktor.server.engine.embeddedServer +import io.ktor.server.request.receiveText +import io.ktor.server.response.header +import io.ktor.server.response.respond +import io.ktor.server.response.respondText +import io.ktor.server.response.respondTextWriter +import io.ktor.server.routing.Route +import io.ktor.server.routing.delete +import io.ktor.server.routing.get +import io.ktor.server.routing.post +import io.ktor.server.routing.routing +import io.modelcontextprotocol.kotlin.sdk.client.Client +import io.modelcontextprotocol.kotlin.sdk.client.ClientOptions +import io.modelcontextprotocol.kotlin.sdk.client.StreamableHttpClientTransport +import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.Tool +import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema +import io.modelcontextprotocol.kotlin.test.utils.actualPort +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.put +import kotlinx.serialization.json.putJsonObject +import kotlin.test.Test +import io.ktor.client.engine.cio.CIO as ClientCIO +import io.ktor.server.cio.CIO as ServerCIO + +private const val SESSION_ID_HEADER = "mcp-session-id" +private const val HOST = "127.0.0.1" +private const val MCP_PATH = "/mcp" + +private val INITIALIZE_RESULT = """ + { + "capabilities": {"tools": {"listChanged": false}}, + "protocolVersion": "2025-03-26", + "serverInfo": {"name": "test-server", "version": "1.0.0"} + } +""".trimIndent() + +private val TOOLS_LIST_RESULT = """ + { + "tools": [ + { + "name": "get_weather", + "title": "Weather Information Provider", + "description": "Get current weather information for a location", + "inputSchema": { + "type": "object", + "properties": { + "location": {"type": "string", "description": "City name or zip code"} + }, + "required": ["location"] + }, + "outputSchema": { + "type": "object", + "properties": { + "temperature": {"type": "number", "description": "Temperature, Celsius"} + }, + "required": ["temperature"] + }, + "_meta": {} + } + ] + } +""".trimIndent() + +private const val PROGRESS_NOTIFICATION_1 = + """{"jsonrpc":"2.0","method":"notifications/progress","params":{"progressToken":"upload-123","progress":50,"total":100}}""" + +private const val PROGRESS_NOTIFICATION_2 = + """{"jsonrpc":"2.0","method":"notifications/progress","params":{"progressToken":"upload-123","progress":75,"total":100}}""" + +internal class StreamableHttpClientTransportIntegrationTest { + + @Test + fun `client receives progress notifications via GET SSE and lists tools`(): Unit = runBlocking(Dispatchers.IO) { + val sessionId = "sid-progress" + runWithServer({ + mcpPostRoute(sessionId, extraResults = mapOf("tools/list" to TOOLS_LIST_RESULT)) + get(MCP_PATH) { + call.response.header(SESSION_ID_HEADER, sessionId) + call.respondTextWriter(contentType = ContentType.Text.EventStream) { + write(sseEvent(id = "1", data = PROGRESS_NOTIFICATION_1)) + flush() + delay(200) + write(sseEvent(id = "2", data = PROGRESS_NOTIFICATION_2)) + flush() + awaitCancellation() + } + } + }) { url -> + val client = newClient() + client.connect(StreamableHttpClientTransport(client = newHttpClient(), url = url)) + + val listToolsResult = client.listTools() + + listToolsResult.tools shouldContain Tool( + name = "get_weather", + title = "Weather Information Provider", + description = "Get current weather information for a location", + inputSchema = ToolSchema( + properties = buildJsonObject { + putJsonObject("location") { + put("type", "string") + put("description", "City name or zip code") + } + }, + required = listOf("location"), + ), + outputSchema = ToolSchema( + properties = buildJsonObject { + putJsonObject("temperature") { + put("type", "number") + put("description", "Temperature, Celsius") + } + }, + required = listOf("temperature"), + ), + annotations = null, + meta = EmptyJsonObject, + ) + + client.close() + } + } + + @Test + fun `terminateSession sends DELETE request and clears sessionId`(): Unit = runBlocking(Dispatchers.IO) { + val sessionId = "sid-terminate" + runWithServer({ + mcpPostRoute(sessionId) + get(MCP_PATH) { + call.response.header(SESSION_ID_HEADER, sessionId) + call.respondTextWriter(contentType = ContentType.Text.EventStream) { + awaitCancellation() + } + } + delete(MCP_PATH) { + call.respond(HttpStatusCode.OK) + } + }) { url -> + val client = newClient() + val transport = StreamableHttpClientTransport(client = newHttpClient(), url = url) + client.connect(transport) + + transport.sessionId shouldBe sessionId + transport.terminateSession() + transport.sessionId shouldBe null + + client.close() + } + } + + @Test + fun `client survives 405 on GET SSE`(): Unit = runBlocking(Dispatchers.IO) { + val sessionId = "sid-405" + runWithServer({ + mcpPostRoute(sessionId, extraResults = mapOf("ping" to "{}")) + get(MCP_PATH) { + call.respondText( + text = "", + contentType = ContentType.Text.EventStream, + status = HttpStatusCode.MethodNotAllowed, + ) + } + }) { url -> + val client = newClient() + client.connect(StreamableHttpClientTransport(client = newHttpClient(), url = url)) + + client.ping() + + client.close() + } + } + + @Test + fun `client survives non streaming JSON response on GET SSE`(): Unit = runBlocking(Dispatchers.IO) { + val sessionId = "sid-json" + runWithServer({ + mcpPostRoute(sessionId, extraResults = mapOf("ping" to "{}")) + get(MCP_PATH) { + call.response.header(SESSION_ID_HEADER, sessionId) + call.respondText( + text = "", + contentType = ContentType.Application.Json, + status = HttpStatusCode.OK, + ) + } + }) { url -> + val client = newClient() + client.connect(StreamableHttpClientTransport(client = newHttpClient(), url = url)) + + client.ping() + + client.close() + } + } + + private fun Route.mcpPostRoute(sessionId: String, extraResults: Map = emptyMap()) { + post(MCP_PATH) { + val body = call.receiveText() + val parsed = Json.parseToJsonElement(body).jsonObject + val method = parsed["method"]?.jsonPrimitive?.content + val idJson = parsed["id"]?.toString() ?: "null" + call.response.header(SESSION_ID_HEADER, sessionId) + when { + method == "initialize" -> call.respondText( + text = jsonRpcResult(idJson, INITIALIZE_RESULT), + contentType = ContentType.Application.Json, + status = HttpStatusCode.OK, + ) + + method == "notifications/initialized" -> call.respond(HttpStatusCode.Accepted) + + method != null && method in extraResults -> call.respondText( + text = jsonRpcResult(idJson, extraResults.getValue(method)), + contentType = ContentType.Application.Json, + status = HttpStatusCode.OK, + ) + + else -> call.respond(HttpStatusCode.NotFound) + } + } + } + + private suspend fun runWithServer(routes: Route.() -> Unit, block: suspend (url: String) -> Unit) { + val server = embeddedServer(ServerCIO, host = HOST, port = 0) { + routing { routes() } + }.startSuspend(wait = false) + try { + val port = server.actualPort() + block("http://$HOST:$port$MCP_PATH") + } finally { + server.stopSuspend(1000, 2000) + } + } + + private fun newClient(): Client = Client( + clientInfo = Implementation(name = "client1", version = "1.0.0"), + options = ClientOptions(capabilities = ClientCapabilities()), + ) + + private fun newHttpClient(): HttpClient = HttpClient(ClientCIO) { + install(SSE) + } + + private fun jsonRpcResult(idJson: String, resultJson: String): String = + """{"jsonrpc":"2.0","id":$idJson,"result":$resultJson}""" + + private fun sseEvent(id: String, data: String): String = buildString { + append("event: message\n") + append("id: $id\n") + append("data: $data\n\n") + } +} diff --git a/kotlin-sdk-client/build.gradle.kts b/kotlin-sdk-client/build.gradle.kts index ae7a314..fbb1300 100644 --- a/kotlin-sdk-client/build.gradle.kts +++ b/kotlin-sdk-client/build.gradle.kts @@ -55,7 +55,6 @@ kotlin { implementation(libs.ktor.client.apache5) implementation(libs.mockk) implementation(libs.junit.jupiter.params) - implementation(libs.mokksy) implementation(dependencies.platform(libs.netty.bom)) runtimeOnly(libs.slf4j.simple) } diff --git a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt index 8810552..b380f64 100644 --- a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt +++ b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt @@ -478,6 +478,79 @@ class StreamableHttpClientTransportTest { } } + @Test + fun testSkipEmptySSE() = runTest { + val transport = createTransport { request -> + if (request.method == HttpMethod.Post) { + val sseContent = buildString { + // Event 1: empty data — must be skipped without error + appendLine("id: a") + appendLine("data:") + appendLine() + // Event 2: whitespace-only data — must be skipped without error + appendLine("id: b") + appendLine("data: \t ") + appendLine() + // Event 3: multi-line data lines that together form a valid JSON-RPC response + appendLine("id: c") + appendLine("event: message") + appendLine("data: {") + appendLine("""data: "jsonrpc":"2.0",""") + appendLine("""data: "id":"test-1",""") + appendLine("""data: "result":{""") + appendLine("""data: "protocolVersion":"2025-06-18",""") + appendLine("""data: "capabilities":{},""") + appendLine("""data: "serverInfo":{"name":"server","version":"1.0.0"}""") + appendLine("data: }") + appendLine("data: }") + appendLine() + } + + respond( + content = ByteReadChannel(sseContent), + status = HttpStatusCode.OK, + headers = headersOf( + HttpHeaders.ContentType, + ContentType.Text.EventStream.toString(), + ), + ) + } else { + respond("", HttpStatusCode.OK) + } + } + + val receivedMessages = mutableListOf() + val messageReceived = CompletableDeferred() + + transport.onMessage { message -> + receivedMessages.add(message) + if (!messageReceived.isCompleted) { + messageReceived.complete(Unit) + } + } + + transport.start() + + transport.send( + JSONRPCRequest( + id = "test-1", + method = "initialize", + params = buildJsonObject { }, + ), + ) + + eventually { + messageReceived.await() + } + + receivedMessages shouldHaveSize 1 + val response = receivedMessages[0] + response.shouldBeInstanceOf() + response.id shouldBe RequestId.StringId("test-1") + + transport.close() + } + @Test fun testInlineSSEInResponse() = runTest { val transport = createTransport { request -> diff --git a/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/AbstractStreamableHttpClientTest.kt b/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/AbstractStreamableHttpClientTest.kt deleted file mode 100644 index 4a04e81..0000000 --- a/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/AbstractStreamableHttpClientTest.kt +++ /dev/null @@ -1,42 +0,0 @@ -package io.modelcontextprotocol.kotlin.sdk.client - -import io.ktor.client.HttpClient -import io.ktor.client.engine.apache5.Apache5 -import io.ktor.client.plugins.logging.LogLevel -import io.ktor.client.plugins.logging.Logging -import io.ktor.client.plugins.sse.SSE -import org.junit.jupiter.api.AfterAll -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.TestInstance - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -internal abstract class AbstractStreamableHttpClientTest { - - // start mokksy on random port - protected val mockMcp: MockMcp = MockMcp(verbose = true) - - @AfterEach - fun afterEach() { - mockMcp.verifyNoUnexpectedRequests() - } - - @AfterAll - fun afterAll() { - mockMcp.verifyNoUnmatchedStubs() - mockMcp.close() - } - - protected suspend fun connect(client: Client) { - client.connect( - StreamableHttpClientTransport( - url = mockMcp.url, - client = HttpClient(Apache5) { - install(SSE) - install(Logging) { - level = LogLevel.ALL - } - }, - ), - ) - } -} diff --git a/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/MockMcp.kt b/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/MockMcp.kt deleted file mode 100644 index de9d2b3..0000000 --- a/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/MockMcp.kt +++ /dev/null @@ -1,237 +0,0 @@ -package io.modelcontextprotocol.kotlin.sdk.client - -import dev.mokksy.mokksy.BuildingStep -import dev.mokksy.mokksy.Mokksy -import dev.mokksy.mokksy.StubConfiguration -import dev.mokksy.mokksy.shutdown -import dev.mokksy.mokksy.start -import io.ktor.http.ContentType -import io.ktor.http.HttpMethod -import io.ktor.http.HttpStatusCode -import io.ktor.sse.ServerSentEvent -import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest -import io.modelcontextprotocol.kotlin.sdk.types.RequestId -import kotlinx.coroutines.flow.Flow -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.buildJsonObject -import kotlinx.serialization.json.contentOrNull -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import kotlinx.serialization.json.putJsonObject - -const val MCP_SESSION_ID_HEADER = "MCP-Session-Id" - -internal class MockMcp(verbose: Boolean = false) : AutoCloseable { - - private val mokksy: Mokksy = Mokksy(verbose = verbose).apply { - start() - } - - fun verifyNoUnexpectedRequests() { - mokksy.verifyNoUnexpectedRequests() - } - - fun verifyNoUnmatchedStubs() { - mokksy.verifyNoUnmatchedStubs() - } - - val url = "${mokksy.baseUrl()}/mcp" - - fun onInitialize( - clientName: String? = null, - sessionId: String, - protocolVersion: String = "2025-03-26", - serverName: String = "Mock MCP Server", - serverVersion: String = "1.0.0", - capabilities: JsonObject = buildJsonObject { - putJsonObject("tools") { - put("listChanged", JsonPrimitive(false)) - } - }, - ) { - val predicates = if (clientName != null) { - arrayOf<(JSONRPCRequest?) -> Boolean>({ - it?.params?.jsonObject - ?.get("clientInfo")?.jsonObject - ?.get("name")?.jsonPrimitive - ?.contentOrNull == clientName - }) - } else { - emptyArray() - } - - handleWithResult( - jsonRpcMethod = "initialize", - sessionId = sessionId, - bodyPredicates = predicates, - // language=json - result = """ - { - "capabilities": $capabilities, - "protocolVersion": "$protocolVersion", - "serverInfo": { - "name": "$serverName", - "version": "$serverVersion" - }, - "_meta": { - "foo": "bar" - } - } - """.trimIndent(), - ) - } - - fun onJSONRPCRequest( - httpMethod: HttpMethod = HttpMethod.Post, - jsonRpcMethod: String, - expectedSessionId: String? = null, - vararg bodyPredicates: (JSONRPCRequest) -> Boolean, - ): BuildingStep = mokksy.method( - configuration = StubConfiguration(removeAfterMatch = true), - httpMethod = httpMethod, - requestType = JSONRPCRequest::class, - ) { - path("/mcp") - expectedSessionId?.let { - containsHeader(MCP_SESSION_ID_HEADER, it) - } - bodyMatchesPredicate( - description = "JSON-RPC version is '2.0'", - predicate = - { - it!!.jsonrpc == "2.0" - }, - ) - bodyMatchesPredicate( - description = "JSON-RPC Method should be '$jsonRpcMethod'", - predicate = - { - it!!.method == jsonRpcMethod - }, - ) - bodyPredicates.forEach { predicate -> - bodyMatchesPredicate(predicate = { predicate.invoke(it!!) }) - } - } - - fun handleWithResult( - httpMethod: HttpMethod = HttpMethod.Post, - jsonRpcMethod: String, - expectedSessionId: String? = null, - sessionId: String, - contentType: ContentType = ContentType.Application.Json, - statusCode: HttpStatusCode = HttpStatusCode.OK, - vararg bodyPredicates: (JSONRPCRequest) -> Boolean, - result: () -> JsonObject, - ) { - onJSONRPCRequest( - httpMethod = httpMethod, - jsonRpcMethod = jsonRpcMethod, - expectedSessionId = expectedSessionId, - bodyPredicates = bodyPredicates, - ) respondsWith { - val requestId = when (val id = request.body().id) { - is RequestId.NumberId -> id.value.toString() - is RequestId.StringId -> "\"${id.value}\"" - } - val resultObject = result.invoke() - // language=json - body = """ - { - "jsonrpc": "2.0", - "id": $requestId, - "result": $resultObject - } - """.trimIndent() - this.contentType = contentType - headers += MCP_SESSION_ID_HEADER to sessionId - httpStatus = statusCode - } - } - - fun handleWithResult( - httpMethod: HttpMethod = HttpMethod.Post, - jsonRpcMethod: String, - expectedSessionId: String? = null, - sessionId: String, - contentType: ContentType = ContentType.Application.Json, - statusCode: HttpStatusCode = HttpStatusCode.OK, - vararg bodyPredicates: (JSONRPCRequest) -> Boolean, - result: String, - ) { - handleWithResult( - httpMethod = httpMethod, - jsonRpcMethod = jsonRpcMethod, - expectedSessionId = expectedSessionId, - sessionId = sessionId, - contentType = contentType, - statusCode = statusCode, - bodyPredicates = bodyPredicates, - result = { - Json.parseToJsonElement(result).jsonObject - }, - ) - } - - fun handleJSONRPCRequest( - httpMethod: HttpMethod = HttpMethod.Post, - jsonRpcMethod: String, - expectedSessionId: String? = null, - sessionId: String, - contentType: ContentType = ContentType.Application.Json, - statusCode: HttpStatusCode = HttpStatusCode.OK, - vararg bodyPredicates: (JSONRPCRequest?) -> Boolean, - bodyBuilder: () -> String = { "" }, - ) { - onJSONRPCRequest( - httpMethod = httpMethod, - jsonRpcMethod = jsonRpcMethod, - expectedSessionId = expectedSessionId, - bodyPredicates = bodyPredicates, - ) respondsWith { - body = bodyBuilder.invoke() - this.contentType = contentType - headers += MCP_SESSION_ID_HEADER to sessionId - httpStatus = statusCode - } - } - - fun onSubscribe(httpMethod: HttpMethod = HttpMethod.Post, sessionId: String): BuildingStep = mokksy.method( - httpMethod = httpMethod, - name = "MCP GETs", - requestType = Any::class, - ) { - path("/mcp") - containsHeader(MCP_SESSION_ID_HEADER, sessionId) - containsHeader("Accept", "application/json,text/event-stream") - containsHeader("Cache-Control", "no-store") - } - - fun handleSubscribeWithGet(sessionId: String, block: () -> Flow) { - onSubscribe( - httpMethod = HttpMethod.Get, - sessionId = sessionId, - ) respondsWithSseStream { - headers += MCP_SESSION_ID_HEADER to sessionId - this.flow = block.invoke() - } - } - - fun mockUnsubscribeRequest(sessionId: String) { - mokksy.delete( - configuration = StubConfiguration(removeAfterMatch = true), - requestType = JSONRPCRequest::class, - ) { - path("/mcp") - containsHeader(MCP_SESSION_ID_HEADER, sessionId) - } respondsWith { - body = null - } - } - - override fun close() { - mokksy.shutdown() - } -} diff --git a/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTest.kt b/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTest.kt deleted file mode 100644 index 43be8c9..0000000 --- a/kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTest.kt +++ /dev/null @@ -1,293 +0,0 @@ -package io.modelcontextprotocol.kotlin.sdk.client - -import io.kotest.matchers.collections.shouldContain -import io.kotest.matchers.shouldBe -import io.ktor.http.ContentType -import io.ktor.http.HttpMethod -import io.ktor.http.HttpStatusCode -import io.ktor.sse.ServerSentEvent -import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities -import io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject -import io.modelcontextprotocol.kotlin.sdk.types.Implementation -import io.modelcontextprotocol.kotlin.sdk.types.Tool -import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.runBlocking -import kotlinx.serialization.json.buildJsonObject -import kotlinx.serialization.json.put -import kotlinx.serialization.json.putJsonObject -import org.junit.jupiter.api.TestInstance -import kotlin.test.Test -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.seconds -import kotlin.uuid.ExperimentalUuidApi -import kotlin.uuid.Uuid - -@OptIn(ExperimentalUuidApi::class) -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -internal class StreamableHttpClientTest : AbstractStreamableHttpClientTest() { - - @Test - fun `Should skip empty SSE`(): Unit = runBlocking { - val client = Client( - clientInfo = Implementation( - name = "client1", - version = "1.0.0", - ), - options = ClientOptions( - capabilities = ClientCapabilities(), - ), - ) - val sessionId = Uuid.random().toString() - - mockMcp.onJSONRPCRequest( - httpMethod = HttpMethod.Post, - jsonRpcMethod = "initialize", - ).respondsWithStream { - headers += MCP_SESSION_ID_HEADER to sessionId - flow = flowOf( - "id: ${Uuid.random()}\n", - "data:\n", // empty data - "\n", - "id: ${Uuid.random()}\n", - "data: \t \n", // tabs and spaces - "\n", - "id: ${Uuid.random()}\n", - "event: message\n", - // multiline data - "data: {\n", - "data: \"result\":{\n" + - "data: \"protocolVersion\":\"2025-06-18\",\n" + - "data: \"capabilities\":{},\n" + - "data: \"serverInfo\":{\"name\":\"simple-streamable-http-server\",\"version\":\"1.0.0\"}\n" + - "data: },\n" + - "data: \"jsonrpc\":\"2.0\",\n" + - "data: \"id\":\"7ce065b0678f49e5b04ce5a0fcc7d518\"\n" + - "data: }\n", - "\n", - ) - } - - mockMcp.handleJSONRPCRequest( - jsonRpcMethod = "notifications/initialized", - expectedSessionId = sessionId, - sessionId = sessionId, - statusCode = HttpStatusCode.Accepted, - ) - - mockMcp.handleSubscribeWithGet(sessionId) { - emptyFlow() - } - - connect(client) - } - - @Test - fun `test streamableHttpClient`() = runBlocking { - val client = Client( - clientInfo = Implementation( - name = "client1", - version = "1.0.0", - ), - options = ClientOptions( - capabilities = ClientCapabilities(), - ), - ) - - val sessionId = Uuid.random().toString() - - mockMcp.onInitialize( - clientName = "client1", - sessionId = sessionId, - ) - - mockMcp.handleJSONRPCRequest( - jsonRpcMethod = "notifications/initialized", - expectedSessionId = sessionId, - sessionId = sessionId, - statusCode = HttpStatusCode.Accepted, - ) - - mockMcp.handleSubscribeWithGet(sessionId) { - flow { - delay(500.milliseconds) - emit( - ServerSentEvent( - event = "message", - id = "1", - //language=json - data = - """{"jsonrpc":"2.0","method":"notifications/progress","params":{"progressToken":"upload-123","progress":50,"total":100}}""", - ), - ) - delay(200.milliseconds) - emit( - ServerSentEvent( - //language=json - data = - """{"jsonrpc":"2.0","method":"notifications/progress","params":{"progressToken":"upload-123","progress":50,"total":100}}""", - ), - ) - } - } - - // TODO: how to get notifications via Client API? - - mockMcp.handleWithResult( - jsonRpcMethod = "tools/list", - sessionId = sessionId, - // language=json - result = """ - { - "tools": [ - { - "name": "get_weather", - "title": "Weather Information Provider", - "description": "Get current weather information for a location", - "inputSchema": { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "City name or zip code" - } - }, - "required": ["location"] - }, - "outputSchema": { - "type": "object", - "properties": { - "temperature": { - "type": "number", - "description": "Temperature, Celsius" - } - }, - "required": ["temperature"] - }, - "_meta": {} - } - ] - } - """.trimIndent(), - ) - - connect(client) - - val listToolsResult = client.listTools() - - listToolsResult.tools shouldContain Tool( - name = "get_weather", - title = "Weather Information Provider", - description = "Get current weather information for a location", - inputSchema = ToolSchema( - properties = buildJsonObject { - putJsonObject("location") { - put("type", "string") - put("description", "City name or zip code") - } - }, - required = listOf("location"), - ), - outputSchema = ToolSchema( - properties = buildJsonObject { - putJsonObject("temperature") { - put("type", "number") - put("description", "Temperature, Celsius") - } - }, - required = listOf("temperature"), - ), - annotations = null, - meta = EmptyJsonObject, - ) - - client.close() - } - - @Test - fun `terminateSession sends DELETE request`() = runBlocking { - val client = Client( - clientInfo = Implementation(name = "client1", version = "1.0.0"), - options = ClientOptions(capabilities = ClientCapabilities()), - ) - val sessionId = Uuid.random().toString() - - mockMcp.onInitialize(clientName = "client1", sessionId = sessionId) - mockMcp.handleJSONRPCRequest( - jsonRpcMethod = "notifications/initialized", - expectedSessionId = sessionId, - sessionId = sessionId, - statusCode = HttpStatusCode.Accepted, - ) - mockMcp.handleSubscribeWithGet(sessionId) { emptyFlow() } - - connect(client) - - mockMcp.mockUnsubscribeRequest(sessionId = sessionId) - (client.transport as StreamableHttpClientTransport).terminateSession() - (client.transport as StreamableHttpClientTransport).sessionId shouldBe null - - client.close() - } - - @Test - fun `handle MethodNotAllowed`() = runBlocking { - checkSupportNonStreamingResponse( - ContentType.Text.EventStream, - HttpStatusCode.MethodNotAllowed, - ) - } - - @Test - fun `handle non-streaming response`() = runBlocking { - checkSupportNonStreamingResponse( - ContentType.Application.Json, - HttpStatusCode.OK, - ) - } - - private suspend fun checkSupportNonStreamingResponse(contentType: ContentType, statusCode: HttpStatusCode) { - val sessionId = "SID_${Uuid.random().toHexString()}" - val clientName = "client-${Uuid.random().toHexString()}" - val client = Client( - clientInfo = Implementation(name = clientName, version = "1.0.0"), - options = ClientOptions( - capabilities = ClientCapabilities(), - ), - ) - - mockMcp.onInitialize(clientName = clientName, sessionId = sessionId) - - mockMcp.handleJSONRPCRequest( - jsonRpcMethod = "notifications/initialized", - expectedSessionId = sessionId, - sessionId = sessionId, - statusCode = HttpStatusCode.Accepted, - ) - - mockMcp.onSubscribe( - httpMethod = HttpMethod.Get, - sessionId = sessionId, - ) respondsWith { - headers += MCP_SESSION_ID_HEADER to sessionId - body = null - httpStatus = statusCode - this.contentType = contentType - } - - mockMcp.handleWithResult(jsonRpcMethod = "ping", sessionId = sessionId) { - buildJsonObject {} - } - - connect(client) - - delay(1.seconds) - - client.ping() // connection is still alive - - client.close() - } -} From ebc53f0ded3a309dcd6458bca16fcb52450b11d2 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Mon, 18 May 2026 13:22:26 +0200 Subject: [PATCH 022/178] feat!: capabilities for tasks, elicitation (#732) closes #544 Replaces opaque `JsonObject?` modelling of `elicitation` with a typed `ClientCapabilities.Elicitation` (`form`, `url`), and adds the new `tasks` capability on both `ClientCapabilities` and `ServerCapabilities` (with `list`, `cancel`, per-request-type augmentation). Wires capability assertions for `tasks/*` methods and `notifications/tasks/status` into `Client` and `ServerSession` ## How Has This Been Tested? unit tests ## Breaking Changes yes now elicitation is a specific class in capabilities ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../kotlin/sdk/client/ClientTest.kt | 4 +- .../kotlin/sdk/client/Client.kt | 31 ++ .../sdk/client/ClientAssertCapabilityTest.kt | 152 ++++++++++ kotlin-sdk-core/api/kotlin-sdk-core.api | 281 ++++++++++++++++-- .../kotlin/sdk/types/capabilities.dsl.kt | 22 +- .../kotlin/sdk/types/capabilities.kt | 122 +++++++- .../kotlin/sdk/types/CapabilitiesTest.kt | 121 +++++++- .../sdk/types/dsl/CapabilitiesDslTest.kt | 11 +- .../kotlin/sdk/types/dsl/InitializeDslTest.kt | 12 +- .../kotlin/sdk/server/ServerSession.kt | 34 +++ .../ServerSessionAssertCapabilityTest.kt | 147 +++++++++ 11 files changed, 872 insertions(+), 65 deletions(-) create mode 100644 kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt create mode 100644 kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionAssertCapabilityTest.kt diff --git a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt index e5f6638..5c00b23 100644 --- a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt +++ b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt @@ -1058,7 +1058,7 @@ class ClientTest { Implementation(name = "test client", version = "1.0"), ClientOptions( capabilities = ClientCapabilities( - elicitation = EmptyJsonObject, + elicitation = ClientCapabilities.Elicitation(), ), ), ) @@ -1270,7 +1270,7 @@ class ClientTest { ): Pair = kotlinx.coroutines.coroutineScope { val client = Client( Implementation(name = "test client", version = "1.0"), - ClientOptions(capabilities = ClientCapabilities(elicitation = EmptyJsonObject)), + ClientOptions(capabilities = ClientCapabilities(elicitation = ClientCapabilities.Elicitation())), ) client.setElicitationHandler(handler) diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt index d71c091..ee865af 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt @@ -174,6 +174,7 @@ public open class Client(private val clientInfo: Implementation, options: Client "prompts" -> caps?.prompts != null "resources" -> caps?.resources != null "tools" -> caps?.tools != null + "tasks" -> caps?.tasks != null else -> true } @@ -267,6 +268,12 @@ public open class Client(private val clientInfo: Implementation, options: Client } } + Method.Defined.TasksGet, + Method.Defined.TasksResult, + Method.Defined.TasksList, + Method.Defined.TasksCancel, + -> assertTasksCapabilityForMethod(method) + Method.Defined.Initialize, Method.Defined.Ping -> { // No specific capability required } @@ -277,6 +284,24 @@ public open class Client(private val clientInfo: Implementation, options: Client } } + private fun assertTasksCapabilityForMethod(method: Method) { + val tasks = serverCapabilities?.tasks + ?: error("Server does not support tasks (required for $method)") + when (method) { + Method.Defined.TasksList -> checkNotNull(tasks.list) { + "Server does not support listing tasks (required for $method)" + } + + Method.Defined.TasksCancel -> checkNotNull(tasks.cancel) { + "Server does not support cancelling tasks (required for $method)" + } + + else -> { + // TasksGet, TasksResult: base tasks capability suffices. + } + } + } + override fun assertNotificationCapability(method: Method) { when (method) { Method.Defined.NotificationsRootsListChanged -> { @@ -285,6 +310,12 @@ public open class Client(private val clientInfo: Implementation, options: Client } } + Method.Defined.NotificationsTasksStatus -> { + checkNotNull(capabilities.tasks) { + "Client does not support tasks (required for $method)" + } + } + Method.Defined.NotificationsInitialized, Method.Defined.NotificationsCancelled, Method.Defined.NotificationsProgress, diff --git a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt new file mode 100644 index 0000000..2f322ec --- /dev/null +++ b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt @@ -0,0 +1,152 @@ +package io.modelcontextprotocol.kotlin.sdk.client + +import io.kotest.matchers.string.shouldContain +import io.modelcontextprotocol.kotlin.sdk.shared.Transport +import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions +import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.InitializeResult +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse +import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION +import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertFailsWith + +/** + * Tests for the protected helper [Client.assertCapability]. + * + * `assertCapability(capability, method)` is `protected`, so this suite uses + * a small subclass [TestClient] that re-exports it via [TestClient.exposedAssertCapability]. + * Server capabilities are seeded by completing the initialization handshake through + * [CapabilitiesTransport], which replays a configurable [ServerCapabilities] in its + * `initialize` response. + */ +class ClientAssertCapabilityTest { + + @Test + fun `assertCapability tasks throws when server has no tasks capability`() = runTest { + val client = newTestClient(serverCapabilities = ServerCapabilities()) + val ex = assertFailsWith { + client.exposedAssertCapability("tasks", "tasks/list") + } + ex.message.orEmpty() shouldContain "Server does not support tasks" + } + + @Test + fun `TasksGet throws when server has no tasks capability`() = runTest { + val client = newTestClient(serverCapabilities = ServerCapabilities()) + val ex = assertFailsWith { + client.exposedAssertCapabilityForMethod(Method.Defined.TasksGet) + } + ex.message.orEmpty() shouldContain "Server does not support tasks" + } + + @Test + fun `TasksGet does not throw when server declared tasks`() = runTest { + val client = newTestClient( + serverCapabilities = ServerCapabilities(tasks = ServerCapabilities.Tasks()), + ) + client.exposedAssertCapabilityForMethod(Method.Defined.TasksGet) + } + + @Test + fun `TasksList throws when server tasks list is null`() = runTest { + val client = newTestClient( + serverCapabilities = ServerCapabilities(tasks = ServerCapabilities.Tasks()), + ) + val ex = assertFailsWith { + client.exposedAssertCapabilityForMethod(Method.Defined.TasksList) + } + ex.message.orEmpty() shouldContain "Server does not support listing tasks" + } + + @Test + fun `TasksCancel throws when server tasks cancel is null`() = runTest { + val client = newTestClient( + serverCapabilities = ServerCapabilities(tasks = ServerCapabilities.Tasks()), + ) + val ex = assertFailsWith { + client.exposedAssertCapabilityForMethod(Method.Defined.TasksCancel) + } + ex.message.orEmpty() shouldContain "Server does not support cancelling tasks" + } + + @Test + fun `NotificationsTasksStatus throws when client has no tasks capability`() = runTest { + val client = newTestClient(clientCapabilities = ClientCapabilities()) + val ex = assertFailsWith { + client.exposedAssertNotificationCapability(Method.Defined.NotificationsTasksStatus) + } + ex.message.orEmpty() shouldContain "Client does not support tasks" + } + + private suspend fun newTestClient( + serverCapabilities: ServerCapabilities = ServerCapabilities(), + clientCapabilities: ClientCapabilities = ClientCapabilities(), + ): TestClient { + val client = TestClient( + Implementation("test-client", "1.0.0"), + ClientOptions(capabilities = clientCapabilities), + ) + val transport = CapabilitiesTransport(serverCapabilities) + client.connect(transport) + return client + } + + /** + * Test-only [Client] subclass that exposes the protected + * [Client.assertCapability], [Client.assertCapabilityForMethod], and + * [Client.assertNotificationCapability] helpers to the test code. + */ + private class TestClient(clientInfo: Implementation, options: ClientOptions = ClientOptions()) : + Client(clientInfo, options) { + fun exposedAssertCapability(capability: String, method: String): Unit = assertCapability(capability, method) + fun exposedAssertCapabilityForMethod(method: Method): Unit = assertCapabilityForMethod(method) + fun exposedAssertNotificationCapability(method: Method): Unit = assertNotificationCapability(method) + } + + /** + * Minimal in-memory [Transport] that responds to `initialize` with a configurable + * [ServerCapabilities]. Other JSON-RPC traffic (e.g. the `notifications/initialized` + * sent by [Client.connect]) is silently consumed. + */ + private class CapabilitiesTransport(private val serverCapabilities: ServerCapabilities) : Transport { + private var onMessageBlock: (suspend (JSONRPCMessage) -> Unit)? = null + private var onCloseBlock: (() -> Unit)? = null + + override suspend fun start() = Unit + + override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) { + if (message is JSONRPCRequest && message.method == "initialize") { + onMessageBlock?.invoke( + JSONRPCResponse( + id = message.id, + result = InitializeResult( + protocolVersion = LATEST_PROTOCOL_VERSION, + capabilities = serverCapabilities, + serverInfo = Implementation("mock-server", "1.0.0"), + ), + ), + ) + } + } + + override suspend fun close() { + onCloseBlock?.invoke() + } + + override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) { + onMessageBlock = block + } + + override fun onClose(block: () -> Unit) { + onCloseBlock = block + } + + override fun onError(block: (Throwable) -> Unit) = Unit + } +} diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index c843aea..b588eef 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -607,23 +607,25 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CancelledNotificatio public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Companion; public fun ()V - public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)V - public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)V + public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)V public synthetic fun (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling; public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots; - public final fun component3 ()Lkotlinx/serialization/json/JsonObject; - public final fun component4 ()Lkotlinx/serialization/json/JsonObject; - public final fun component5 ()Ljava/util/Map; - public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities; - public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities; + public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation; + public final fun component4 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks; + public final fun component5 ()Lkotlinx/serialization/json/JsonObject; + public final fun component6 ()Ljava/util/Map; + public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities; public fun equals (Ljava/lang/Object;)Z - public final fun getElicitation ()Lkotlinx/serialization/json/JsonObject; + public final fun getElicitation ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation; public final fun getExperimental ()Lkotlinx/serialization/json/JsonObject; public final fun getExtensions ()Ljava/util/Map; public final fun getRoots ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots; public final fun getSampling ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling; + public final fun getTasks ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks; public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -640,11 +642,42 @@ public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ClientCapa } public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Companion { - public final fun getElicitation ()Lkotlinx/serialization/json/JsonObject; + public final fun getElicitation ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation; public final fun getSampling ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Sampling; public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation$Companion; + public fun ()V + public fun (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)V + public synthetic fun (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lkotlinx/serialization/json/JsonObject; + public final fun component2 ()Lkotlinx/serialization/json/JsonObject; + public final fun copy (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation; + public fun equals (Ljava/lang/Object;)Z + public final fun getForm ()Lkotlinx/serialization/json/JsonObject; + public final fun getUrl ()Lkotlinx/serialization/json/JsonObject; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots$Companion; public fun ()V @@ -705,11 +738,132 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$S public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Companion; + public fun ()V + public fun (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests;)V + public synthetic fun (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lkotlinx/serialization/json/JsonObject; + public final fun component2 ()Lkotlinx/serialization/json/JsonObject; + public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests; + public final fun copy (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks; + public fun equals (Ljava/lang/Object;)Z + public final fun getCancel ()Lkotlinx/serialization/json/JsonObject; + public final fun getList ()Lkotlinx/serialization/json/JsonObject; + public final fun getRequests ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Companion; + public fun ()V + public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation;)V + public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling; + public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation; + public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests; + public fun equals (Ljava/lang/Object;)Z + public final fun getElicitation ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation; + public final fun getSampling ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation$Companion; + public fun ()V + public fun (Lkotlinx/serialization/json/JsonObject;)V + public synthetic fun (Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lkotlinx/serialization/json/JsonObject; + public final fun copy (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation; + public fun equals (Ljava/lang/Object;)Z + public final fun getCreate ()Lkotlinx/serialization/json/JsonObject; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Elicitation$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling$Companion; + public fun ()V + public fun (Lkotlinx/serialization/json/JsonObject;)V + public synthetic fun (Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lkotlinx/serialization/json/JsonObject; + public final fun copy (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling; + public fun equals (Ljava/lang/Object;)Z + public final fun getCreateMessage ()Lkotlinx/serialization/json/JsonObject; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Tasks$Requests$Sampling$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilitiesBuilder { public fun ()V public final fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities; - public final fun elicitation (Lkotlin/jvm/functions/Function1;)V - public final fun elicitation (Lkotlinx/serialization/json/JsonObject;)V + public final fun elicitation (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;)V public final fun experimental (Lkotlin/jvm/functions/Function1;)V public final fun experimental (Lkotlinx/serialization/json/JsonObject;)V public final fun extensions (Ljava/util/Map;)V @@ -4303,17 +4457,18 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Sampling_dslKt { public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Companion; public fun ()V - public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)V - public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)V + public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools; public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources; public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts; public final fun component4 ()Lkotlinx/serialization/json/JsonObject; public final fun component5 ()Lkotlinx/serialization/json/JsonObject; - public final fun component6 ()Lkotlinx/serialization/json/JsonObject; - public final fun component7 ()Ljava/util/Map; - public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities; - public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities; + public final fun component6 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks; + public final fun component7 ()Lkotlinx/serialization/json/JsonObject; + public final fun component8 ()Ljava/util/Map; + public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities; public fun equals (Ljava/lang/Object;)Z public final fun getCompletions ()Lkotlinx/serialization/json/JsonObject; public final fun getExperimental ()Lkotlinx/serialization/json/JsonObject; @@ -4321,6 +4476,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities { public final fun getLogging ()Lkotlinx/serialization/json/JsonObject; public final fun getPrompts ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts; public final fun getResources ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources; + public final fun getTasks ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks; public final fun getTools ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -4403,6 +4559,97 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$R public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Companion; + public fun ()V + public fun (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests;)V + public synthetic fun (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lkotlinx/serialization/json/JsonObject; + public final fun component2 ()Lkotlinx/serialization/json/JsonObject; + public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests; + public final fun copy (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks; + public fun equals (Ljava/lang/Object;)Z + public final fun getCancel ()Lkotlinx/serialization/json/JsonObject; + public final fun getList ()Lkotlinx/serialization/json/JsonObject; + public final fun getRequests ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Companion; + public fun ()V + public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools;)V + public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools; + public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests; + public fun equals (Ljava/lang/Object;)Z + public final fun getTools ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools$Companion; + public fun ()V + public fun (Lkotlinx/serialization/json/JsonObject;)V + public synthetic fun (Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lkotlinx/serialization/json/JsonObject; + public final fun copy (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools; + public fun equals (Ljava/lang/Object;)Z + public final fun getCall ()Lkotlinx/serialization/json/JsonObject; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tasks$Requests$Tools$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools$Companion; public fun ()V diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.dsl.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.dsl.kt index 75e923b..0d8b2b7 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.dsl.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/capabilities.dsl.kt @@ -38,7 +38,7 @@ import kotlinx.serialization.json.buildJsonObject public class ClientCapabilitiesBuilder @PublishedApi internal constructor() { private var sampling: ClientCapabilities.Sampling? = null private var roots: ClientCapabilities.Roots? = null - private var elicitation: JsonObject? = null + private var elicitation: ClientCapabilities.Elicitation? = null private var extensions: Map? = null private var experimental: JsonObject? = null @@ -47,7 +47,7 @@ public class ClientCapabilitiesBuilder @PublishedApi internal constructor() { * * Pass `ClientCapabilities.Sampling()` to enable base sampling with no sub-capabilities. * Construct `ClientCapabilities.Sampling(tools = EmptyJsonObject, context = EmptyJsonObject)` - * directly to enable SEP-1577 sub-capabilities. + * directly to enable tools/context sub-capabilities. * * Example: * ```kotlin @@ -99,26 +99,10 @@ public class ClientCapabilitiesBuilder @PublishedApi internal constructor() { * * @param value The elicitation capability configuration */ - public fun elicitation(value: JsonObject) { + public fun elicitation(value: ClientCapabilities.Elicitation) { this.elicitation = value } - /** - * Indicates that the client supports elicitation from the server with custom configuration. - * - * Example: - * ```kotlin - * capabilities { - * elicitation { - * put("mode", JsonPrimitive("interactive")) - * } - * } - * ``` - * - * @param block Lambda for building the elicitation configuration - */ - public fun elicitation(block: JsonObjectBuilder.() -> Unit): Unit = elicitation(buildJsonObject(block)) - /** * Defines extensions that the client supports. * 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 e13a750..cd78b58 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 @@ -41,9 +41,11 @@ public data class Implementation( * supports that capability. * * @property sampling Present if the client supports sampling from an LLM. - * Use [ClientCapabilities.Sampling] to configure SEP-1577 sub-capabilities (tools, context). + * Use [ClientCapabilities.Sampling] to configure tools/context sub-capabilities. * @property roots Present if the client supports listing roots. * @property elicitation Present if the client supports elicitation from the server. + * Use [ClientCapabilities.Elicitation] to configure form/url mode sub-capabilities. + * @property tasks Present if the client supports task-augmented requests, listing, or cancellation. * @property experimental Experimental, non-standard capabilities that the client supports. * Keys are capability names, values are capability-specific configuration objects. * @property extensions Optional extensions that the client supports. @@ -54,23 +56,33 @@ public data class Implementation( public data class ClientCapabilities( public val sampling: Sampling? = null, public val roots: Roots? = null, - public val elicitation: JsonObject? = null, + public val elicitation: Elicitation? = null, + public val tasks: Tasks? = null, public val experimental: JsonObject? = null, public val extensions: Map? = null, ) { /** - * Source-compatibility constructor retaining the pre-SEP-1577 `sampling: JsonObject?` - * shape. Any non-null [sampling] is converted to an empty [Sampling] (sub-capabilities - * cannot be recovered from the old opaque `JsonObject`). + * Source-compatibility constructor retaining the older `sampling: JsonObject?` / + * `elicitation: JsonObject?` shapes. Any non-null [sampling] is converted to an + * empty [Sampling], and any non-null [elicitation] is converted to an empty + * [Elicitation] (sub-capabilities cannot be recovered from the old opaque + * `JsonObject`). */ @Deprecated( - "ClientCapabilities.sampling is now typed. Pass a ClientCapabilities.Sampling? " + + "ClientCapabilities.sampling and ClientCapabilities.elicitation are now typed. " + + "Pass typed ClientCapabilities.Sampling? / ClientCapabilities.Elicitation? " + "instead of JsonObject?.", ReplaceWith( - "ClientCapabilities(sampling?.let { ClientCapabilities.Sampling() }, " + - "roots, elicitation, experimental, extensions)", + "ClientCapabilities(" + + "sampling?.let { ClientCapabilities.Sampling() }, " + + "roots, " + + "elicitation?.let { ClientCapabilities.Elicitation() }, " + + "tasks = null, " + + "experimental = experimental, " + + "extensions = extensions)", ), + level = DeprecationLevel.WARNING, ) public constructor( sampling: JsonObject?, @@ -81,7 +93,8 @@ public data class ClientCapabilities( ) : this( sampling = sampling?.let { Sampling() }, roots = roots, - elicitation = elicitation, + elicitation = elicitation?.let { Elicitation() }, + tasks = null, experimental = experimental, extensions = extensions, ) @@ -101,11 +114,11 @@ public data class ClientCapabilities( /** * @property sampling convenience value to enable the base sampling capability with no sub-capabilities - * @property elicitation convenience value to enable the elicitation capability + * @property elicitation convenience value to enable the elicitation capability with default form mode */ public companion object { public val sampling: Sampling = Sampling() - public val elicitation: JsonObject = EmptyJsonObject + public val elicitation: Elicitation = Elicitation() } /** @@ -120,6 +133,60 @@ public data class ClientCapabilities( */ @Serializable public data class Roots(val listChanged: Boolean? = null) + + /** + * Sub-capabilities for elicitation. + * + * An empty [Elicitation] (both fields null) is equivalent to declaring `form` mode only. + * + * @property form Present if the client supports form-mode elicitation + * (in-band structured data collection). + * @property url Present if the client supports url-mode elicitation + * (out-of-band interaction via URL navigation). + */ + @Serializable + public data class Elicitation(public val form: JsonObject? = null, public val url: JsonObject? = null) + + /** + * Sub-capabilities for tasks (client side). + * + * Declares which client-side requests can be augmented with task execution, + * and whether the client supports listing and cancelling tasks. + * + * @property list Present if the client supports the `tasks/list` operation. + * @property cancel Present if the client supports the `tasks/cancel` operation. + * @property requests Present if the client supports task-augmented sampling and/or elicitation requests. + */ + @Serializable + public data class Tasks( + public val list: JsonObject? = null, + public val cancel: JsonObject? = null, + public val requests: Requests? = null, + ) { + /** + * Task-augmentable client-side request categories. + * + * @property sampling Present if the client supports task-augmented `sampling/createMessage` requests. + * @property elicitation Present if the client supports task-augmented `elicitation/create` requests. + */ + @Serializable + public data class Requests( + public val sampling: Sampling? = null, + public val elicitation: Elicitation? = null, + ) { + /** + * @property createMessage Present if the client supports task-augmented `sampling/createMessage` requests. + */ + @Serializable + public data class Sampling(public val createMessage: JsonObject? = null) + + /** + * @property create Present if the client supports task-augmented `elicitation/create` requests. + */ + @Serializable + public data class Elicitation(public val create: JsonObject? = null) + } + } } /** @@ -137,6 +204,7 @@ public data class ClientCapabilities( * @property logging Present if the server supports sending log messages to the client. * @property completions Present if the server supports argument autocompletion suggestions. * Keys are capability names, values are capability-specific configuration objects. + * @property tasks Present if the server supports task-augmented requests, listing, or cancellation. * @property experimental Experimental, non-standard capabilities that the server supports. * @property extensions Optional extensions that the server supports. * Keys are extension identifiers (e.g., `"io.modelcontextprotocol/ui"`), @@ -149,6 +217,7 @@ public data class ServerCapabilities( val prompts: Prompts? = null, val logging: JsonObject? = null, val completions: JsonObject? = null, + val tasks: Tasks? = null, val experimental: JsonObject? = null, val extensions: Map? = null, ) { @@ -199,4 +268,35 @@ public data class ServerCapabilities( */ @Serializable public data class Prompts(val listChanged: Boolean? = null) + + /** + * Sub-capabilities for tasks (server side). + * + * Declares which server-side requests can be augmented with task execution, + * and whether the server supports listing and cancelling tasks. + * + * @property list Present if the server supports the `tasks/list` operation. + * @property cancel Present if the server supports the `tasks/cancel` operation. + * @property requests Present if the server supports task-augmented tool call requests. + */ + @Serializable + public data class Tasks( + public val list: JsonObject? = null, + public val cancel: JsonObject? = null, + public val requests: Requests? = null, + ) { + /** + * Task-augmentable server-side request categories. + * + * @property tools Present if the server supports task-augmented `tools/call` requests. + */ + @Serializable + public data class Requests(public val tools: Tools? = null) { + /** + * @property call Present if the server supports task-augmented `tools/call` requests. + */ + @Serializable + public data class Tools(public val call: JsonObject? = null) + } + } } diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt index 8b2e4f8..06949a6 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt @@ -313,7 +313,7 @@ class CapabilitiesTest { assertEquals(ClientCapabilities.Sampling(), capabilities.sampling) assertEquals(true, capabilities.roots?.listChanged) - assertEquals(EmptyJsonObject, capabilities.elicitation) + assertEquals(ClientCapabilities.Elicitation(), capabilities.elicitation) } @Test @@ -804,4 +804,123 @@ class CapabilitiesTest { val caps = ClientCapabilities() caps.sampling shouldBe null } + + @Test + fun `should serialize ServerCapabilities with tasks`() { + val capabilities = ServerCapabilities( + tasks = ServerCapabilities.Tasks( + list = EmptyJsonObject, + cancel = EmptyJsonObject, + requests = ServerCapabilities.Tasks.Requests( + tools = ServerCapabilities.Tasks.Requests.Tools(call = EmptyJsonObject), + ), + ), + ) + verifySerialization( + capabilities, + McpJson, + """ + { + "tasks": { + "list": {}, + "cancel": {}, + "requests": { + "tools": { + "call": {} + } + } + } + } + """.trimIndent(), + ) + } + + @Test + fun `should deserialize ServerCapabilities with tasks`() { + val json = """ + { + "tasks": { + "list": {}, + "requests": {"tools": {"call": {}}} + } + } + """.trimIndent() + val capabilities = verifyDeserialization(McpJson, json) + assertEquals(EmptyJsonObject, capabilities.tasks?.list) + assertNull(capabilities.tasks?.cancel) + assertEquals(EmptyJsonObject, capabilities.tasks?.requests?.tools?.call) + } + + @Test + fun `should serialize ClientCapabilities with tasks`() { + val capabilities = ClientCapabilities( + tasks = ClientCapabilities.Tasks( + list = EmptyJsonObject, + cancel = EmptyJsonObject, + requests = ClientCapabilities.Tasks.Requests( + sampling = ClientCapabilities.Tasks.Requests.Sampling(createMessage = EmptyJsonObject), + elicitation = ClientCapabilities.Tasks.Requests.Elicitation(create = EmptyJsonObject), + ), + ), + ) + verifySerialization( + capabilities, + McpJson, + """ + { + "tasks": { + "list": {}, + "cancel": {}, + "requests": { + "sampling": {"createMessage": {}}, + "elicitation": {"create": {}} + } + } + } + """.trimIndent(), + ) + } + + @Test + fun `should serialize ClientCapabilities with structured elicitation form and url`() { + val capabilities = ClientCapabilities( + elicitation = ClientCapabilities.Elicitation(form = EmptyJsonObject, url = EmptyJsonObject), + ) + verifySerialization( + capabilities, + McpJson, + """ + { + "elicitation": { + "form": {}, + "url": {} + } + } + """.trimIndent(), + ) + } + + @Test + fun `should deserialize ClientCapabilities with elicitation and tasks`() { + val json = """ + { + "elicitation": {"form": {}, "url": {}}, + "tasks": { + "list": {}, + "cancel": {}, + "requests": { + "sampling": {"createMessage": {}}, + "elicitation": {"create": {}} + } + } + } + """.trimIndent() + val capabilities = verifyDeserialization(McpJson, json) + assertEquals(EmptyJsonObject, capabilities.elicitation?.form) + assertEquals(EmptyJsonObject, capabilities.elicitation?.url) + assertEquals(EmptyJsonObject, capabilities.tasks?.list) + assertEquals(EmptyJsonObject, capabilities.tasks?.cancel) + assertEquals(EmptyJsonObject, capabilities.tasks?.requests?.sampling?.createMessage) + assertEquals(EmptyJsonObject, capabilities.tasks?.requests?.elicitation?.create) + } } diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/CapabilitiesDslTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/CapabilitiesDslTest.kt index ee2fe43..25d9ee6 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/CapabilitiesDslTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/CapabilitiesDslTest.kt @@ -44,11 +44,7 @@ class CapabilitiesDslTest { capabilities { sampling(ClientCapabilities.Sampling(tools = EmptyJsonObject)) roots(listChanged = true) - elicitation { - put("mode", "interactive") - put("timeout", 30) - put("retries", 3) - } + elicitation(ClientCapabilities.Elicitation(form = EmptyJsonObject, url = EmptyJsonObject)) experimental { put("customFeature", true) put("version", "1.0") @@ -74,9 +70,8 @@ class CapabilitiesDslTest { listChanged shouldBe true } elicitation shouldNotBeNull { - get("mode")?.jsonPrimitive?.content shouldBe "interactive" - get("timeout")?.jsonPrimitive?.content shouldBe "30" - get("retries")?.jsonPrimitive?.content shouldBe "3" + form shouldBe EmptyJsonObject + url shouldBe EmptyJsonObject } experimental shouldNotBeNull { get("customFeature")?.jsonPrimitive?.content shouldBe "true" diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/InitializeDslTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/InitializeDslTest.kt index 17e5ae6..da2a4cb 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/InitializeDslTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/dsl/InitializeDslTest.kt @@ -22,9 +22,7 @@ class InitializeDslTest { capabilities { sampling(ClientCapabilities.Sampling()) roots(listChanged = true) - elicitation { - put("mode", "interactive") - } + elicitation(ClientCapabilities.Elicitation(form = EmptyJsonObject)) experimental { put("custom", true) } @@ -46,7 +44,7 @@ class InitializeDslTest { request.params.capabilities.shouldNotBeNull { sampling shouldNotBeNull { } roots?.listChanged shouldBe true - elicitation?.get("mode")?.jsonPrimitive?.content shouldBe "interactive" + elicitation?.form shouldBe EmptyJsonObject experimental?.get("custom")?.jsonPrimitive?.content shouldBe "true" extensions shouldNotBeNull { get("io.modelcontextprotocol/ui") shouldBe EmptyJsonObject @@ -78,7 +76,7 @@ class InitializeDslTest { @Test fun `capabilities DSL should support direct typed values`() { val samplingValue = ClientCapabilities.Sampling(tools = EmptyJsonObject) - val elicitationObj = buildJsonObject { put("key", "value") } + val elicitationValue = ClientCapabilities.Elicitation(form = EmptyJsonObject, url = EmptyJsonObject) val experimentalObj = buildJsonObject { put("key", "value") } val extensionsMap = mapOf( "io.modelcontextprotocol/ui" to buildJsonObject { put("key", "value") }, @@ -88,7 +86,7 @@ class InitializeDslTest { protocolVersion = "1.0" capabilities { sampling(samplingValue) - elicitation(elicitationObj) + elicitation(elicitationValue) experimental(experimentalObj) extensions(extensionsMap) } @@ -97,7 +95,7 @@ class InitializeDslTest { request.params.capabilities.shouldNotBeNull { sampling shouldBe samplingValue - elicitation shouldBe elicitationObj + elicitation shouldBe elicitationValue experimental shouldBe experimentalObj extensions shouldBe extensionsMap } diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt index e7da26f..d215bd5 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt @@ -172,6 +172,12 @@ public open class ServerSession( } } + Defined.TasksGet, + Defined.TasksResult, + Defined.TasksList, + Defined.TasksCancel, + -> assertTasksCapabilityForMethod(method) + Defined.Ping -> { // No specific capability required } @@ -182,6 +188,28 @@ public open class ServerSession( } } + private fun assertTasksCapabilityForMethod(method: Method) { + val tasks = clientCapabilities?.tasks + ?: error("Client does not support tasks (required for ${method.value})") + when (method) { + Defined.TasksList -> { + if (tasks.list == null) { + error("Client does not support listing tasks (required for ${method.value})") + } + } + + Defined.TasksCancel -> { + if (tasks.cancel == null) { + error("Client does not support cancelling tasks (required for ${method.value})") + } + } + + else -> { + // TasksGet, TasksResult: base tasks capability suffices. + } + } + } + /** * Asserts that the server can handle the specified notification method. * @@ -225,6 +253,12 @@ public open class ServerSession( } } + Defined.NotificationsTasksStatus -> { + if (serverCapabilities.tasks == null) { + error("Server does not support tasks (required for ${method.value})") + } + } + Defined.NotificationsCancelled, Defined.NotificationsProgress, -> { diff --git a/kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionAssertCapabilityTest.kt b/kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionAssertCapabilityTest.kt new file mode 100644 index 0000000..a172e96 --- /dev/null +++ b/kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionAssertCapabilityTest.kt @@ -0,0 +1,147 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.kotest.matchers.string.shouldContain +import io.modelcontextprotocol.kotlin.sdk.shared.Transport +import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions +import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION +import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.RequestId +import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.toJSON +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertFailsWith + +/** + * Tests for the protected helpers [ServerSession.assertCapabilityForMethod] and + * [ServerSession.assertNotificationCapability]. + * + * Both helpers are `protected`, so this suite uses a small subclass [TestServerSession] + * that re-exports them via [TestServerSession.exposedAssertCapabilityForMethod] and + * [TestServerSession.exposedAssertNotificationCapability]. Client capabilities are + * seeded by replaying an [InitializeRequest] through [InitializeReplayTransport]: + * the transport drives the inbound side of the handshake on `start()`, which causes + * the session's internal [Method.Defined.Initialize] handler to populate + * [ServerSession.clientCapabilities]. + */ +class ServerSessionAssertCapabilityTest { + + @Test + fun `server TasksGet throws when client has no tasks capability`() = runTest { + val session = newTestServerSession(clientCapabilities = ClientCapabilities()) + val ex = assertFailsWith { + session.exposedAssertCapabilityForMethod(Method.Defined.TasksGet) + } + ex.message.orEmpty() shouldContain "Client does not support tasks" + } + + @Test + fun `server TasksGet succeeds when client declared tasks`() = runTest { + val session = newTestServerSession( + clientCapabilities = ClientCapabilities(tasks = ClientCapabilities.Tasks()), + ) + session.exposedAssertCapabilityForMethod(Method.Defined.TasksGet) + } + + @Test + fun `server TasksList throws when client tasks list is null`() = runTest { + val session = newTestServerSession( + clientCapabilities = ClientCapabilities(tasks = ClientCapabilities.Tasks()), + ) + val ex = assertFailsWith { + session.exposedAssertCapabilityForMethod(Method.Defined.TasksList) + } + ex.message.orEmpty() shouldContain "Client does not support listing tasks" + } + + @Test + fun `server TasksCancel throws when client tasks cancel is null`() = runTest { + val session = newTestServerSession( + clientCapabilities = ClientCapabilities(tasks = ClientCapabilities.Tasks()), + ) + val ex = assertFailsWith { + session.exposedAssertCapabilityForMethod(Method.Defined.TasksCancel) + } + ex.message.orEmpty() shouldContain "Client does not support cancelling tasks" + } + + @Test + fun `server NotificationsTasksStatus throws when server has no tasks capability`() = runTest { + val session = newTestServerSession(serverCapabilities = ServerCapabilities()) + val ex = assertFailsWith { + session.exposedAssertNotificationCapability(Method.Defined.NotificationsTasksStatus) + } + ex.message.orEmpty() shouldContain "Server does not support tasks" + } + + private suspend fun newTestServerSession( + clientCapabilities: ClientCapabilities = ClientCapabilities(), + serverCapabilities: ServerCapabilities = ServerCapabilities(), + ): TestServerSession { + val session = TestServerSession( + serverInfo = Implementation("test-server", "1.0.0"), + options = ServerOptions(capabilities = serverCapabilities), + instructions = null, + ) + val transport = InitializeReplayTransport(clientCapabilities) + session.connect(transport) + return session + } + + /** + * Test-only [ServerSession] subclass that exposes the protected + * [ServerSession.assertCapabilityForMethod] and + * [ServerSession.assertNotificationCapability] helpers to the test code. + */ + private class TestServerSession(serverInfo: Implementation, options: ServerOptions, instructions: String?) : + ServerSession(serverInfo, options, instructions) { + fun exposedAssertCapabilityForMethod(method: Method): Unit = assertCapabilityForMethod(method) + fun exposedAssertNotificationCapability(method: Method): Unit = assertNotificationCapability(method) + } + + /** + * Minimal in-memory [Transport] that drives the server-side initialize handshake. + * + * On [start], it dispatches an [InitializeRequest] carrying the configured + * [clientCapabilities] to the session via [onMessage]. The session's internal + * `initialize` handler runs synchronously and populates + * [ServerSession.clientCapabilities] before [start] returns. Other JSON-RPC + * traffic the session subsequently emits is silently consumed. + */ + private class InitializeReplayTransport(private val clientCapabilities: ClientCapabilities) : Transport { + private var onMessageBlock: (suspend (JSONRPCMessage) -> Unit)? = null + private var onCloseBlock: (() -> Unit)? = null + + override suspend fun start() { + val initializeRequest = InitializeRequest( + params = InitializeRequestParams( + protocolVersion = LATEST_PROTOCOL_VERSION, + capabilities = clientCapabilities, + clientInfo = Implementation("mock-client", "1.0.0"), + ), + ).toJSON().copy(id = RequestId.NumberId(1)) + onMessageBlock?.invoke(initializeRequest) + } + + override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) = Unit + + override suspend fun close() { + onCloseBlock?.invoke() + } + + override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) { + onMessageBlock = block + } + + override fun onClose(block: () -> Unit) { + onCloseBlock = block + } + + override fun onError(block: (Throwable) -> Unit) = Unit + } +} From 97a429f42488fcd99e627f64d95d81a405add39f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 13:52:17 +0200 Subject: [PATCH 023/178] chore(deps): bump org.junit.jupiter:junit-jupiter-params from 5.14.3 to 5.14.4 in the testing group across 1 directory (#768) Bumps the testing group with 1 update in the / directory: [org.junit.jupiter:junit-jupiter-params](https://github.com/junit-team/junit-framework). Updates `org.junit.jupiter:junit-jupiter-params` from 5.14.3 to 5.14.4
    Release notes

    Sourced from org.junit.jupiter:junit-jupiter-params's releases.

    JUnit 5.14.4 = Platform 1.14.4 + Jupiter 5.14.4 + Vintage 5.14.4

    See Release Notes.

    Full Changelog: https://github.com/junit-team/junit-framework/compare/r5.14.3...r5.14.4

    Commits
    • 096fd69 Release 5.14.4
    • 11fd02b Remove JDK 24 (EOL)
    • 5b7f023 Fix integration tests on JDK 27
    • 18f842a Test against JDK 26 (GA) and JDK 27 (EA)
    • a5bf336 Polish 5.14.4 release notes
    • 7667c14 Fix race condition in NodeTestTask (#5427)
    • ac01f2d Include full display name in legacy XML reports (#5524)
    • fbd4a8e Include class template invocation index in legacy reporting names
    • 7d6f0c0 Only check PDF for GA releases
    • 14f534d Test 5.14.x against JDK 25 ga (#5623)
    • Additional commits viewable in compare view

    Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | org.junit.jupiter:junit-jupiter-params | [>= 6.a, < 7] |
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5b04ca4..2480fb0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ mockk = "1.14.9" serialization = "1.11.0" slf4j = "2.0.17" logback = "1.5.32" -junit = "5.14.3" +junit = "5.14.4" [libraries] # Plugins From 9764036ec51f4f1bbeb8e01649c99653fb4bb8b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 14:13:35 +0200 Subject: [PATCH 024/178] chore(deps): bump org.slf4j:slf4j-simple from 2.0.17 to 2.0.18 in the infrastructure group across 1 directory (#769) Bumps the infrastructure group with 1 update in the / directory: org.slf4j:slf4j-simple. Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2480fb0..bf36c70 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ ktor = "3.3.3" logging = "8.0.02" mockk = "1.14.9" serialization = "1.11.0" -slf4j = "2.0.17" +slf4j = "2.0.18" logback = "1.5.32" junit = "5.14.4" From af7c5e13174465ef75fef90be46b250f3e1992db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 15:18:30 +0200 Subject: [PATCH 025/178] chore(deps): bump the other-dependencies group across 5 directories with 3 updates (#770) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 3 updates in the /samples/kotlin-mcp-client directory: [gradle-wrapper](https://github.com/gradle/gradle), [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java) and org.slf4j:slf4j-simple. Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and org.slf4j:slf4j-simple. Bumps the other-dependencies group with 1 update in the /samples/kotlinlang-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 2 updates in the /samples/simple-streamable-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and org.slf4j:slf4j-simple. Bumps the other-dependencies group with 2 updates in the /samples/weather-stdio-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and org.slf4j:slf4j-simple. Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `com.anthropic:anthropic-java` from 2.31.0 to 2.32.0
    Release notes

    Sourced from com.anthropic:anthropic-java's releases.

    v2.32.0

    2.32.0 (2026-05-13)

    Full Changelog: v2.31.0...v2.32.0

    Features

    • api: Add BetaManagedAgentsSearchResultBlock types (253feaa)
    • api: Add support for cache diagnostics beta (7a32231)
    • mcp: add mcp tool helpers (#1161) (5d58812)

    Chores

    Changelog

    Sourced from com.anthropic:anthropic-java's changelog.

    2.32.0 (2026-05-13)

    Full Changelog: v2.31.0...v2.32.0

    Features

    • api: Add BetaManagedAgentsSearchResultBlock types (253feaa)
    • api: Add support for cache diagnostics beta (7a32231)
    • mcp: add mcp tool helpers (#1161) (5d58812)

    Chores

    Commits
    • 72d9622 release: 2.32.0
    • b99fa17 feat(api): Add support for cache diagnostics beta
    • 54fefae test: re-enable beta skill/version create tests (#1243)
    • 5224fff chore(api): spec updates
    • dd0d0da codegen metadata
    • 3f9458f feat(api): Add BetaManagedAgentsSearchResultBlock types
    • c43e2f1 ci: pin GitHub Actions to commit SHAs
    • 5228802 feat(mcp): add mcp tool helpers (#1161)
    • 1bc3d65 ci(release-please): don't split out aws release versioning for now (#332)
    • See full diff in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `org.slf4j:slf4j-simple` from 2.0.17 to 2.0.18 Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.0 to 9.5.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by upd... _Description has been truncated_ Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 6d4a979..f425a56 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] -anthropic = "2.31.0" +anthropic = "2.32.0" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" shadow = "9.4.1" -slf4j = "2.0.17" +slf4j = "2.0.18" [libraries] anthropic-java = { group = "com.anthropic", name = "anthropic-java", version.ref = "anthropic" } diff --git a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties index b52fb7e..df6a6ad 100644 --- a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 2eccae2..91d7878 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" -slf4j = "2.0.17" +slf4j = "2.0.18" shadow = "9.4.1" [libraries] diff --git a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties index b52fb7e..df6a6ad 100644 --- a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties index b52fb7e..df6a6ad 100644 --- a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 3296f05..70a87ca 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin = "2.3.21" ktor = "3.3.3" junit = "6.0.3" mcp-kotlin = "0.12.0" -slf4j = "2.0.17" +slf4j = "2.0.18" shadow = "9.4.1" [libraries] diff --git a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties index b52fb7e..df6a6ad 100644 --- a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 8eee298..ac62c36 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -5,7 +5,7 @@ ktor = "3.3.3" logging = "8.0.02" mcp-kotlin = "0.12.0" shadow = "9.4.1" -slf4j = "2.0.17" +slf4j = "2.0.18" [libraries] kotlin-logging = { group = "io.github.oshai", name = "kotlin-logging-jvm", version.ref = "logging" } diff --git a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties index b52fb7e..df6a6ad 100644 --- a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From c8545606bb87faf7595dafa7269f31f5a5f75703 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 19:59:31 +0200 Subject: [PATCH 026/178] chore(deps): bump the all-dependencies group across 1 directory with 2 updates (#777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 2 updates in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [tsx](https://github.com/privatenumber/tsx). Updates `@types/node` from 25.6.2 to 25.9.0

    Commits

    Updates `tsx` from 4.21.0 to 4.22.1
    Release notes

    Sourced from tsx's releases.

    v4.22.1

    4.22.1 (2026-05-17)

    Bug Fixes

    • resolve tsconfig path aliases containing a colon (#780) (6979f28)

    This release is also available on:

    v4.22.0

    4.22.0 (2026-05-14)

    Features


    This release is also available on:

    v4.21.1

    4.21.1 (2026-05-14)

    Bug Fixes

    • support Node 20.11/21.2 import.meta paths (acf3d8f)
    • support Node.js 24.15.0 (c1d2d45)
    • support Node.js 26.1.0 and 25.9.0 (1d7e528)

    This release is also available on:

    Commits
    • 6979f28 fix: resolve tsconfig path aliases containing a colon (#780)
    • b29f6ee feat: upgrade esbuild to 0.28 (#789)
    • 0dd17e9 test: cover registerHooks loader composition
    • acf3d8f fix: support Node 20.11/21.2 import.meta paths
    • 4bbef80 test: cover configDir paths without baseUrl
    • dddc5ce test: cover sync-hook watch reruns and cleanup retries
    • 09e8f8c test: assert CLI runs without warnings
    • 1d7e528 fix: support Node.js 26.1.0 and 25.9.0
    • c1d2d45 fix: support Node.js 24.15.0
    • d04672d test: update node version feature gates
    • Additional commits viewable in compare view
    Maintainer changes

    This version was pushed to npm by GitHub Actions, a new releaser for tsx since your current version.


    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 264 ++++++++---------- .../src/jvmTest/typescript/package.json | 4 +- 2 files changed, 122 insertions(+), 146 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 6aa468d..ac2f59d 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,16 +15,16 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.6.2", + "@types/node": "^25.9.0", "cors": "^2.8.6", - "tsx": "^4.21.0", + "tsx": "^4.22.1", "typescript": "^6.0.3" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", "cpu": [ "ppc64" ], @@ -39,9 +39,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", "cpu": [ "arm" ], @@ -56,9 +56,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", "cpu": [ "arm64" ], @@ -73,9 +73,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", "cpu": [ "x64" ], @@ -90,9 +90,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", "cpu": [ "arm64" ], @@ -107,9 +107,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", "cpu": [ "x64" ], @@ -124,9 +124,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", "cpu": [ "arm64" ], @@ -141,9 +141,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", "cpu": [ "x64" ], @@ -158,9 +158,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", "cpu": [ "arm" ], @@ -175,9 +175,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", "cpu": [ "arm64" ], @@ -192,9 +192,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", "cpu": [ "ia32" ], @@ -209,9 +209,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", "cpu": [ "loong64" ], @@ -226,9 +226,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", "cpu": [ "mips64el" ], @@ -243,9 +243,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", "cpu": [ "ppc64" ], @@ -260,9 +260,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", "cpu": [ "riscv64" ], @@ -277,9 +277,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", "cpu": [ "s390x" ], @@ -294,9 +294,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", "cpu": [ "x64" ], @@ -311,9 +311,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", "cpu": [ "arm64" ], @@ -328,9 +328,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", "cpu": [ "x64" ], @@ -345,9 +345,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", "cpu": [ "arm64" ], @@ -362,9 +362,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", "cpu": [ "x64" ], @@ -379,9 +379,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", "cpu": [ "arm64" ], @@ -396,9 +396,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", "cpu": [ "x64" ], @@ -413,9 +413,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", "cpu": [ "arm64" ], @@ -430,9 +430,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", "cpu": [ "ia32" ], @@ -447,9 +447,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", "cpu": [ "x64" ], @@ -579,13 +579,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.6.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.2.tgz", - "integrity": "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==", + "version": "25.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.0.tgz", + "integrity": "sha512-AOQwYUNolgy3VosiRqXrACUXTN8nJUtPl7FJXMqZVyxiiCLhQuG3jXKvCS1ALr+Y2OmZhzzLVlYPEqJaiqkaJQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.19.0" + "undici-types": ">=7.24.0 <7.24.7" } }, "node_modules/@types/qs": { @@ -888,9 +888,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -901,32 +901,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" } }, "node_modules/escape-html": { @@ -1147,19 +1147,6 @@ "node": ">= 0.4" } }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -1508,16 +1495,6 @@ "node": ">=0.10.0" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -1703,14 +1680,13 @@ } }, "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.1.tgz", + "integrity": "sha512-TvncJykhxAzFCk0VQZKBTClall4Pm7qXDSodb6uxi8QFa8X8mT6ABjxxsQ2opDRYxG7AzcRWXaFtruz5HJKuWg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" + "esbuild": "~0.28.0" }, "bin": { "tsx": "dist/cli.mjs" @@ -1751,9 +1727,9 @@ } }, "node_modules/undici-types": { - "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, "license": "MIT" }, diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 6ec358a..4e776e9 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,9 +16,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.6.2", + "@types/node": "^25.9.0", "cors": "^2.8.6", - "tsx": "^4.21.0", + "tsx": "^4.22.1", "typescript": "^6.0.3" } } From 6d5bac1e6792fc42ca476527df19c56f51666885 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 21:09:59 +0200 Subject: [PATCH 027/178] chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.5.0 to 9.5.1.
    Release notes

    Sourced from gradle-wrapper's releases.

    9.5.1

    The Gradle team is excited to announce Gradle 9.5.1.

    Here are the highlights of this release:

    • Task provenance in reports and failure messages
    • Type-safe accessors for precompiled Kotlin Settings plugins

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: atm1020, mataha, Adam, Attila Kelemen, Benedikt Ritter, Björn Kautler, Caro Silva Rode, CHANHAN, Dmitry Nezavitin, Eng Zer Jun, KugelLibelle, Madalin Valceleanu, Markus Gaisbauer, Oliver Kopp, Philip Wedemann, ploober, Roberto Perez Alcolea, Rohit Anand, Suvrat Acharya, Ujwal Suresh Vanjare, Victor Merkulov

    Upgrade instructions

    Switch your build to use Gradle 9.5.1 by updating your wrapper:

    ./gradlew wrapper --gradle-version=9.5.1 && ./gradlew
    wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • fd78213 Update Documentation Infrastructure: Fix scrolling issue in user manual (#37861)
    • 7758437 fix scroll
    • 2fd605f Only try to run as worker thread in DefaultBuildOperationQueue (#37845)
    • af69849 Release notes for Gradle 9.5.1 (#37853)
    • f4d9d03 Release notes for Gradle 9.5.1
    • 01eda3a Address review feedback on worker-lease retry changes
    • 7024e15 Revert enrich file visitor with size info on release branch (#37848)
    • d51476f Fix tryRunAsWorkerThread null-return test to match contract
    • 090ebab Revert "Add getLength() to FilePropertyVisitor.VisitState"
    • bceab24 Revert "Fix annotation"
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b52fb7e..df6a6ad 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 1ff5f003b657efef39e41f00591e693afa1757e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 14:53:06 +0200 Subject: [PATCH 028/178] chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/typescript (#779) Bumps [qs](https://github.com/ljharb/qs) from 6.14.2 to 6.15.2.
    Changelog

    Sourced from qs's changelog.

    6.15.2

    • [Fix] stringify: skip null/undefined entries in arrayFormat: 'comma' + encodeValuesOnly instead of crashing in encoder
    • [Fix] stringify: use configured delimiter after charsetSentinel (#555)
    • [Fix] stringify: apply formatter to encoded key under strictNullHandling (#554)
    • [Fix] stringify: skip null/undefined filter-array entries instead of crashing in encoder (#551)
    • [Fix] parse: handle nested bracket groups and add regression tests (#530)
    • [readme] fix grammar (#550)
    • [Dev Deps] update @ljharb/eslint-config
    • [Tests] add regression tests for keys containing percent-encoded bracket text

    6.15.1

    • [Fix] parse: parameterLimit: Infinity with throwOnLimitExceeded: true silently drops all parameters
    • [Deps] update @ljharb/eslint-config
    • [Dev Deps] update @ljharb/eslint-config, iconv-lite
    • [Tests] increase coverage

    6.15.0

    • [New] parse: add strictMerge option to wrap object/primitive conflicts in an array (#425, #122)
    • [Fix] duplicates option should not apply to bracket notation keys (#514)
    Commits
    • 9aca407 v6.15.2
    • 5e33d33 [Dev Deps] update @ljharb/eslint-config
    • 21f80b3 [Fix] stringify: skip null/undefined entries in arrayFormat: 'comma' + `e...
    • a0a81ea [Fix] stringify: use configured delimiter after charsetSentinel
    • e3062f7 [Fix] stringify: apply formatter to encoded key under strictNullHandling
    • 0c180a4 [Fix] stringify: skip null/undefined filter-array entries instead of crashi...
    • 3a8b94a [Tests] add regression tests for keys containing percent-encoded bracket text
    • 96755ab [readme] fix grammar
    • a419ce5 [Fix] parse: handle nested bracket groups and add regression tests
    • 3f5e1c5 v6.15.1
    • Additional commits viewable in compare view

    [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=qs&package-manager=npm_and_yarn&previous-version=6.14.2&new-version=6.15.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/modelcontextprotocol/kotlin-sdk/network/alerts).
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index ac2f59d..6dbdf45 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1448,9 +1448,9 @@ } }, "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" From 78066a9cf6970618ef72a8c9b48c8c2fca03c387 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 13:10:59 +0000 Subject: [PATCH 029/178] chore(deps): bump the all-dependencies group across 1 directory with 2 updates (#784) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 2 updates in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [tsx](https://github.com/privatenumber/tsx). Updates `@types/node` from 25.9.0 to 25.9.1
    Commits

    Updates `tsx` from 4.22.1 to 4.22.3
    Release notes

    Sourced from tsx's releases.

    v4.22.3

    4.22.3 (2026-05-19)

    Bug Fixes

    • decode typed loader source (dce02fc)
    • preserve entrypoint with TypeScript preload hooks (68f72f3)

    This release is also available on:

    v4.22.2

    4.22.2 (2026-05-18)

    Bug Fixes

    • preserve CJS JSON require in ESM hooks (35b700b)
    • preserve named exports from CommonJS TypeScript (11de737)
    • support module.exports require(esm) interop (cf8f199)

    This release is also available on:

    Commits
    • dce02fc fix: decode typed loader source
    • 68f72f3 fix: preserve entrypoint with TypeScript preload hooks
    • 69455cf test: cover package exports for ambiguous ESM reexports
    • 35b700b fix: preserve CJS JSON require in ESM hooks
    • ef807db chore: update testing dependencies
    • 3917090 test: document compatibility test taxonomy
    • de8113f refactor: centralize Node capability facts
    • c1f62db test: consolidate tsconfig path edge coverage
    • 4e08174 test: consolidate loader hook coverage
    • 674bb30 test: consolidate tsImport commonjs mts coverage
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 16 ++++++++-------- .../src/jvmTest/typescript/package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 6dbdf45..9e757a5 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,9 +15,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.9.0", + "@types/node": "^25.9.1", "cors": "^2.8.6", - "tsx": "^4.22.1", + "tsx": "^4.22.3", "typescript": "^6.0.3" } }, @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.0.tgz", - "integrity": "sha512-AOQwYUNolgy3VosiRqXrACUXTN8nJUtPl7FJXMqZVyxiiCLhQuG3jXKvCS1ALr+Y2OmZhzzLVlYPEqJaiqkaJQ==", + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", "dev": true, "license": "MIT", "dependencies": { @@ -1680,9 +1680,9 @@ } }, "node_modules/tsx": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.1.tgz", - "integrity": "sha512-TvncJykhxAzFCk0VQZKBTClall4Pm7qXDSodb6uxi8QFa8X8mT6ABjxxsQ2opDRYxG7AzcRWXaFtruz5HJKuWg==", + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.3.tgz", + "integrity": "sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 4e776e9..40c58b3 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,9 +16,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.9.0", + "@types/node": "^25.9.1", "cors": "^2.8.6", - "tsx": "^4.22.1", + "tsx": "^4.22.3", "typescript": "^6.0.3" } } From ff4b6232ba1a107058f6243463c9f7298b52dd76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 18:27:57 +0200 Subject: [PATCH 030/178] chore(deps): bump the other-dependencies group across 3 directories with 3 updates (#781) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework). Bumps the other-dependencies group with 1 update in the /samples/weather-stdio-server directory: [io.github.oshai:kotlin-logging-jvm](https://github.com/oshai/kotlin-logging). Updates `com.anthropic:anthropic-java` from 2.32.0 to 2.34.0
    Release notes

    Sourced from com.anthropic:anthropic-java's releases.

    v2.34.0

    2.34.0 (2026-05-21)

    Full Changelog: v2.33.0...v2.34.0

    Features

    • api: Add support for thinking-token-count beta for estimated tokens in thinking block deltas when streaming (c814c7a)

    Bug Fixes

    • test: set required estimatedTokens on BetaThinkingDelta in BetaMessageAccumulatorTest (04aedf3)

    v2.33.0

    2.33.0 (2026-05-19)

    Full Changelog: v2.32.0...v2.33.0

    Features

    • client: Add support for self-hosted sandboxes in CMA with sandbox helpers (d519362)
    Changelog

    Sourced from com.anthropic:anthropic-java's changelog.

    2.34.0 (2026-05-21)

    Full Changelog: v2.33.0...v2.34.0

    Features

    • api: Add support for thinking-token-count beta for estimated tokens in thinking block deltas when streaming (c814c7a)

    Bug Fixes

    • test: set required estimatedTokens on BetaThinkingDelta in BetaMessageAccumulatorTest (04aedf3)

    2.33.0 (2026-05-19)

    Full Changelog: v2.32.0...v2.33.0

    Features

    • client: Add support for self-hosted sandboxes in CMA with sandbox helpers (d519362)
    Commits
    • 765ec0e release: 2.34.0
    • 56c637f fix(test): set required estimatedTokens on BetaThinkingDelta in BetaMessageAc...
    • 5d636b2 feat(api): Add support for thinking-token-count beta for estimated tokens in ...
    • ba2d183 release: 2.33.0
    • 56312db feat(client): Add support for self-hosted sandboxes in CMA with sandbox helpers
    • See full diff in compare view

    Updates `org.junit.jupiter:junit-jupiter` from 6.0.3 to 6.1.0
    Release notes

    Sourced from org.junit.jupiter:junit-jupiter's releases.

    JUnit 6.1.0 = Platform 6.1.0 + Jupiter 6.1.0 + Vintage 6.1.0

    See Release Notes.

    New Contributors

    Full Changelog: https://github.com/junit-team/junit-framework/compare/r6.0.3...r6.1.0

    JUnit 6.1.0-RC1 = Platform 6.1.0-RC1 + Jupiter 6.1.0-RC1 + Vintage 6.1.0-RC1

    See Release Notes.

    New Contributors

    Full Changelog: https://github.com/junit-team/junit-framework/compare/r6.1.0-M1...r6.1.0-RC1

    JUnit 6.1.0-M1 = Platform 6.1.0-M1 + Jupiter 6.1.0-M1 + Vintage 6.1.0-M1

    See Release Notes.

    New Contributors

    Full Changelog: https://github.com/junit-team/junit-framework/compare/r6.0.0...r6.1.0-M1

    Commits

    Updates `io.github.oshai:kotlin-logging-jvm` from 8.0.02 to 8.0.03
    Release notes

    Sourced from io.github.oshai:kotlin-logging-jvm's releases.

    8.0.03

    What's Changed

    Full Changelog: https://github.com/oshai/kotlin-logging/compare/8.0.02...8.0.03

    Commits
    • b641856 bump version to 8.0.04
    • 3e6096d Fix #598: Allow external configuration of logStartupMessage via Properties an...
    • See full diff in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index f425a56..c263c59 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.32.0" +anthropic = "2.34.0" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 70a87ca..b607a1c 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.3.21" ktor = "3.3.3" -junit = "6.0.3" +junit = "6.1.0" mcp-kotlin = "0.12.0" slf4j = "2.0.18" shadow = "9.4.1" diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index ac62c36..daf5fc1 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ coroutines = "1.11.0" kotlin = "2.3.21" ktor = "3.3.3" -logging = "8.0.02" +logging = "8.0.03" mcp-kotlin = "0.12.0" shadow = "9.4.1" slf4j = "2.0.18" From 37ee423308078a5daa57bb76953c79f1bcc6c7dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 16:45:06 +0000 Subject: [PATCH 031/178] chore(deps): bump the infrastructure group with 2 updates (#783) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the infrastructure group with 2 updates: [io.github.oshai:kotlin-logging](https://github.com/oshai/kotlin-logging) and [io.netty:netty-bom](https://github.com/netty/netty). Updates `io.github.oshai:kotlin-logging` from 8.0.02 to 8.0.03
    Release notes

    Sourced from io.github.oshai:kotlin-logging's releases.

    8.0.03

    What's Changed

    Full Changelog: https://github.com/oshai/kotlin-logging/compare/8.0.02...8.0.03

    Commits
    • b641856 bump version to 8.0.04
    • 3e6096d Fix #598: Allow external configuration of logStartupMessage via Properties an...
    • See full diff in compare view

    Updates `io.netty:netty-bom` from 4.2.13.Final to 4.2.14.Final
    Release notes

    Sourced from io.netty:netty-bom's releases.

    netty-4.2.14.Final

    What's Changed

    New Contributors

    Full Changelog: https://github.com/netty/netty/compare/netty-4.2.13.Final...netty-4.2.14.Final

    Commits
    • 0a60b75 [maven-release-plugin] prepare release netty-4.2.14.Final
    • 72df658 Fix MQTT decoder size check after variable header replay (#16787)
    • 7125dba MQTT: Allow MQTT 5 CONNECT with password only (#16833)
    • 9e19320 IoUring: Stop generic FileRegion drain loop when transferred() reaches count(...
    • 4ce9f17 Route synchronous onLookupComplete exceptions via fireExceptionCaught (#16794)
    • f7b1b7d Fix memoryAddress() for direct ByteBuffers wrapped by Unpooled without Unsafe...
    • 0ccb265 IpFilter: Fix ClassCastException caused by IpSubnetFilter if only ipv6 rules ...
    • a6aeb6d Resolve all localhost addresses without querying DNS servers (#16749)
    • c328ba2 Fix ResumptionController wrapping (#16815)
    • bc5862b HTTP2: Use 100 as default max concurrent streams setting (#16804)
    • Additional commits viewable in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bf36c70..54c27c0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kover = "0.9.8" ktlint = "14.2.0" knit = "0.5.1" mavenPublish = "0.36.0" -netty = "4.2.13.Final" +netty = "4.2.14.Final" # libraries version awaitility = "4.3.0" @@ -18,7 +18,7 @@ coroutines = "1.11.0" kotest = "6.1.11" kotlinx-io = "0.9.0" ktor = "3.3.3" -logging = "8.0.02" +logging = "8.0.03" mockk = "1.14.9" serialization = "1.11.0" slf4j = "2.0.18" From 0adfb3bcdb06843a9da6617e0a50c604a6747339 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Mon, 1 Jun 2026 12:10:01 +0200 Subject: [PATCH 032/178] fix!: harden lifecycle, dispatchers, back-pressure (#778) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #573 fixes #574 fixes #708 - Handlers ran on `Dispatchers.IO` → now `Dispatchers.Default`, configurable via `handlerDispatcher`. - Reader/writer dispatcher exposed as `ioDispatcher` (default `IODispatcher.limitedParallelism(2)`). - Optional caller-supplied `CoroutineScope` so the pipeline isn't detached from the caller's tree. - `CancellationException` consistently rethrown across all pumps. - Unbounded channels → bounded with graceful drain on close (in-flight outbound flushed before `onClose`). - Input `Source` now closed on natural EOF / reader error (was leaking for non-`System.in` sources). - Race between `start()` and `close()` fixed via 3-state CAS + `setupComplete` barrier replacing `AtomicBoolean`. ## How Has This Been Tested? unit and integration tests ## Breaking Changes - Handlers default to `Dispatchers.Default` (was `Dispatchers.IO`). Override with `handlerDispatcher = Dispatchers.IO` if your handlers perform blocking I/O. - `send()` suspends under back-pressure instead of buffering unbounded. - `StdioServerTransport(input, output)` ctor is `@Deprecated` (WARNING) in favor of `StdioServerTransport(input, output) { ... }`. Still binary-compatible. ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .gitignore | 2 +- kotlin-sdk-server/api/kotlin-sdk-server.api | 11 + .../kotlin/sdk/server/StdioServerTransport.kt | 452 ++++++++++++------ .../sdk/server/StdioServerTransportTest.kt | 342 ++++++++++++- 4 files changed, 651 insertions(+), 156 deletions(-) diff --git a/.gitignore b/.gitignore index d9f0fde..805579c 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,7 @@ node_modules dist ### SWE agents ### -.claude/settings.local.json +.claude/ .junie/ ### Conformance test results ### diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.api b/kotlin-sdk-server/api/kotlin-sdk-server.api index f400e80..3acaa64 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.api @@ -219,11 +219,22 @@ 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 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; public fun send (Lio/modelcontextprotocol/kotlin/sdk/types/JSONRPCMessage;Lio/modelcontextprotocol/kotlin/sdk/shared/TransportSendOptions;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun start (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } +public final class io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransport$Builder { + public final fun getHandlerDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher; + public final fun getIoDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher; + public final fun getScope ()Lkotlinx/coroutines/CoroutineScope; + public final fun setHandlerDispatcher (Lkotlinx/coroutines/CoroutineDispatcher;)V + public final fun setIoDispatcher (Lkotlinx/coroutines/CoroutineDispatcher;)V + public final fun setScope (Lkotlinx/coroutines/CoroutineScope;)V +} + public final class io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransport : io/modelcontextprotocol/kotlin/sdk/shared/AbstractTransport { public static final field STANDALONE_SSE_STREAM_ID Ljava/lang/String; public fun ()V 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 a4d588c..2b76089 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 @@ -7,13 +7,23 @@ import io.modelcontextprotocol.kotlin.sdk.shared.ReadBuffer import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions import io.modelcontextprotocol.kotlin.sdk.shared.serializeMessage import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.McpDsl +import io.modelcontextprotocol.kotlin.sdk.types.McpException +import io.modelcontextprotocol.kotlin.sdk.types.RPCError import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.ClosedSendChannelException +import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -23,191 +33,345 @@ import kotlinx.io.Source import kotlinx.io.buffered import kotlinx.io.readByteArray import kotlinx.io.writeString -import kotlin.concurrent.atomics.AtomicBoolean +import kotlin.concurrent.atomics.AtomicReference import kotlin.concurrent.atomics.ExperimentalAtomicApi -import kotlin.coroutines.CoroutineContext private const val READ_BUFFER_SIZE = 8192L /** - * A server transport that communicates with a client via standard I/O. + * Server-side MCP transport that exchanges JSON-RPC messages over arbitrary byte streams. * - * Reads from input [Source] and writes to output [Sink]. + * Reads framed messages from the supplied [Source] and writes framed messages to the supplied + * [Sink]. Three internal coroutines drive the pipeline: * - * @constructor Creates a new instance of [StdioServerTransport]. - * @param inputStream The input [Source] used to receive data. - * @param outputStream The output [Sink] used to send data. + * - **reader** — pulls bytes from the input source into the parsing buffer; runs on + * [Builder.ioDispatcher]. + * - **processor** — parses messages out of the buffer and invokes the registered message handler; + * runs on [Builder.handlerDispatcher] (defaults to [Dispatchers.Default]) so blocking handler + * code does not starve the I/O pool. + * - **writer** — serialises outbound messages and flushes them to the output sink; runs on + * [Builder.ioDispatcher]. + * + * Both internal channels are bounded, so a slow handler or slow output naturally back-pressures + * the upstream producer — [send] suspends when the outbound channel is full. + * + * Both explicit [close] and a natural EOF from the input perform a graceful drain: in-flight + * outbound messages are flushed before `onClose` fires, and the input source and output sink are + * released. + * + * Example: + * ```kotlin + * val transport = StdioServerTransport( + * input = System.`in`.asSource().buffered(), + * output = System.out.asSink().buffered(), + * ) { + * scope = myScope + * } + * transport.start() + * ``` */ @OptIn(ExperimentalAtomicApi::class) -public class StdioServerTransport(private val inputStream: Source, outputStream: Sink) : AbstractTransport() { +public class StdioServerTransport private constructor( + private val input: Source, + output: Sink, + private val scope: CoroutineScope?, + private val handlerDispatcher: CoroutineDispatcher, + private val ioDispatcher: CoroutineDispatcher, +) : AbstractTransport() { + + /** + * Creates a [StdioServerTransport] reading from [input] and writing to [output], with + * optional configuration applied through a [Builder] block. + * + * @param input source the transport reads JSON-RPC messages from + * @param output sink the transport writes JSON-RPC messages to + * @param block configuration applied to the underlying [Builder] + */ + public constructor( + input: Source, + output: Sink, + block: Builder.() -> Unit = {}, + ) : this(Builder(input, output).apply(block)) + + private constructor(builder: Builder) : this( + input = builder.input, + output = builder.output, + scope = builder.scope, + handlerDispatcher = builder.handlerDispatcher, + ioDispatcher = builder.ioDispatcher, + ) + + /** + * Creates a [StdioServerTransport] from the given input source and output sink with default + * configuration. Retained for binary compatibility; prefer the [Builder]-based constructor. + * + * @param inputStream source the transport reads JSON-RPC messages from + * @param outputStream sink the transport writes JSON-RPC messages to + */ + @Deprecated( + message = "Use StdioServerTransport(input, output) { ... } instead.", + replaceWith = ReplaceWith("StdioServerTransport(input = inputStream, output = outputStream)"), + level = DeprecationLevel.WARNING, + ) + public constructor(inputStream: Source, outputStream: Sink) : this( + input = inputStream, + output = outputStream, + scope = null, + handlerDispatcher = Dispatchers.Default, + ioDispatcher = IODispatcher.limitedParallelism(2), + ) private val logger = KotlinLogging.logger {} private val readBuffer = ReadBuffer() - private val initialized: AtomicBoolean = AtomicBoolean(false) - private var readingJob: Job? = null - private var sendingJob: Job? = null - private var processingJob: Job? = null + private val readChannel = Channel(Channel.BUFFERED) + private val writeChannel = Channel(Channel.BUFFERED) + private val outputSink = output.buffered() - private val coroutineContext: CoroutineContext = IODispatcher + SupervisorJob() - private val scope = CoroutineScope(coroutineContext) - private val readChannel = Channel(Channel.UNLIMITED) - private val writeChannel = Channel(Channel.UNLIMITED) - private val outputSink = outputStream.buffered() + private enum class State { New, Operational, Stopped } + private val state: AtomicReference = AtomicReference(State.New) + + private var readerJob: Job? = null + private var processorJob: Job? = null + private var writerJob: Job? = null + + private var effectiveScope: CoroutineScope? = null + private val ownsScope: Boolean = (scope == null) + + private val setupComplete = CompletableDeferred() + + /** + * Starts the reader, processor, and writer coroutines. Must be called exactly once before + * messages can be exchanged; subsequent calls throw. + */ override suspend fun start() { - if (!initialized.compareAndSet(expectedValue = false, newValue = true)) { - error("StdioServerTransport already started!") + if (!state.compareAndSet(State.New, State.Operational)) { + when (state.load()) { + State.Stopped -> error("StdioServerTransport is already closed!") + else -> error("StdioServerTransport already started!") + } } - // Launch a coroutine to read from stdin - readingJob = launchReadingJob() + try { + val resolvedScope = scope ?: CoroutineScope( + currentCoroutineContext() + IODispatcher + SupervisorJob(), + ) + effectiveScope = resolvedScope - // Launch a coroutine to process messages from readChannel - processingJob = launchProcessingJob() - - // Launch a coroutine to handle message sending - sendingJob = launchSendingJob() + readerJob = resolvedScope.launch( + ioDispatcher + CoroutineName("StdioServerTransport.reader"), + ) { readerPump() } + processorJob = resolvedScope.launch( + handlerDispatcher + CoroutineName("StdioServerTransport.processor"), + start = CoroutineStart.UNDISPATCHED, + ) { processorPump() } + writerJob = resolvedScope.launch( + ioDispatcher + CoroutineName("StdioServerTransport.writer"), + start = CoroutineStart.UNDISPATCHED, + ) { writerPump() } + } finally { + setupComplete.complete(Unit) + } } - private fun launchReadingJob(): Job { - val job = scope.launch { - val buf = Buffer() - try { - while (isActive) { - val bytesRead = inputStream.readAtMostTo(buf, READ_BUFFER_SIZE) - if (bytesRead == -1L) { - // EOF reached - break - } - if (bytesRead > 0) { - val chunk = buf.readByteArray() - readChannel.send(chunk) + private suspend fun readerPump() { + val buf = Buffer() + try { + while (currentCoroutineContext().isActive) { + val bytesRead = input.readAtMostTo(buf, READ_BUFFER_SIZE) + if (bytesRead == -1L) break + if (bytesRead > 0) { + val chunk = buf.readByteArray() + readChannel.send(chunk) + } + } + } catch (e: CancellationException) { + throw e + } catch (e: Throwable) { + if (state.load() == State.Stopped) { + logger.debug(e) { "Reader interrupted by close()" } + } else { + logger.error(e) { "Error reading from input source" } + _onError(e) + } + } finally { + readChannel.close() + } + } + + private suspend fun processorPump() { + try { + for (chunk in readChannel) { + readBuffer.append(chunk) + while (true) { + val message = try { + readBuffer.readMessage() + } catch (e: CancellationException) { + throw e + } catch (e: Throwable) { + _onError(e) + null + } ?: break + try { + _onMessage(message) + } catch (e: CancellationException) { + throw e + } catch (e: Throwable) { + logger.error(e) { "Error processing message" } + _onError(e) } } - } catch (e: CancellationException) { - throw e - } catch (e: Throwable) { - logger.error(e) { "Error reading from stdin" } - _onError.invoke(e) - } finally { - // Reached EOF or error, close connection - close() - } - } - job.invokeOnCompletion { cause -> - logJobCompletion("Message reading", cause) - } - return job - } - - private fun launchProcessingJob(): Job { - val job = scope.launch { - try { - for (chunk in readChannel) { - readBuffer.append(chunk) - processReadBuffer() - } - } catch (e: CancellationException) { - throw e - } catch (e: Throwable) { - _onError.invoke(e) - } - } - job.invokeOnCompletion { cause -> - logJobCompletion("Processing", cause) - } - return job - } - - private fun launchSendingJob(): Job { - val job = scope.launch { - try { - for (message in writeChannel) { - val json = serializeMessage(message) - outputSink.writeString(json) - outputSink.flush() - } - } catch (e: CancellationException) { - throw e - } catch (e: Throwable) { - logger.error(e) { "Error writing to stdout" } - _onError.invoke(e) - } - } - job.invokeOnCompletion { cause -> - logJobCompletion("Message sending", cause) - if (cause is CancellationException) { - readingJob?.cancel(cause) - } - } - return job - } - - private suspend fun processReadBuffer() { - while (true) { - val message = try { - readBuffer.readMessage() - } catch (e: Throwable) { - _onError.invoke(e) - null - } - - if (message == null) break - // Async invocation broke delivery order - try { - _onMessage.invoke(message) - } catch (e: CancellationException) { - throw e - } catch (e: Throwable) { - logger.error(e) { "Error processing message" } - _onError.invoke(e) } + } catch (e: CancellationException) { + throw e + } catch (e: Throwable) { + _onError(e) + } finally { + writeChannel.close() } } - private fun logJobCompletion(jobName: String, cause: Throwable?) { - when (cause) { - is CancellationException -> { - } - - null -> { - logger.debug { "$jobName job completed" } - } - - else -> { - logger.debug(cause) { "$jobName job completed exceptionally" } + private suspend fun writerPump() { + try { + for (message in writeChannel) { + val json = serializeMessage(message) + outputSink.writeString(json) + outputSink.flush() } + } catch (e: CancellationException) { + throw e + } catch (e: Throwable) { + logger.error(e) { "Error writing to output sink" } + _onError(e) + } finally { + transitionToStoppedNaturally() } } + /** + * Closes the transport. When called after [start], waits for in-flight outbound messages to be + * flushed, releases the input source and output sink, cancels the internal scope when the + * transport owns it, and invokes `onClose`. When called before [start], transitions directly + * to the closed state without releasing the input/output or invoking `onClose` — the caller + * remains responsible for resources that were never handed off to a running transport. Safe to + * call multiple times and safe to race with [start]. + */ override suspend fun close() { - if (!initialized.compareAndSet(expectedValue = true, newValue = false)) return + var previous: State + do { + previous = state.load() + } while (previous != State.Stopped && !state.compareAndSet(previous, State.Stopped)) + + if (previous == State.New) { + setupComplete.complete(Unit) + return + } withContext(NonCancellable) { - writeChannel.close() - sendingJob?.cancelAndJoin() + setupComplete.await() - runCatching { - inputStream.close() - }.onFailure { logger.warn(it) { "Failed to close stdin" } } + if (previous == State.Stopped) { + writerJob?.join() + return@withContext + } - readingJob?.cancel() + runCatching { input.close() } + .onFailure { logger.warn(it) { "Failed to close input source" } } + readerJob?.cancel() readChannel.close() - - processingJob?.cancelAndJoin() - + processorJob?.cancelAndJoin() + writeChannel.close() + writerJob?.join() + runCatching { outputSink.close() } + .onFailure { logger.warn(it) { "Failed to close output sink" } } readBuffer.clear() - - runCatching { - outputSink.flush() - outputSink.close() - }.onFailure { logger.warn(it) { "Failed to close stdout" } } - + if (ownsScope) { + effectiveScope?.coroutineContext?.get(Job)?.cancel() + } invokeOnCloseCallback() } } + /** + * Queues [message] for the writer coroutine. Suspends when the outbound channel is full, + * applying back-pressure to the caller. Throws [McpException] with + * [RPCError.ErrorCode.CONNECTION_CLOSED] if the transport has not been started or has + * already closed. + * + * @param message JSON-RPC message to send + * @param options transport-specific send options; ignored by this transport + */ override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) { - writeChannel.send(message) + when (state.load()) { + State.New -> throw McpException( + code = RPCError.ErrorCode.CONNECTION_CLOSED, + message = "Transport is not started", + ) + + State.Stopped -> throw McpException( + code = RPCError.ErrorCode.CONNECTION_CLOSED, + message = "Transport is closed", + ) + + State.Operational -> Unit + } + try { + writeChannel.send(message) + } catch (e: CancellationException) { + throw e + } catch (e: ClosedSendChannelException) { + throw McpException( + code = RPCError.ErrorCode.CONNECTION_CLOSED, + message = "Transport is closed", + cause = e, + ) + } + } + + private fun transitionToStoppedNaturally() { + if (!state.compareAndSet(State.Operational, State.Stopped)) return + runCatching { input.close() } + .onFailure { logger.warn(it) { "Failed to close input source" } } + runCatching { outputSink.close() } + .onFailure { logger.warn(it) { "Failed to close output sink" } } + readBuffer.clear() + if (ownsScope) { + // Non-null in practice: writer launches after effectiveScope is published. + effectiveScope?.coroutineContext?.get(Job)?.cancel() + } + invokeOnCloseCallback() + } + + /** + * Configuration builder for [StdioServerTransport]. Used via the + * `StdioServerTransport(input, output) { ... }` factory; the I/O endpoints are supplied + * positionally, while [scope], [handlerDispatcher], and [ioDispatcher] are configurable + * inside the block. + * + * Example: + * ```kotlin + * StdioServerTransport(input, output) { + * scope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + * handlerDispatcher = myHandlerDispatcher + * ioDispatcher = Dispatchers.IO + * } + * ``` + * + * @property scope Optional caller-supplied [CoroutineScope]. When non-null, the transport's + * pipeline coroutines run as children of this scope and the transport does not tear it + * down on [close]. When `null`, the transport creates and owns an internal scope. + * @property handlerDispatcher Dispatcher for invoking the registered message handler. + * Defaults to [Dispatchers.Default]. + * @property ioDispatcher Dispatcher for the reader and writer coroutines. Must allow at + * least two threads to run concurrently so the reader and writer don't block each other. + * The default is a two-thread view of the platform I/O dispatcher + * (`IODispatcher.limitedParallelism(2)`); pass a different value to share or isolate I/O + * threads with the rest of your application. + */ + @McpDsl + public class Builder internal constructor(internal val input: Source, internal val output: Sink) { + public var scope: CoroutineScope? = null + public var handlerDispatcher: CoroutineDispatcher = Dispatchers.Default + public var ioDispatcher: CoroutineDispatcher = IODispatcher.limitedParallelism(2) } } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransportTest.kt index 32123a6..c6370a1 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StdioServerTransportTest.kt @@ -5,17 +5,29 @@ import io.kotest.assertions.throwables.shouldThrow import io.kotest.assertions.withClue import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain import io.modelcontextprotocol.kotlin.sdk.shared.ReadBuffer import io.modelcontextprotocol.kotlin.sdk.shared.serializeMessage import io.modelcontextprotocol.kotlin.sdk.types.InitializedNotification import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.McpException import io.modelcontextprotocol.kotlin.sdk.types.PingRequest +import io.modelcontextprotocol.kotlin.sdk.types.RPCError import io.modelcontextprotocol.kotlin.sdk.types.toJSON import io.modelcontextprotocol.kotlin.test.utils.runIntegrationTest import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.cancel +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeout +import kotlinx.coroutines.withTimeoutOrNull import kotlinx.io.Buffer import kotlinx.io.RawSink import kotlinx.io.RawSource @@ -33,9 +45,12 @@ import java.io.ByteArrayOutputStream import java.io.IOException import java.io.PipedInputStream import java.io.PipedOutputStream +import java.util.concurrent.CountDownLatch +import java.util.concurrent.Executors import kotlin.test.assertFalse import kotlin.test.assertTrue import kotlin.test.fail +import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -71,13 +86,13 @@ class StdioServerTransportTest { @Test fun `should be safe to close before start`() = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) server.close() // initialized guard makes this a no-op; must not throw } @Test fun `should start then close cleanly`() = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) server.onError { error -> throw error } @@ -96,7 +111,7 @@ class StdioServerTransportTest { @Test fun `should not read until started`() = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) server.onError { error -> throw error } @@ -125,7 +140,7 @@ class StdioServerTransportTest { @Test fun `should read multiple messages`() = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) server.onError { error -> throw error } @@ -162,7 +177,7 @@ class StdioServerTransportTest { @ParameterizedTest(name = "[{index}] input throws {0}") @MethodSource("inputErrors") fun `should invoke onError when input stream throws`(throwable: Throwable): Unit = runIntegrationTest { - val server = StdioServerTransport(FaultyRawSource(throwable).buffered(), printOutput) + val server = StdioServerTransport(input = FaultyRawSource(throwable).buffered(), output = printOutput) val capturedError = CompletableDeferred() server.onError { capturedError.complete(it) } server.onMessage {} @@ -176,7 +191,7 @@ class StdioServerTransportTest { @ParameterizedTest(name = "[{index}] output throws {0}") @MethodSource("outputErrors") fun `should invoke onError when output sink throws`(throwable: Throwable): Unit = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, FaultyRawSink(throwable).buffered()) + val server = StdioServerTransport(input = bufferedInput, output = FaultyRawSink(throwable).buffered()) val capturedError = CompletableDeferred() server.onError { capturedError.complete(it) } server.onMessage {} @@ -190,7 +205,7 @@ class StdioServerTransportTest { @Test fun `should call onClose when input EOF is reached`(): Unit = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) val didClose = CompletableDeferred() server.onError { throw it } server.onClose { didClose.complete(Unit) } @@ -206,7 +221,7 @@ class StdioServerTransportTest { @Test fun `should throw when starting twice`(): Unit = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) server.onMessage {} server.start() withClue("Server should not start twice") { @@ -217,10 +232,24 @@ class StdioServerTransportTest { server.close() } + @Test + fun `should report 'closed' error message when starting after close`(): Unit = runIntegrationTest { + val server = StdioServerTransport(input = bufferedInput, output = printOutput) + server.onError {} + server.onMessage {} + server.start() + server.close() + + val ex = shouldThrow { + server.start() + } + ex.message shouldContain "closed" + } + @ParameterizedTest(name = "[{index}] handler throws {0}") @MethodSource("handlerErrors") fun `should continue processing messages after handler throws`(throwable: Throwable) = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) val capturedErrors = mutableListOf() val receivedMessages = mutableListOf() val secondMessageProcessed = CompletableDeferred() @@ -253,7 +282,7 @@ class StdioServerTransportTest { @Test fun `should not invoke onError for CancellationException in handler`() = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) val capturedError = CompletableDeferred() server.onError { capturedError.complete(it) } @@ -281,7 +310,7 @@ class StdioServerTransportTest { @Test fun `should continue receiving valid messages after malformed JSON is skipped`() = runIntegrationTest { - val server = StdioServerTransport(bufferedInput, printOutput) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) val received = CompletableDeferred() // ReadBuffer silently skips unparseable lines — no onError callback expected server.onError {} @@ -299,6 +328,297 @@ class StdioServerTransportTest { server.close() } + @Test + fun `should throw McpException when send is called before start`() = runIntegrationTest { + val server = StdioServerTransport(input = bufferedInput, output = printOutput) + val ex = shouldThrow { + server.send(PingRequest().toJSON()) + } + ex.code shouldBe RPCError.ErrorCode.CONNECTION_CLOSED + } + + @Test + fun `should throw McpException when send is called after close`() = runIntegrationTest { + val server = StdioServerTransport(input = bufferedInput, output = printOutput) + server.onError {} + server.onMessage {} + server.start() + server.close() + + val ex = shouldThrow { + server.send(PingRequest().toJSON()) + } + ex.code shouldBe RPCError.ErrorCode.CONNECTION_CLOSED + } + + @Test + fun `should drain in-flight outbound messages on graceful close`() = runIntegrationTest { + val server = StdioServerTransport(input = bufferedInput, output = printOutput) + server.onError {} + server.onMessage {} + server.start() + + val numMessages = 50 + repeat(numMessages) { + server.send(PingRequest().toJSON()) + } + server.close() + + val outputLines = String(output.toByteArray()).lines().count { it.isNotBlank() } + outputLines shouldBe numMessages + } + + @Test + fun `should fail-fast when reader throws non-EOF IOException`() = runIntegrationTest { + val ioError = IOException("transient stream failure") + val server = StdioServerTransport(input = FaultyRawSource(ioError).buffered(), output = printOutput) + val errorCaptured = CompletableDeferred() + val closeCaptured = CompletableDeferred() + server.onError { errorCaptured.complete(it) } + server.onClose { closeCaptured.complete(Unit) } + server.onMessage {} + + server.start() + + errorCaptured.await() shouldBe ioError + closeCaptured.await() + } + + @Test + fun `should close input source on natural EOF`() = runIntegrationTest { + val inputClosed = CompletableDeferred() + val eofSource = object : RawSource { + override fun readAtMostTo(sink: Buffer, byteCount: Long): Long = -1L + override fun close() { + inputClosed.complete(Unit) + } + } + val server = StdioServerTransport(input = eofSource.buffered(), output = printOutput) + val onCloseFired = CompletableDeferred() + server.onError {} + server.onMessage {} + server.onClose { onCloseFired.complete(Unit) } + + server.start() + + inputClosed.await() + onCloseFired.await() + } + + // region: concurrency + + @Test + fun `should be safe under concurrent start and close`() = runIntegrationTest(timeout = 30.seconds) { + val iterations = 2000 + repeat(iterations) { iteration -> + val server = StdioServerTransport(input = Buffer(), output = Buffer()) + server.onError {} + server.onMessage {} + + coroutineScope { + launch(Dispatchers.Default) { + try { + server.start() + } catch (_: IllegalStateException) { + } + } + launch(Dispatchers.Default) { + server.close() + } + } + + withClue("iteration $iteration: send() after race should fail with CONNECTION_CLOSED") { + val ex = shouldThrow { + server.send(PingRequest().toJSON()) + } + ex.code shouldBe RPCError.ErrorCode.CONNECTION_CLOSED + } + } + } + + @Test + fun `should suspend send under back-pressure`() = runIntegrationTest(timeout = 30.seconds) { + val unblock = CountDownLatch(1) + val blockingSink = object : RawSink { + override fun write(source: Buffer, byteCount: Long) { + source.clear() + unblock.await() + } + + override fun flush() { + // noop + } + + override fun close() { + unblock.countDown() + } + } + val server = StdioServerTransport(input = bufferedInput, output = blockingSink.buffered()) + server.onError {} + server.onMessage {} + server.start() + + val maxAttempts = 256 + var suspendedAt = -1 + for (i in 0 until maxAttempts) { + val ok = withTimeoutOrNull(100.milliseconds) { server.send(PingRequest().toJSON()) } + if (ok == null) { + suspendedAt = i + break + } + } + assertTrue( + suspendedAt in 0 until maxAttempts, + "send() should have suspended within $maxAttempts attempts, got suspendedAt=$suspendedAt", + ) + // Unblock writer so close() can drain. + unblock.countDown() + server.close() + } + + @Test + fun `should not hang close when handler suspends indefinitely`() = runIntegrationTest { + val server = StdioServerTransport(input = bufferedInput, output = printOutput) + val handlerEntered = CompletableDeferred() + val neverComplete = CompletableDeferred() + server.onError {} + server.onMessage { + handlerEntered.complete(Unit) + neverComplete.await() + } + server.start() + + inputWriter.write(serializeMessage(PingRequest().toJSON())) + inputWriter.flush() + + handlerEntered.await() + server.close() + } + + @Test + fun `should not hang close when onMessage was never registered`() = runIntegrationTest { + val server = StdioServerTransport(input = bufferedInput, output = printOutput) + server.onError {} + server.start() + + inputWriter.write(serializeMessage(PingRequest().toJSON())) + inputWriter.flush() + + delay(200.milliseconds) + + server.close() + } + + // endregion + + // region: scope and dispatcher knobs + + @Test + fun `should honor externally provided CoroutineScope`() = runIntegrationTest { + val externalScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + val server = StdioServerTransport(input = bufferedInput, output = printOutput) { + scope = externalScope + } + val closeCaptured = CompletableDeferred() + server.onError {} + server.onClose { closeCaptured.complete(Unit) } + server.onMessage {} + + server.start() + externalScope.cancel() + + closeCaptured.await() + + val ex = shouldThrow { + server.send(PingRequest().toJSON()) + } + ex.code shouldBe RPCError.ErrorCode.CONNECTION_CLOSED + } + + @Test + fun `should use ioDispatcher for reader and writer`() = runIntegrationTest { + val threadName = "stdio-test-io-thread" + val executor = Executors.newFixedThreadPool(2) { r -> Thread(r, threadName) } + try { + val readerThread = CompletableDeferred() + val writerThread = CompletableDeferred() + val unblockReader = CountDownLatch(1) + val recordingInput = object : RawSource { + override fun readAtMostTo(sink: Buffer, byteCount: Long): Long { + if (!readerThread.isCompleted) { + readerThread.complete(Thread.currentThread().name) + } + unblockReader.await() + return -1L + } + + override fun close() { + unblockReader.countDown() + } + } + val recordingOutput = object : RawSink { + override fun write(source: Buffer, byteCount: Long) { + if (!writerThread.isCompleted) { + writerThread.complete(Thread.currentThread().name) + } + source.clear() + } + + override fun flush() { + // noop + } + + override fun close() { + // noop + } + } + val server = StdioServerTransport( + input = recordingInput.buffered(), + output = recordingOutput.buffered(), + ) { + ioDispatcher = executor.asCoroutineDispatcher() + } + server.onError {} + server.onMessage {} + server.start() + + readerThread.await() shouldContain threadName + server.send(PingRequest().toJSON()) + writerThread.await() shouldContain threadName + + server.close() + } finally { + executor.shutdownNow() + } + } + + @Test + fun `should use handlerDispatcher for message handling`() = runIntegrationTest { + val threadName = "stdio-test-handler-thread" + val executor = Executors.newSingleThreadExecutor { r -> Thread(r, threadName) } + try { + val server = StdioServerTransport(input = bufferedInput, output = printOutput) { + handlerDispatcher = executor.asCoroutineDispatcher() + } + val observedThreadName = CompletableDeferred() + server.onError {} + server.onMessage { + observedThreadName.complete(Thread.currentThread().name) + } + server.start() + + inputWriter.write(serializeMessage(PingRequest().toJSON())) + inputWriter.flush() + + observedThreadName.await() shouldContain threadName + server.close() + } finally { + executor.shutdownNow() + } + } + + // endregion + private fun inputErrors() = listOf( IOException("simulated read failure"), RuntimeException("unexpected read exception"), From 0eb18228538c5410957e73933509fca2c00902c1 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Mon, 1 Jun 2026 12:33:39 +0200 Subject: [PATCH 033/178] Update Ktor to version 3.4.3 (#785) ktor 3.3.3 -> 3.4.3 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 54c27c0..4982b6d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ collections-immutable = "0.4.0" coroutines = "1.11.0" kotest = "6.1.11" kotlinx-io = "0.9.0" -ktor = "3.3.3" +ktor = "3.4.3" logging = "8.0.03" mockk = "1.14.9" serialization = "1.11.0" From 6e6f80512fb8fcc9f3c031cfd693ccbcf9c4aaab Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 2 Jun 2026 12:31:28 +0200 Subject: [PATCH 034/178] Merge commit from fork --- kotlin-sdk-core/api/kotlin-sdk-core.api | 6 +++ .../kotlin/sdk/shared/ReadBuffer.kt | 40 ++++++++++++++++++- .../kotlin/sdk/shared/ReadBufferTest.kt | 33 +++++++++++++++ .../kotlin/sdk/server/StdioServerTransport.kt | 3 ++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index b588eef..0895722 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -125,6 +125,12 @@ public final class io/modelcontextprotocol/kotlin/sdk/shared/RequestOptions : io public fun toString ()Ljava/lang/String; } +public final class io/modelcontextprotocol/kotlin/sdk/shared/TooLongFrameException : java/io/IOException { + public fun (JI)V + public final fun getFrameSize ()J + public final fun getMaxFrameSize ()I +} + public abstract interface class io/modelcontextprotocol/kotlin/sdk/shared/Transport { public abstract fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun onClose (Lkotlin/jvm/functions/Function0;)V diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBuffer.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBuffer.kt index c0c853f..8102cf6 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBuffer.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBuffer.kt @@ -4,13 +4,24 @@ import io.github.oshai.kotlinlogging.KotlinLogging import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage import io.modelcontextprotocol.kotlin.sdk.types.McpJson import kotlinx.io.Buffer +import kotlinx.io.IOException import kotlinx.io.indexOf import kotlinx.io.readString /** * Buffers a continuous stdio stream into discrete JSON-RPC messages. + * + * A single newline-terminated frame may not exceed an internal size cap (16 MiB): a peer that streams + * bytes without ever sending a newline triggers a [TooLongFrameException] from [readMessage] instead + * of growing the buffer without bound. A non-positive cap disables the check. */ -public class ReadBuffer { +public class ReadBuffer internal constructor(private val maxFrameSize: Int) { + + public constructor() : this(DEFAULT_MAX_FRAME_SIZE) + + internal companion object { + internal const val DEFAULT_MAX_FRAME_SIZE: Int = 16 * 1024 * 1024 + } private val logger = KotlinLogging.logger { } @@ -53,7 +64,11 @@ public class ReadBuffer { private fun readNextLine(): String? { val lfIndex = if (buffer.exhausted()) -1L else buffer.indexOf('\n'.code.toByte()) - if (lfIndex == -1L) return null + if (lfIndex == -1L) { + failIfFrameTooLong(buffer.size) + return null + } + failIfFrameTooLong(lfIndex) return if (lfIndex == 0L) { buffer.skip(1) @@ -71,6 +86,13 @@ public class ReadBuffer { } } + private fun failIfFrameTooLong(frameSize: Long) { + if (maxFrameSize in 1..(line) /** Serializes a [JSONRPCMessage] to its JSON string representation with a trailing newline. */ diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBufferTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBufferTest.kt index 7b4f053..e5e50f8 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBufferTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ReadBufferTest.kt @@ -6,7 +6,9 @@ import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification import kotlinx.serialization.json.Json import kotlin.test.Test +import kotlin.test.assertContains import kotlin.test.assertEquals +import kotlin.test.assertFailsWith import kotlin.test.assertNull class ReadBufferTest { @@ -75,4 +77,35 @@ class ReadBufferTest { val message = readBuffer.readMessage() assertEquals(testMessage, message) } + + @Test + fun `should fail when an unframed blob exceeds the cap`() { + val readBuffer = ReadBuffer(maxFrameSize = 64) + // No newline ever arrives: the memory-exhaustion vector. + readBuffer.append(ByteArray(100) { 'a'.code.toByte() }) + val ex = assertFailsWith { readBuffer.readMessage() } + assertContains(ex.message.orEmpty(), "maximum size") + } + + @Test + fun `should fail when a completed line exceeds the cap`() { + val readBuffer = ReadBuffer(maxFrameSize = 64) + readBuffer.append(ByteArray(100) { 'a'.code.toByte() } + '\n'.code.toByte()) + assertFailsWith { readBuffer.readMessage() } + } + + @Test + fun `should not enforce a cap when maxFrameSize is non-positive`() { + val readBuffer = ReadBuffer(maxFrameSize = 0) + // Well beyond any small cap and still no newline — must not throw when disabled. + readBuffer.append(ByteArray(8192) { 'a'.code.toByte() }) + assertNull(readBuffer.readMessage()) + } + + @Test + fun `should parse a message that fits under the cap`() { + val readBuffer = ReadBuffer(maxFrameSize = 1024) + readBuffer.append(serializeMessage(testMessage).encodeToByteArray()) + assertEquals(testMessage, readBuffer.readMessage()) + } } 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 2b76089..9261be2 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 @@ -4,6 +4,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging import io.modelcontextprotocol.kotlin.sdk.internal.IODispatcher import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport import io.modelcontextprotocol.kotlin.sdk.shared.ReadBuffer +import io.modelcontextprotocol.kotlin.sdk.shared.TooLongFrameException import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions import io.modelcontextprotocol.kotlin.sdk.shared.serializeMessage import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage @@ -208,6 +209,8 @@ public class StdioServerTransport private constructor( readBuffer.readMessage() } catch (e: CancellationException) { throw e + } catch (e: TooLongFrameException) { + throw e } catch (e: Throwable) { _onError(e) null From b7eeeb12058099f980fa98d1468506489a6b5f32 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 2 Jun 2026 13:30:40 +0200 Subject: [PATCH 035/178] release: 0.13.0 (#796) bump version to 0.13.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e145506..e5294e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kotlin.daemon.jvmargs=-Xmx4G kotlin.native.ignoreDisabledTargets=true group=io.modelcontextprotocol -version=0.12.0 +version=0.13.0 From 59b44a30e4ab816bc4658cfab3be69b90bf76063 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:59:56 +0200 Subject: [PATCH 036/178] chore(deps): bump the other-dependencies group across 5 directories with 4 updates (#789) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java) and [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 2 updates in the /samples/kotlinlang-mcp-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow) and [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback). Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 2 updates in the /samples/weather-stdio-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow) and [io.github.oshai:kotlin-logging-jvm](https://github.com/oshai/kotlin-logging). Updates `com.anthropic:anthropic-java` from 2.34.0 to 2.35.0
    Release notes

    Sourced from com.anthropic:anthropic-java's releases.

    v2.35.0

    2.35.0 (2026-05-28)

    Full Changelog: v2.34.1...v2.35.0

    Features

    • api: Add support for claude-opus-4-8, mid-conversation system blocks, and usage.output_tokens_details (3e4621e)

    v2.34.1

    2.34.1 (2026-05-27)

    Full Changelog: v2.34.0...v2.34.1

    Bug Fixes

    • structured-outputs: support all nullability annotations (#1254) (95e4391)

    Documentation

    • replace literal newlines (c5573d9)
    Changelog

    Sourced from com.anthropic:anthropic-java's changelog.

    2.35.0 (2026-05-28)

    Full Changelog: v2.34.1...v2.35.0

    Features

    • api: Add support for claude-opus-4-8, mid-conversation system blocks, and usage.output_tokens_details (3e4621e)

    2.34.1 (2026-05-27)

    Full Changelog: v2.34.0...v2.34.1

    Bug Fixes

    • structured-outputs: support all nullability annotations (#1254) (95e4391)

    Documentation

    • replace literal newlines (c5573d9)
    Commits
    • 65d26cc release: 2.35.0
    • f901010 feat(api): Add support for claude-opus-4-8, mid-conversation system blocks, a...
    • bc1bdd9 release: 2.34.1
    • f27e209 fix(structured-outputs): support all nullability annotations (#1254)
    • 62ef906 docs: replace literal newlines
    • dc19d08 ci: run breaking change detection on every branch (#1224)
    • 1382286 codegen metadata
    • See full diff in compare view

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `ch.qos.logback:logback-classic` from 1.5.32 to 1.5.34
    Release notes

    Sourced from ch.qos.logback:logback-classic's releases.

    Logback 1.5.34

    2026-06-01 Release of logback version 1.5.34

    • In case certain StackTraceElement values returned by the Throwable.getStackTrace method are null, StackTraceElementProxy substitutes a dummy instance instead of throwing an IllegalArgumentException. This resolves [issues #1040](qos-ch/logback#1040), reported by Naotsugu Kobayashi.

    • HardenedObjectInputStream will now throw an InvalidClassException during deserialization attempts of Proxy classes. This change addresses potential deserialization whitelist bypass vulnerability reported by York Shen and registered as CVE-2026-10532.

    • A bitwise identical binary of this version can be reproduced by building from source code at commit e62272ac152469aec1ede056c3c7d0d7314e7bfe associated with the tag v_1.5.34. This release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

    Logback 1.5.33

    2026-05-27 Release of logback version 1.5.33

    • PropertiesConfiguratorModelHandler now registers properties file URLs to the ConfigurationWatchList when scan is enabled (via local scan="true" attribute or top-level configuration scan), ensuring changes are detected and reconfiguration occurs. This problem was reported in issues/1034.

    • When processing <conversionRule> elements and both class and converterClass attributes are specified, silently use the class attribute without issuing a warning. However, if the attribute values differ, a warning will be issued. This change was requested in issues/1031.

    • HardenedModelInputStream will no longer accept to deserialize all classes located under the "java.lang" and "java.util" packages but a limited number of explicitly authorized classes in those packages. This potential deserialization whitelist bypass vulnerability was reported by York Shen and registered as CVE-2026-9828.

    • SSL parameters for SSLSocketAppender now enable hostname verification by default. Moreover, the default protocol is now "TLSv1.2". This potential vulnerability was reported by York Shen.

    • When printing the status message field, ViewStatusMessagesServletBase now escapes special characters such as "&" as character entities. This potential vulnerability was reported by York Shen.

    • A bit-wise identical binary of this version can be reproduced by building from source code at commit 124e8b49b55ac34d08743a0646bd463410192647 associated with the tag v_1.5.33. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

    Commits
    • e62272a prepare release 1.5.34
    • 1e9e926 add resolveProxyClassRejectsDynamicProxies unit test
    • 2de5cbe added StackTraceElementProxyTest, minor edits to AGENTS.md
    • 0e9b927 in case StackTraceElement is null use a substitute, fixing issues/1040
    • f7a0654 prevent resolveProxyClass bypass
    • 249b81f docs are no longer distributed
    • 1c3b26a start work on 1.5.34-SNAPSHOT
    • 124e8b4 prepare release 1.5.33
    • d8fd6f2 escapeTags in message field when printing status messages
    • 95edbeb hostnameVerification default to true in SSLParametersConfiguration, SSL.DEFAU...
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Updates `io.github.oshai:kotlin-logging-jvm` from 8.0.03 to 8.0.4
    Release notes

    Sourced from io.github.oshai:kotlin-logging-jvm's releases.

    8.0.4

    Align to semver.

    Full Changelog: https://github.com/oshai/kotlin-logging/compare/8.0.03...8.0.4

    Commits

    Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.2

    Changed

    • Update jdependency to support Java 27. (#2033)
    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 4 ++-- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 4 ++-- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- samples/weather-stdio-server/gradle/libs.versions.toml | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index c263c59..42d700e 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,9 +1,9 @@ [versions] -anthropic = "2.34.0" +anthropic = "2.35.0" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" -shadow = "9.4.1" +shadow = "9.4.2" slf4j = "2.0.18" [libraries] diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 91d7878..165d096 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" slf4j = "2.0.18" -shadow = "9.4.1" +shadow = "9.4.2" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 5b7988e..9a68e31 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -4,8 +4,8 @@ ktor = "3.3.3" mcp-kotlin = "0.12.0" serialization = "1.11.0" coroutines = "1.11.0" -logback = "1.5.32" -shadow = "9.4.1" +logback = "1.5.34" +shadow = "9.4.2" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index b607a1c..07bdac1 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -4,7 +4,7 @@ ktor = "3.3.3" junit = "6.1.0" mcp-kotlin = "0.12.0" slf4j = "2.0.18" -shadow = "9.4.1" +shadow = "9.4.2" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index daf5fc1..d7a6fcb 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -2,9 +2,9 @@ coroutines = "1.11.0" kotlin = "2.3.21" ktor = "3.3.3" -logging = "8.0.03" +logging = "8.0.4" mcp-kotlin = "0.12.0" -shadow = "9.4.1" +shadow = "9.4.2" slf4j = "2.0.18" [libraries] From 32cc44115d601ae0dea1dde6e6dd487ce6a7d355 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 14:48:50 +0200 Subject: [PATCH 037/178] chore(deps): bump org.jetbrains.kotlinx:atomicfu-gradle-plugin from 0.32.1 to 0.33.0 in the kotlinx group across 1 directory (#791) Bumps the kotlinx group with 1 update in the / directory: [org.jetbrains.kotlinx:atomicfu-gradle-plugin](https://github.com/Kotlin/kotlinx.atomicfu). Updates `org.jetbrains.kotlinx:atomicfu-gradle-plugin` from 0.32.1 to 0.33.0
    Release notes

    Sourced from org.jetbrains.kotlinx:atomicfu-gradle-plugin's releases.

    0.33.0

    • Deprecated atomic array types provided by the atomicfu. Use types provided by the Kotlin standard library instead. (#591)
    • Published jar files now include Implementation-* attributes in their manifests (#592)
    • Updated ASM to 9.10.1 (#595)
    • Various build infra updates
    Changelog

    Sourced from org.jetbrains.kotlinx:atomicfu-gradle-plugin's changelog.

    Versoin 0.33.0

    • Deprecated atomic array types provided by the atomicfu. Use types provided by the Kotlin standard library instead. (#591)
    • Published jar files now include Implementation-* attributes in their manifests (#592)
    • Updated ASM to 9.10.1 (#595)
    • Various build infra updates
    Commits
    • fc175fc Version 0.33.0
    • dc6187a Update dependencies (#595)
    • 8e23c32 Deprecate AFU array types (#591)
    • 0d27eb1 Do not use deprecated js(compiler: KotlinJsCompilerType, ...) DSL (#594)
    • 6c6b2d6 Fill Implementation-* attributes in JAR's manifests (#592)
    • a658e7d KT-84955: add a suppressor for gradle plugin error checker for native target ...
    • 1dd25ee Add logic to handle changed .kotlin_module file name in test (#581)
    • See full diff in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4982b6d..e8fbe8d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] # plugins version -atomicfu = "0.32.1" +atomicfu = "0.33.0" binaryCompatibilityValidatorPlugin = "0.18.1" detekt = "2.0.0-alpha.3" dokka = "2.2.0" From 4b726c8f5f250735ead11052ff89dbf63d82a7c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:49:40 +0200 Subject: [PATCH 038/178] chore(deps): bump io.mockk:mockk from 1.14.9 to 1.14.11 in the testing group across 1 directory (#792) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the testing group with 1 update in the / directory: [io.mockk:mockk](https://github.com/mockk/mockk). Updates `io.mockk:mockk` from 1.14.9 to 1.14.11
    Release notes

    Sourced from io.mockk:mockk's releases.

    v1.14.11

    What's Changed

    New Contributors

    Full Changelog: https://github.com/mockk/mockk/compare/1.14.9...v1.14.11

    Commits
    • d5617fc Version bump for v1.14.11
    • d4e6a00 Merge pull request #1530 from hspedro/fix/726-openj9-classcast-message-format
    • 98e91bc fix: handle OpenJ9 CCE message in JvmAutoHinter
    • 945f746 Merge pull request #1529 from snowykte0426/fix/1273-jvmtiagent-agp85-native-l...
    • 35cc073 [ 1273-jvmtiagent ] chore: stop tracking .claude/scheduled_tasks.lock
    • d6aa82b [ 1273-jvmtiagent ] chore: drop useLegacyPackaging workaround
    • 85a907c [ 1273-jvmtiagent ] chore: apply spotless formatting
    • 7d9aec1 [ 1273-jvmtiagent ] fix: extract .so when findLibrary returns a path with '='
    • 1d5d30e [ 1273-jvmtiagent ] test: verify findLibrary resolves mockkjvmtiagent to a va...
    • 21a6a3a [ 1273-jvmtiagent]fix: pass findLibrary path directly to attach JvmtiAgent
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e8fbe8d..83e7a6f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ kotest = "6.1.11" kotlinx-io = "0.9.0" ktor = "3.4.3" logging = "8.0.03" -mockk = "1.14.9" +mockk = "1.14.11" serialization = "1.11.0" slf4j = "2.0.18" logback = "1.5.32" From cf88353b35216998a6d379b2ef10daeccb47de82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 16:39:32 +0200 Subject: [PATCH 039/178] chore(deps): bump ch.qos.logback:logback-classic from 1.5.32 to 1.5.34 (#794) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.32 to 1.5.34.
    Release notes

    Sourced from ch.qos.logback:logback-classic's releases.

    Logback 1.5.34

    2026-06-01 Release of logback version 1.5.34

    • In case certain StackTraceElement values returned by the Throwable.getStackTrace method are null, StackTraceElementProxy substitutes a dummy instance instead of throwing an IllegalArgumentException. This resolves [issues #1040](qos-ch/logback#1040), reported by Naotsugu Kobayashi.

    • HardenedObjectInputStream will now throw an InvalidClassException during deserialization attempts of Proxy classes. This change addresses potential deserialization whitelist bypass vulnerability reported by York Shen and registered as CVE-2026-10532.

    • A bitwise identical binary of this version can be reproduced by building from source code at commit e62272ac152469aec1ede056c3c7d0d7314e7bfe associated with the tag v_1.5.34. This release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

    Logback 1.5.33

    2026-05-27 Release of logback version 1.5.33

    • PropertiesConfiguratorModelHandler now registers properties file URLs to the ConfigurationWatchList when scan is enabled (via local scan="true" attribute or top-level configuration scan), ensuring changes are detected and reconfiguration occurs. This problem was reported in issues/1034.

    • When processing <conversionRule> elements and both class and converterClass attributes are specified, silently use the class attribute without issuing a warning. However, if the attribute values differ, a warning will be issued. This change was requested in issues/1031.

    • HardenedModelInputStream will no longer accept to deserialize all classes located under the "java.lang" and "java.util" packages but a limited number of explicitly authorized classes in those packages. This potential deserialization whitelist bypass vulnerability was reported by York Shen and registered as CVE-2026-9828.

    • SSL parameters for SSLSocketAppender now enable hostname verification by default. Moreover, the default protocol is now "TLSv1.2". This potential vulnerability was reported by York Shen.

    • When printing the status message field, ViewStatusMessagesServletBase now escapes special characters such as "&" as character entities. This potential vulnerability was reported by York Shen.

    • A bit-wise identical binary of this version can be reproduced by building from source code at commit 124e8b49b55ac34d08743a0646bd463410192647 associated with the tag v_1.5.33. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

    Commits
    • e62272a prepare release 1.5.34
    • 1e9e926 add resolveProxyClassRejectsDynamicProxies unit test
    • 2de5cbe added StackTraceElementProxyTest, minor edits to AGENTS.md
    • 0e9b927 in case StackTraceElement is null use a substitute, fixing issues/1040
    • f7a0654 prevent resolveProxyClass bypass
    • 249b81f docs are no longer distributed
    • 1c3b26a start work on 1.5.34-SNAPSHOT
    • 124e8b4 prepare release 1.5.33
    • d8fd6f2 escapeTags in message field when printing status messages
    • 95edbeb hostnameVerification default to true in SSLParametersConfiguration, SSL.DEFAU...
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 83e7a6f..8474680 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ logging = "8.0.03" mockk = "1.14.11" serialization = "1.11.0" slf4j = "2.0.18" -logback = "1.5.32" +logback = "1.5.34" junit = "5.14.4" [libraries] From 2f71156483845752f4678287e466810eff468ea6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:07:54 +0200 Subject: [PATCH 040/178] chore(deps): bump tsx from 4.22.3 to 4.22.4 in /integration-test/src/jvmTest/typescript in the all-dependencies group across 1 directory (#795) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 1 update in the /integration-test/src/jvmTest/typescript directory: [tsx](https://github.com/privatenumber/tsx). Updates `tsx` from 4.22.3 to 4.22.4
    Release notes

    Sourced from tsx's releases.

    v4.22.4

    4.22.4 (2026-05-31)

    Bug Fixes

    • resolve CommonJS directory requires inside dependencies (#803) (1ce8463)

    This release is also available on:

    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 8 ++++---- integration-test/src/jvmTest/typescript/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 9e757a5..6e5fb5f 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -17,7 +17,7 @@ "@types/express": "^5.0.6", "@types/node": "^25.9.1", "cors": "^2.8.6", - "tsx": "^4.22.3", + "tsx": "^4.22.4", "typescript": "^6.0.3" } }, @@ -1680,9 +1680,9 @@ } }, "node_modules/tsx": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.3.tgz", - "integrity": "sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 40c58b3..0fafdb9 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -18,7 +18,7 @@ "@types/express": "^5.0.6", "@types/node": "^25.9.1", "cors": "^2.8.6", - "tsx": "^4.22.3", + "tsx": "^4.22.4", "typescript": "^6.0.3" } } From 52f8b0fa919c59dcae068e85b8e337f532704128 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 01:30:10 +0200 Subject: [PATCH 041/178] chore(deps): bump the infrastructure group across 1 directory with 2 updates (#797) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the infrastructure group with 2 updates in the / directory: [io.github.oshai:kotlin-logging](https://github.com/oshai/kotlin-logging) and [io.netty:netty-bom](https://github.com/netty/netty). Updates `io.github.oshai:kotlin-logging` from 8.0.03 to 8.0.4
    Release notes

    Sourced from io.github.oshai:kotlin-logging's releases.

    8.0.4

    Align to semver.

    Full Changelog: https://github.com/oshai/kotlin-logging/compare/8.0.03...8.0.4

    Commits

    Updates `io.netty:netty-bom` from 4.2.14.Final to 4.2.15.Final
    Release notes

    Sourced from io.netty:netty-bom's releases.

    netty-4.2.15.Final

    Security fixes

    • CVE-2026-48059: memory exhaustion in io.netty:netty-codec-haproxy (high).
    • CVE-2026-47691: DNS cache poisoning in io.netty:netty-resolver-dns (high).
    • CVE-2026-XXXXX: DDoS in io.netty:netty-codec-http2.
    • CVE-2026-XXXXX: memory exhaustion in io.netty:netty-codec-redis (high).
    • CVE-2026-44250: memory exhaustion in io.netty:netty-codec-redis (high).
    • CVE-2026-44890: memory exhaustion in io.netty:netty-codec-redis (high).
    • CVE-2026-XXXXX: information disclosure and denial of service in io.netty:netty-codec-classes-quic.
    • CVE-2026-44249: IPv6 subnet filter bypass in io.netty:netty-handler (high).
    • CVE-2026-XXXXX: request smuggling in io.netty:netty-codec-http.
    • CVE-2026-44892: memory exhaustion in io.netty:netty-codec-http3 (high).
    • CVE-2026-44893: memory leak in io.netty:netty-codec-haproxy (high).
    • CVE-2026-44894: traffic amplification in io.netty:netty-codec-classes-quic (high).
    • CVE-2026-XXXXX: TLS hostname verification accidentally disabled in io.netty:netty-handler (high).
    • CVE-2026-45673: DNS cache poisoning in io.netty:netty-resolver-dns.
    • CVE-2026-45416: excessive memory usage from SNIHandler in io.netty:netty-handler (high).
    • CVE-2026-45536: file descriptor leak in io.netty:netty-transport-native-epoll and io.netty:netty-transport-native-kqueue.
    • CVE-2026-45674: DNS cache poisoning in io.netty:netty-resolver-dns (high).
    • CVE-2026-46340: memory exhaustion in io.netty:netty-transport-sctp (high).
    • CVE-2026-47244: denial of service in io.netty:netty-codec-http2.
    • CVE-2026-48006: memory exhaustion in io.netty:netty-codec-redis (high).
    • CVE-2026-48748: memory exhaustion in io.netty:netty-codec-http3 (high).
    • CVE-2026-48043: memory exhaustion in io.netty:netty-codec-http2.

    What's Changed

    New Contributors

    Full Changelog: https://github.com/netty/netty/compare/netty-4.2.14.Final...netty-4.2.15.Final

    Commits
    • a41f7b2 [maven-release-plugin] prepare release netty-4.2.15.Final
    • 2394530 Auto-port 4.2: MQTT: Reject malformed no-payload packets with non-zero Remain...
    • 0bd1657 Add maxWindowLog parameter to ZstdDecoder to bound memory allocation (#16850)
    • 76291f5 Fix SCTP and Redis tests (#16893)
    • e067b6e Fix revapi warnings (#16885)
    • 5a52600 Pass maxAllocation to Brotli and Zstd decoders (#16844)
    • 541add0 Merge commit from fork
    • 270800e Merge commit from fork
    • 3d45a1e Merge commit from fork
    • 75127ca Merge commit from fork
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8474680..4904ea4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kover = "0.9.8" ktlint = "14.2.0" knit = "0.5.1" mavenPublish = "0.36.0" -netty = "4.2.14.Final" +netty = "4.2.15.Final" # libraries version awaitility = "4.3.0" @@ -18,7 +18,7 @@ coroutines = "1.11.0" kotest = "6.1.11" kotlinx-io = "0.9.0" ktor = "3.4.3" -logging = "8.0.03" +logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" slf4j = "2.0.18" From a1f11fae2e8a5150360fec4dccbd34b6686fcaec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 05:31:56 +0200 Subject: [PATCH 042/178] chore(deps): bump hono from 4.12.18 to 4.12.23 in /integration-test/src/jvmTest/typescript (#799) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [hono](https://github.com/honojs/hono) from 4.12.18 to 4.12.23.
    Release notes

    Sourced from hono's releases.

    v4.12.23

    What's Changed

    Full Changelog: https://github.com/honojs/hono/compare/v4.12.22...v4.12.23

    v4.12.22

    What's Changed

    New Contributors

    Full Changelog: https://github.com/honojs/hono/compare/v4.12.21...v4.12.22

    v4.12.21

    Security fixes

    This release includes fixes for the following security issues:

    app.mount() strips mount prefix using undecoded path, causing incorrect routing for percent-encoded paths

    Affects: app.mount(). Fixes prefix stripping using the raw URL pathname instead of the decoded path, where percent-encoded characters in the mount prefix or path could cause the prefix to be removed at the wrong position, resulting in the sub-application receiving an incorrect path. GHSA-2gcr-mfcq-wcc3

    IP Restriction bypasses static deny rules for non-canonical IPv6

    Affects: hono/ip-restriction. Fixes IP address comparison using string equality, where non-canonical IPv6 representations of a denied address — such as compressed forms or hex-notation IPv4-mapped addresses — could bypass static deny rules. GHSA-xrhx-7g5j-rcj5

    Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie injection

    Affects: hono/cookie. Fixes missing validation of sameSite and priority options against injection characters (;, \r, \n), where user-controlled input passed to either option could inject additional attributes into the Set-Cookie response header. GHSA-3hrh-pfw6-9m5x

    JWT middleware accepts any Authorization scheme, not only Bearer

    Affects: hono/jwt, hono/jwk. Fixes missing scheme validation in the Authorization header, where any two-part header value was accepted regardless of the scheme name, allowing non-Bearer schemes to pass JWT authentication. GHSA-f577-qrjj-4474


    Users who use app.mount(), hono/ip-restriction, hono/cookie, or hono/jwt/hono/jwk are encouraged to upgrade to this version.

    ... (truncated)

    Commits
    • 83bfb3b 4.12.23
    • bcd290a fix(utils/ipaddr): do not compress a single 0 group to :: (#4971)
    • c968177 feat(compress): add contentTypeFilter option and `COMPRESSIBLE_CONTENT_TYPE_R...
    • 0265a54 docs(contribution): add AI Usage Policy (#4970)
    • c84c5d2 feat(context): export the Context class publicly (#4543)
    • 82dad62 fix(serve-static): normalize all backslashes in file paths, not just the firs...
    • 2f01b77 4.12.22
    • 6bc0dff feat: add msgpack as a compressible content type (#4957)
    • 7e0555d fix(deno): echo negotiated WebSocket subprotocol in upgrade response (#4955)
    • f0ed246 fix(compress): respect Accept-Encoding when encoding option is set (#4951)
    • Additional commits viewable in compare view

    [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=hono&package-manager=npm_and_yarn&previous-version=4.12.18&new-version=4.12.23)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/modelcontextprotocol/kotlin-sdk/network/alerts).
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 6e5fb5f..ed07e4e 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1184,9 +1184,9 @@ } }, "node_modules/hono": { - "version": "4.12.18", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz", - "integrity": "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==", + "version": "4.12.23", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.23.tgz", + "integrity": "sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==", "license": "MIT", "engines": { "node": ">=16.9.0" From 75920e1eb789ad183ea51c8dc338db638207a59a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:39:50 +0200 Subject: [PATCH 043/178] chore(deps): bump mcp-kotlin from 0.12.0 to 0.13.0 in /samples/kotlinlang-mcp-server (#824) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.12.0 to 0.13.0. Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Updates `io.modelcontextprotocol:kotlin-sdk-testing` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-testing's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 9a68e31..fdef6d3 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.3.21" ktor = "3.3.3" -mcp-kotlin = "0.12.0" +mcp-kotlin = "0.13.0" serialization = "1.11.0" coroutines = "1.11.0" logback = "1.5.34" From fd8afcf27fbebb26daef87fdf0328b0aa0159185 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:14:31 +0200 Subject: [PATCH 044/178] chore(deps): bump com.anthropic:anthropic-java from 2.35.0 to 2.40.1 in /samples/kotlin-mcp-client in the other-dependencies group across 1 directory (#818) Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Updates `com.anthropic:anthropic-java` from 2.35.0 to 2.40.1
    Release notes

    Sourced from com.anthropic:anthropic-java's releases.

    v2.40.1

    2.40.1 (2026-06-09)

    Full Changelog: v2.40.0...v2.40.1

    Bug Fixes

    • api: add frontier_llm refusal category (1627fd3)

    v2.40.0

    2.40.0 (2026-06-09)

    Full Changelog: v2.39.0...v2.40.0

    Features

    • api: add support for Managed Agents deployments and environment variable credentials (628720b)

    v2.39.0

    2.39.0 (2026-06-09)

    Full Changelog: v2.38.0...v2.39.0

    Features

    • api: add support for claude-mythos-5 and claude-fable-5, with support for server-side fallbacks on refusal (835fb42)
    • client: adds client-side fallbacks middleware for API providers that do not support server-side fallbacks (835fb42)

    Bug Fixes

    • 3p middleware ordering (#34) (d01da3a)
    • streaming: merge message_delta usage without dropping or rejecting iterations (#39) (e3af118)

    v2.38.0

    2.38.0 (2026-06-06)

    Full Changelog: v2.37.0...v2.38.0

    Features

    • api: small updates to Managed Agents types (c7b08d8)

    v2.37.0

    2.37.0 (2026-06-05)

    Full Changelog: v2.36.0...v2.37.0

    Features

    ... (truncated)

    Changelog

    Sourced from com.anthropic:anthropic-java's changelog.

    2.40.1 (2026-06-09)

    Full Changelog: v2.40.0...v2.40.1

    Bug Fixes

    • api: add frontier_llm refusal category (1627fd3)

    2.40.0 (2026-06-09)

    Full Changelog: v2.39.0...v2.40.0

    Features

    • api: add support for Managed Agents deployments and environment variable credentials (628720b)

    2.39.0 (2026-06-09)

    Full Changelog: v2.38.0...v2.39.0

    Features

    • api: add support for claude-mythos-5 and claude-fable-5, with support for server-side fallbacks on refusal (835fb42)
    • client: adds client-side fallbacks middleware for API providers that do not support server-side fallbacks (835fb42)

    Bug Fixes

    • 3p middleware ordering (#34) (d01da3a)
    • streaming: merge message_delta usage without dropping or rejecting iterations (#39) (e3af118)

    2.38.0 (2026-06-06)

    Full Changelog: v2.37.0...v2.38.0

    Features

    • api: small updates to Managed Agents types (c7b08d8)

    2.37.0 (2026-06-05)

    Full Changelog: v2.36.0...v2.37.0

    Features

    • api: mark Claude Opus 4.1 as deprecated (693cbb4)

    2.36.0 (2026-06-04)

    Full Changelog: v2.35.0...v2.36.0

    ... (truncated)

    Commits
    • 43b8020 release: 2.40.1 (#350)
    • 8f3e69b release: 2.40.0
    • 1540132 feat(api): add support for Managed Agents deployments and environment variabl...
    • a214f31 release: 2.39.0
    • 194e2f4 feat(api): add support for claude-mythos-5 and claude-fable-5, with support f...
    • 56a2a49 fix(streaming): merge message_delta usage without dropping or rejecting itera...
    • a8c6d0f fix: 3p middleware ordering (#34)
    • 79e8568 release: 2.38.0
    • e7c8e6e feat(api): small updates to Managed Agents types
    • edc1ae0 release: 2.37.0
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 42d700e..2b5eb49 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.35.0" +anthropic = "2.40.1" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.12.0" From 0851f367972699fc3c588c0c8cabe7023cc03485 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:37:03 +0200 Subject: [PATCH 045/178] chore(deps): bump io.modelcontextprotocol:kotlin-sdk-client from 0.12.0 to 0.13.0 in /samples/kotlin-mcp-client (#820) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.modelcontextprotocol:kotlin-sdk-client](https://github.com/modelcontextprotocol/kotlin-sdk) from 0.12.0 to 0.13.0.
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 2b5eb49..033fbdc 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -2,7 +2,7 @@ anthropic = "2.40.1" kotlin = "2.3.21" ktor = "3.3.3" -mcp-kotlin = "0.12.0" +mcp-kotlin = "0.13.0" shadow = "9.4.2" slf4j = "2.0.18" From b71df8be126deceab628c701a79b03fb3177a697 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 10:54:57 +0000 Subject: [PATCH 046/178] chore(deps): bump @types/node from 25.9.1 to 25.9.3 in /integration-test/src/jvmTest/typescript in the all-dependencies group across 1 directory (#821) Bumps the all-dependencies group with 1 update in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 25.9.1 to 25.9.3
    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 8 ++++---- integration-test/src/jvmTest/typescript/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index ed07e4e..3dab623 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,7 +15,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.9.1", + "@types/node": "^25.9.3", "cors": "^2.8.6", "tsx": "^4.22.4", "typescript": "^6.0.3" @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", - "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "version": "25.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz", + "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 0fafdb9..629b3bb 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,7 +16,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.9.1", + "@types/node": "^25.9.3", "cors": "^2.8.6", "tsx": "^4.22.4", "typescript": "^6.0.3" From 2b9bc78165f85aff0c1eec99c483af3e87dbe312 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:13:14 +0000 Subject: [PATCH 047/178] chore(deps): bump mcp-kotlin from 0.12.0 to 0.13.0 in /samples/kotlin-mcp-server (#823) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.12.0 to 0.13.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 165d096..bd87373 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.3.21" ktor = "3.3.3" -mcp-kotlin = "0.12.0" +mcp-kotlin = "0.13.0" slf4j = "2.0.18" shadow = "9.4.2" From 251bacdc447d21a0c0031aaaca8bfd6c27f5c3aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:27:40 +0000 Subject: [PATCH 048/178] chore(deps): bump mcp-kotlin from 0.12.0 to 0.13.0 in /samples/simple-streamable-server (#826) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.12.0 to 0.13.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 07bdac1..ba5b0e7 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.3.21" ktor = "3.3.3" junit = "6.1.0" -mcp-kotlin = "0.12.0" +mcp-kotlin = "0.13.0" slf4j = "2.0.18" shadow = "9.4.2" From 479527c7bb2274c50c3ce112801c3ee242d3fb69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:18:19 +0200 Subject: [PATCH 049/178] chore(deps): bump mcp-kotlin from 0.12.0 to 0.13.0 in /samples/weather-stdio-server (#828) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.12.0 to 0.13.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.12.0 to 0.13.0
    Release notes

    Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

    0.13.0

    Description

    Adds a tasks capability and a typed elicitation capability, hardens transport lifecycle, dispatchers, and back-pressure, and enables DNS rebinding protection by default.

    Breaking Changes

    Typed elicitation capability and new tasks capability by @​devcrocod in #732

    ClientCapabilities.elicitation is now a typed ClientCapabilities.Elicitation (form, url) instead of a raw JsonObject?, and both ClientCapabilities and ServerCapabilities gained a typed tasks capability. The constructors of both types changed and are binary-incompatible; recompilation is required.

    Transport handlers now run on Dispatchers.Default by @​devcrocod in #778

    Handlers moved from Dispatchers.IO to Dispatchers.Default (override via handlerDispatcher), send() now suspends under back-pressure instead of buffering unbounded, and the two-argument StdioServerTransport(input, output) constructor is deprecated in favor of the builder-lambda form. Also fixes a start()/close() race, consistent CancellationException propagation, and an input-Source leak (closes #573, #574, #708).

    DNS rebinding protection enabled by default by @​devcrocod in #659

    enableDnsRebindingProtection now defaults to true on mcpStreamableHttp/mcpStatelessStreamableHttp, and the Route.mcp() / Application.mcp() overloads gained enableDnsRebindingProtection, allowedHosts, and allowedOrigins parameters (binary-incompatible on JVM). Only localhost, 127.0.0.1, and [::1] are allowed by default; opt out with enableDnsRebindingProtection = false. The Configuration.enableDnsRebindingProtection, .allowedHosts, and .allowedOrigins properties are deprecated in favor of the new DnsRebindingProtection plugin.

    Features

    • Add a tasks capability (list, cancel, and per-request augmentation for sampling and elicitation) on ClientCapabilities and ServerCapabilities, with assertions for tasks/* and notifications/tasks/status enforced by Client and ServerSession by @​devcrocod in #732
    • Configurable handlerDispatcher and ioDispatcher, plus an optional caller-supplied CoroutineScope, on transports by @​devcrocod in #778

    Fixed

    • Fire onClose callbacks on SseClientTransport when the SSE session ends — whether closed gracefully or terminated by an error — matching the other client transports by @​jskjw157 in #738

    Security

    • Enable DNS rebinding protection by default across all HTTP transports, including the SSE endpoints that previously had none (see Breaking Changes for migration) by @​devcrocod in #659
    • Cap a single stdio JSON-RPC frame at 16 MiB, throwing the new TooLongFrameException instead of buffering unbounded when a peer never sends a newline terminator by @​devcrocod in 6e6f805

    Maintenance

    • Remove the test-only dev.mokksy:mokksy dependency in favor of MockEngine and embeddedServer by @​devcrocod in #754

    Dependencies

    • Ktor to v3.4.3 in #785
    • kotlinx.coroutines to v1.11.0 in #760
    • kotlin-logging to v8.0.03 in #752, #783
    • 24 further Dependabot updates across sample projects, TypeScript conformance-test fixtures, and build/test tooling (JUnit, slf4j-simple, Gradle wrapper, anthropic-java)

    Full Changelog: https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.12.0...0.13.0

    Commits
    • b7eeeb1 release: 0.13.0 (#796)
    • 6e6f805 Merge commit from fork
    • 0eb1822 Update Ktor to version 3.4.3 (#785)
    • 0adfb3b fix!: harden lifecycle, dispatchers, back-pressure (#778)
    • 37ee423 chore(deps): bump the infrastructure group with 2 updates (#783)
    • ff4b623 chore(deps): bump the other-dependencies group across 3 directories with 3 up...
    • 78066a9 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • 1ff5f00 chore(deps): bump qs from 6.14.2 to 6.15.2 in /integration-test/src/jvmTest/t...
    • 6d5bac1 chore(deps): bump gradle-wrapper from 9.5.0 to 9.5.1 (#776)
    • c854560 chore(deps): bump the all-dependencies group across 1 directory with 2 update...
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index d7a6fcb..3e99ead 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ coroutines = "1.11.0" kotlin = "2.3.21" ktor = "3.3.3" logging = "8.0.4" -mcp-kotlin = "0.12.0" +mcp-kotlin = "0.13.0" shadow = "9.4.2" slf4j = "2.0.18" From d65c50735b6b8753a6db2fa3fc489ed24ed1f5c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:36:48 +0200 Subject: [PATCH 050/178] chore(deps): bump esbuild from 0.28.0 to 0.28.1 in /integration-test/src/jvmTest/typescript (#831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [esbuild](https://github.com/evanw/esbuild) from 0.28.0 to 0.28.1.
    Release notes

    Sourced from esbuild's releases.

    v0.28.1

    • Disallow \ in local development server HTTP requests (GHSA-g7r4-m6w7-qqqr)

      This release fixes a security issue where HTTP requests to esbuild's local development server could traverse outside of the serve directory on Windows using a \ backslash character. It happened due to the use of Go's path.Clean() function, which only handles Unix-style / characters. HTTP requests with paths containing \ are no longer allowed.

      Thanks to @​dellalibera for reporting this issue.

    • Add integrity checks to the Deno API (GHSA-gv7w-rqvm-qjhr)

      The previous release of esbuild added integrity checks to esbuild's npm install script. This release also adds integrity checks to esbuild's Deno install script. Now esbuild's Deno API will also fail with an error if the downloaded esbuild binary contains something other than the expected content.

      Note that esbuild's Deno API installs from registry.npmjs.org by default, but allows the NPM_CONFIG_REGISTRY environment variable to override this with a custom package registry. This change means that the esbuild executable served by NPM_CONFIG_REGISTRY must now match the expected content.

      Thanks to @​sondt99 for reporting this issue.

    • Avoid inlining using and await using declarations (#4482)

      Previously esbuild's minifier sometimes incorrectly inlined using and await using declarations into subsequent uses of that declaration, which then fails to dispose of the resource correctly. This bug happened because inlining was done for let and const declarations by avoiding doing it for var declarations, which no longer worked when more declaration types were added. Here's an example:

      // Original code
      {
        using x = new Resource()
        x.activate()
      }
      

      // Old output (with --minify)
      new Resource().activate();

      // New output (with --minify)
      {using e=new Resource;e.activate()}

    • Fix module evaluation when an error is thrown (#4461, #4467)

      If an error is thrown during module evaluation, esbuild previously didn't preserve the state of the module for subsequent module references. This was observable if import() or require() is used to import a module multiple times. The thrown error is supposed to be thrown by every call to import() or require(), not just the first. With this release, esbuild will now throw the same error every time you call import() or require() on a module that throws during its evaluation.

    • Fix some edge cases around the new operator (#4477)

      Previously esbuild incorrectly printed certain edge cases involving complex expressions inside the target of a new expression (specifically an optional chain and/or a tagged template literal). The generated code for the new target was not correctly wrapped with parentheses, and either contained a syntax error or had different semantics. These edge cases have been fixed so that they now correctly wrap the new target in parentheses. Here is an example of some affected code:

      // Original code
      new (foo()`bar`)()
      new (foo()?.bar)()
      

      // Old output
      new foo()bar();
      new (foo())?.bar();

    ... (truncated)

    Changelog

    Sourced from esbuild's changelog.

    0.28.1

    • Disallow \ in local development server HTTP requests (GHSA-g7r4-m6w7-qqqr)

      This release fixes a security issue where HTTP requests to esbuild's local development server could traverse outside of the serve directory on Windows using a \ backslash character. It happened due to the use of Go's path.Clean() function, which only handles Unix-style / characters. HTTP requests with paths containing \ are no longer allowed.

      Thanks to @​dellalibera for reporting this issue.

    • Add integrity checks to the Deno API (GHSA-gv7w-rqvm-qjhr)

      The previous release of esbuild added integrity checks to esbuild's npm install script. This release also adds integrity checks to esbuild's Deno install script. Now esbuild's Deno API will also fail with an error if the downloaded esbuild binary contains something other than the expected content.

      Note that esbuild's Deno API installs from registry.npmjs.org by default, but allows the NPM_CONFIG_REGISTRY environment variable to override this with a custom package registry. This change means that the esbuild executable served by NPM_CONFIG_REGISTRY must now match the expected content.

      Thanks to @​sondt99 for reporting this issue.

    • Avoid inlining using and await using declarations (#4482)

      Previously esbuild's minifier sometimes incorrectly inlined using and await using declarations into subsequent uses of that declaration, which then fails to dispose of the resource correctly. This bug happened because inlining was done for let and const declarations by avoiding doing it for var declarations, which no longer worked when more declaration types were added. Here's an example:

      // Original code
      {
        using x = new Resource()
        x.activate()
      }
      

      // Old output (with --minify)
      new Resource().activate();

      // New output (with --minify)
      {using e=new Resource;e.activate()}

    • Fix module evaluation when an error is thrown (#4461, #4467)

      If an error is thrown during module evaluation, esbuild previously didn't preserve the state of the module for subsequent module references. This was observable if import() or require() is used to import a module multiple times. The thrown error is supposed to be thrown by every call to import() or require(), not just the first. With this release, esbuild will now throw the same error every time you call import() or require() on a module that throws during its evaluation.

    • Fix some edge cases around the new operator (#4477)

      Previously esbuild incorrectly printed certain edge cases involving complex expressions inside the target of a new expression (specifically an optional chain and/or a tagged template literal). The generated code for the new target was not correctly wrapped with parentheses, and either contained a syntax error or had different semantics. These edge cases have been fixed so that they now correctly wrap the new target in parentheses. Here is an example of some affected code:

      // Original code
      new (foo()`bar`)()
      new (foo()?.bar)()
      

      // Old output
      new foo()bar();
      new (foo())?.bar();

    ... (truncated)

    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 214 +++++++++--------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 3dab623..de65fb2 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -22,9 +22,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", - "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -39,9 +39,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", - "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -56,9 +56,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", - "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -73,9 +73,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", - "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -90,9 +90,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", - "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -107,9 +107,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", - "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -124,9 +124,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", - "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -141,9 +141,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", - "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -158,9 +158,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", - "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -175,9 +175,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", - "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -192,9 +192,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", - "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -209,9 +209,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", - "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -226,9 +226,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", - "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -243,9 +243,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", - "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -260,9 +260,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", - "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -277,9 +277,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", - "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -294,9 +294,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", - "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -311,9 +311,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", - "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -328,9 +328,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", - "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -345,9 +345,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", - "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -362,9 +362,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", - "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -379,9 +379,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", - "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -396,9 +396,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", - "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -413,9 +413,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", - "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -430,9 +430,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", - "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -447,9 +447,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", - "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -888,9 +888,9 @@ } }, "node_modules/esbuild": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", - "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -901,32 +901,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.0", - "@esbuild/android-arm": "0.28.0", - "@esbuild/android-arm64": "0.28.0", - "@esbuild/android-x64": "0.28.0", - "@esbuild/darwin-arm64": "0.28.0", - "@esbuild/darwin-x64": "0.28.0", - "@esbuild/freebsd-arm64": "0.28.0", - "@esbuild/freebsd-x64": "0.28.0", - "@esbuild/linux-arm": "0.28.0", - "@esbuild/linux-arm64": "0.28.0", - "@esbuild/linux-ia32": "0.28.0", - "@esbuild/linux-loong64": "0.28.0", - "@esbuild/linux-mips64el": "0.28.0", - "@esbuild/linux-ppc64": "0.28.0", - "@esbuild/linux-riscv64": "0.28.0", - "@esbuild/linux-s390x": "0.28.0", - "@esbuild/linux-x64": "0.28.0", - "@esbuild/netbsd-arm64": "0.28.0", - "@esbuild/netbsd-x64": "0.28.0", - "@esbuild/openbsd-arm64": "0.28.0", - "@esbuild/openbsd-x64": "0.28.0", - "@esbuild/openharmony-arm64": "0.28.0", - "@esbuild/sunos-x64": "0.28.0", - "@esbuild/win32-arm64": "0.28.0", - "@esbuild/win32-ia32": "0.28.0", - "@esbuild/win32-x64": "0.28.0" + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, "node_modules/escape-html": { From 75a944fb8ce249eb36a6800eabeddca7cf8b40e2 Mon Sep 17 00:00:00 2001 From: Mukunda Rao Katta Date: Wed, 17 Jun 2026 10:11:23 -0700 Subject: [PATCH 051/178] fix: polish SEP-1577 sampling handling (#765) ## Summary - reject empty sampling content in SamplingMessage and CreateMessageResult constructors - clarify sampling validation docs and emit an explicit error when tool_use is not followed by tool_result - return sampled text from the conformance test_sampling tool instead of content object strings Fixes #730 ## Testing - ./gradlew -Dorg.gradle.java.installations.paths="/Users/ubl/Documents/New project/oss-contributions/.jdks/jdk-21.0.11+10/Contents/Home" :kotlin-sdk-core:jvmTest :kotlin-sdk-server:jvmTest :conformance-test:compileKotlin Co-authored-by: Pavel Gorgulov --- .../kotlin/sdk/conformance/ConformanceTools.kt | 8 +++++++- .../kotlin/sdk/types/sampling.kt | 8 ++++++++ .../kotlin/sdk/types/SamplingTest.kt | 18 ++++++++++++++++++ .../kotlin/sdk/server/SamplingValidation.kt | 7 +++++-- .../kotlin/sdk/server/SamplingTest.kt | 18 ++++++++++++++++++ 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceTools.kt b/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceTools.kt index e288272..c81c98c 100644 --- a/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceTools.kt +++ b/conformance-test/src/main/kotlin/io/modelcontextprotocol/kotlin/sdk/conformance/ConformanceTools.kt @@ -179,7 +179,13 @@ fun Server.registerConformanceTools() { ), ), ) - CallToolResult(listOf(TextContent(result.content.joinToString("\n") { it.toString() }))) + val sampledText = result.content.joinToString("\n") { content -> + when (content) { + is TextContent -> content.text + else -> "Non-text sampling content: ${content::class.simpleName}" + } + } + CallToolResult(listOf(TextContent(sampledText))) } // 9. Elicitation diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt index 211fdc7..4526405 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt @@ -91,6 +91,10 @@ public data class SamplingMessage( @SerialName("_meta") val meta: JsonObject? = null, ) { + init { + require(content.isNotEmpty()) { "content must contain at least one block" } + } + /** * Convenience constructor for a single-block message. Wraps [content] in a * singleton list so call sites can write `SamplingMessage(Role.User, TextContent("hi"))` @@ -273,6 +277,10 @@ public data class CreateMessageResult( @SerialName("_meta") override val meta: JsonObject? = null, ) : ClientResult { + init { + require(content.isNotEmpty()) { "content must contain at least one block" } + } + /** * Convenience constructor for a single-block response. Wraps [content] in a * singleton list so call sites can write diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt index 62a82cd..b2c8cf0 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt @@ -302,6 +302,13 @@ class SamplingTest { (m.content[0] as TextContent).text shouldBe "hi" } + @Test + fun `SamplingMessage rejects empty content`() { + assertFailsWith { + SamplingMessage(role = Role.User, content = emptyList()) + } + } + @Test fun `SamplingMessage single-element content serialises as single object`() { val m = SamplingMessage(role = Role.User, content = listOf(TextContent("hi"))) @@ -408,6 +415,17 @@ class SamplingTest { (decoded.content[0] as TextContent).text shouldBe "hi" } + @Test + fun `CreateMessageResult rejects empty content`() { + assertFailsWith { + CreateMessageResult( + role = Role.Assistant, + content = emptyList(), + model = "test-model", + ) + } + } + // ============================================================================ // SamplingContentSerializer (single-or-array wire heuristic) // ============================================================================ diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingValidation.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingValidation.kt index ef40808..8243171 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingValidation.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingValidation.kt @@ -20,8 +20,8 @@ import io.modelcontextprotocol.kotlin.sdk.types.ToolUseContent * 3. If the previous message contains `tool_use` blocks, the last message's * `tool_result` ids MUST form exactly the same set. * - * On the first violation throws [IllegalArgumentException]. No-op when there are fewer - * than two messages or no tool_use / tool_result blocks are involved. + * On the first violation throws [IllegalArgumentException]. No-op when no + * tool_use / tool_result blocks are involved. */ internal fun validateSamplingMessages(messages: List) { if (messages.isEmpty()) return @@ -44,6 +44,9 @@ internal fun validateSamplingMessages(messages: List) { if (hasPreviousToolUse) { val toolUseIds = previous.filterIsInstance().map { it.id }.toSet() val toolResultIds = last.filterIsInstance().map { it.toolUseId }.toSet() + require(toolResultIds.isNotEmpty()) { + "tool_use blocks from previous message must be followed by matching tool_result blocks" + } require(toolUseIds == toolResultIds) { "ids of tool_result blocks and tool_use blocks from previous message do not match" } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingTest.kt index 2b5446b..cfcbb62 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SamplingTest.kt @@ -8,6 +8,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.ToolUseContent import kotlinx.serialization.json.JsonObject import org.junit.jupiter.api.assertDoesNotThrow import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertFailsWith /** @@ -83,4 +84,21 @@ class SamplingTest { ) } } + + @Test + fun `validate tool_use requires explicit tool_result in last message`() { + val error = assertFailsWith { + validateSamplingMessages( + listOf( + SamplingMessage(Role.Assistant, toolUse("c1")), + SamplingMessage(Role.User, TextContent("missing result")), + ), + ) + } + + assertEquals( + "tool_use blocks from previous message must be followed by matching tool_result blocks", + error.message, + ) + } } From d21728eccab4b59a2a850eb417695c624d95bab4 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Thu, 18 Jun 2026 08:54:54 +0200 Subject: [PATCH 052/178] fix: bound inline SSE event size in Streamable HTTP client (#841) Bound the size of a single inline SSE event parsed from a POST response in `StreamableHttpClientTransport`, so a non-conforming or unbounded server response cannot grow the client's buffer without limit. ## How Has This Been Tested? New unit tests ## Breaking Changes none ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- kotlin-sdk-client/api/kotlin-sdk-client.api | 4 +- .../client/StreamableHttpClientTransport.kt | 42 ++++++- .../http/StreamableHttpClientTransportTest.kt | 106 +++++++++++++++++- 3 files changed, 144 insertions(+), 8 deletions(-) diff --git a/kotlin-sdk-client/api/kotlin-sdk-client.api b/kotlin-sdk-client/api/kotlin-sdk-client.api index 8b6fb79..0a544f5 100644 --- a/kotlin-sdk-client/api/kotlin-sdk-client.api +++ b/kotlin-sdk-client/api/kotlin-sdk-client.api @@ -101,8 +101,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/client/StdioClientTranspor } public final class io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport : io/modelcontextprotocol/kotlin/sdk/shared/AbstractClientTransport { - public fun (Lio/ktor/client/HttpClient;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/client/ReconnectionOptions;Lkotlin/jvm/functions/Function1;)V - public synthetic fun (Lio/ktor/client/HttpClient;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/client/ReconnectionOptions;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lio/ktor/client/HttpClient;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/client/ReconnectionOptions;ILkotlin/jvm/functions/Function1;)V + public synthetic fun (Lio/ktor/client/HttpClient;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/client/ReconnectionOptions;ILkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun (Lio/ktor/client/HttpClient;Ljava/lang/String;Lkotlin/time/Duration;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun (Lio/ktor/client/HttpClient;Ljava/lang/String;Lkotlin/time/Duration;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun getProtocolVersion ()Ljava/lang/String; 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 c27ed79..a63c1d2 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 @@ -21,8 +21,10 @@ import io.ktor.http.HttpMethod import io.ktor.http.HttpStatusCode import io.ktor.http.contentType import io.ktor.http.isSuccess +import io.ktor.utils.io.charsets.TooLongLineException import io.ktor.utils.io.readUTF8Line import io.modelcontextprotocol.kotlin.sdk.shared.AbstractClientTransport +import io.modelcontextprotocol.kotlin.sdk.shared.TooLongFrameException import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification @@ -50,6 +52,14 @@ private const val MCP_SESSION_ID_HEADER = "mcp-session-id" private const val MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version" private const val MCP_RESUMPTION_TOKEN_HEADER = "Last-Event-ID" +/** + * Default maximum size, in characters, of a single inline SSE event assembled from a POST response. + * + * Mirrors the stdio transport's 16 MiB frame cap: a server that streams `data:` lines without ever + * terminating the event cannot grow the client's buffer without bound. + */ +private const val DEFAULT_MAX_INLINE_SSE_EVENT_SIZE: Int = 16 * 1024 * 1024 + /** * Represents an error from the Streamable HTTP transport. * @@ -75,15 +85,23 @@ private sealed interface ConnectResult { * @param client Ktor HTTP client used for all requests * @param url MCP endpoint URL * @param reconnectionOptions reconnection backoff and retry-limit settings for the SSE stream + * @param maxInlineSseEventSize maximum size, in characters, of a single inline SSE event parsed from a + * POST response; a server that exceeds it (including by never terminating an event) fails the send + * with [io.modelcontextprotocol.kotlin.sdk.shared.TooLongFrameException]. Defaults to 16 MiB. * @param requestBuilder builder applied to every outgoing HTTP request, e.g. for adding auth headers */ public class StreamableHttpClientTransport( private val client: HttpClient, private val url: String, private val reconnectionOptions: ReconnectionOptions = ReconnectionOptions(), + private val maxInlineSseEventSize: Int = DEFAULT_MAX_INLINE_SSE_EVENT_SIZE, private val requestBuilder: HttpRequestBuilder.() -> Unit = {}, ) : AbstractClientTransport() { + init { + require(maxInlineSseEventSize > 0) { "maxInlineSseEventSize must be greater than 0" } + } + @Deprecated( "Use constructor with ReconnectionOptions", replaceWith = ReplaceWith( @@ -98,7 +116,12 @@ public class StreamableHttpClientTransport( url: String, reconnectionTime: Duration?, requestBuilder: HttpRequestBuilder.() -> Unit = {}, - ) : this(client, url, ReconnectionOptions(initialReconnectionDelay = reconnectionTime ?: 1.seconds), requestBuilder) + ) : this( + client, + url, + ReconnectionOptions(initialReconnectionDelay = reconnectionTime ?: 1.seconds), + requestBuilder = requestBuilder, + ) override val logger: KLogger = KotlinLogging.logger {} @@ -458,7 +481,14 @@ public class StreamableHttpClientTransport( } while (!channel.isClosedForRead) { - val line = channel.readUTF8Line() ?: break + // Bound each line so a server that streams a line without ever terminating it cannot + // exhaust client memory; readUTF8Line returns null at the end of the stream. + val line = try { + channel.readUTF8Line(maxInlineSseEventSize) + } catch (_: TooLongLineException) { + throw TooLongFrameException(maxInlineSseEventSize.toLong() + 1, maxInlineSseEventSize) + } + if (line == null) break if (line.isEmpty()) { dispatch(id = id, eventName = eventName, data = sb.toString()) // reset @@ -472,7 +502,13 @@ public class StreamableHttpClientTransport( line.startsWith("event:") -> eventName = line.substringAfter("event:").trim() - line.startsWith("data:") -> sb.append(line.substringAfter("data:").trim()) + line.startsWith("data:") -> { + sb.append(line.substringAfter("data:").trim()) + // Cap an event assembled from many data: lines that never sees a terminating blank line. + if (sb.length > maxInlineSseEventSize) { + throw TooLongFrameException(sb.length.toLong(), maxInlineSseEventSize) + } + } line.startsWith("retry:") -> line.substringAfter("retry:").trim().toLongOrNull()?.let { localServerRetryDelay = it.milliseconds diff --git a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt index b380f64..ef55867 100644 --- a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt +++ b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt @@ -19,6 +19,7 @@ import io.ktor.http.headersOf import io.ktor.utils.io.ByteReadChannel import io.modelcontextprotocol.kotlin.sdk.client.Client import io.modelcontextprotocol.kotlin.sdk.client.StreamableHttpClientTransport +import io.modelcontextprotocol.kotlin.sdk.shared.TooLongFrameException import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification @@ -43,11 +44,15 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertNull import kotlin.test.assertTrue +import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds class StreamableHttpClientTransportTest { - private fun createTransport(handler: MockRequestHandler): StreamableHttpClientTransport { + private fun createTransport( + maxInlineSseEventSize: Int = 16 * 1024 * 1024, + handler: MockRequestHandler, + ): StreamableHttpClientTransport { val mockEngine = MockEngine(handler) val httpClient = HttpClient(mockEngine) { install(SSE) { @@ -55,7 +60,11 @@ class StreamableHttpClientTransportTest { } } - return StreamableHttpClientTransport(httpClient, url = "http://localhost:8080/mcp") + return StreamableHttpClientTransport( + httpClient, + url = "http://localhost:8080/mcp", + maxInlineSseEventSize = maxInlineSseEventSize, + ) } private fun buildSseMessage(id: String, method: String, params: String): String = buildString { @@ -551,6 +560,97 @@ class StreamableHttpClientTransportTest { transport.close() } + @Test + fun testInlineSseRejectsEventExceedingMaxSize() = runTest { + // A malicious server streams an endless single event: many `data:` lines that accumulate + // past the cap and never send the blank-line terminator that would flush the buffer. + val maxInlineSseEventSize = 64 + val transport = createTransport(maxInlineSseEventSize) { request -> + if (request.method == HttpMethod.Post) { + val sseContent = buildString { + appendLine("event: message") + // 20 lines × 16 chars = 320 chars of accumulated data, no terminating blank line. + repeat(20) { appendLine("data: ${"A".repeat(16)}") } + } + respond( + content = ByteReadChannel(sseContent), + status = HttpStatusCode.OK, + headers = headersOf(HttpHeaders.ContentType, ContentType.Text.EventStream.toString()), + ) + } else { + respond("", HttpStatusCode.OK) + } + } + + val receivedMessages = mutableListOf() + val receivedErrors = mutableListOf() + transport.onMessage { receivedMessages.add(it) } + transport.onError { receivedErrors.add(it) } + transport.start() + + val error = assertFailsWith { + transport.send(JSONRPCRequest(id = "req-1", method = "test", params = buildJsonObject { })) + } + + error.cause.shouldBeInstanceOf() + receivedErrors.filterIsInstance() shouldHaveSize 1 + receivedMessages shouldHaveSize 0 + transport.close() + } + + @Test + fun testInlineSseEventExactlyAtMaxSizeIsAccepted() = runTest { + // An event whose assembled data length equals the cap must still be accepted and dispatched: + // the guard rejects only sizes strictly greater than the cap (parity with ReadBuffer). + val part1 = """{"jsonrpc":"2.0",""" + val part2 = """"method":"notifications/tools/list_changed"}""" + val maxInlineSseEventSize = (part1 + part2).length + + val transport = createTransport(maxInlineSseEventSize) { request -> + if (request.method == HttpMethod.Post) { + val sseContent = buildString { + appendLine("event: message") + appendLine("data: $part1") + appendLine("data: $part2") + appendLine() + } + respond( + content = ByteReadChannel(sseContent), + status = HttpStatusCode.OK, + headers = headersOf(HttpHeaders.ContentType, ContentType.Text.EventStream.toString()), + ) + } else { + respond("", HttpStatusCode.OK) + } + } + + val receivedMessages = mutableListOf() + val receivedErrors = mutableListOf() + val messageReceived = CompletableDeferred() + transport.onMessage { + receivedMessages.add(it) + if (!messageReceived.isCompleted) messageReceived.complete(Unit) + } + transport.onError { receivedErrors.add(it) } + transport.start() + + transport.send(JSONRPCRequest(id = "req-1", method = "test", params = buildJsonObject { })) + + eventually { messageReceived.await() } + + receivedMessages shouldHaveSize 1 + (receivedMessages[0] as JSONRPCNotification).method shouldBe "notifications/tools/list_changed" + receivedErrors shouldHaveSize 0 + transport.close() + } + + @Test + fun testNonPositiveMaxInlineSseEventSizeThrows() { + assertFailsWith { + createTransport(maxInlineSseEventSize = 0) { respond("", HttpStatusCode.OK) } + } + } + @Test fun testInlineSSEInResponse() = runTest { val transport = createTransport { request -> @@ -716,7 +816,7 @@ class StreamableHttpClientTransportTest { eventually { while (receivedMessages.isEmpty()) { - delay(10) + delay(10.milliseconds) } } From c8a1103b163509e6f58900ec3bd99307031faeef Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 23 Jun 2026 22:14:59 +0200 Subject: [PATCH 053/178] feat: sep-1036 add URL Mode Elicitation (#843) closes #410 ## How Has This Been Tested? integration and unit tests ## Breaking Changes none ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../kotlin/sdk/client/ClientTest.kt | 187 ++++++++++++++++++ .../kotlin/sdk/server/ClientConnectionTest.kt | 2 + kotlin-sdk-client/api/kotlin-sdk-client.api | 1 + .../kotlin/sdk/client/Client.kt | 45 ++++- kotlin-sdk-core/api/kotlin-sdk-core.api | 40 +++- .../kotlin/sdk/shared/Protocol.kt | 2 +- .../kotlin/sdk/types/McpException.kt | 21 +- .../types/UrlElicitationRequiredException.kt | 65 ++++++ .../kotlin/sdk/types/capabilities.kt | 9 + .../kotlin/sdk/types/elicitation.kt | 5 + .../kotlin/sdk/types/jsonRpc.kt | 7 + .../kotlin/sdk/types/CapabilitiesTest.kt | 20 ++ .../kotlin/sdk/types/ElicitationTest.kt | 83 ++++++++ .../kotlin/sdk/server/ClientConnection.kt | 9 + .../kotlin/sdk/server/Server.kt | 4 + 15 files changed, 494 insertions(+), 6 deletions(-) create mode 100644 kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredException.kt diff --git a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt index 5c00b23..5dfcf61 100644 --- a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt +++ b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt @@ -14,7 +14,10 @@ import io.modelcontextprotocol.kotlin.sdk.types.CreateMessageResult import io.modelcontextprotocol.kotlin.sdk.types.DoubleSchema import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestFormParams import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestURLParams import io.modelcontextprotocol.kotlin.sdk.types.ElicitResult +import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotification +import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotificationParams import io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest @@ -46,6 +49,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.Tool import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema import io.modelcontextprotocol.kotlin.sdk.types.UntitledMultiSelectEnumSchema import io.modelcontextprotocol.kotlin.sdk.types.UntitledSingleSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.UrlElicitationRequiredException import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.cancel @@ -1251,6 +1255,189 @@ class ClientTest { client.close() } + // ── URL-mode elicitation (SEP-1036) ───────────────────────────────── + + @Test + fun `should handle URL mode elicitation end-to-end`() = runTest { + val client = Client( + Implementation(name = "test client", version = "1.0"), + ClientOptions( + capabilities = ClientCapabilities( + elicitation = ClientCapabilities.Elicitation(url = EmptyJsonObject), + ), + ), + ) + + val elicitationId = "550e8400-e29b-41d4-a716-446655440000" + val url = "https://oauth.example.com/authorize" + + client.setElicitationHandler { request -> + val params = assertIs(request.params) + assertEquals(elicitationId, params.elicitationId) + assertEquals(url, params.url) + ElicitResult(action = ElicitResult.Action.Accept) + } + + val (clientTransport, serverTransport) = InMemoryTransport.createLinkedPair() + val server = Server( + serverInfo = Implementation(name = "test server", version = "1.0"), + options = ServerOptions(capabilities = ServerCapabilities()), + ) + + val serverSessionResult = CompletableDeferred() + listOf( + launch { client.connect(clientTransport) }, + launch { serverSessionResult.complete(server.createSession(serverTransport)) }, + ).joinAll() + val serverSession = serverSessionResult.await() + + val result = serverSession.createElicitation( + message = "Authorize access to continue", + elicitationId = elicitationId, + url = url, + ) + + assertEquals(ElicitResult.Action.Accept, result.action) + assertNull(result.content) + + client.close() + } + + @Test + fun `should reject URL mode elicitation when client supports only form mode`() = runTest { + val (client, serverSession) = setupElicitationPair { + ElicitResult(action = ElicitResult.Action.Accept) + } + + val exception = assertFailsWith { + serverSession.createElicitation( + message = "Authorize", + elicitationId = "id-1", + url = "https://example.com/auth", + ) + } + assertTrue(exception.message!!.contains("elicitation.url")) + + client.close() + } + + @Test + fun `should deliver elicitation complete notification to client`() = runTest { + val received = CompletableDeferred() + val client = Client( + Implementation(name = "test client", version = "1.0"), + ClientOptions( + capabilities = ClientCapabilities( + elicitation = ClientCapabilities.Elicitation(url = EmptyJsonObject), + ), + ), + ) + client.setElicitationCompleteHandler { received.complete(it) } + + val (clientTransport, serverTransport) = InMemoryTransport.createLinkedPair() + val server = Server( + serverInfo = Implementation(name = "test server", version = "1.0"), + options = ServerOptions(capabilities = ServerCapabilities()), + ) + + val serverSessionResult = CompletableDeferred() + listOf( + launch { client.connect(clientTransport) }, + launch { serverSessionResult.complete(server.createSession(serverTransport)) }, + ).joinAll() + val serverSession = serverSessionResult.await() + + val elicitationId = "complete-id-1" + serverSession.sendElicitationComplete( + ElicitationCompleteNotification(ElicitationCompleteNotificationParams(elicitationId = elicitationId)), + ) + + val notification = received.await() + assertEquals(elicitationId, notification.params.elicitationId) + + client.close() + } + + @Test + fun `should reject elicitation complete when client supports only form mode`() = runTest { + val (client, serverSession) = setupElicitationPair { + ElicitResult(action = ElicitResult.Action.Accept) + } + + val exception = assertFailsWith { + serverSession.sendElicitationComplete( + ElicitationCompleteNotification(ElicitationCompleteNotificationParams(elicitationId = "id-1")), + ) + } + assertTrue(exception.message!!.contains("elicitation.url")) + + client.close() + } + + @Test + fun `setElicitationCompleteHandler should require url capability`() = runTest { + val client = Client( + Implementation(name = "test client", version = "1.0"), + ClientOptions( + capabilities = ClientCapabilities( + elicitation = ClientCapabilities.Elicitation(), + ), + ), + ) + + assertFailsWith { + client.setElicitationCompleteHandler { } + } + } + + @Test + fun `should surface URL elicitation required error to client as typed exception`() = runTest { + val client = Client( + Implementation(name = "test client", version = "1.0"), + ClientOptions( + capabilities = ClientCapabilities( + elicitation = ClientCapabilities.Elicitation(url = EmptyJsonObject), + ), + ), + ) + + val elicitationId = "auth-required-1" + val url = "https://oauth.example.com/authorize" + + val (clientTransport, serverTransport) = InMemoryTransport.createLinkedPair() + val server = Server( + serverInfo = Implementation(name = "test server", version = "1.0"), + options = ServerOptions(capabilities = ServerCapabilities(tools = ServerCapabilities.Tools(true))), + ) + server.addTool("needs-auth", "Requires URL elicitation") { + throw UrlElicitationRequiredException( + listOf( + ElicitRequestURLParams( + message = "Authorize to continue", + elicitationId = elicitationId, + url = url, + ), + ), + ) + } + + val serverSessionResult = CompletableDeferred() + listOf( + launch { client.connect(clientTransport) }, + launch { serverSessionResult.complete(server.createSession(serverTransport)) }, + ).joinAll() + serverSessionResult.await() + + val exception = assertFailsWith { + client.callTool(name = "needs-auth", arguments = emptyMap()) + } + val elicitation = exception.elicitations.single() + assertEquals(elicitationId, elicitation.elicitationId) + assertEquals(url, elicitation.url) + + client.close() + } + private fun defaultsTestSchema(): ElicitRequestParams.RequestedSchema = ElicitRequestParams.RequestedSchema( properties = mapOf( "name" to StringSchema(description = "User name", default = "John Doe"), diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionTest.kt index ee8953a..581e5ae 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionTest.kt @@ -9,6 +9,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.CallToolRequestParams import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotification import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotificationParams +import io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject import io.modelcontextprotocol.kotlin.sdk.types.GetPromptRequest import io.modelcontextprotocol.kotlin.sdk.types.GetPromptRequestParams import io.modelcontextprotocol.kotlin.sdk.types.ListRootsRequest @@ -61,6 +62,7 @@ class ClientConnectionTest : AbstractServerFeaturesTest() { override fun getClientCapabilities(): ClientCapabilities = ClientCapabilities( roots = ClientCapabilities.Roots(listChanged = true), + elicitation = ClientCapabilities.Elicitation(url = EmptyJsonObject), ) private val sampleRoots = listOf(Root("file:///project", "Project Root")) diff --git a/kotlin-sdk-client/api/kotlin-sdk-client.api b/kotlin-sdk-client/api/kotlin-sdk-client.api index 0a544f5..1493a30 100644 --- a/kotlin-sdk-client/api/kotlin-sdk-client.api +++ b/kotlin-sdk-client/api/kotlin-sdk-client.api @@ -34,6 +34,7 @@ public class io/modelcontextprotocol/kotlin/sdk/client/Client : io/modelcontextp public final fun removeRoot (Ljava/lang/String;)Z public final fun removeRoots (Ljava/util/List;)I public final fun sendRootsListChanged (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun setElicitationCompleteHandler (Lkotlin/jvm/functions/Function1;)V public final fun setElicitationHandler (Lkotlin/jvm/functions/Function1;)V public final fun setLoggingLevel (Lio/modelcontextprotocol/kotlin/sdk/types/LoggingLevel;Lio/modelcontextprotocol/kotlin/sdk/shared/RequestOptions;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun setLoggingLevel$default (Lio/modelcontextprotocol/kotlin/sdk/client/Client;Lio/modelcontextprotocol/kotlin/sdk/types/LoggingLevel;Lio/modelcontextprotocol/kotlin/sdk/shared/RequestOptions;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt index ee865af..b88cb1b 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt @@ -19,6 +19,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.DoubleSchema import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequest import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestFormParams import io.modelcontextprotocol.kotlin.sdk.types.ElicitResult +import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotification import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult import io.modelcontextprotocol.kotlin.sdk.types.GetPromptRequest import io.modelcontextprotocol.kotlin.sdk.types.GetPromptResult @@ -63,6 +64,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.TitledSingleSelectEnumSchema import io.modelcontextprotocol.kotlin.sdk.types.UnsubscribeRequest import io.modelcontextprotocol.kotlin.sdk.types.UntitledMultiSelectEnumSchema import io.modelcontextprotocol.kotlin.sdk.types.UntitledSingleSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.supportsUrl import io.modelcontextprotocol.kotlin.sdk.types.toJson import kotlinx.atomicfu.atomic import kotlinx.atomicfu.getAndUpdate @@ -70,6 +72,7 @@ import kotlinx.atomicfu.update import kotlinx.collections.immutable.minus import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toPersistentSet +import kotlinx.coroutines.CompletableDeferred import kotlinx.serialization.SerializationException import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject @@ -643,9 +646,18 @@ public open class Client(private val clientInfo: Implementation, options: Client /** * Sets the elicitation handler. * - * When the handler returns [ElicitResult.Action.Accept], any properties missing from + * The handler receives both form-mode ([ElicitRequestFormParams]) and URL-mode + * ([io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestURLParams]) requests; + * branch on `request.params` to tell them apart. For URL mode, + * the host application must obtain explicit user consent and display the target domain before + * navigating — the SDK never opens or validates the URL — and should return + * [ElicitResult.Action.Decline] or [ElicitResult.Action.Cancel] when it cannot or will not proceed. + * A URL-mode [ElicitResult.Action.Accept] only signals consent; the outcome arrives out-of-band via + * [setElicitationCompleteHandler]. + * + * When a form-mode handler returns [ElicitResult.Action.Accept], any properties missing from * [ElicitResult.content] are automatically populated with default values defined in the - * elicitation schema. + * elicitation schema. URL-mode responses carry no content. * * @param handler The elicitation handler. * @throws IllegalStateException if the client does not support elicitation. @@ -663,6 +675,35 @@ public open class Client(private val clientInfo: Implementation, options: Client } } + /** + * Sets the handler invoked when the server reports that a URL-mode elicitation has completed. + * + * The handler is called for every `notifications/elicitation/complete` notification. Because the + * server only sends this for an out-of-band (URL-mode) interaction, the client must support url-mode + * elicitation. The client is responsible for correlating the notification's `elicitationId` with a + * pending elicitation, ignoring unknown or already-completed identifiers, and providing a manual way + * to continue if a notification never arrives. + * + * @param handler Invoked with each completion notification. + * @throws IllegalStateException if the client does not support url-mode elicitation. + */ + public fun setElicitationCompleteHandler(handler: (ElicitationCompleteNotification) -> Unit) { + check(capabilities.elicitation.supportsUrl) { + logger.error { + "Failed to set elicitation-complete handler: client does not support url-mode elicitation" + } + "Client does not support url-mode elicitation." + } + logger.info { "Setting the elicitation-complete handler" } + + setNotificationHandler( + Method.Defined.NotificationsElicitationComplete, + ) { notification -> + handler(notification) + CompletableDeferred(Unit) + } + } + // --- Internal Handlers --- private fun applyElicitationDefaults(request: ElicitRequest, result: ElicitResult): ElicitResult { diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index 0895722..1904dc7 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -610,6 +610,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CancelledNotificatio public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesKt { + public static final fun getSupportsUrl (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Elicitation;)Z +} + public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Companion; public fun ()V @@ -3128,7 +3132,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Logging_dslKt { public abstract interface annotation class io/modelcontextprotocol/kotlin/sdk/types/McpDsl : java/lang/annotation/Annotation { } -public final class io/modelcontextprotocol/kotlin/sdk/types/McpException : java/lang/Exception { +public class io/modelcontextprotocol/kotlin/sdk/types/McpException : java/lang/Exception { public fun (I)V public fun (ILjava/lang/String;)V public fun (ILjava/lang/String;Lkotlinx/serialization/json/JsonElement;)V @@ -3744,6 +3748,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/RPCError$ErrorCode { public static final field PARSE_ERROR I public static final field REQUEST_TIMEOUT I public static final field RESOURCE_NOT_FOUND I + public static final field URL_ELICITATION_REQUIRED I } public final class io/modelcontextprotocol/kotlin/sdk/types/ReadResourceRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest { @@ -5814,6 +5819,39 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/UntitledSingleSelect public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData$Companion; + public fun (Ljava/util/List;)V + public final fun component1 ()Ljava/util/List; + public final fun copy (Ljava/util/List;)Lio/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData;Ljava/util/List;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData; + public fun equals (Ljava/lang/Object;)Z + public final fun getElicitations ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredData$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredException : io/modelcontextprotocol/kotlin/sdk/types/McpException { + public fun (Ljava/util/List;Ljava/lang/String;)V + public synthetic fun (Ljava/util/List;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getElicitations ()Ljava/util/List; +} + public abstract interface class io/modelcontextprotocol/kotlin/sdk/types/WithMeta { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/WithMeta$Companion; public abstract fun getMeta ()Lkotlinx/serialization/json/JsonObject; diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt index 8f86c03..50dc356 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt @@ -393,7 +393,7 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio handler(response, null) } else { checkNotNull(error) - val mcpException = McpException( + val mcpException = McpException.fromError( code = error.error.code, message = error.error.message, data = error.error.data, diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/McpException.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/McpException.kt index 56c851b..6a9015b 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/McpException.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/McpException.kt @@ -12,9 +12,26 @@ import kotlin.jvm.JvmOverloads * @property data optional additional error payload as a JSON element * @param cause the original cause */ -public class McpException @JvmOverloads public constructor( +public open class McpException @JvmOverloads public constructor( public val code: Int, message: String = "MCP error $code", public val data: JsonElement? = null, cause: Throwable? = null, -) : Exception(message, cause) +) : Exception(message, cause) { + internal companion object { + /** + * Reconstructs the most specific [McpException] subtype for a JSON-RPC error. + * + * Recognizes [RPCError.ErrorCode.URL_ELICITATION_REQUIRED] errors and returns a + * [UrlElicitationRequiredException] when [data] carries valid URL-mode elicitations; + * otherwise returns a plain [McpException]. Never throws — a malformed payload simply + * degrades to a plain [McpException]. + */ + fun fromError(code: Int, message: String, data: JsonElement?): McpException { + if (code == RPCError.ErrorCode.URL_ELICITATION_REQUIRED && data != null) { + UrlElicitationRequiredException.fromDataOrNull(message, data)?.let { return it } + } + return McpException(code = code, message = message, data = data) + } + } +} diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredException.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredException.kt new file mode 100644 index 0000000..f3da768 --- /dev/null +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/UrlElicitationRequiredException.kt @@ -0,0 +1,65 @@ +package io.modelcontextprotocol.kotlin.sdk.types + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.encodeToJsonElement + +/** + * Payload carried by the [data][RPCError.data] of a [RPCError.ErrorCode.URL_ELICITATION_REQUIRED] error. + * + * @property elicitations The URL-mode elicitations that must be completed before the original request + * can succeed. Each entry is equivalent to an `elicitation/create` request. + */ +@Serializable +public data class UrlElicitationRequiredData(val elicitations: List) + +/** + * Signals that one or more URL-mode elicitations must be completed before a request can be processed. + * + * Serialized over the wire as a JSON-RPC error with code [RPCError.ErrorCode.URL_ELICITATION_REQUIRED] + * and [data][RPCError.data] holding the [elicitations]. A server throws this from a request handler to + * tell the client that a URL-mode elicitation is required; the client receives it from any request as a + * typed exception, equivalent to receiving an `elicitation/create` request. + * + * The client is responsible for obtaining explicit user consent and surfacing each [ElicitRequestURLParams] + * before navigation — the SDK never opens or validates URLs. + * + * Example client-side handling: + * ```kotlin + * try { + * client.callTool(name = "create_repo", arguments = args) + * } catch (e: UrlElicitationRequiredException) { + * for (elicitation in e.elicitations) { + * // Show elicitation.message and the target domain, then ask the user for consent. + * if (userConsents(elicitation.url)) openInBrowser(elicitation.url) + * // Await completion via Client.setElicitationCompleteHandler, then optionally retry the call. + * } + * } + * ``` + * + * @property elicitations The required URL-mode elicitations (always non-empty). + */ +public class UrlElicitationRequiredException( + public val elicitations: List, + message: String = defaultMessage(elicitations), +) : McpException( + code = RPCError.ErrorCode.URL_ELICITATION_REQUIRED, + message = message, + data = McpJson.encodeToJsonElement(UrlElicitationRequiredData(elicitations)), +) { + internal companion object { + private fun defaultMessage(elicitations: List): String = + if (elicitations.size > 1) "URL elicitations are required" else "URL elicitation is required" + + /** + * Reconstructs a [UrlElicitationRequiredException] from JSON-RPC error [data], or `null` when the + * payload is absent, malformed, or carries no elicitations. Never throws. + */ + fun fromDataOrNull(message: String, data: JsonElement): UrlElicitationRequiredException? = + runCatching { McpJson.decodeFromJsonElement(data).elicitations } + .getOrNull() + ?.takeIf { it.isNotEmpty() } + ?.let { UrlElicitationRequiredException(it, message) } + } +} 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 cd78b58..ecb8c48 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 @@ -189,6 +189,15 @@ public data class ClientCapabilities( } } +/** + * Whether the client supports url-mode elicitation (out-of-band interaction via URL navigation). + * + * `false` when the client declared no elicitation capability at all, or only form mode (an empty + * [ClientCapabilities.Elicitation] is treated as form mode only). + */ +public val ClientCapabilities.Elicitation?.supportsUrl: Boolean + get() = this?.url != null + /** * Capabilities that a server may support. * 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 a0ee74c..1bb73e6 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 @@ -133,6 +133,11 @@ public data class ElicitRequestFormParams( * Directs the user to an external URL for out-of-band interactions (e.g., OAuth flows, * payment processing, or entering sensitive credentials) that must not pass through the MCP client. * + * Handling the [url] is the responsibility of the host application: it should require HTTPS, clearly + * display the target domain, obtain explicit user consent, and open the URL in a secure browser context. + * The SDK neither opens, fetches, nor validates the URL. URLs must only appear in URL-mode requests — + * never render a URL from a form-mode request as a clickable link. + * * @property message The message explaining why the interaction is needed. * @property elicitationId A unique identifier for this elicitation. The client MUST treat * this ID as an opaque value. diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt index 7eefdb5..a9d465f 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt @@ -269,6 +269,13 @@ public data class RPCError(val code: Int, val message: String, val data: JsonEle /** Resource not found */ public const val RESOURCE_NOT_FOUND: Int = -32002 + /** + * A URL-mode elicitation must be completed before the request can be processed. + * The error [data][RPCError.data] carries the required URL-mode elicitations + * (see [UrlElicitationRequiredException]). + */ + public const val URL_ELICITATION_REQUIRED: Int = -32042 + // Standard JSON-RPC 2.0 error codes /** Invalid JSON was received */ diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt index 06949a6..3468aae 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/CapabilitiesTest.kt @@ -923,4 +923,24 @@ class CapabilitiesTest { assertEquals(EmptyJsonObject, capabilities.tasks?.requests?.sampling?.createMessage) assertEquals(EmptyJsonObject, capabilities.tasks?.requests?.elicitation?.create) } + + // ── Elicitation supportsUrl predicate ─────────────────────────────── + + @Test + fun `supportsUrl is false when no elicitation capability is declared`() { + val elicitation: ClientCapabilities.Elicitation? = null + elicitation.supportsUrl shouldBe false + } + + @Test + fun `supportsUrl is false for an empty form-only capability`() { + ClientCapabilities.Elicitation().supportsUrl shouldBe false + ClientCapabilities.Elicitation(form = EmptyJsonObject).supportsUrl shouldBe false + } + + @Test + fun `supportsUrl is true when url mode is declared`() { + ClientCapabilities.Elicitation(url = EmptyJsonObject).supportsUrl shouldBe true + ClientCapabilities.Elicitation(form = EmptyJsonObject, url = EmptyJsonObject).supportsUrl shouldBe true + } } 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 1a41863..bd5ef06 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 @@ -10,6 +10,7 @@ import io.modelcontextprotocol.kotlin.test.utils.verifyDeserialization import io.modelcontextprotocol.kotlin.test.utils.verifySerialization import kotlinx.serialization.json.boolean import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.encodeToJsonElement import kotlinx.serialization.json.int import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put @@ -273,4 +274,86 @@ class ElicitationTest { ) } } + + // ── URLElicitationRequired error (-32042) ─────────────────────────── + + @Test + fun `UrlElicitationRequiredException carries code and serialized elicitations`() { + val elicitation = ElicitRequestURLParams( + message = "Authorize access to continue", + elicitationId = "550e8400-e29b-41d4-a716-446655440000", + url = "https://oauth.example.com/authorize", + ) + val exception = UrlElicitationRequiredException(listOf(elicitation)) + + exception.code shouldBe RPCError.ErrorCode.URL_ELICITATION_REQUIRED + exception.elicitations shouldBe listOf(elicitation) + + val data = exception.data.shouldNotBeNull() + McpJson.encodeToString(data) shouldEqualJson """ + { + "elicitations": [ + { + "message": "Authorize access to continue", + "elicitationId": "550e8400-e29b-41d4-a716-446655440000", + "url": "https://oauth.example.com/authorize", + "mode": "url" + } + ] + } + """.trimIndent() + } + + @Test + fun `fromError reconstructs typed exception for -32042 with valid data`() { + val data = McpJson.encodeToJsonElement( + UrlElicitationRequiredData( + listOf(ElicitRequestURLParams(message = "m", elicitationId = "id-1", url = "https://example.com/a")), + ), + ) + + val exception = McpException.fromError( + code = RPCError.ErrorCode.URL_ELICITATION_REQUIRED, + message = "needs auth", + data = data, + ) + + val typed = exception.shouldBeInstanceOf() + typed.message shouldBe "needs auth" + typed.elicitations.single().elicitationId shouldBe "id-1" + } + + @Test + fun `fromError returns plain McpException for unrelated code`() { + val exception = McpException.fromError( + code = RPCError.ErrorCode.INVALID_PARAMS, + message = "bad params", + data = null, + ) + (exception is UrlElicitationRequiredException) shouldBe false + exception.code shouldBe RPCError.ErrorCode.INVALID_PARAMS + } + + @Test + fun `fromError degrades to plain McpException for -32042 with malformed data`() { + val malformed = buildJsonObject { put("unexpected", "shape") } + + val exception = McpException.fromError( + code = RPCError.ErrorCode.URL_ELICITATION_REQUIRED, + message = "x", + data = malformed, + ) + + (exception is UrlElicitationRequiredException) shouldBe false + exception.code shouldBe RPCError.ErrorCode.URL_ELICITATION_REQUIRED + } + + @Test + fun `fromError degrades to plain McpException when elicitations empty`() { + val data = McpJson.encodeToJsonElement(UrlElicitationRequiredData(emptyList())) + + val exception = McpException.fromError(RPCError.ErrorCode.URL_ELICITATION_REQUIRED, "x", data) + + (exception is UrlElicitationRequiredException) shouldBe false + } } diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt index 9b4b2f3..343774b 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt @@ -25,6 +25,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.ResourceListChangedNotification import io.modelcontextprotocol.kotlin.sdk.types.ResourceUpdatedNotification import io.modelcontextprotocol.kotlin.sdk.types.ServerNotification import io.modelcontextprotocol.kotlin.sdk.types.ToolListChangedNotification +import io.modelcontextprotocol.kotlin.sdk.types.supportsUrl private val logger = KotlinLogging.logger {} @@ -238,6 +239,11 @@ internal class ClientConnectionImpl(private val session: ServerSession) : Client override suspend fun createElicitation(request: ElicitRequest, options: RequestOptions?): ElicitResult { val params = request.params + if (params is ElicitRequestURLParams) { + require(session.clientCapabilities?.elicitation.supportsUrl) { + "Client did not advertise elicitation.url capability; cannot send a URL-mode elicitation." + } + } logger.debug { when (params) { is ElicitRequestFormParams -> @@ -299,6 +305,9 @@ internal class ClientConnectionImpl(private val session: ServerSession) : Client } override suspend fun sendElicitationComplete(notification: ElicitationCompleteNotification) { + require(session.clientCapabilities?.elicitation.supportsUrl) { + "Client did not advertise elicitation.url capability; cannot send an elicitation completion notification." + } logger.debug { "Sending elicitation complete notification for: ${notification.params.elicitationId}" } notification(notification) } diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt index 1b7bfe7..c0d3e84 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt @@ -46,6 +46,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.ToolAnnotations import io.modelcontextprotocol.kotlin.sdk.types.ToolExecution import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema import io.modelcontextprotocol.kotlin.sdk.types.UnsubscribeRequest +import io.modelcontextprotocol.kotlin.sdk.types.UrlElicitationRequiredException import io.modelcontextprotocol.kotlin.sdk.utils.MatchResult import io.modelcontextprotocol.kotlin.sdk.utils.PathSegmentTemplateMatcher import io.modelcontextprotocol.kotlin.sdk.utils.ResourceTemplateMatcher @@ -651,6 +652,9 @@ public open class Server( } } catch (e: CancellationException) { throw e + } catch (e: UrlElicitationRequiredException) { + // Surface a required URL-mode elicitation as a JSON-RPC error (-32042) + throw e } catch (e: Exception) { logger.error(e) { "Error executing tool ${requestParams.name}" } CallToolResult( From c5abfe493a1967c7d09c8c7c238d6f6fab2ba691 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:31:48 +0000 Subject: [PATCH 054/178] chore(deps): bump @types/node from 25.9.3 to 26.0.0 in /integration-test/src/jvmTest/typescript in the all-dependencies group across 1 directory (#853) Bumps the all-dependencies group with 1 update in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 25.9.3 to 26.0.0
    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 16 ++++++++-------- .../src/jvmTest/typescript/package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index de65fb2..7e3293c 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,7 +15,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.9.3", + "@types/node": "^26.0.0", "cors": "^2.8.6", "tsx": "^4.22.4", "typescript": "^6.0.3" @@ -579,13 +579,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.9.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz", - "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz", + "integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": ">=7.24.0 <7.24.7" + "undici-types": "~8.3.0" } }, "node_modules/@types/qs": { @@ -1727,9 +1727,9 @@ } }, "node_modules/undici-types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", - "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", "dev": true, "license": "MIT" }, diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 629b3bb..00f0961 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,7 +16,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^25.9.3", + "@types/node": "^26.0.0", "cors": "^2.8.6", "tsx": "^4.22.4", "typescript": "^6.0.3" From bb265cc6e5df7d0ebf48dbdbc16a914046179da7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jun 2026 23:09:37 +0200 Subject: [PATCH 055/178] chore(deps): bump hono from 4.12.23 to 4.12.27 in /integration-test/src/jvmTest/typescript (#837) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [hono](https://github.com/honojs/hono) from 4.12.23 to 4.12.27.
    Release notes

    Sourced from hono's releases.

    v4.12.27

    Security fixes

    This release includes fixes for the following security issues:

    hono/jsx does not isolate context per request

    Affects: hono/jsx, hono/jsx-renderer. During SSR, context was stored process-wide instead of per request, so useContext()/useRequestContext() read after an await in an async component could return another concurrent request's value — leading to cross-request data disclosure or authorization checks against the wrong request. GHSA-hvrm-45r6-mjfj

    Server-Side XSS via JSX escaping bypass in cx()

    Affects: hono/css. cx() marked its composed class name as already-escaped without escaping the input, so untrusted input passed as a class name could break out of the JSX class attribute during SSR and inject markup (XSS). GHSA-w62v-xxxg-mg59

    API Gateway v1 adapter can drop a repeated request header value

    Affects: hono/aws-lambda. The API Gateway v1 (and VPC Lattice) adapter de-duplicated repeated header values by substring instead of exact match, dropping a value that is a substring of another (e.g. 203.0.113.1 dropped when 203.0.113.10 is present) — affecting logic such as X-Forwarded-For-based IP restriction. GHSA-xgm2-5f3f-mvvc


    Users of hono/jsx/hono/jsx-renderer, hono/css (cx()), or the hono/aws-lambda API Gateway v1 / VPC Lattice adapters are encouraged to upgrade.

    v4.12.26

    What's Changed

    Full Changelog: https://github.com/honojs/hono/compare/v4.12.25...v4.12.26

    v4.12.25

    Security fixes

    This release includes fixes for the following security issues:

    CORS Middleware reflects any Origin with credentials when origin defaults to the wildcard

    Affects: hono/cors. Fixes the wildcard origin reflecting the request Origin and sending Access-Control-Allow-Credentials: true when credentials: true is set without an explicit origin, where any site a logged-in user visited could make credentialed cross-origin requests and read responses from cookie-authenticated endpoints. GHSA-88fw-hqm2-52qc

    Body Limit Middleware can be bypassed on AWS Lambda by understating Content-Length

    Affects: hono/body-limit on AWS Lambda (hono/aws-lambda, hono/lambda-edge). Fixes the request being built with the client-declared Content-Length while the body is delivered fully buffered, where a client could declare a small Content-Length with a much larger body and slip past the configured size limit. GHSA-rv63-4mwf-qqc2

    Path traversal in serve-static on Windows via encoded backslash (%5C)

    Affects: serveStatic on Windows (Node, Bun, Deno adapters). Fixes the path guard allowing a lone backslash, where an encoded backslash (%5C) decoded to \ was treated as a separator by the Windows path resolver, letting a single URL segment escape into a middleware-guarded subtree. GHSA-wwfh-h76j-fc44

    AWS Lambda adapter merges multiple Set-Cookie headers into one value, dropping cookies on ALB single-header and Lattice

    ... (truncated)

    Commits
    • 97c6fe1 4.12.27
    • aa92177 Merge commit from fork
    • cd3f6f7 Merge commit from fork
    • d4853a8 fix(jsx): make merged context-isolation tests pass tsc type check (#5037)
    • 6735fea fix(jsx): cast awaitedFallback through unknown to fix Deno type check (#5036)
    • fab3b13 Merge commit from fork
    • 9f0dadf ci: use npm Staged publishing (#5035)
    • 27b7992 4.12.26
    • d29982c chore: replace arg and glob with Bun native APIs in build script
    • 16215d5 chore: remove unused devcontainer and gitpod configs (#5029)
    • Additional commits viewable in compare view
    Maintainer changes

    This version was pushed to npm by GitHub Actions, a new releaser for hono since your current version.


    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 7e3293c..0fa51a9 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1184,9 +1184,9 @@ } }, "node_modules/hono": { - "version": "4.12.23", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.23.tgz", - "integrity": "sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA==", + "version": "4.12.27", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.27.tgz", + "integrity": "sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==", "license": "MIT", "engines": { "node": ">=16.9.0" From 2edcb51d799f9c2a98082485dc189d457a35c27f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 15:31:46 +0200 Subject: [PATCH 056/178] chore(deps): bump the other-dependencies group across 5 directories with 3 updates (#854) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-client directory: [gradle-wrapper](https://github.com/gradle/gradle) and [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 2 updates in the /samples/kotlinlang-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback). Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/weather-stdio-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `com.anthropic:anthropic-java` from 2.40.1 to 2.43.0
    Release notes

    Sourced from com.anthropic:anthropic-java's releases.

    v2.43.0

    2.43.0 (2026-06-18)

    Full Changelog: v2.42.0...v2.43.0

    Features

    • helpers: introduce x-stainless-helper telemetry + tag the refusal-fallback interceptor (#91) (a14925b)

    v2.42.0

    2.42.0 (2026-06-18)

    Full Changelog: v2.41.1...v2.42.0

    Features

    • api: add support for new code_execution_20260120 tool (1a1a6b9)

    v2.41.1

    2.41.1 (2026-06-18)

    Full Changelog: v2.41.0...v2.41.1

    Chores

    Build System

    v2.41.0

    2.41.0 (2026-06-17)

    Full Changelog: v2.40.1...v2.41.0

    Bug Fixes

    • client: bad model definitions (96787c6)
    • foundry: align baseUrl contract with the other SDKs (/anthropic in baseUrl, no path rewrite) (#84) (e651d93)

    Chores

    • api: remove retired models from API and SDKs (da1c93d)
    • upgrade all deps (#73) (e57f1b5)

    Styles

    ... (truncated)

    Changelog

    Sourced from com.anthropic:anthropic-java's changelog.

    2.43.0 (2026-06-18)

    Full Changelog: v2.42.0...v2.43.0

    Features

    • helpers: introduce x-stainless-helper telemetry + tag the refusal-fallback interceptor (#91) (a14925b)

    2.42.0 (2026-06-18)

    Full Changelog: v2.41.1...v2.42.0

    Features

    • api: add support for new code_execution_20260120 tool (1a1a6b9)

    2.41.1 (2026-06-18)

    Full Changelog: v2.41.0...v2.41.1

    Chores

    Build System

    2.41.0 (2026-06-17)

    Full Changelog: v2.40.1...v2.41.0

    Bug Fixes

    • client: bad model definitions (96787c6)
    • foundry: align baseUrl contract with the other SDKs (/anthropic in baseUrl, no path rewrite) (#84) (e651d93)

    Chores

    • api: remove retired models from API and SDKs (da1c93d)
    • upgrade all deps (#73) (e57f1b5)

    Styles

    ... (truncated)

    Commits
    • 8e217ec release: 2.43.0
    • 8f4d5be feat(helpers): introduce x-stainless-helper telemetry + tag the refusal-fallb...
    • 60e15dd release: 2.42.0
    • e430bfb feat(api): add support for new code_execution_20260120 tool
    • 3c27033 release: 2.41.1
    • 1d77d61 build: fix signing for publishing (#90)
    • 78e23a5 chore: fix release runs-on (#354)
    • 946fe2a release: 2.41.0
    • 536e177 style: apply formatting (#88)
    • f719e12 fix(client): bad model definitions
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Updates `gradle-wrapper` from 9.5.1 to 9.6.0
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking ... _Description has been truncated_ Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/kotlin-mcp-client/gradlew | 4 ++-- samples/kotlin-mcp-client/gradlew.bat | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/kotlin-mcp-server/gradlew | 4 ++-- samples/kotlin-mcp-server/gradlew.bat | 4 ++-- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/kotlinlang-mcp-server/gradlew | 4 ++-- samples/kotlinlang-mcp-server/gradlew.bat | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/simple-streamable-server/gradlew | 4 ++-- samples/simple-streamable-server/gradlew.bat | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/weather-stdio-server/gradlew | 4 ++-- samples/weather-stdio-server/gradlew.bat | 4 ++-- 17 files changed, 27 insertions(+), 27 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 033fbdc..7479186 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.40.1" +anthropic = "2.43.0" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.13.0" diff --git a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties index df6a6ad..eb84db6 100644 --- a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlin-mcp-client/gradlew b/samples/kotlin-mcp-client/gradlew index b9bb139..249efbb 100755 --- a/samples/kotlin-mcp-client/gradlew +++ b/samples/kotlin-mcp-client/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: diff --git a/samples/kotlin-mcp-client/gradlew.bat b/samples/kotlin-mcp-client/gradlew.bat index aa5f10b..8508ef6 100644 --- a/samples/kotlin-mcp-client/gradlew.bat +++ b/samples/kotlin-mcp-client/gradlew.bat @@ -19,7 +19,7 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## @@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2 -@rem Execute Gradle +@rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel diff --git a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties index df6a6ad..eb84db6 100644 --- a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlin-mcp-server/gradlew b/samples/kotlin-mcp-server/gradlew index b9bb139..249efbb 100755 --- a/samples/kotlin-mcp-server/gradlew +++ b/samples/kotlin-mcp-server/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: diff --git a/samples/kotlin-mcp-server/gradlew.bat b/samples/kotlin-mcp-server/gradlew.bat index aa5f10b..8508ef6 100644 --- a/samples/kotlin-mcp-server/gradlew.bat +++ b/samples/kotlin-mcp-server/gradlew.bat @@ -19,7 +19,7 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## @@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2 -@rem Execute Gradle +@rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index fdef6d3..69dfe7e 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -4,7 +4,7 @@ ktor = "3.3.3" mcp-kotlin = "0.13.0" serialization = "1.11.0" coroutines = "1.11.0" -logback = "1.5.34" +logback = "1.5.35" shadow = "9.4.2" [libraries] diff --git a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties index df6a6ad..eb84db6 100644 --- a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlinlang-mcp-server/gradlew b/samples/kotlinlang-mcp-server/gradlew index b9bb139..249efbb 100755 --- a/samples/kotlinlang-mcp-server/gradlew +++ b/samples/kotlinlang-mcp-server/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: diff --git a/samples/kotlinlang-mcp-server/gradlew.bat b/samples/kotlinlang-mcp-server/gradlew.bat index aa5f10b..8508ef6 100644 --- a/samples/kotlinlang-mcp-server/gradlew.bat +++ b/samples/kotlinlang-mcp-server/gradlew.bat @@ -19,7 +19,7 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## @@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2 -@rem Execute Gradle +@rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel diff --git a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties index df6a6ad..eb84db6 100644 --- a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/simple-streamable-server/gradlew b/samples/simple-streamable-server/gradlew index b9bb139..249efbb 100755 --- a/samples/simple-streamable-server/gradlew +++ b/samples/simple-streamable-server/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: diff --git a/samples/simple-streamable-server/gradlew.bat b/samples/simple-streamable-server/gradlew.bat index aa5f10b..8508ef6 100644 --- a/samples/simple-streamable-server/gradlew.bat +++ b/samples/simple-streamable-server/gradlew.bat @@ -19,7 +19,7 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## @@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2 -@rem Execute Gradle +@rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel diff --git a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties index df6a6ad..eb84db6 100644 --- a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/weather-stdio-server/gradlew b/samples/weather-stdio-server/gradlew index b9bb139..249efbb 100755 --- a/samples/weather-stdio-server/gradlew +++ b/samples/weather-stdio-server/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: diff --git a/samples/weather-stdio-server/gradlew.bat b/samples/weather-stdio-server/gradlew.bat index aa5f10b..8508ef6 100644 --- a/samples/weather-stdio-server/gradlew.bat +++ b/samples/weather-stdio-server/gradlew.bat @@ -19,7 +19,7 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## @@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2 -@rem Execute Gradle +@rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel From a84ff59b53c26feec583cbfffa2e61d50e92c8a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 13:51:56 +0000 Subject: [PATCH 057/178] chore(deps): bump actions/checkout from 6 to 7 in the all-actions group across 1 directory (#852) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-actions group with 1 update in the / directory: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 6 to 7

    Release notes

    Sourced from actions/checkout's releases.

    v7.0.0

    What's Changed

    New Contributors

    Full Changelog: https://github.com/actions/checkout/compare/v6.0.3...v7.0.0

    v6.0.3

    What's Changed

    New Contributors

    Full Changelog: https://github.com/actions/checkout/compare/v6...v6.0.3

    v6.0.2

    What's Changed

    Full Changelog: https://github.com/actions/checkout/compare/v6.0.1...v6.0.2

    v6.0.1

    What's Changed

    Full Changelog: https://github.com/actions/checkout/compare/v6...v6.0.1

    Changelog

    Sourced from actions/checkout's changelog.

    Changelog

    v7.0.0

    v6.0.3

    v6.0.2

    v6.0.1

    v6.0.0

    v5.0.1

    v5.0.0

    v4.3.1

    v4.3.0

    v4.2.2

    v4.2.1

    ... (truncated)

    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/apidocs.yaml | 2 +- .github/workflows/build.yml | 6 +++--- .github/workflows/codeql.yml | 2 +- .github/workflows/conformance.yml | 8 ++++---- .github/workflows/gradle-publish.yml | 2 +- .github/workflows/samples.yml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/apidocs.yaml b/.github/workflows/apidocs.yaml index 995f7d8..510af19 100644 --- a/.github/workflows/apidocs.yaml +++ b/.github/workflows/apidocs.yaml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v5 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ad4cc7a..2b6e415 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: max-workers: 2 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v5 @@ -126,7 +126,7 @@ jobs: contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v5 @@ -168,7 +168,7 @@ jobs: name: "Build Sample: ${{ matrix.sample }}" timeout-minutes: 10 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v5 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5697b61..f25ec64 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v5 diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 4058d02..2511286 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -25,7 +25,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK uses: actions/setup-java@v5 @@ -76,7 +76,7 @@ jobs: - sse-retry steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK uses: actions/setup-java@v5 @@ -107,7 +107,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK uses: actions/setup-java@v5 @@ -146,7 +146,7 @@ jobs: - auth/cross-app-access-complete-flow steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK uses: actions/setup-java@v5 diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index 6ed0756..f9df053 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -17,7 +17,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK 21 uses: actions/setup-java@v5 with: diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml index 2c910fd..89de699 100644 --- a/.github/workflows/samples.yml +++ b/.github/workflows/samples.yml @@ -36,7 +36,7 @@ jobs: name: Build Sample (${{ matrix.sample }}) timeout-minutes: 10 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v5 From 3274244f7d018d4108d8611c95eb10cc7dbc18ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 21:27:25 +0000 Subject: [PATCH 058/178] chore(deps): bump gradle-wrapper from 9.5.1 to 9.6.0 (#851) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.5.1 to 9.6.0.
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.0

    The Gradle team is excited to announce Gradle 9.6.0.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.0 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.0 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    9.6.0 RC3

    ... (truncated)

    Commits
    • 3f750f0 Update distro size for Gradle 9.6.0 release (#38243)
    • ae93cfa update distro size
    • f7e22b5 Update Gradle wrapper to version 9.6.0-rc-3 (#38227)
    • 71a8eb9 Update Gradle wrapper to version 9.6.0-rc-3
    • 70a8745 Prepare release notes for Gradle 9.6.0RC3 (#38220)
    • 9706522 some final polishing for release notes
    • af308eb Restore GradleInternal.getRootProject overload for binary compatibility (#38214)
    • 239361b Restore GradleInternal.getRootProject overload for binary compatibility
    • 896dc44 Update Gradle wrapper to version 9.6.0-rc-2 (#38187)
    • 2d4ec25 Update Gradle wrapper to version 9.6.0-rc-2
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- gradlew.bat | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df6a6ad..eb84db6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/gradlew b/gradlew index b9bb139..249efbb 100755 --- a/gradlew +++ b/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: diff --git a/gradlew.bat b/gradlew.bat index aa5f10b..8508ef6 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,7 +19,7 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## @@ -72,7 +72,7 @@ echo location of your Java installation. 1>&2 -@rem Execute Gradle +@rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel From 2967696e6ca32dcaddb88fe890a2127010e07edb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 21:49:27 +0000 Subject: [PATCH 059/178] chore(deps): bump com.vanniktech:gradle-maven-publish-plugin from 0.36.0 to 0.37.0 in the gradle-plugins group across 1 directory (#848) Bumps the gradle-plugins group with 1 update in the / directory: [com.vanniktech:gradle-maven-publish-plugin](https://github.com/vanniktech/gradle-maven-publish-plugin). Updates `com.vanniktech:gradle-maven-publish-plugin` from 0.36.0 to 0.37.0
    Release notes

    Sourced from com.vanniktech:gradle-maven-publish-plugin's releases.

    0.37.0

    • When publishing to Maven Central, redundant checksum files are now excluded by default: checksums of .asc signature files (gradle/gradle#20232) and the sha256/sha512 checksums, which are never read by Gradle or Maven Central. The published checksums can be configured through checksums(...) in the DSL or the mavenCentralChecksums Gradle property (default md5,sha1). Signature checksum exclusion can be controlled through excludeSignatureChecksums() or the mavenCentralExcludeSignatureChecksums Gradle property.
    • Maven Central deployment id is being logged after upload.

    Minimum supported versions

    • JDK 17
    • Gradle 9.0.0
    • Android Gradle Plugin 8.13.0
    • Kotlin Gradle Plugin 2.2.0

    Compatibility tested up to

    • JDK 26
    • Gradle 9.6.0
    • Gradle 9.7.0-milestone-1
    • Android Gradle Plugin 9.2.1
    • Android Gradle Plugin 9.3.0-rc01
    • Android Gradle Plugin 9.4.0-alpha01
    • Kotlin Gradle Plugin 2.4.0

    0.37.0-rc1

    • When publishing to Maven Central, redundant checksum files are now excluded by default: checksums of .asc signature files (gradle/gradle#20232) and the sha256/sha512 checksums, which are never read by Gradle or Maven Central. The published checksums can be configured through checksums(...) in the DSL or the mavenCentralChecksums Gradle property (default md5,sha1). Signature checksum exclusion can be controlled through excludeSignatureChecksums() or the mavenCentralExcludeSignatureChecksums Gradle property.
    • Maven Central deployment id is being logged after upload.

    Minimum supported versions

    • JDK 17
    • Gradle 9.0.0
    • Android Gradle Plugin 8.13.0
    • Kotlin Gradle Plugin 2.2.0

    Compatibility tested up to

    • JDK 26
    • Gradle 9.6.0
    • Gradle 9.7.0-milestone-1
    • Android Gradle Plugin 9.2.1
    • Android Gradle Plugin 9.3.0-rc01
    • Android Gradle Plugin 9.4.0-alpha01
    • Kotlin Gradle Plugin 2.4.0
    Changelog

    Sourced from com.vanniktech:gradle-maven-publish-plugin's changelog.

    0.37.0 (2026-06-21)

    • When publishing to Maven Central, redundant checksum files are now excluded by default: checksums of .asc signature files (gradle/gradle#20232) and the sha256/sha512 checksums, which are never read by Gradle or Maven Central. The published checksums can be configured through checksums(...) in the DSL or the mavenCentralChecksums Gradle property (default md5,sha1). Signature checksum exclusion can be controlled through excludeSignatureChecksums() or the mavenCentralExcludeSignatureChecksums Gradle property.
    • Maven Central deployment id is being logged after upload.

    Minimum supported versions

    • JDK 17
    • Gradle 9.0.0
    • Android Gradle Plugin 8.13.0
    • Kotlin Gradle Plugin 2.2.0

    Compatibility tested up to

    • JDK 26
    • Gradle 9.6.0
    • Gradle 9.7.0-milestone-1
    • Android Gradle Plugin 9.2.1
    • Android Gradle Plugin 9.3.0-rc01
    • Android Gradle Plugin 9.4.0-alpha01
    • Kotlin Gradle Plugin 2.4.0
    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4904ea4..0b2929d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ kotlin = "2.3.21" kover = "0.9.8" ktlint = "14.2.0" knit = "0.5.1" -mavenPublish = "0.36.0" +mavenPublish = "0.37.0" netty = "4.2.15.Final" # libraries version From cca883aa3ff9c4c700287585c8e5db13d599d14d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 00:43:56 +0200 Subject: [PATCH 060/178] chore(deps): bump the kotest group across 1 directory with 3 updates (#847) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotest group with 3 updates in the / directory: [io.kotest:kotest-assertions-core](https://github.com/kotest/kotest), [io.kotest:kotest-assertions-json](https://github.com/kotest/kotest) and [io.kotest:kotest-assertions-ktor](https://github.com/kotest/kotest). Updates `io.kotest:kotest-assertions-core` from 6.1.11 to 6.2.1
    Release notes

    Sourced from io.kotest:kotest-assertions-core's releases.

    v6.2.1

    What's Changed

    Full Changelog: https://github.com/kotest/kotest/compare/v6.2.0...v6.2.1

    v6.2.0

    ✨ Features

    New matchers / assertions

    comparables.shouldBeAtLeast — @​AlexCue987 (#5831) MultipleMatcherResult for combining multiple matcher results — @​sksamuel (#5723) shouldContainExactCopies for lists — @​AlexCue987 (#5913) Character matchers — @​JordanLongstaff (#5921) shouldBeSingle matcher — @​sksamuel (#6028) shouldContainRepeats for strings — @​AlexCue987 (#6004) Infix form for inspectors — @​alfonsoristorato (#5920) Block-asserting overload for shouldBeFailure — @​alfonsoristorato (#5927) Per-call Eq overrides via a withEqs DSL — @​PreAgile (#6010) Per-element data class diffs in collection comparisons — @​PreAgile (#5835)

    Framework / API

    Run data tests singularly — @​alfonsoristorato (#5574) New JVM test-suites module (deprecates JunitXmlReporter) — @​sksamuel (#5801) Support isolation modes on all KMP platforms — @​sksamuel (#5806) Breadcrumbs support for Kotest spec files — @​sksamuel (#5793) Type-safe test metadata API — @​PreAgile (#5905) Public API for creating custom styles — @​sksamuel (#5814) Support multiple --test args joined by semicolon in KOTEST_INCLUDE_PATTERN — @​sksamuel (#5922) Extend life of deprecated Test containers and add onStart — @​sksamuel (#5896) Make Arb.stringPattern multiplatform — @​wilmveel (#6008) Complete the permutations module — @​sksamuel (#6016) Add Wasm WASI target to kotest-property and kotest-property-permutations — @​jsoizo (#6129) Make fibonacci interval functions public — @​mvanhorn (#6135) Add Android instrumented test module — @​sksamuel (#5900)

    IntelliJ plugin

    N-times setter for test invocation — @​alfonsoristorato (#5815) Invocation count on the Kotest producer — @​alfonsoristorato (#5837) Singular data-test run on the Kotest producer — @​alfonsoristorato (#5843) Amper-aware run-configuration producer — @​sksamuel (#5999)

    ... (truncated)

    Commits
    • 9ae8a1d Make flaky "throws FileNotFoundException for some time" eventually test deter...
    • a16146f Fix data objects being considered equal in DataClassEq (#6144) (#6145)
    • 47fe8d4 remove KotestInternal in TestFactory (#6146)
    • b39700c fix docs (#6147)
    • 8006dbd Remove usages of K1's KtUltraLightClass from kotest plugin sources (#6143)
    • 07b21d7 Add support for deprecated Kotlin targets in Android and Native conve… (#6141)
    • 96f71e0 docs: add KDoc to ArrayEq (#6140)
    • 7f2b14a Cut docs for 6.2
    • ead01c0 Override additional Kotlin version properties for IC-261 in release workflow
    • f3134ea align compile toolchain with minimum supported Kotlin version for KLIB ABI co...
    • Additional commits viewable in compare view

    Updates `io.kotest:kotest-assertions-json` from 6.1.11 to 6.2.1
    Release notes

    Sourced from io.kotest:kotest-assertions-json's releases.

    v6.2.1

    What's Changed

    Full Changelog: https://github.com/kotest/kotest/compare/v6.2.0...v6.2.1

    v6.2.0

    ✨ Features

    New matchers / assertions

    comparables.shouldBeAtLeast — @​AlexCue987 (#5831) MultipleMatcherResult for combining multiple matcher results — @​sksamuel (#5723) shouldContainExactCopies for lists — @​AlexCue987 (#5913) Character matchers — @​JordanLongstaff (#5921) shouldBeSingle matcher — @​sksamuel (#6028) shouldContainRepeats for strings — @​AlexCue987 (#6004) Infix form for inspectors — @​alfonsoristorato (#5920) Block-asserting overload for shouldBeFailure — @​alfonsoristorato (#5927) Per-call Eq overrides via a withEqs DSL — @​PreAgile (#6010) Per-element data class diffs in collection comparisons — @​PreAgile (#5835)

    Framework / API

    Run data tests singularly — @​alfonsoristorato (#5574) New JVM test-suites module (deprecates JunitXmlReporter) — @​sksamuel (#5801) Support isolation modes on all KMP platforms — @​sksamuel (#5806) Breadcrumbs support for Kotest spec files — @​sksamuel (#5793) Type-safe test metadata API — @​PreAgile (#5905) Public API for creating custom styles — @​sksamuel (#5814) Support multiple --test args joined by semicolon in KOTEST_INCLUDE_PATTERN — @​sksamuel (#5922) Extend life of deprecated Test containers and add onStart — @​sksamuel (#5896) Make Arb.stringPattern multiplatform — @​wilmveel (#6008) Complete the permutations module — @​sksamuel (#6016) Add Wasm WASI target to kotest-property and kotest-property-permutations — @​jsoizo (#6129) Make fibonacci interval functions public — @​mvanhorn (#6135) Add Android instrumented test module — @​sksamuel (#5900)

    IntelliJ plugin

    N-times setter for test invocation — @​alfonsoristorato (#5815) Invocation count on the Kotest producer — @​alfonsoristorato (#5837) Singular data-test run on the Kotest producer — @​alfonsoristorato (#5843) Amper-aware run-configuration producer — @​sksamuel (#5999)

    ... (truncated)

    Commits
    • 9ae8a1d Make flaky "throws FileNotFoundException for some time" eventually test deter...
    • a16146f Fix data objects being considered equal in DataClassEq (#6144) (#6145)
    • 47fe8d4 remove KotestInternal in TestFactory (#6146)
    • b39700c fix docs (#6147)
    • 8006dbd Remove usages of K1's KtUltraLightClass from kotest plugin sources (#6143)
    • 07b21d7 Add support for deprecated Kotlin targets in Android and Native conve… (#6141)
    • 96f71e0 docs: add KDoc to ArrayEq (#6140)
    • 7f2b14a Cut docs for 6.2
    • ead01c0 Override additional Kotlin version properties for IC-261 in release workflow
    • f3134ea align compile toolchain with minimum supported Kotlin version for KLIB ABI co...
    • Additional commits viewable in compare view

    Updates `io.kotest:kotest-assertions-ktor` from 6.1.11 to 6.2.1
    Release notes

    Sourced from io.kotest:kotest-assertions-ktor's releases.

    v6.2.1

    What's Changed

    Full Changelog: https://github.com/kotest/kotest/compare/v6.2.0...v6.2.1

    v6.2.0

    ✨ Features

    New matchers / assertions

    comparables.shouldBeAtLeast — @​AlexCue987 (#5831) MultipleMatcherResult for combining multiple matcher results — @​sksamuel (#5723) shouldContainExactCopies for lists — @​AlexCue987 (#5913) Character matchers — @​JordanLongstaff (#5921) shouldBeSingle matcher — @​sksamuel (#6028) shouldContainRepeats for strings — @​AlexCue987 (#6004) Infix form for inspectors — @​alfonsoristorato (#5920) Block-asserting overload for shouldBeFailure — @​alfonsoristorato (#5927) Per-call Eq overrides via a withEqs DSL — @​PreAgile (#6010) Per-element data class diffs in collection comparisons — @​PreAgile (#5835)

    Framework / API

    Run data tests singularly — @​alfonsoristorato (#5574) New JVM test-suites module (deprecates JunitXmlReporter) — @​sksamuel (#5801) Support isolation modes on all KMP platforms — @​sksamuel (#5806) Breadcrumbs support for Kotest spec files — @​sksamuel (#5793) Type-safe test metadata API — @​PreAgile (#5905) Public API for creating custom styles — @​sksamuel (#5814) Support multiple --test args joined by semicolon in KOTEST_INCLUDE_PATTERN — @​sksamuel (#5922) Extend life of deprecated Test containers and add onStart — @​sksamuel (#5896) Make Arb.stringPattern multiplatform — @​wilmveel (#6008) Complete the permutations module — @​sksamuel (#6016) Add Wasm WASI target to kotest-property and kotest-property-permutations — @​jsoizo (#6129) Make fibonacci interval functions public — @​mvanhorn (#6135) Add Android instrumented test module — @​sksamuel (#5900)

    IntelliJ plugin

    N-times setter for test invocation — @​alfonsoristorato (#5815) Invocation count on the Kotest producer — @​alfonsoristorato (#5837) Singular data-test run on the Kotest producer — @​alfonsoristorato (#5843) Amper-aware run-configuration producer — @​sksamuel (#5999)

    ... (truncated)

    Commits
    • 9ae8a1d Make flaky "throws FileNotFoundException for some time" eventually test deter...
    • a16146f Fix data objects being considered equal in DataClassEq (#6144) (#6145)
    • 47fe8d4 remove KotestInternal in TestFactory (#6146)
    • b39700c fix docs (#6147)
    • 8006dbd Remove usages of K1's KtUltraLightClass from kotest plugin sources (#6143)
    • 07b21d7 Add support for deprecated Kotlin targets in Android and Native conve… (#6141)
    • 96f71e0 docs: add KDoc to ArrayEq (#6140)
    • 7f2b14a Cut docs for 6.2
    • ead01c0 Override additional Kotlin version properties for IC-261 in release workflow
    • f3134ea align compile toolchain with minimum supported Kotlin version for KLIB ABI co...
    • Additional commits viewable in compare view

    Updates `io.kotest:kotest-assertions-json` from 6.1.11 to 6.2.1
    Release notes

    Sourced from io.kotest:kotest-assertions-json's releases.

    v6.2.1

    What's Changed

    Full Changelog: https://github.com/kotest/kotest/compare/v6.2.0...v6.2.1

    v6.2.0

    ✨ Features

    New matchers / assertions

    comparables.shouldBeAtLeast — @​AlexCue987 (#5831) MultipleMatcherResult for combining multiple matcher results — @​sksamuel (#5723) shouldContainExactCopies for lists — @​AlexCue987 (#5913) Character matchers — @​JordanLongstaff (#5921) shouldBeSingle matcher — @​sksamuel (#6028) shouldContainRepeats for strings — @​AlexCue987 (#6004) Infix form for inspectors — @​alfonsoristorato (#5920) Block-asserting overload for shouldBeFailure — @​alfonsoristorato (#5927) Per-call Eq overrides via a withEqs DSL — @​PreAgile (#6010) Per-element data class diffs in collection comparisons — @​PreAgile (#5835)

    Framework / API

    Run data tests singularly — @​alfonsoristorato (#5574) New JVM test-suites module (deprecates JunitXmlReporter) — @​sksamuel (#5801) Support isolation modes on all KMP platforms — @​sksamuel (#5806) Breadcrumbs support for Kotest spec files — @​sksamuel (#5793) Type-safe test metadata API — @​PreAgile (#5905) Public API for creating custom styles — @​sksamuel (#5814) Support multiple --test args joined by semicolon in KOTEST_INCLUDE_PATTERN — @​sksamuel (#5922) Extend life of deprecated Test containers and add onStart — @​sksamuel (#5896) Make Arb.stringPattern multiplatform — @​wilmveel (#6008) Complete the permutations module — @​sksamuel (#6016) Add Wasm WASI target to kotest-property and kotest-property-permutations — @​jsoizo (#6129) Make fibonacci interval functions public — @​mvanhorn (#6135) Add Android instrumented test module — @​sksamuel (#5900)

    IntelliJ plugin

    N-times setter for test invocation — @​alfonsoristorato (#5815) Invocation count on the Kotest producer — @​alfonsoristorato (#5837) Singular data-test run on the Kotest producer — @​alfonsoristorato (#5843) Amper-aware run-configuration producer — @​sksamuel (#5999)

    ... (truncated)

    Commits
    • 9ae8a1d Make flaky "throws FileNotFoundException for some time" eventually test deter...
    • a16146f Fix data objects being considered equal in DataClassEq (#6144) (#6145)
    • 47fe8d4 remove KotestInternal in TestFactory (#6146)
    • b39700c fix docs (#6147)
    • 8006dbd Remove usages of K1's KtUltraLightClass from kotest plugin sources (#6143)
    • 07b21d7 Add support for deprecated Kotlin targets in Android and Native conve… (#6141)
    • 96f71e0 docs: add KDoc to ArrayEq (#6140)
    • 7f2b14a Cut docs for 6.2
    • ead01c0 Override additional Kotlin version properties for IC-261 in release workflow
    • f3134ea align compile toolchain with minimum supported Kotlin version for KLIB ABI co...
    • Additional commits viewable in compare view

    Updates `io.kotest:kotest-assertions-ktor` from 6.1.11 to 6.2.1
    Release notes

    Sourced from io.kotest:kotest-assertions-ktor's releases.

    v6.2.1

    What's Changed

    Full Changelog: https://github.com/kotest/kotest/compare/v6.2.0...v6.2.1

    v6.2.0

    ✨ Features

    New matchers / assertions

    comparables.shouldBeAtLeast — @​AlexCue987 (#5831) MultipleMatcherResult for combining multiple matcher results — @​sksamuel (#5723) shouldContainExactCopies for lists — @​AlexCue987 (#5913) Character matchers — @​JordanLongstaff (#5921) shouldBeSingle matcher — @​sksamuel (#6028) shouldContainRepeats for strings — @​AlexCue987 (#6004) Infix form for inspectors — @​alfonsoristorato (#5920) Block-asserting overload for shouldBeFailure — @​alfonsoristorato (#5927) Per-call Eq overrides via a withEqs DSL — @​PreAgile (#6010) Per-element data class diffs in collection comparisons — @​PreAgile (#5835)

    Framework / API

    Run data tests singularly — @​alfonsoristorato (#5574) New JVM test-suites module (deprecates JunitXmlReporter) — @​sksamuel (#5801) Support isolation modes on all KMP platforms — @​sksamuel (#5806) Breadcrumbs support for Kotest spec files — @​sksamuel (#5793) Type-safe test metadata API — @​PreAgile (#5905) Public API for creating custom styles — @​sksamuel (#5814) Support multiple --test args joined by semicolon in KOTEST_INCLUDE_PATTERN — @​sksamuel (#5922) Extend life of deprecated Test containers and add onStart — @​sksamuel (#5896) Make Arb.stringPattern multiplatform — @​wilmveel (#6008) Complete the permutations module — @​sksamuel (#6016) Add Wasm WASI target to kotest-property and kotest-property-permutations — @​jsoizo (#6129) Make fibonacci interval functions public — @​mvanhorn (#6135) Add Android instrumented test module — @​sksamuel (#5900)

    IntelliJ plugin

    N-times setter for test invocation — @​alfonsoristorato (#5815) Invocation count on the Kotest producer — @​alfonsoristorato (#5837) Singular data-test run on the Kotest producer — @​alfonsoristorato (#5843) Amper-aware run-configuration producer — @​sksamuel (#5999)

    ... (truncated)

    Commits
    • 9ae8a1d Make flaky "throws FileNotFoundException for some time" eventually test deter...
    • a16146f Fix data objects being considered equal in DataClassEq (#6144) (#6145)
    • 47fe8d4 remove KotestInternal in TestFactory (#6146)
    • b39700c fix docs (#6147)
    • 8006dbd Remove usages of K1's KtUltraLightClass from kotest plugin sources (#6143)
    • 07b21d7 Add support for deprecated Kotlin targets in Android and Native conve… (#6141)
    • 96f71e0 docs: add KDoc to ArrayEq (#6140)
    • 7f2b14a Cut docs for 6.2
    • ead01c0 Override additional Kotlin version properties for IC-261 in release workflow
    • f3134ea align compile toolchain with minimum supported Kotlin version for KLIB ABI co...
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0b2929d..b35612e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ netty = "4.2.15.Final" awaitility = "4.3.0" collections-immutable = "0.4.0" coroutines = "1.11.0" -kotest = "6.1.11" +kotest = "6.2.1" kotlinx-io = "0.9.0" ktor = "3.4.3" logging = "8.0.4" From b6f4ad5a9fe52ef4b3937e224854e325771a4207 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jun 2026 21:12:13 +0200 Subject: [PATCH 061/178] chore(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.4.0 to 0.5.0 in the kotlinx group across 1 directory (#833) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotlinx group with 1 update in the / directory: [org.jetbrains.kotlinx:kotlinx-collections-immutable](https://github.com/Kotlin/kotlinx.collections.immutable). Updates `org.jetbrains.kotlinx:kotlinx-collections-immutable` from 0.4.0 to 0.5.0
    Release notes

    Sourced from org.jetbrains.kotlinx:kotlinx-collections-immutable's releases.

    v0.5.0

    This release renames the copy-returning methods on PersistentCollection, PersistentList, and PersistentMap to participial forms (KEEP-0459) — add→adding, put→putting, set→replacingAt, clear→cleared, and the rest. The old imperative names continue to compile in 0.5.x as @Deprecated(WARNING), become a compile error in 0.6.0, and are removed in 0.7.0. First shipped in 0.5.0-beta01; 0.5.0 is the stable release, with only internal fixes since.

    To migrate, apply the IDE quick-fixes, follow the migration guide, or use the 0.5.x migration skill with an AI assistant — each applies the rename the deprecation warnings name.

    Changes since 0.4.0:

    • Renamed copy-returning methods to participial forms; deprecated the old names #233
    • Enabled the Kotlin return-value checker (-Xreturn-value-checker=full) for the core module #243
    • Updated Kotlin to 2.3.0 #242
    • Configured JDK release 8 for the Kotlin compiler #239
    • Populated Implementation-* attributes in published JAR manifests #237
    • Enabled Dokka documentation generation, upgraded to Dokka 2.2.0 #225, #245, #248

    Full changelog: https://github.com/Kotlin/kotlinx.collections.immutable/compare/v0.4.0...v0.5.0

    v0.5.0-beta01

    This release renames copy-returning methods on PersistentCollection, PersistentList, and PersistentMap to participial forms — the old imperative names continue to compile in 0.5.x as @Deprecated(WARNING), become a compile error in 0.6.0, and are removed in 0.7.0. Concretely, add → adding, put → putting, clear → cleared, set → replacingAt, removeAt → removingAt, and the rest of the family (see the migration guide for the full table). The rename follows KEEP-0459 — Naming Conventions for Copy-Returning Operations.

    If your code uses any of these methods, please read the migration guide for the full rename table, the deprecation timeline, and the recommended IDE quick-fix workflow.

    This is a beta — 0.5.0 is planned to drop the -beta suffix soon, and once it ships stable the participial names are committed (any further rename would need its own deprecation cycle). If any of the renames feels awkward or you've hit a migration problem, please share it on [issue #232](Kotlin/kotlinx.collections.immutable#232) before then.

    What's changed

    • Renamed PersistentCollection mutating-copy methods to participial forms (add/remove/set/put/clear → adding/removing/setting/putting/clearing and *ed variants) and deprecated the original names #233
    • Enabled the Kotlin return-value checker (-Xreturn-value-checker=full) for the core module and annotated select internal helpers with @IgnorableReturnValue where discarding the result is intentional #243
    • Updated Kotlin to version 2.3.0 #242
    • Configured JDK release to 8 for the Kotlin compiler #239
    • Populated Implementation-Title/Implementation-Version/Implementation-Vendor in published JAR manifests #237
    • Enabled Dokka documentation generation and upgraded Dokka to 2.2.0 #225, #245, #248
    Changelog

    Sourced from org.jetbrains.kotlinx:kotlinx-collections-immutable's changelog.

    0.5.0

    • Promoted 0.5.0-beta01 to stable; no API or behavior changes

    0.5.0-beta01

    • Renamed copy-returning methods on PersistentCollection, PersistentList, and PersistentMap from imperative to participial forms (add/remove/put/clear/set/removeAt/… → adding/removing/putting/cleared/replacingAt/removingAt/…) per KEEP-0459 and deprecated the original names #233
    • Enabled the Kotlin return-value checker (-Xreturn-value-checker=full) for the core module and annotated select internal helpers with @IgnorableReturnValue where discarding the result is intentional #243
    • Updated Kotlin to version 2.3.0 #242
    • Configured JDK release to 8 for the Kotlin compiler #239
    • Populated Implementation-Title/Implementation-Version/Implementation-Vendor in published JAR manifests #237
    • Enabled Dokka documentation generation and upgraded Dokka to 2.2.0 #225, #245, #248
    Commits
    • 0727896 Release v0.5.0
    • 0e1a24c Document return values in the KDoc summary instead of @return (#256)
    • 2069a62 Fix equals/hashCode contract violation in random-operations stress tests (#262)
    • 6f7abb9 Updated team infra plugin (#260)
    • 15a77d7 Fix the package-list location (#258)
    • 1ab038c Add .kotlin to .gitignore to exclude build metadata produced by KGP (#259)
    • dc6ba40 Add top-level README for kotlinx-collections-immutable module (#255)
    • a6ad2e1 Release v0.5.0-beta01
    • 54f4815 Rename PersistentCollection methods to participial forms and deprecate origin...
    • 753924c Added missing reference to deployment id parameter (#250)
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b35612e..cf6d374 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ netty = "4.2.15.Final" # libraries version awaitility = "4.3.0" -collections-immutable = "0.4.0" +collections-immutable = "0.5.0" coroutines = "1.11.0" kotest = "6.2.1" kotlinx-io = "0.9.0" From d93f47f1e57a2c1fbdd835679bae7e701cc15096 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:14:48 +0200 Subject: [PATCH 062/178] chore(deps): bump ch.qos.logback:logback-classic from 1.5.34 to 1.5.37 (#857) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.34 to 1.5.37.
    Release notes

    Sourced from ch.qos.logback:logback-classic's releases.

    Logback 1.5.37

    2026-06-26 Release of logback version 1.5.37

    • Given the numerous vulnerabilities related to conditional configuration processing based on the evaluation of Java expressions using the Janino library, support for such expressions has been removed. Users are offered the an online migration service or the element introduced in version 1.5.20. See the relevant documentation for more details.

    • A bitwise identical binary of this version can be reproduced by building from source code at commit c1df7f522e648eec7b4ef6a12c8758fec0f00048 associated with the tag v_1.5.37. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

    Logback 1.5.36

    2026-06-25 Release of logback version 1.5.36

    • The 'condition' attribute in <if> elements now reject certain references that are associated with ACE attacks. This issue was reported by "yulate" (yulate531@gmail.com.com) and registered as CVE-2026-13006.

    • A bitwise identical binary of this version can be reproduced by building from source code at commit 9b94c37562bf25a6a944146701d42ee6c4eee888 associated with the tag v_1.5.36. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

    Logback 1.5.35

    026-06-23 Release of logback version 1.5.35

    • The 'condition' attribute in <if> elements now rejects unicode escape sequences (\u and \U). This closes a bypass of the existing prohibition on the new operator in Janino-evaluated conditions. This issue was reported by IcySun (icysun@qq.com) and registered as CVE-2026-13006.

    • Added ConfiguratorRank.AUTHENTICATING (rank 100), the highest configurator rank, for certified/authenticating configurators discovered via the ServiceLoader mechanism. ContextInitializer now requires that at most one such configurator exist on the classpath; if more than one is found, initialization aborts with an error.

    • ConsoleCharsetPropertyDefiner is no longer shipped. The Java 21 multi-release compilation of logback-core has been disabled, which removes this class from the published artifact. Configurations that referenced ch.qos.logback.core.property.ConsoleCharsetPropertyDefiner will need an alternative approach for console charset detection.

    • The logback-examples module is now included in artifacts published to Maven Central.

    • JoranConfigurator.makeAnotherInstance() and DefaultJoranConfigurator.performMultiStepConfigurationFileSearch() are now protected, allowing derived configurators to override these methods.

    • A bitwise identical binary of this version can be reproduced by building from source code at commit 08bd1598d565d83444f72983935e7da4746783b7 associated with the tag v_1.5.35. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

    Commits

    [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ch.qos.logback:logback-classic&package-manager=gradle&previous-version=1.5.34&new-version=1.5.37)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cf6d374..6faaf2a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" slf4j = "2.0.18" -logback = "1.5.34" +logback = "1.5.37" junit = "5.14.4" [libraries] From 4103b87d6952f7e72b0fc9ddfdb2f59a0a39d0ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2026 14:17:43 +0200 Subject: [PATCH 063/178] chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 in the kotlinx group across 1 directory (#855) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotlinx group with 1 update in the / directory: [org.jetbrains.kotlinx:kotlinx-io-core](https://github.com/Kotlin/kotlinx-io). Updates `org.jetbrains.kotlinx:kotlinx-io-core` from 0.9.0 to 0.9.1
    Release notes

    Sourced from org.jetbrains.kotlinx:kotlinx-io-core's releases.

    v0.9.1

    Features

    • Dropped an old workaround for unsupported Android version #508
    • Reimplemented module loading for WasmJs #506

    Thanks to @​ilgonmic and @​MohammedKHC for their contributions!

    Changelog

    Sourced from org.jetbrains.kotlinx:kotlinx-io-core's changelog.

    0.9.1

    Published 26 June 2026

    Features

    • Dropped an old workaround for unsupported Android version #508
    • Reimplemented module loading for WasmJs #506
    Commits
    • 362bdc3 Release 0.9.1
    • e5ae2f0 Merge branch 'develop'
    • 2997caf Drop workaround for Android 4.2.2 getsockname bug (#508)
    • a1d6bd9 Use IIFE to asynchronously load a module instead of globalThis (#506)
    • d53d449 Update feedback channels in contributing guidelines
    • 34f1579 Merge branch 'develop'
    • 82caeb2 Document segment pool configuration (#494)
    • See full diff in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6faaf2a..ae38db6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ awaitility = "4.3.0" collections-immutable = "0.5.0" coroutines = "1.11.0" kotest = "6.2.1" -kotlinx-io = "0.9.0" +kotlinx-io = "0.9.1" ktor = "3.4.3" logging = "8.0.4" mockk = "1.14.11" From cd91652be115064c0b9fc43ba1c517893131ba92 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Mon, 29 Jun 2026 14:38:44 +0200 Subject: [PATCH 064/178] fix: validate Origin against localhost by default in DNS rebinding protection (#840) Default the `Origin` allowlist to localhost when `DnsRebindingProtection` relies on the localhost host defaults, so a request with a valid `Host` but a hostile (or `null`) `Origin` is no longer accepted. ## How Has This Been Tested? unit tests ## Breaking Changes Behavioral change only ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../kotlin/sdk/server/HostValidation.kt | 10 ++++ .../kotlin/sdk/server/KtorServer.kt | 21 +++++++-- .../sdk/server/DnsRebindingProtectionTest.kt | 46 +++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt index 88b56bc..ef010fe 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/HostValidation.kt @@ -19,6 +19,16 @@ import io.modelcontextprotocol.kotlin.sdk.types.RPCError */ internal val LOCALHOST_ALLOWED_HOSTS: List = listOf("localhost", "127.0.0.1", "[::1]") +/** + * Default list of `Origin` values allowed for localhost DNS rebinding protection. + * + * Mirrors [LOCALHOST_ALLOWED_HOSTS] but carries a scheme so the values parse as URLs: + * [extractOriginHost] rejects schemeless input. Comparison is hostname-only and + * scheme-agnostic, so these entries also match `https://` origins on the same host. + */ +internal val LOCALHOST_ALLOWED_ORIGINS: List = + listOf("http://localhost", "http://127.0.0.1", "http://[::1]") + /** * Characters that are valid in a URL but must not appear in an HTTP `Host` header. * Rejecting them prevents the parser from accepting malformed values 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 d6191df..7e47d76 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 @@ -41,7 +41,9 @@ private val logger = KotlinLogging.logger {} * @param allowedHosts hostnames allowed in the `Host` header. Defaults to `localhost`, `127.0.0.1`, `[::1]`. * @param allowedOrigins origins allowed in the `Origin` header, compared by hostname only * (scheme and port are ignored). Requests without an `Origin` header are allowed. - * Pass `null` to skip origin validation. + * When `null` while the localhost host defaults are in effect (no custom `allowedHosts`), + * the `Origin` header is validated against `localhost`, `127.0.0.1`, `[::1]`. + * With custom `allowedHosts`, `null` skips origin validation. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. * @throws IllegalStateException if the [SSE] plugin is not installed. @@ -71,7 +73,9 @@ public fun Route.mcp( * @param allowedHosts hostnames allowed in the `Host` header. Defaults to `localhost`, `127.0.0.1`, `[::1]`. * @param allowedOrigins origins allowed in the `Origin` header, compared by hostname only * (scheme and port are ignored). Requests without an `Origin` header are allowed. - * Pass `null` to skip origin validation. + * When `null` while the localhost host defaults are in effect (no custom `allowedHosts`), + * the `Origin` header is validated against `localhost`, `127.0.0.1`, `[::1]`. + * With custom `allowedHosts`, `null` skips origin validation. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. * @throws IllegalStateException if the [SSE] plugin is not installed. @@ -119,7 +123,9 @@ public fun Route.mcp( * @param allowedHosts hostnames allowed in the `Host` header. Defaults to `localhost`, `127.0.0.1`, `[::1]`. * @param allowedOrigins origins allowed in the `Origin` header, compared by hostname only * (scheme and port are ignored). Requests without an `Origin` header are allowed. - * Pass `null` to skip origin validation. + * When `null` while the localhost host defaults are in effect (no custom `allowedHosts`), + * the `Origin` header is validated against `localhost`, `127.0.0.1`, `[::1]`. + * With custom `allowedHosts`, `null` skips origin validation. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. */ @@ -205,7 +211,9 @@ private fun Application.mcpStreamableHttp( * If `null` and DNS rebinding protection is enabled, defaults to `localhost`, `127.0.0.1`, `[::1]`. * @param allowedOrigins A list of allowed `Origin` header values, compared by hostname only * (scheme and port are ignored). Requests without an `Origin` header are allowed. - * If `null`, origin validation is disabled. + * When `null` while the localhost host defaults are in effect (no custom `allowedHosts`), + * the `Origin` header is validated against `localhost`, `127.0.0.1`, `[::1]`. + * With custom `allowedHosts`, `null` skips origin validation. * @param eventStore An optional [EventStore] instance to enable resumable event stream functionality. * Allows storing and replaying events. * @param block factory block with access to the [RoutingContext] (for reading request headers) @@ -451,6 +459,9 @@ private fun Route.installDnsRebindingProtection(enabled: Boolean, hosts: List Date: Mon, 29 Jun 2026 15:07:06 +0200 Subject: [PATCH 065/178] chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.6.0 to 9.6.1.
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index eb84db6..a9db115 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 19db4b04e3d578635d4a60e190bc5f9f23bc53f4 Mon Sep 17 00:00:00 2001 From: Takuya Akamatsu Date: Tue, 30 Jun 2026 00:18:53 +0900 Subject: [PATCH 066/178] fix(client): gate completion/complete on the completions capability (#846) Gate `completion/complete` on the server's `completions` capability instead of `prompts`. closes #845 ## Motivation and Context A server that declares `completions` but not `prompts` is currently rejected for completion. Details in #845. ## How Has This Been Tested? New `ClientAssertCapabilityTest` cases; they fail on `main` and pass with this change. `apiCheck` / `ktlintCheck` / `detekt` pass. ## Breaking Changes None. ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed Co-authored-by: Pavel Gorgulov --- .../kotlin/sdk/client/Client.kt | 9 +++++++-- .../sdk/client/ClientAssertCapabilityTest.kt | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt index b88cb1b..59f2b7e 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt @@ -242,13 +242,18 @@ public open class Client(private val clientInfo: Implementation, options: Client Method.Defined.PromptsGet, Method.Defined.PromptsList, - Method.Defined.CompletionComplete, -> { checkNotNull(serverCapabilities?.prompts) { "Server does not support prompts (required for $method)" } } + Method.Defined.CompletionComplete -> { + checkNotNull(serverCapabilities?.completions) { + "Server does not support completions (required for $method)" + } + } + Method.Defined.ResourcesList, Method.Defined.ResourcesTemplatesList, Method.Defined.ResourcesRead, @@ -394,7 +399,7 @@ public open class Client(private val clientInfo: Implementation, options: Client * @param params The completion request parameters. * @param options Optional request options. * @return The completion result returned by the server, or `null` if none. - * @throws IllegalStateException If the server does not support prompts or completion. + * @throws IllegalStateException If the server does not support completions. */ public suspend fun complete(params: CompleteRequest, options: RequestOptions? = null): CompleteResult = request(params, options) diff --git a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt index 2f322ec..e9379a7 100644 --- a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt +++ b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientAssertCapabilityTest.kt @@ -84,6 +84,25 @@ class ClientAssertCapabilityTest { ex.message.orEmpty() shouldContain "Client does not support tasks" } + @Test + fun `CompletionComplete does not throw when server declared completions`() = runTest { + val client = newTestClient( + serverCapabilities = ServerCapabilities(completions = ServerCapabilities.Completions), + ) + client.exposedAssertCapabilityForMethod(Method.Defined.CompletionComplete) + } + + @Test + fun `CompletionComplete throws when server has no completions capability`() = runTest { + val client = newTestClient( + serverCapabilities = ServerCapabilities(prompts = ServerCapabilities.Prompts()), + ) + val ex = assertFailsWith { + client.exposedAssertCapabilityForMethod(Method.Defined.CompletionComplete) + } + ex.message.orEmpty() shouldContain "Server does not support completions" + } + private suspend fun newTestClient( serverCapabilities: ServerCapabilities = ServerCapabilities(), clientCapabilities: ClientCapabilities = ClientCapabilities(), From 0221b8db3d596a8add753786048126564ad70b78 Mon Sep 17 00:00:00 2001 From: King Star Date: Tue, 30 Jun 2026 15:46:43 +0800 Subject: [PATCH 067/178] fix(client): close stdio read sources during shutdown (#798) ## Summary Fixes `StdioClientTransport.close()` so shutdown does not hang when the stdin read loop is blocked waiting for input. ## Root Cause / Context `StdioClientTransport.closeResources()` stopped the transport coroutine scope and then waited for the scope job to finish. On the JVM, a `Source.readAtMostTo()` call backed by a blocking Java stream does not necessarily return when the coroutine is cancelled. If the read loop stayed blocked, `close()` could wait indefinitely. ## Changes - Close the stdin source during stdio client shutdown before waiting for transport coroutines to finish. - Also close the optional stderr source during shutdown. - Keep source-close failures non-fatal and log them at debug level. - Add a JVM regression test with a `RawSource` that blocks in `readAtMostTo()` until `close()` is called. - Assert the close path completes, emits `onClose`, and does not invoke `onError`. ## Scope / Risk This is limited to `StdioClientTransport` shutdown behavior. It does not change the public API or server transports. The regression coverage is JVM-focused because the reported hang is caused by a blocking Java stream read. ## Verification ```bash ./gradlew :integration-test:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.client.StdioClientTransportTest' ./gradlew :kotlin-sdk-client:jvmTest ./gradlew :kotlin-sdk-client:ktlintCheck :integration-test:ktlintCheck :kotlin-sdk-client:detekt :integration-test:detekt :kotlin-sdk-client:apiCheck ``` Closes #514 --- .../sdk/client/StdioClientTransportTest.kt | 61 +++++++++++++++++++ .../kotlin/sdk/client/StdioClientTransport.kt | 10 +++ 2 files changed, 71 insertions(+) diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransportTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransportTest.kt index 585af3f..fc3c1d3 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransportTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransportTest.kt @@ -7,9 +7,13 @@ import io.modelcontextprotocol.kotlin.sdk.types.McpException import io.modelcontextprotocol.kotlin.test.utils.createSleepyProcessBuilder import io.modelcontextprotocol.kotlin.test.utils.createTeeProcessBuilder import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withTimeout +import kotlinx.coroutines.withTimeoutOrNull +import kotlinx.io.Buffer +import kotlinx.io.RawSource import kotlinx.io.asSink import kotlinx.io.asSource import kotlinx.io.buffered @@ -18,10 +22,12 @@ 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.CountDownLatch import java.util.concurrent.TimeUnit import kotlin.concurrent.atomics.AtomicBoolean import kotlin.concurrent.atomics.ExperimentalAtomicApi import kotlin.test.assertFalse +import kotlin.test.assertNotNull import kotlin.test.assertTrue import kotlin.test.fail import kotlin.time.Duration.Companion.seconds @@ -109,6 +115,43 @@ class StdioClientTransportTest : BaseTransportTest() { } } + @OptIn(ExperimentalAtomicApi::class) + @Test + fun `should close cleanly while stdin read is blocked`(): Unit = runBlocking(Dispatchers.IO) { + val input = BlockingRawSource() + + val transport = StdioClientTransport( + input = input.buffered(), + output = Buffer(), + ) + + val didClose = AtomicBoolean(false) + transport.onClose { didClose.store(true) } + transport.onError { error -> + fail("Unexpected error while closing transport: $error") + } + + transport.start() + + eventually(2.seconds) { + assertTrue(input.readStarted, "Transport should start reading stdin before close") + } + + val closeJob = async { + transport.close() + } + + val closed = withTimeoutOrNull(1.seconds) { + closeJob.await() + } + + input.close() + closeJob.await() + + assertNotNull(closed, "Transport.close() should not wait for stdin to produce data or EOF") + assertTrue(didClose.load(), "Transport should be closed after close() call") + } + @Test fun `should read messages`() = runTest { val processBuilder = createTeeProcessBuilder() @@ -147,4 +190,22 @@ class StdioClientTransportTest : BaseTransportTest() { process.waitFor() process.destroyForcibly() } + + private class BlockingRawSource : RawSource { + private val closed = CountDownLatch(1) + + @Volatile + var readStarted: Boolean = false + private set + + override fun readAtMostTo(sink: Buffer, byteCount: Long): Long { + readStarted = true + closed.await() + return -1L + } + + override fun close() { + closed.countDown() + } + } } diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransport.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransport.kt index 63f681c..5e990ee 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransport.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StdioClientTransport.kt @@ -244,10 +244,20 @@ public class StdioClientTransport @JvmOverloads public constructor( override suspend fun closeResources() { withContext(NonCancellable) { scope.stopProcessing("Closed") + closeReadSources() scope.coroutineContext[Job]?.join() // Wait for all coroutines to complete } } + private fun closeReadSources() { + runCatching { input.close() } + .onFailure { logger.debug(it) { "Error closing stdin source" } } + error?.let { source -> + runCatching { source.close() } + .onFailure { logger.debug(it) { "Error closing stderr source" } } + } + } + private fun sendOutboundMessage(message: JSONRPCMessage, sink: Sink, mainScope: CoroutineScope) { try { val json = serializeMessage(message) From d2b1509147722305da481e3c939940253b066ecd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 11:44:40 +0200 Subject: [PATCH 068/178] chore(deps): bump the other-dependencies group across 5 directories with 5 updates (#865) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 3 updates in the /samples/kotlin-mcp-client directory: [gradle-wrapper](https://github.com/gradle/gradle), [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java) and [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 3 updates in the /samples/kotlinlang-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle), [com.gradleup.shadow](https://github.com/GradleUp/shadow) and [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback). Bumps the other-dependencies group with 3 updates in the /samples/simple-streamable-server directory: [gradle-wrapper](https://github.com/gradle/gradle), [com.gradleup.shadow](https://github.com/GradleUp/shadow) and [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework). Bumps the other-dependencies group with 2 updates in the /samples/weather-stdio-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and [com.gradleup.shadow](https://github.com/GradleUp/shadow). Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.anthropic:anthropic-java` from 2.43.0 to 2.45.0
    Release notes

    Sourced from com.anthropic:anthropic-java's releases.

    v2.45.0

    2.45.0 (2026-06-29)

    Full Changelog: v2.44.1...v2.45.0

    Features

    • api: add support for 20260318 web fetch and support tools (f38d0e6)

    Bug Fixes

    • add web tools 20260318 delegate overloads to StructuredMessageCreateParams (#120) (a66f7a3)

    v2.44.1

    2.44.1 (2026-06-26)

    Full Changelog: v2.44.0...v2.44.1

    Bug Fixes

    • bedrock: use daemon threads for the SSE transcoding pool (#97) (0678c4d)
    • skill creation (#119) (5dadc03)

    Chores

    • api: accept user profile ID's when counting tokens (ee8b72d)
    • delete unnecessary dir (#108) (35a9662)
    • docs: updates to descriptions and example values (6686e6b)

    Build System

    • add detekt rules (#109) (86b8f8d)
    • derive umbrella Dokka aggregation from re-exported modules (#110) (82c00c7)

    v2.44.0

    2.44.0 (2026-06-24)

    Full Changelog: v2.43.0...v2.44.0

    Features

    • client: add support for system.message streaming events (e27e961)

    Chores

    • api: add support for new refusal category (8c1bd29)

    ... (truncated)

    Changelog

    Sourced from com.anthropic:anthropic-java's changelog.

    2.45.0 (2026-06-29)

    Full Changelog: v2.44.1...v2.45.0

    Features

    • api: add support for 20260318 web fetch and support tools (f38d0e6)

    Bug Fixes

    • add web tools 20260318 delegate overloads to StructuredMessageCreateParams (#120) (a66f7a3)

    2.44.1 (2026-06-26)

    Full Changelog: v2.44.0...v2.44.1

    Bug Fixes

    • bedrock: use daemon threads for the SSE transcoding pool (#97) (0678c4d)
    • skill creation (#119) (5dadc03)

    Chores

    • api: accept user profile ID's when counting tokens (ee8b72d)
    • delete unnecessary dir (#108) (35a9662)
    • docs: updates to descriptions and example values (6686e6b)

    Build System

    • add detekt rules (#109) (86b8f8d)
    • derive umbrella Dokka aggregation from re-exported modules (#110) (82c00c7)

    2.44.0 (2026-06-24)

    Full Changelog: v2.43.0...v2.44.0

    Features

    • client: add support for system.message streaming events (e27e961)

    Chores

    • api: add support for new refusal category (8c1bd29)
    • api: add support for sending User Profile ID in request headers (8d69cbe)

    ... (truncated)

    Commits
    • 66da1ba release: 2.45.0
    • ae4a759 fix: add web tools 20260318 delegate overloads to StructuredMessageCreatePara...
    • 89455ee feat(api): add support for 20260318 web fetch and support tools
    • ca57c4e release: 2.44.1
    • 2e9d127 fix: skill creation (#119)
    • 4ee08d6 fix(bedrock): use daemon threads for the SSE transcoding pool (#97)
    • b6bf663 chore(docs): updates to descriptions and example values
    • fea6ca0 build: add detekt rules (#109)
    • 35963af chore(api): accept user profile ID's when counting tokens
    • 0b00c21 chore: delete unnecessary dir (#108)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

    For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

    Reporting problems

    If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

    We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

    Commits
    • 309d128 Update fixed issues in release notes for 9.6.1 (#38328)
    • 040a978 Update fixed issues in release notes for 9.6.1
    • e0b8325 Restore --non-interactive flag instead of --interactive/--no-interactive (#38...
    • 946f3e6 Limit explicit temp file permission setting to intended use case (#38300)
    • 65f8224 Restore --non-interactive flag instead of --interactive/--no-interactive
    • e346a5e Adjust CLI flag to configure non-interactive console (#38301)
    • 9b53be9 Adjust CLI flag to configure non-interactive console
    • 0dd3b53 Limit explicit temp file permission setting to intended use case
    • 48e5ac2 Add reproducers
    • 25598fd Prepare 9.6.1 patch release (#38293)
    • Additional commits viewable in compare view

    Updates `com.gradleup.shadow` from 9.4.2 to 9.4.3
    Release notes

    Sourced from com.gradleup.shadow's releases.

    9.4.3

    Changed

    • Update dependencies for resolving CVEs. (#2069)
    Commits

    Updates `gradle-wrapper` from 9.6.0 to 9.6.1
    Release notes

    Sourced from gradle-wrapper's releases.

    9.6.1

    The Gradle team is excited to announce Gradle 9.6.1.

    Here are the highlights of this release:

    • Improved Configuration Cache hit rates
    • Additional CLI rendering options
    • Important project hierarchy lookup deprecations

    Read the Release Notes

    We would like to thank the following community members for their contributions to this release of Gradle: Aharnish Solanki, Benedikt Johannes, Devendra Reddy Pennabadi, Dmytro Rodionov, Dreeam, Elías Hernández Rodríguez, Eng Zer Jun, FinlayRJW, Kamal Kansal, Marcono1234, Nelson Osacky, Philip Wedemann, Ravi, Roberto Perez Alcolea, Ryan Schmitt, Sebastian Schuberth, seunghun.ham, sk-reddy17, Suvrat Acharya, Vedant Madane.

    Upgrade instructions

    Switch your build to use Gradle 9.6.1 by updating your wrapper:

    ./gradlew :wrapper --gradle-version=9.6.1 &&
    ./gradlew :wrapper
    

    See the Gradle 9.x upgrade guide to l... _Description has been truncated_ Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/simple-streamable-server/gradle/libs.versions.toml | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 7479186..0b9018d 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,9 +1,9 @@ [versions] -anthropic = "2.43.0" +anthropic = "2.45.0" kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.13.0" -shadow = "9.4.2" +shadow = "9.4.3" slf4j = "2.0.18" [libraries] diff --git a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties index eb84db6..a9db115 100644 --- a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index bd87373..56bf5f1 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin = "2.3.21" ktor = "3.3.3" mcp-kotlin = "0.13.0" slf4j = "2.0.18" -shadow = "9.4.2" +shadow = "9.4.3" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties index eb84db6..a9db115 100644 --- a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 69dfe7e..26e89b2 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -4,8 +4,8 @@ ktor = "3.3.3" mcp-kotlin = "0.13.0" serialization = "1.11.0" coroutines = "1.11.0" -logback = "1.5.35" -shadow = "9.4.2" +logback = "1.5.37" +shadow = "9.4.3" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties index eb84db6..a9db115 100644 --- a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index ba5b0e7..723994b 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] kotlin = "2.3.21" ktor = "3.3.3" -junit = "6.1.0" +junit = "6.1.1" mcp-kotlin = "0.13.0" slf4j = "2.0.18" -shadow = "9.4.2" +shadow = "9.4.3" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties index eb84db6..a9db115 100644 --- a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 3e99ead..e805236 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -4,7 +4,7 @@ kotlin = "2.3.21" ktor = "3.3.3" logging = "8.0.4" mcp-kotlin = "0.13.0" -shadow = "9.4.2" +shadow = "9.4.3" slf4j = "2.0.18" [libraries] diff --git a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties index eb84db6..a9db115 100644 --- a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From bbf77bae93970d382ef97bf1569d57ed6d434ded Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:18:27 +0200 Subject: [PATCH 069/178] chore(deps): bump @types/node from 26.0.0 to 26.0.1 in /integration-test/src/jvmTest/typescript in the all-dependencies group across 1 directory (#864) Bumps the all-dependencies group with 1 update in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@types/node` from 26.0.0 to 26.0.1

    Commits

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 8 ++++---- integration-test/src/jvmTest/typescript/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 0fa51a9..befd50e 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,7 +15,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.0.0", + "@types/node": "^26.0.1", "cors": "^2.8.6", "tsx": "^4.22.4", "typescript": "^6.0.3" @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz", - "integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==", + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.1.tgz", + "integrity": "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 00f0961..aa8d9db 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,7 +16,7 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.0.0", + "@types/node": "^26.0.1", "cors": "^2.8.6", "tsx": "^4.22.4", "typescript": "^6.0.3" From 35da063c23e0e89571939d8cb0cba6621d997ebe Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 30 Jun 2026 20:43:45 +0200 Subject: [PATCH 070/178] fix: bound request body size in SSE and Streamable HTTP transports (#839) Caps the size of incoming HTTP POST bodies in both server transports so an oversized request can no longer exhaust server memory ## How Has This Been Tested? new tests ## Breaking Changes binary incompatible for SseServerTransport constuctors ## Types of changes - [x] Bug fix (non-breaking change which fixes a - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https: - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- kotlin-sdk-server/api/kotlin-sdk-server.api | 15 +-- .../kotlin/sdk/server/KtorServer.kt | 23 +++- .../kotlin/sdk/server/RequestBody.kt | 34 ++++++ .../kotlin/sdk/server/SSEServerTransport.kt | 21 +++- .../server/StreamableHttpServerTransport.kt | 20 +--- .../kotlin/sdk/server/RequestBodyTest.kt | 103 ++++++++++++++++++ .../sdk/server/SseServerTransportTest.kt | 90 +++++++++++++++ .../StreamableHttpServerTransportTest.kt | 38 ++++++- 8 files changed, 308 insertions(+), 36 deletions(-) create mode 100644 kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBody.kt create mode 100644 kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBodyTest.kt create mode 100644 kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SseServerTransportTest.kt diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.api b/kotlin-sdk-server/api/kotlin-sdk-server.api index 3acaa64..6094b7c 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.api @@ -51,12 +51,12 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/HostValidationKt { } public final class io/modelcontextprotocol/kotlin/sdk/server/KtorServerKt { - public static final fun mcp (Lio/ktor/server/application/Application;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V - public static final fun mcp (Lio/ktor/server/routing/Route;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V - public static final fun mcp (Lio/ktor/server/routing/Route;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;)V - public static synthetic fun mcp$default (Lio/ktor/server/application/Application;ZLjava/util/List;Ljava/util/List;Lkotlin/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;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V - public static synthetic fun mcp$default (Lio/ktor/server/routing/Route;ZLjava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public static final fun mcp (Lio/ktor/server/application/Application;ZLjava/util/List;Ljava/util/List;JLkotlin/jvm/functions/Function1;)V + public static final fun mcp (Lio/ktor/server/routing/Route;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;JLkotlin/jvm/functions/Function1;)V + public static final fun mcp (Lio/ktor/server/routing/Route;ZLjava/util/List;Ljava/util/List;JLkotlin/jvm/functions/Function1;)V + 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 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 final fun mcpStreamableHttp (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 @@ -208,7 +208,8 @@ public class io/modelcontextprotocol/kotlin/sdk/server/ServerSession : io/modelc } public final class io/modelcontextprotocol/kotlin/sdk/server/SseServerTransport : io/modelcontextprotocol/kotlin/sdk/shared/AbstractTransport { - public fun (Ljava/lang/String;Lio/ktor/server/sse/ServerSSESession;)V + public fun (Ljava/lang/String;Lio/ktor/server/sse/ServerSSESession;J)V + public synthetic fun (Ljava/lang/String;Lio/ktor/server/sse/ServerSSESession;JILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getSessionId ()Ljava/lang/String; public final fun handleMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; 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 7e47d76..ec0652b 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 @@ -44,6 +44,8 @@ private val logger = KotlinLogging.logger {} * When `null` while the localhost host defaults are in effect (no custom `allowedHosts`), * the `Origin` header is validated against `localhost`, `127.0.0.1`, `[::1]`. * With custom `allowedHosts`, `null` skips origin validation. + * @param maxRequestBodySize maximum allowed size, in bytes, of an incoming POST body; larger requests are + * rejected with `413 Payload Too Large`. Defaults to 4 MiB. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. * @throws IllegalStateException if the [SSE] plugin is not installed. @@ -55,10 +57,11 @@ public fun Route.mcp( enableDnsRebindingProtection: Boolean = true, allowedHosts: List? = null, allowedOrigins: List? = null, + maxRequestBodySize: Long = DEFAULT_MAX_REQUEST_BODY_SIZE, block: ServerSSESession.() -> Server, ) { route(path) { - mcp(enableDnsRebindingProtection, allowedHosts, allowedOrigins, block) + mcp(enableDnsRebindingProtection, allowedHosts, allowedOrigins, maxRequestBodySize, block) } } @@ -76,15 +79,19 @@ public fun Route.mcp( * When `null` while the localhost host defaults are in effect (no custom `allowedHosts`), * the `Origin` header is validated against `localhost`, `127.0.0.1`, `[::1]`. * With custom `allowedHosts`, `null` skips origin validation. + * @param maxRequestBodySize maximum allowed size, in bytes, of an incoming POST body; larger requests are + * rejected with `413 Payload Too Large`. Defaults to 4 MiB. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. * @throws IllegalStateException if the [SSE] plugin is not installed. */ @KtorDsl +@Suppress("LongParameterList") public fun Route.mcp( enableDnsRebindingProtection: Boolean = true, allowedHosts: List? = null, allowedOrigins: List? = null, + maxRequestBodySize: Long = DEFAULT_MAX_REQUEST_BODY_SIZE, block: ServerSSESession.() -> Server, ) { try { @@ -103,7 +110,7 @@ public fun Route.mcp( val transportManager = TransportManager() sse { - mcpSseEndpoint("", transportManager, block) + mcpSseEndpoint("", transportManager, maxRequestBodySize, block) } post { @@ -126,21 +133,25 @@ public fun Route.mcp( * When `null` while the localhost host defaults are in effect (no custom `allowedHosts`), * the `Origin` header is validated against `localhost`, `127.0.0.1`, `[::1]`. * With custom `allowedHosts`, `null` skips origin validation. + * @param maxRequestBodySize maximum allowed size, in bytes, of an incoming POST body; larger requests are + * rejected with `413 Payload Too Large`. Defaults to 4 MiB. * @param block factory block with access to the [ServerSSESession] * that creates and returns the [Server] to handle the connection. */ @KtorDsl +@Suppress("LongParameterList") public fun Application.mcp( enableDnsRebindingProtection: Boolean = true, allowedHosts: List? = null, allowedOrigins: List? = null, + maxRequestBodySize: Long = DEFAULT_MAX_REQUEST_BODY_SIZE, block: ServerSSESession.() -> Server, ) { installMcpContentNegotiation() install(SSE) routing { - mcp(enableDnsRebindingProtection, allowedHosts, allowedOrigins, block) + mcp(enableDnsRebindingProtection, allowedHosts, allowedOrigins, maxRequestBodySize, block) } } @@ -327,9 +338,10 @@ public fun Application.mcpStatelessStreamableHttp( private suspend fun ServerSSESession.mcpSseEndpoint( postEndpoint: String, transportManager: TransportManager, + maxRequestBodySize: Long, block: ServerSSESession.() -> Server, ) { - val transport = mcpSseTransport(postEndpoint, transportManager) + val transport = mcpSseTransport(postEndpoint, transportManager, maxRequestBodySize) val server = block() @@ -348,8 +360,9 @@ private suspend fun ServerSSESession.mcpSseEndpoint( private fun ServerSSESession.mcpSseTransport( postEndpoint: String, transportManager: TransportManager, + maxRequestBodySize: Long, ): SseServerTransport { - val transport = SseServerTransport(postEndpoint, this) + val transport = SseServerTransport(postEndpoint, this, maxRequestBodySize) transportManager.addTransport(transport.sessionId, transport) logger.info { "New SSE connection established and stored with sessionId: ${transport.sessionId}" } diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBody.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBody.kt new file mode 100644 index 0000000..0cc4143 --- /dev/null +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBody.kt @@ -0,0 +1,34 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.ktor.server.application.ApplicationCall +import io.ktor.server.request.receiveChannel +import io.ktor.utils.io.readRemaining +import kotlinx.io.Buffer +import kotlinx.io.IOException +import kotlinx.io.readString + +/** Default maximum size (in bytes) for an incoming HTTP request body: 4 MiB. */ +internal const val DEFAULT_MAX_REQUEST_BODY_SIZE: Long = 4L * 1024 * 1024 + +/** Signals that an incoming request body exceeded the maximum size a transport is willing to read. */ +internal class RequestBodyTooLargeException(val maxBodySize: Long) : + IOException("Request body exceeds the maximum of $maxBodySize bytes.") + +/** + * Reads the request body as a UTF-8 string, rejecting bodies larger than [maxBytes]. + * + * At most `maxBytes + 1` bytes are ever pulled from the request channel, so an oversized or unframed + * body cannot exhaust memory regardless of the (untrusted) `Content-Length` header. + * + * @throws RequestBodyTooLargeException if the body exceeds [maxBytes] + */ +internal suspend fun ApplicationCall.receiveTextWithLimit(maxBytes: Long): String { + val buffer = Buffer() + val readLimit = if (maxBytes == Long.MAX_VALUE) maxBytes else maxBytes + 1 + val read = receiveChannel().readRemaining(readLimit).transferTo(buffer) + if (read > maxBytes) { + buffer.clear() + throw RequestBodyTooLargeException(maxBytes) + } + return buffer.readString() +} diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SSEServerTransport.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SSEServerTransport.kt index a6d4618..f525ec2 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SSEServerTransport.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SSEServerTransport.kt @@ -5,7 +5,6 @@ import io.ktor.http.HttpStatusCode import io.ktor.http.encodeURLPath import io.ktor.server.application.ApplicationCall import io.ktor.server.request.contentType -import io.ktor.server.request.receiveText import io.ktor.server.response.respondText import io.ktor.server.sse.ServerSSESession import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport @@ -29,10 +28,19 @@ internal const val SESSION_ID_PARAM = "sessionId" * * @param endpoint relative or absolute URL the client will POST messages to * @param session active SSE session used to deliver server-to-client events + * @param maxRequestBodySize maximum allowed size, in bytes, of an incoming POST body; larger requests are + * rejected with `413 Payload Too Large` without being buffered in full. Defaults to 4 MiB. */ @OptIn(ExperimentalAtomicApi::class) -public class SseServerTransport(private val endpoint: String, private val session: ServerSSESession) : - AbstractTransport() { +public class SseServerTransport( + private val endpoint: String, + private val session: ServerSSESession, + private val maxRequestBodySize: Long = DEFAULT_MAX_REQUEST_BODY_SIZE, +) : AbstractTransport() { + init { + require(maxRequestBodySize > 0) { "maxRequestBodySize must be greater than 0" } + } + private val initialized: AtomicBoolean = AtomicBoolean(false) /** Unique identifier for this transport session, generated randomly on creation. */ @@ -77,6 +85,7 @@ public class SseServerTransport(private val endpoint: String, private val sessio val message = "SSE connection not established" call.respondText(message, status = HttpStatusCode.InternalServerError) _onError.invoke(IllegalStateException(message)) + return } val body = try { @@ -85,9 +94,13 @@ public class SseServerTransport(private val endpoint: String, private val sessio error("Unsupported content-type: $ct") } - call.receiveText() + call.receiveTextWithLimit(maxRequestBodySize) } catch (e: CancellationException) { throw e + } catch (e: RequestBodyTooLargeException) { + call.respondText(e.message ?: "Request body too large", status = HttpStatusCode.PayloadTooLarge) + _onError.invoke(e) + return } catch (e: Exception) { call.respondText("Invalid message: ${e.message}", status = HttpStatusCode.BadRequest) _onError.invoke(e) 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 ae8a39d..c213350 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 @@ -8,7 +8,6 @@ import io.ktor.server.application.ApplicationCall import io.ktor.server.request.contentType import io.ktor.server.request.header import io.ktor.server.request.httpMethod -import io.ktor.server.request.receiveText import io.ktor.server.response.header import io.ktor.server.response.respond import io.ktor.server.response.respondNullable @@ -48,7 +47,6 @@ import kotlin.uuid.Uuid internal const val MCP_SESSION_ID_HEADER = "mcp-session-id" private const val MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version" private const val MCP_RESUMPTION_TOKEN_HEADER = "Last-Event-ID" -private const val DEFAULT_MAX_REQUEST_BODY_SIZE: Long = 4L * 1024 * 1024 // 4 MB private const val MIN_PRIMING_EVENT_PROTOCOL_VERSION = "2025-11-25" /** @@ -703,23 +701,13 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } private suspend fun parseBody(call: ApplicationCall): List? { - val maxSize = configuration.maxRequestBodySize - val contentLength = call.request.header(HttpHeaders.ContentLength)?.toLongOrNull() ?: 0L - if (contentLength > maxSize) { + val body = try { + call.receiveTextWithLimit(configuration.maxRequestBodySize) + } catch (e: RequestBodyTooLargeException) { call.reject( HttpStatusCode.PayloadTooLarge, RPCError.ErrorCode.INVALID_REQUEST, - "Invalid Request: message size exceeds maximum of $maxSize bytes", - ) - return null - } - - val body = call.receiveText() - if (body.length.toLong() > maxSize) { - call.reject( - HttpStatusCode.PayloadTooLarge, - RPCError.ErrorCode.INVALID_REQUEST, - "Invalid Request: message size exceeds maximum of $maxSize bytes", + "Invalid Request: message size exceeds maximum of ${e.maxBodySize} bytes", ) return null } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBodyTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBodyTest.kt new file mode 100644 index 0000000..9dc30cf --- /dev/null +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/RequestBodyTest.kt @@ -0,0 +1,103 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.kotest.matchers.shouldBe +import io.ktor.client.request.post +import io.ktor.client.request.setBody +import io.ktor.client.statement.bodyAsText +import io.ktor.http.HttpStatusCode +import io.ktor.server.response.respondText +import io.ktor.server.routing.post +import io.ktor.server.routing.routing +import io.ktor.server.testing.ApplicationTestBuilder +import io.ktor.server.testing.testApplication +import kotlin.test.Test + +class RequestBodyTest { + + /** Wires a POST endpoint that echoes the body when it fits, or replies 413 when it is too large. */ + private fun ApplicationTestBuilder.installEchoEndpoint(maxBytes: Long) { + install(io.ktor.server.sse.SSE) + application { + routing { + post("/echo") { + val text = try { + call.receiveTextWithLimit(maxBytes) + } catch (e: RequestBodyTooLargeException) { + call.respondText(e.message ?: "too large", status = HttpStatusCode.PayloadTooLarge) + return@post + } + call.respondText(text) + } + } + } + } + + @Test + fun `body under the limit is returned intact`() = testApplication { + installEchoEndpoint(maxBytes = 1024) + val payload = "hello world" + + val response = client.post("/echo") { setBody(payload) } + + response.status shouldBe HttpStatusCode.OK + response.bodyAsText() shouldBe payload + } + + @Test + fun `body exactly at the limit is accepted`() = testApplication { + val payload = "x".repeat(64) + installEchoEndpoint(maxBytes = payload.length.toLong()) + + val response = client.post("/echo") { setBody(payload) } + + response.status shouldBe HttpStatusCode.OK + response.bodyAsText() shouldBe payload + } + + @Test + fun `body exceeding the limit is rejected with 413`() = testApplication { + val payload = "x".repeat(65) + installEchoEndpoint(maxBytes = 64) + + val response = client.post("/echo") { setBody(payload) } + + response.status shouldBe HttpStatusCode.PayloadTooLarge + } + + @Test + fun `large body exceeding the limit is rejected without buffering it whole`() = testApplication { + // 8 MB body against a 4 MB limit: must be rejected. + installEchoEndpoint(maxBytes = 4L * 1024 * 1024) + val payload = "x".repeat(8 * 1024 * 1024) + + val response = client.post("/echo") { setBody(payload) } + + response.status shouldBe HttpStatusCode.PayloadTooLarge + } + + @Test + fun `multibyte UTF-8 body larger than a read chunk decodes intact`() = testApplication { + // Emoji is 4 bytes in UTF-8; a payload larger than the internal read chunk forces the + // accumulated bytes to span multiple chunks. Decoding once at the end must not corrupt + // characters that straddle a chunk boundary. + val unit = "a😀b" // mixes 1- and 4-byte code units so boundaries land mid-character + val payload = unit.repeat(40_000) // well over a 64 KiB read chunk + installEchoEndpoint(maxBytes = payload.encodeToByteArray().size.toLong()) + + val response = client.post("/echo") { setBody(payload) } + + response.status shouldBe HttpStatusCode.OK + response.bodyAsText() shouldBe payload + } + + @Test + fun `body is returned intact when the limit is Long MAX_VALUE`() = testApplication { + installEchoEndpoint(maxBytes = Long.MAX_VALUE) + val payload = "hello world" + + val response = client.post("/echo") { setBody(payload) } + + response.status shouldBe HttpStatusCode.OK + response.bodyAsText() shouldBe payload + } +} diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SseServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SseServerTransportTest.kt new file mode 100644 index 0000000..a0756f3 --- /dev/null +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/SseServerTransportTest.kt @@ -0,0 +1,90 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.kotest.matchers.shouldBe +import io.ktor.client.request.post +import io.ktor.client.request.prepareGet +import io.ktor.client.request.setBody +import io.ktor.client.statement.HttpResponse +import io.ktor.client.statement.bodyAsChannel +import io.ktor.http.ContentType +import io.ktor.http.HttpStatusCode +import io.ktor.http.contentType +import io.ktor.server.application.install +import io.ktor.server.routing.post +import io.ktor.server.routing.routing +import io.ktor.server.sse.SSE +import io.ktor.server.sse.ServerSSESession +import io.ktor.server.testing.testApplication +import io.ktor.utils.io.readLine +import io.mockk.mockk +import java.util.concurrent.atomic.AtomicBoolean +import kotlin.test.Test + +class SseServerTransportTest : AbstractKtorExtensionsTest() { + + @Test + fun `handlePostMessage on a not-started transport does not deliver the message`() = testApplication { + // A registered onMessage callback opens the delivery gate, so if the not-initialized branch + // falls through it would wrongly hand the message to the application. It must return instead. + val transport = SseServerTransport("/messages", mockk(relaxed = true)) + val delivered = AtomicBoolean(false) + transport.onMessage { delivered.set(true) } + + application { + routing { + post("/messages") { transport.handlePostMessage(call) } + } + } + + val response = client.post("/messages") { + contentType(ContentType.Application.Json) + setBody("""{"jsonrpc":"2.0","id":1,"method":"ping"}""") + } + + response.status shouldBe HttpStatusCode.InternalServerError + delivered.get() shouldBe false + } + + @Test + fun `SSE POST exceeding maxRequestBodySize is rejected with 413`() = testApplication { + application { + install(SSE) + routing { + mcp(enableDnsRebindingProtection = false, maxRequestBodySize = MAX_BODY) { testServer() } + } + } + + client.prepareGet("/").execute { response -> + val sessionId = response.readSessionId() + requireNotNull(sessionId) { "sessionId not found in SSE endpoint event" } + + // A body one byte over the configured limit must be rejected before processing. + val oversized = "x".repeat((MAX_BODY + 1).toInt()) + val postResponse = client.post("/?sessionId=$sessionId") { + contentType(ContentType.Application.Json) + setBody(oversized) + } + postResponse.status shouldBe HttpStatusCode.PayloadTooLarge + } + } + + private suspend fun HttpResponse.readSessionId(): String? { + val channel = bodyAsChannel() + var eventName: String? = null + while (!channel.isClosedForRead) { + val line = channel.readLine() ?: break + when { + line.startsWith("event:") -> eventName = line.substringAfter("event:").trim() + + line.startsWith("data:") && eventName == "endpoint" -> { + return line.substringAfter("data:").trim().substringAfter("sessionId=").ifEmpty { null } + } + } + } + return null + } + + private companion object { + const val MAX_BODY = 1024L + } +} diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt index f6dda15..d7dec4e 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt @@ -24,6 +24,8 @@ import io.ktor.server.routing.post import io.ktor.server.routing.routing import io.ktor.server.testing.ApplicationTestBuilder import io.ktor.server.testing.testApplication +import io.ktor.utils.io.ByteReadChannel +import io.ktor.utils.io.readLine import io.ktor.utils.io.readUTF8Line import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult @@ -421,6 +423,34 @@ class StreamableHttpServerTransportTest { response.status shouldBe HttpStatusCode.PayloadTooLarge } + @Test + fun `POST with oversized chunked body and no Content-Length returns 413`() = testApplication { + configTestServer() + + val client = createTestClient() + + val transport = StreamableHttpServerTransport( + StreamableHttpServerTransport.Configuration(enableJsonResponse = true, maxRequestBodySize = 1024), + ) + transport.onMessage { message -> + if (message is JSONRPCRequest) { + transport.send(JSONRPCResponse(message.id, EmptyResult())) + } + } + + configureTransportEndpoint(transport) + + // Stream the body as a channel so the client uses chunked transfer-encoding with no + // Content-Length header: the size limit must hold without trusting the (absent) header. + val oversized = ByteReadChannel("x".repeat(4096).encodeToByteArray()) + val response = client.post(path) { + addStreamableHeaders() + setBody(oversized) + } + + response.status shouldBe HttpStatusCode.PayloadTooLarge + } + @ParameterizedTest @MethodSource("maxBodySizeTestCases") fun `POST with custom max request body size validates payload size`( @@ -507,7 +537,7 @@ class StreamableHttpServerTransportTest { // New stream is alive val secondChannel = secondResponse.bodyAsChannel() - val firstLine = secondChannel.readUTF8Line() + val firstLine = secondChannel.readLine() firstLine.shouldNotBeNull() secondChannel.isClosedForRead shouldBe false } @@ -546,7 +576,7 @@ class StreamableHttpServerTransportTest { header("mcp-protocol-version", LATEST_PROTOCOL_VERSION) }.execute { response -> response.status shouldBe HttpStatusCode.OK - response.bodyAsChannel().readUTF8Line() + response.bodyAsChannel().readLine() } // Step 3: Immediately reconnect — the transport should close the stale @@ -561,7 +591,7 @@ class StreamableHttpServerTransportTest { response.headers[MCP_SESSION_ID_HEADER] shouldBe sessionId val channel = response.bodyAsChannel() - val firstLine = channel.readUTF8Line() + val firstLine = channel.readLine() firstLine.shouldNotBeNull() channel.isClosedForRead shouldBe false } @@ -604,7 +634,7 @@ class StreamableHttpServerTransportTest { // Verify the stream is alive by reading at least one line (flush event) val channel = response.bodyAsChannel() - val firstLine = channel.readUTF8Line() + val firstLine = channel.readLine() firstLine.shouldNotBeNull() channel.isClosedForRead shouldBe false } From 57e546d378b8fb7251d7aeecc3452cb9fdf7c9cf Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 30 Jun 2026 22:04:15 +0200 Subject: [PATCH 071/178] feat: SEP-1686 Tasks (#844) finished SEP-1686 closes #421 ## Breaking Changes none ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- kotlin-sdk-core/api/kotlin-sdk-core.api | 26 ++++++---- .../kotlin/sdk/types/sampling.kt | 9 ++++ .../kotlin/sdk/types/tools.kt | 9 ++++ .../kotlin/sdk/types/SamplingTest.kt | 20 ++++++++ .../kotlin/sdk/types/ToolsTest.kt | 51 +++++++++++++++++++ 5 files changed, 105 insertions(+), 10 deletions(-) diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index 1904dc7..cdee342 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -390,6 +390,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequest : io public final fun getName ()Ljava/lang/String; public fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams; public synthetic fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestParams; + public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata; public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -421,17 +422,19 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequestBuild public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams : io/modelcontextprotocol/kotlin/sdk/types/RequestParams { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams$Companion; - public synthetic fun (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Lkotlinx/serialization/json/JsonObject; - public final fun component3-VI-3G7E ()Lkotlinx/serialization/json/JsonObject; - public final fun copy-EDEVuBg (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams; - public static synthetic fun copy-EDEVuBg$default (Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams; + public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata; + public final fun component4-VI-3G7E ()Lkotlinx/serialization/json/JsonObject; + public final fun copy-6R815Ik (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams; + public static synthetic fun copy-6R815Ik$default (Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams; public fun equals (Ljava/lang/Object;)Z public final fun getArguments ()Lkotlinx/serialization/json/JsonObject; public fun getMeta-VI-3G7E ()Lkotlinx/serialization/json/JsonObject; public final fun getName ()Ljava/lang/String; + public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata; public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -1161,6 +1164,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest public synthetic fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestParams; public final fun getStopSequences ()Ljava/util/List; public final fun getSystemPrompt ()Ljava/lang/String; + public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata; public final fun getTemperature ()Ljava/lang/Double; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -1205,11 +1209,12 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams : io/modelcontextprotocol/kotlin/sdk/types/RequestParams { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams$Companion; - public synthetic fun (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()I public final fun component10 ()Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice; - public final fun component11-VI-3G7E ()Lkotlinx/serialization/json/JsonObject; + public final fun component11 ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata; + public final fun component12-VI-3G7E ()Lkotlinx/serialization/json/JsonObject; public final fun component2 ()Ljava/util/List; public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences; public final fun component4 ()Ljava/lang/String; @@ -1218,8 +1223,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest public final fun component7 ()Ljava/util/List; public final fun component8 ()Lkotlinx/serialization/json/JsonObject; public final fun component9 ()Ljava/util/List; - public final fun copy-APmi5RE (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams; - public static synthetic fun copy-APmi5RE$default (Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams; + public final fun copy-7OuPiQU (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams; + public static synthetic fun copy-7OuPiQU$default (Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams; public fun equals (Ljava/lang/Object;)Z public final fun getIncludeContext ()Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext; public final fun getMaxTokens ()I @@ -1229,6 +1234,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest public final fun getModelPreferences ()Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences; public final fun getStopSequences ()Ljava/util/List; public final fun getSystemPrompt ()Ljava/lang/String; + public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata; public final fun getTemperature ()Ljava/lang/Double; public final fun getToolChoice ()Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice; public final fun getTools ()Ljava/util/List; diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt index 4526405..7cc2685 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/sampling.kt @@ -182,6 +182,12 @@ public data class CreateMessageRequest(override val params: CreateMessageRequest public val metadata: JsonObject? get() = params.metadata + /** + * Task metadata, if the caller is requesting task-augmented execution. + */ + public val task: TaskMetadata? + get() = params.task + /** * Metadata for this request. May include a progressToken for out-of-band progress notifications. */ @@ -216,6 +222,8 @@ public data class CreateMessageRequest(override val params: CreateMessageRequest * @property toolChoice Optional policy controlling how the model uses the provided [tools]. * The client MUST return an error if this field is present but the client did not advertise * [ClientCapabilities.Sampling.tools]. + * @property task If set, requests task-augmented execution. A receiver that supports it returns + * a [CreateTaskResult] (result via `tasks/result`); otherwise it returns a [CreateMessageResult] directly. * @property meta Optional metadata for this request. May include a progressToken for * out-of-band progress notifications. */ @@ -231,6 +239,7 @@ public data class CreateMessageRequestParams( val metadata: JsonObject? = null, val tools: List? = null, val toolChoice: ToolChoice? = null, + val task: TaskMetadata? = null, @SerialName("_meta") override val meta: RequestMeta? = null, ) : RequestParams diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/tools.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/tools.kt index 2ff890a..1f0f54e 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/tools.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/tools.kt @@ -203,6 +203,12 @@ public data class CallToolRequest(override val params: CallToolRequestParams) : public val arguments: JsonObject? get() = params.arguments + /** + * Task metadata, if the caller is requesting task-augmented execution. + */ + public val task: TaskMetadata? + get() = params.task + /** * Metadata for this request. May include a progressToken for out-of-band progress notifications. */ @@ -216,6 +222,8 @@ public data class CallToolRequest(override val params: CallToolRequestParams) : * @property name The name of the tool to invoke. * @property arguments Arguments to pass to the tool. Keys are argument names, values are the argument values. * The structure must match the tool's input schema. + * @property task If set, requests task-augmented execution. A receiver that supports it returns + * a [CreateTaskResult] (result via `tasks/result`); otherwise it returns a [CallToolResult] directly. * @property meta Optional metadata for this request. May include a progressToken for * out-of-band progress notifications. */ @@ -223,6 +231,7 @@ public data class CallToolRequest(override val params: CallToolRequestParams) : public data class CallToolRequestParams( val name: String, val arguments: JsonObject? = null, + val task: TaskMetadata? = null, @SerialName("_meta") override val meta: RequestMeta? = null, ) : RequestParams diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt index b2c8cf0..b7bc5cf 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/SamplingTest.kt @@ -367,6 +367,26 @@ class SamplingTest { decoded.toolChoice shouldBe ToolChoice(mode = ToolChoice.Mode.Required) } + @Test + fun `CreateMessageRequestParams task defaults to null and is omitted when encoding`() { + val params = CreateMessageRequestParams(maxTokens = 100, messages = emptyList()) + params.task shouldBe null + val encoded = McpJson.encodeToString(CreateMessageRequestParams.serializer(), params) + assertEquals(false, "\"task\"" in encoded) + } + + @Test + fun `CreateMessageRequestParams round-trips task`() { + val original = CreateMessageRequestParams( + maxTokens = 100, + messages = emptyList(), + task = TaskMetadata(ttl = 60_000L), + ) + val encoded = McpJson.encodeToString(CreateMessageRequestParams.serializer(), original) + val decoded = McpJson.decodeFromString(CreateMessageRequestParams.serializer(), encoded) + decoded.task shouldBe TaskMetadata(ttl = 60_000L) + } + @Test fun `StopReason ToolUse serialises as toolUse`() { StopReason.ToolUse.value shouldBe "toolUse" diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ToolsTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ToolsTest.kt index d5e1d5a..358866a 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ToolsTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/ToolsTest.kt @@ -319,6 +319,57 @@ class ToolsTest { assertEquals(ProgressToken(77), params.meta?.progressToken) } + @Test + fun `should serialize CallToolRequest with task augmentation`() { + val request = CallToolRequest( + CallToolRequestParams( + name = "long-running", + arguments = buildJsonObject { put("query", "MCP protocol") }, + task = TaskMetadata(ttl = 60_000L), + ), + ) + + verifySerialization( + request, + McpJson, + """ + { + "method": "tools/call", + "params": { + "name": "long-running", + "arguments": { + "query": "MCP protocol" + }, + "task": { + "ttl": 60000 + } + } + } + """.trimIndent(), + ) + + assertEquals(TaskMetadata(ttl = 60_000L), request.task) + } + + @Test + fun `should omit task from CallToolRequest when null`() { + val request = CallToolRequest(CallToolRequestParams(name = "plain")) + + assertEquals(null, request.task) + verifySerialization( + request, + McpJson, + """ + { + "method": "tools/call", + "params": { + "name": "plain" + } + } + """.trimIndent(), + ) + } + @Test fun `should serialize CallToolResult with structured content`() { val result = CallToolResult( From fc7916fdc7f47590b7c33e9c311185727a40d083 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 30 Jun 2026 22:39:53 +0200 Subject: [PATCH 072/178] release: 0.14.0 (#867) Bump version to 0.14.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e5294e8..434144d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kotlin.daemon.jvmargs=-Xmx4G kotlin.native.ignoreDisabledTargets=true group=io.modelcontextprotocol -version=0.13.0 +version=0.14.0 From 25678bdded92dd9fc30ef572bcf63814ab8aaf35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 15:56:44 +0200 Subject: [PATCH 073/178] chore(deps): bump org.jetbrains.kotlin.jvm from 2.3.21 to 2.4.0 in /samples/kotlin-mcp-client (#819) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [org.jetbrains.kotlin.jvm](https://github.com/JetBrains/kotlin) from 2.3.21 to 2.4.0.
    Release notes

    Sourced from org.jetbrains.kotlin.jvm's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.jvm's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 0b9018d..b84f095 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] anthropic = "2.45.0" -kotlin = "2.3.21" +kotlin = "2.4.0" ktor = "3.3.3" mcp-kotlin = "0.13.0" shadow = "9.4.3" From bb6c1ec2e12d2577f1d045829202ed3308837c99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:45:09 +0200 Subject: [PATCH 074/178] chore(deps): bump kotlin from 2.3.21 to 2.4.0 in /samples/kotlinlang-mcp-server (#825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `kotlin` from 2.3.21 to 2.4.0. Updates `org.jetbrains.kotlin.jvm` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.jvm's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.jvm's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Updates `org.jetbrains.kotlin.plugin.serialization` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 26e89b2..39caf34 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.3.21" +kotlin = "2.4.0" ktor = "3.3.3" mcp-kotlin = "0.13.0" serialization = "1.11.0" From 7937e9cba6e27626da7f747b924f87696b81c223 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 12:11:36 +0200 Subject: [PATCH 075/178] chore(deps): bump io.ktor:ktor-bom from 3.3.3 to 3.5.1 in /samples/kotlin-mcp-server (#860) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.3.3 to 3.5.1.
    Release notes

    Sourced from io.ktor:ktor-bom's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-bom's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 56bf5f1..91c9513 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin = "2.3.21" -ktor = "3.3.3" +ktor = "3.5.1" mcp-kotlin = "0.13.0" slf4j = "2.0.18" shadow = "9.4.3" From c59b87f273480460c292df3c0ec715f74fd1db0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 12:34:29 +0200 Subject: [PATCH 076/178] chore(deps): bump io.ktor:ktor-bom from 3.3.3 to 3.5.1 in /samples/kotlin-mcp-client (#859) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.3.3 to 3.5.1.
    Release notes

    Sourced from io.ktor:ktor-bom's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-bom's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index b84f095..b5167d9 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] anthropic = "2.45.0" kotlin = "2.4.0" -ktor = "3.3.3" +ktor = "3.5.1" mcp-kotlin = "0.13.0" shadow = "9.4.3" slf4j = "2.0.18" From d47429dd35767fe1b08c50b7fbbff5292881b2dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 13:35:57 +0200 Subject: [PATCH 077/178] chore(deps): bump io.ktor:ktor-bom from 3.3.3 to 3.5.1 in /samples/simple-streamable-server (#862) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.3.3 to 3.5.1.
    Release notes

    Sourced from io.ktor:ktor-bom's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-bom's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 723994b..dc7393d 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin = "2.3.21" -ktor = "3.3.3" +ktor = "3.5.1" junit = "6.1.1" mcp-kotlin = "0.13.0" slf4j = "2.0.18" From a19ec03aa2bd098598f907d9a5639cbdf008f109 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 13:59:49 +0200 Subject: [PATCH 078/178] chore(deps): bump io.ktor:ktor-bom from 3.3.3 to 3.5.1 in /samples/weather-stdio-server (#863) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.3.3 to 3.5.1.
    Release notes

    Sourced from io.ktor:ktor-bom's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-bom's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index e805236..4b74090 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] coroutines = "1.11.0" kotlin = "2.3.21" -ktor = "3.3.3" +ktor = "3.5.1" logging = "8.0.4" mcp-kotlin = "0.13.0" shadow = "9.4.3" From 65ce490454a08fee0bb3b522c1653da508f78cb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:22:52 +0200 Subject: [PATCH 079/178] chore(deps): bump io.ktor:ktor-bom from 3.3.3 to 3.5.1 in /samples/kotlinlang-mcp-server (#861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.3.3 to 3.5.1.
    Release notes

    Sourced from io.ktor:ktor-bom's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-bom's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 39caf34..c521eba 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin = "2.4.0" -ktor = "3.3.3" +ktor = "3.5.1" mcp-kotlin = "0.13.0" serialization = "1.11.0" coroutines = "1.11.0" From 365f2625e171aa47c7f6e57f5c485047a4937b8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 14:54:36 +0200 Subject: [PATCH 080/178] chore(deps): bump kotlin from 2.3.21 to 2.4.0 in /samples/weather-stdio-server (#829) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `kotlin` from 2.3.21 to 2.4.0. Updates `org.jetbrains.kotlin.jvm` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.jvm's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.jvm's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Updates `org.jetbrains.kotlin.plugin.serialization` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 4b74090..2acaf66 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] coroutines = "1.11.0" -kotlin = "2.3.21" +kotlin = "2.4.0" ktor = "3.5.1" logging = "8.0.4" mcp-kotlin = "0.13.0" From e8ebf19a32830c3e1838e8f588e4969171c6996a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 20:22:33 +0200 Subject: [PATCH 081/178] chore(deps): bump kotlin from 2.3.21 to 2.4.0 in /samples/simple-streamable-server (#827) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `kotlin` from 2.3.21 to 2.4.0. Updates `org.jetbrains.kotlin.jvm` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.jvm's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.jvm's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Updates `org.jetbrains.kotlin.plugin.serialization` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index dc7393d..e3f8f6a 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.3.21" +kotlin = "2.4.0" ktor = "3.5.1" junit = "6.1.1" mcp-kotlin = "0.13.0" From 594ed4aa86ccc9f4777af735035ab7d4f1f4e0fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 18:43:12 +0000 Subject: [PATCH 082/178] chore(deps): bump kotlin from 2.3.21 to 2.4.0 in /samples/kotlin-mcp-server (#822) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `kotlin` from 2.3.21 to 2.4.0. Updates `org.jetbrains.kotlin.jvm` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.jvm's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.jvm's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Updates `org.jetbrains.kotlin.plugin.serialization` from 2.3.21 to 2.4.0
    Release notes

    Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

    Kotlin 2.4.0

    Changelog

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    ... (truncated)

    Changelog

    Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

    2.4.0

    Analysis API

    • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
    • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
    • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
    • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

    Analysis API. Code Compilation

    • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

    Analysis API. FIR

    • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
    • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
    • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
    • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
    • KT-84596 Improve K2 Jooq completion performance
    • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
    • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
    • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
    • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
    • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

    Analysis API. Infrastructure

    Fixes

    • KT-83905 Analysis API: Improve UX with test data
    • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
    • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
    • KT-84776 The test data manager misses the redundancy check in the update mode
    • KT-84962 The test data manager misses -ea flag
    • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
    • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
    • KT-84279 Test Data Manager fails on a clean build
    • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
    • KT-80379 Extract per-module test generators for AA tests
    • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
    • KT-83200 Track external dependencies of the Analysis API modules

    Analysis API. Light Classes

    • KT-82434 Light classes should prefer enum entries to properties
    • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
    • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

    Analysis API. PSI

    ... (truncated)

    Commits
    • add726c Add ChangeLog for 2.4.0-RC2
    • 69a4a81 [Wasm] Add binaryen per-file arguments
    • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
    • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
    • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
    • 13d25e2 KT-86268: Regression test added
    • f7d1a76 [JKlib] Fix JAR deserializer configuration.
    • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
    • ef14611 Make the default stability of non-final classes Unknown instead of Stable
    • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
    • Additional commits viewable in compare view

    Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 91c9513..5a6217e 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.3.21" +kotlin = "2.4.0" ktor = "3.5.1" mcp-kotlin = "0.13.0" slf4j = "2.0.18" From 1866effd07705bece73f882eb7b210bf04377af8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 22:04:38 +0200 Subject: [PATCH 083/178] chore(deps): bump the ktor group across 1 directory with 15 updates (#832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the ktor group with 15 updates in the / directory: | Package | From | To | | --- | --- | --- | | [io.ktor:ktor-client-apache5](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-client-auth](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-client-core](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-client-logging](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-server-content-negotiation](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-client-content-negotiation](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-serialization-kotlinx-json](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-server-auth](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-server-core](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-server-sse](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-server-websockets](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-client-mock](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-server-test-host](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-client-cio](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | | [io.ktor:ktor-server-cio](https://github.com/ktorio/ktor) | `3.4.3` | `3.5.1` | Updates `io.ktor:ktor-client-apache5` from 3.4.3 to 3.5.1
    Release notes

    Sourced from io.ktor:ktor-client-apache5's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-client-apache5's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Updates `io.ktor:ktor-client-auth` from 3.4.3 to 3.5.1
    Release notes

    Sourced from io.ktor:ktor-client-auth's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-client-auth's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Updates `io.ktor:ktor-client-core` from 3.4.3 to 3.5.1
    Release notes

    Sourced from io.ktor:ktor-client-core's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-client-core's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @​InternalAPI annotation

    ... (truncated)

    Commits
    • 5ba9d6f Release 3.5.1 (#5719)
    • a4f145d KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when… (#5701)
    • 2caf278 Fix failing :ktor-io:compileDarwinMainKotlinMetadata (#5716)
    • 257de90 KTOR-8766 Fix multiple invocations of close from DI
    • e77a168 Fix cache misses with content negotiation 3x (#5714)
    • ed22950 Make huge post test less huge
    • f329069 Update dependency com.github.luben:zstd-jni to v1.5.7-11
    • 6ecd072 Update dependency io.swagger.parser.v3:swagger-parser to v2.1.44
    • a0534cd Update dependency io.pebbletemplates:pebble to v4.1.2
    • 8647e53 Update dependency com.typesafe:config to v1.4.9
    • Additional commits viewable in compare view

    Updates `io.ktor:ktor-client-logging` from 3.4.3 to 3.5.1
    Release notes

    Sourced from io.ktor:ktor-client-logging's releases.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated to the RawSource
    • KTOR-8870 File.readChannel: do not close a non-opened file and ignore closing exceptions
    • KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
    • KTOR-9607 Crash on Android 7: NoSuchMethodError getInstanceStrong() since 3.5.0
    • KTOR-9595 CIO: The engine imports node:net statically and breaks wasmJsBrowser webpack build
    • KTOR-9615 Apache5: The underlying request is not aborted when coroutine Job is cancelled
    • KTOR-8443 RoutingBuilder.contentType does not use parameters when matching
    • KTOR-9425 SessionTransportTransformerEncrypt init block uses wrong IV size for AES-256 (regression of KTOR-661)
    • KTOR-9621 RateLimit plugin is bypassed when the nested authenticate block rejects the request
    • KTOR-8766 DI: The close method is called twice on cleanup of AutoCloseable
    • KTOR-8695 GMTDate() being offset by 369 years on Windows
    • KTOR-9589 Duplicate PROPERTY_SETTER target in @InternalAPI annotation

    ... (truncated)

    Changelog

    Sourced from io.ktor:ktor-client-logging's changelog.

    3.5.1

    Published 25 June 2026

    Improvements

    • KTOR-9492 OpenAPI plugin: handle requireXxx functions in compiler plugin
    • KTOR-9569 Add more details for KDoc of BearerAuthConfig.sendWithoutRequest
    • KTOR-9571 Add KDoc for BearerAuthConfig.realm
    • KTOR-9570 Add Kdoc for BearerAuthConfig.refreshTokens

    Bugfixes

    • KTOR-9646 Fix Kotlin 2.4.0 compiler plugin breaking changes
    • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
    • KTOR-9591 OpenAPI: @JsonClassDiscriminator on sealed types is ignored when generating OpenAPI discriminator schema
    • KTOR-9597 OpenAPI: Schema name collisions because@SerialName of sealed subtypes is used as components.schemas key
    • KTOR-9601 OpenAPI: nullable @​JvmInline value class loses nullability in generated schema
    • KTOR-9620 Some issues related to digest authentication in 3.5.0
    • KTOR-9623 Digest Auth: server must respond with one WWW-Authenticate header for each supported algorithm
    • KTOR-9624 Digest Auth: "Unsupported charset in digest authentication header" for a charset name in lowercase
    • KTOR-9630 Digest Auth: The plugin sends incorrect nonce when server responds with multiple WWW-Authenticate headers
    • KTOR-9565 WebRTC: Peer stops receiving messages after a while on iOS
    • KTOR-9610 WebRtcPeerConnection::close causes ClosedReceiveChannelException for other peer
    • KTOR-9633 WebRTC statistics fetching race condition
    • KTOR-9603 Structured concurrency is violated in WebRTC tests
    • KTOR-9671 Darwin: Semicolons in URL path are sanitized
    • KTOR-9639 Darwin: WebSocket client crashes the process when a PONG arrives after the session is closed
    • KTOR-9575 Darwin: findCharset("UTF-16") maps to NSUTF16LittleEndianStringEncoding causing decoding failure for UTF-16 content with BOM
    • KTOR-9661 HttpCache: InvalidCacheStateException is thrown on 304 when no cached entry matches varyKeys
    • KTOR-9673 Caching always missing with Content Negotiation
    • KTOR-9596 HttpTimeout: HttpRequestTimeoutException on any request with runTest and request timeout defined since 3.5.0
    • KTOR-9632 HttpRequestBuilder.timeout call removes capabilities set in DefaultRequest
    • KTOR-9252 ContentEncoding: Incomplete gzip response causes client/server to hang indefinitely
    • KTOR-9670 Compression: The plugin ignores Accept-Encoding q=0 and most-specific matching
    • KTOR-9614 Zstd Compression: "Destination buffer is too small" exception for a particular sequence of bytes
    • KTOR-9636 CORS plugin drops OPTIONS preflight requests when allowSameOrigin is on
    • KTOR-9659 CORS is skipped when the Origin header contains an IPv6 address
    • KTOR-9574 ContentNegotiation: The charset of Accept-Charset header is used for response deserialization
    • KTOR-9606 KotlinxSerializationConverter: it fails to deserialize an empty channel closed with a delay
    • KTOR-9617 OutputStreamContent and WriterContent can exhaust Dispatchers.IO
    • KTOR-9629 RawSourceChannel: coroutine cancellation is not propagated ... _Description has been truncated_ Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ae38db6..9e864e8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ collections-immutable = "0.5.0" coroutines = "1.11.0" kotest = "6.2.1" kotlinx-io = "0.9.1" -ktor = "3.4.3" +ktor = "3.5.1" logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" From 4531a4c846ef54a5c9352888b4ab6a6541d33d9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jul 2026 22:37:39 +0200 Subject: [PATCH 084/178] chore(deps): bump dev.detekt:detekt-gradle-plugin from 2.0.0-alpha.3 to 2.0.0-alpha.5 (#849) Bumps [dev.detekt:detekt-gradle-plugin](https://github.com/detekt/detekt) from 2.0.0-alpha.3 to 2.0.0-alpha.5.
      Release notes

      Sourced from dev.detekt:detekt-gradle-plugin's releases.

      v2.0.0-alpha.5

      2.0.0-alpha.5 - 2026-06-17

      This is a hotfix release for 2.0.0-alpha.4 where we fixed 2 bugs that were preventing detekt from running correctly.

      Changelog

      • fix: stop leaking ktlint-repackage as a transitive dependency - #9391
      • fix: exclude gradle-public-api from published POM - #9408
      • Stop accepting unsupported API or language versions passed to CLI - #9410

      v2.0.0-alpha.4

      2.0.0-alpha.4 - 2026-06-13

      This is an alpha release of Detekt 2.0.0. Is built against Kotlin 2.4.0, Gradle 9.5.1, AGP 9.2.1 and is tested against JDK 25.

      Notable Changes

      • Support Kotlin 2.4.0 - #9218
      • Add new rule LeakingSessionBoundType - #9242
      • Apply the indent_style configuration to all the ktlint wrapper rules (previsouly this was applied only to the Indentation rule) - #9315

      Breaking Changes

      • Expose Glob-to-Regex functions in psi-utils - #9340
      • Make Detektion immutable - #8583

      Changelog

      • fix: prevent ArrayPrimitive crash on unresolved types - #9364
      • Update ktlint documentation links - #9354
      • Fix PrintStackTrace nested call detection - #9352
      • Fix unused import false positive for companion object member extension properties - #9349
      • Accept punctuation after a link - #9341
      • Fixes UnnecessaryFullyQualifiedName false positive with explicit import shadowing - #9329
      • docs: fix KMP type resolution task names - #9316
      • Stop publishing ktlint-repackage - #9314
      • Stop exposing ktlint's StandardRule to detekt-rules-ktlint-wrapper consumers - #9313
      • Include ktlint-repackage in ktlint-wrapper JAR - #9312
      • Declare DGP compatibility with Gradle's configuration cache - #9311
      • Forward languageVersionSettings to KotlinAnalysisApiEngine.compile - #9305
      • docs: add ForbiddenImport configuration example - #9302
      • Fix UnnecessaryFullyQualifiedName clashes with kotlin package name - #9289
      • Remove excludeImportStatements from Deprecation rule - #9287
      • Improve repackaging of Analysis API dependencies - #9285
      • MaxChainedCallsOnSameLine - Fix AA type leaks - #9261
      • SuspendFunSwallowedCancellation - Fix AA type leaks - #9256
      • feat: Add exhaustive option to OutdatedDocumentation rule, also improve error messages - #9255
      • Excluding generated sources by default - #9251

      ... (truncated)

      Commits
      • 9c6ced6 Stop accepting unsupported API or language versions passed to CLI (#9410)
      • 44526f4 fix: exclude gradle-public-api from published POM (#9408)
      • 6bad2e8 fix: stop leaking ktlint-repackage as a transitive dependency (#9391)
      • fd5683e Update dependency path-to-regexp to v0.2.5 (#9397)
      • 7865b27 fix: resolve npm security vulnerabilities in website and bots dependencies (#...
      • bb582d5 Unbreak snapshot publishing (#9394)
      • 69866dd Update caniuse browser definitions (#9393)
      • bfd3b5d Add Docs for 2.0.0-alpha.4 (#9388)
      • 60300b2 Switch to vanniktech/gradle-maven-publish-plugin for publishing (#9357)
      • 63e0777 Update gradle/actions digest to 3f131e8 (#9386)
      • Additional commits viewable in compare view

      --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: devcrocod --- config/detekt/detekt.yml | 1 - gradle/libs.versions.toml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 98fce0e..a82b404 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -416,7 +416,6 @@ potential-bugs: Deprecation: active: false aliases: ['DEPRECATION'] - excludeImportStatements: false DontDowncastCollectionTypes: active: false DoubleMutabilityForCollection: diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9e864e8..592fa25 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ # plugins version atomicfu = "0.33.0" binaryCompatibilityValidatorPlugin = "0.18.1" -detekt = "2.0.0-alpha.3" +detekt = "2.0.0-alpha.5" dokka = "2.2.0" kotlin = "2.3.21" kover = "0.9.8" From 420b64d1bb2d35e86adf544499e6748ee314ec72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:16:58 +0200 Subject: [PATCH 085/178] chore(deps): bump the kotlin group across 1 directory with 2 updates (#834) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotlin group with 2 updates in the / directory: [org.jetbrains.kotlin:kotlin-gradle-plugin](https://github.com/JetBrains/kotlin) and [org.jetbrains.kotlin:kotlin-serialization](https://github.com/JetBrains/kotlin). Updates `org.jetbrains.kotlin:kotlin-gradle-plugin` from 2.3.21 to 2.4.0
      Release notes

      Sourced from org.jetbrains.kotlin:kotlin-gradle-plugin's releases.

      Kotlin 2.4.0

      Changelog

      Analysis API

      • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
      • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
      • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
      • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

      Analysis API. Code Compilation

      • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

      Analysis API. FIR

      • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
      • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
      • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
      • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
      • KT-84596 Improve K2 Jooq completion performance
      • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
      • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
      • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
      • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
      • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

      Analysis API. Infrastructure

      Fixes

      • KT-83905 Analysis API: Improve UX with test data
      • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
      • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
      • KT-84776 The test data manager misses the redundancy check in the update mode
      • KT-84962 The test data manager misses -ea flag
      • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
      • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
      • KT-84279 Test Data Manager fails on a clean build
      • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
      • KT-80379 Extract per-module test generators for AA tests
      • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
      • KT-83200 Track external dependencies of the Analysis API modules

      Analysis API. Light Classes

      • KT-82434 Light classes should prefer enum entries to properties
      • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
      • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

      ... (truncated)

      Changelog

      Sourced from org.jetbrains.kotlin:kotlin-gradle-plugin's changelog.

      2.4.0

      Analysis API

      • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
      • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
      • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
      • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

      Analysis API. Code Compilation

      • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

      Analysis API. FIR

      • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
      • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
      • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
      • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
      • KT-84596 Improve K2 Jooq completion performance
      • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
      • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
      • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
      • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
      • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

      Analysis API. Infrastructure

      Fixes

      • KT-83905 Analysis API: Improve UX with test data
      • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
      • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
      • KT-84776 The test data manager misses the redundancy check in the update mode
      • KT-84962 The test data manager misses -ea flag
      • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
      • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
      • KT-84279 Test Data Manager fails on a clean build
      • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
      • KT-80379 Extract per-module test generators for AA tests
      • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
      • KT-83200 Track external dependencies of the Analysis API modules

      Analysis API. Light Classes

      • KT-82434 Light classes should prefer enum entries to properties
      • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
      • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

      Analysis API. PSI

      ... (truncated)

      Commits
      • add726c Add ChangeLog for 2.4.0-RC2
      • 69a4a81 [Wasm] Add binaryen per-file arguments
      • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
      • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
      • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
      • 13d25e2 KT-86268: Regression test added
      • f7d1a76 [JKlib] Fix JAR deserializer configuration.
      • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
      • ef14611 Make the default stability of non-final classes Unknown instead of Stable
      • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
      • Additional commits viewable in compare view

      Updates `org.jetbrains.kotlin:kotlin-serialization` from 2.3.21 to 2.4.0
      Release notes

      Sourced from org.jetbrains.kotlin:kotlin-serialization's releases.

      Kotlin 2.4.0

      Changelog

      Analysis API

      • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
      • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
      • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
      • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

      Analysis API. Code Compilation

      • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

      Analysis API. FIR

      • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
      • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
      • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
      • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
      • KT-84596 Improve K2 Jooq completion performance
      • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
      • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
      • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
      • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
      • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

      Analysis API. Infrastructure

      Fixes

      • KT-83905 Analysis API: Improve UX with test data
      • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
      • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
      • KT-84776 The test data manager misses the redundancy check in the update mode
      • KT-84962 The test data manager misses -ea flag
      • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
      • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
      • KT-84279 Test Data Manager fails on a clean build
      • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
      • KT-80379 Extract per-module test generators for AA tests
      • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
      • KT-83200 Track external dependencies of the Analysis API modules

      Analysis API. Light Classes

      • KT-82434 Light classes should prefer enum entries to properties
      • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
      • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

      ... (truncated)

      Changelog

      Sourced from org.jetbrains.kotlin:kotlin-serialization's changelog.

      2.4.0

      Analysis API

      • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
      • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
      • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
      • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

      Analysis API. Code Compilation

      • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

      Analysis API. FIR

      • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
      • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
      • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
      • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
      • KT-84596 Improve K2 Jooq completion performance
      • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
      • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
      • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
      • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
      • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

      Analysis API. Infrastructure

      Fixes

      • KT-83905 Analysis API: Improve UX with test data
      • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
      • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
      • KT-84776 The test data manager misses the redundancy check in the update mode
      • KT-84962 The test data manager misses -ea flag
      • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
      • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
      • KT-84279 Test Data Manager fails on a clean build
      • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
      • KT-80379 Extract per-module test generators for AA tests
      • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
      • KT-83200 Track external dependencies of the Analysis API modules

      Analysis API. Light Classes

      • KT-82434 Light classes should prefer enum entries to properties
      • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
      • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

      Analysis API. PSI

      ... (truncated)

      Commits
      • add726c Add ChangeLog for 2.4.0-RC2
      • 69a4a81 [Wasm] Add binaryen per-file arguments
      • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
      • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
      • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
      • 13d25e2 KT-86268: Regression test added
      • f7d1a76 [JKlib] Fix JAR deserializer configuration.
      • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
      • ef14611 Make the default stability of non-final classes Unknown instead of Stable
      • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
      • Additional commits viewable in compare view

      Updates `org.jetbrains.kotlin:kotlin-serialization` from 2.3.21 to 2.4.0
      Release notes

      Sourced from org.jetbrains.kotlin:kotlin-serialization's releases.

      Kotlin 2.4.0

      Changelog

      Analysis API

      • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
      • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
      • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
      • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

      Analysis API. Code Compilation

      • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

      Analysis API. FIR

      • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
      • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
      • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
      • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
      • KT-84596 Improve K2 Jooq completion performance
      • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
      • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
      • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
      • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
      • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

      Analysis API. Infrastructure

      Fixes

      • KT-83905 Analysis API: Improve UX with test data
      • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
      • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
      • KT-84776 The test data manager misses the redundancy check in the update mode
      • KT-84962 The test data manager misses -ea flag
      • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
      • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
      • KT-84279 Test Data Manager fails on a clean build
      • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
      • KT-80379 Extract per-module test generators for AA tests
      • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
      • KT-83200 Track external dependencies of the Analysis API modules

      Analysis API. Light Classes

      • KT-82434 Light classes should prefer enum entries to properties
      • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
      • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

      ... (truncated)

      Changelog

      Sourced from org.jetbrains.kotlin:kotlin-serialization's changelog.

      2.4.0

      Analysis API

      • KT-83867 OVERLOAD_RESOLUTION_AMBIGUITY false positive with assertEquals in IJ repo
      • KT-83723 [Analysis API] Enable experimental KDoc resolver by default
      • KT-83388 Analysis API: properly support KMP in KotlinPackageProvider
      • KT-65683 Analysis API: Dangling file session creation causes a computeIfAbsent contract violation

      Analysis API. Code Compilation

      • KT-78946 Evaluation of variable with local class in type parameter leads to InventNamesForLocalClasses exception

      Analysis API. FIR

      • KT-68260 K2 AA: InvalidFirElementTypeException “For CALLABLE_REFERENCE_EXPRESSION with text ::lam1, unexpected element of type: no element found” with illegal callable reference call
      • KT-70896 AA: False positive deprecation warning with override of built-in method in JDK mapped class
      • KT-84711 K2 IDE sometimes loses FIR plugin-generated declarations after file changes
      • KT-84625 Analysis API: collectDesignationPath fails for nested classes inside plugin-generated top-level classes
      • KT-84596 Improve K2 Jooq completion performance
      • KT-84525 KaValueParameterSymbol#getHasSynthesizedName returns false for FirDeclarationOrigin.SubstitutionOverride.DeclarationSite
      • KT-83546 Kotlin analysis reach ClsCustomNavigationPolicy
      • KT-84259 Move CommonDefaultImportsProvider to the frontend independent module
      • KT-82945 Analysis API: KotlinIllegalArgumentExceptionWithAttachments: Expected FirResolvedTypeRef with ConeKotlinType but was FirUserTypeRefImpl
      • KT-71135 AA: exception from sealed inheritors checker when analyzeCopy

      Analysis API. Infrastructure

      Fixes

      • KT-83905 Analysis API: Improve UX with test data
      • KT-84913 Extract compiler classes used by the PSI & Analysis API to a separate module
      • KT-64986 Analysis API: Implement Analysis API tests for different KMP Platforms
      • KT-84776 The test data manager misses the redundancy check in the update mode
      • KT-84962 The test data manager misses -ea flag
      • KT-84388 Preserve the EOF status in the test data manager to avoid extra changes
      • KT-84362 Analysis API tests produce many warnings due to "not yet loaded registry"
      • KT-84279 Test Data Manager fails on a clean build
      • KT-83913 Exclude compiler-based Analysis API tests from Git tracking
      • KT-80379 Extract per-module test generators for AA tests
      • KT-84120 Move CLI modules out of kotlin-compiler-fe10-for-ide
      • KT-83200 Track external dependencies of the Analysis API modules

      Analysis API. Light Classes

      • KT-82434 Light classes should prefer enum entries to properties
      • KT-84200 SLC: return type is not boxed for delegated methods with generic original method
      • KT-72451 "CCE: class PsiPrimitiveType cannot be cast to class PsiClassType" with same-named enum class and typealias

      Analysis API. PSI

      ... (truncated)

      Commits
      • add726c Add ChangeLog for 2.4.0-RC2
      • 69a4a81 [Wasm] Add binaryen per-file arguments
      • 8907c63 [KGP] Suppress duplicate compiler warning output when --warning-mode=all is a...
      • f9bef12 [KGP] Add failing test for duplicate compiler warning output via Problems API
      • 7fe49c2 KT-86268: Use 2.4.0 toolchain for abiValidation with older CVs
      • 13d25e2 KT-86268: Regression test added
      • f7d1a76 [JKlib] Fix JAR deserializer configuration.
      • 5cec663 [JKlib] Wire up JvmBuiltInClassDescriptorFactory
      • ef14611 Make the default stability of non-final classes Unknown instead of Stable
      • d76473a [Gradle] Fix GeneralNativeIT.shouldAllowToOverrideDownloadUrl test failures
      • Additional commits viewable in compare view

      --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: devcrocod --- README.md | 2 +- gradle/libs.versions.toml | 2 +- kotlin-sdk-core/api/kotlin-sdk-core.api | 32 ++++++++++++------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 58a2cad..aefadcf 100644 --- a/README.md +++ b/README.md @@ -729,7 +729,7 @@ val client = Client( ) client.setRequestHandler(Method.Defined.SamplingCreateMessage) { request, _ -> - val content = request.messages.lastOrNull()?.content + val content = request.messages.lastOrNull()?.content?.firstOrNull() val prompt = if (content is TextContent) content.text else "your topic" CreateMessageResult( model = "gpt-4o-mini", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 592fa25..e7f4683 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ atomicfu = "0.33.0" binaryCompatibilityValidatorPlugin = "0.18.1" detekt = "2.0.0-alpha.5" dokka = "2.2.0" -kotlin = "2.3.21" +kotlin = "2.4.0" kover = "0.9.8" ktlint = "14.2.0" knit = "0.5.1" diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index cdee342..1935e9a 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -415,7 +415,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequestBuild public final fun arguments (Lkotlin/jvm/functions/Function1;)V public final fun arguments (Lkotlinx/serialization/json/JsonObject;)V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getName ()Ljava/lang/String; public final fun setName (Ljava/lang/String;)V } @@ -954,7 +954,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CompleteRequestBuild public fun ()V public final fun argument (Ljava/lang/String;Ljava/lang/String;)V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/CompleteRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun context (Ljava/util/Map;)V public final fun context (Lkotlin/jvm/functions/Function1;)V public final fun ref (Lio/modelcontextprotocol/kotlin/sdk/types/Reference;)V @@ -1188,7 +1188,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getContext ()Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext; public final fun getMaxTokens ()Ljava/lang/Integer; public final fun getStopSequences ()Ljava/util/List; @@ -1455,7 +1455,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitRequest$Compan public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ElicitRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getMessage ()Ljava/lang/String; public final fun requestedSchema (Lio/modelcontextprotocol/kotlin/sdk/types/ElicitRequestParams$RequestedSchema;)V public final fun requestedSchema (Lkotlin/jvm/functions/Function1;)V @@ -1833,7 +1833,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/GetPromptRequest$Com public final class io/modelcontextprotocol/kotlin/sdk/types/GetPromptRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getArguments ()Ljava/util/Map; public final fun getName ()Ljava/lang/String; public final fun setArguments (Ljava/util/Map;)V @@ -2278,7 +2278,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/InitializeRequest$Co public final class io/modelcontextprotocol/kotlin/sdk/types/InitializeRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/InitializeRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun capabilities (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;)V public final fun capabilities (Lkotlin/jvm/functions/Function1;)V public final fun getProtocolVersion ()Ljava/lang/String; @@ -2668,7 +2668,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListPromptsRequest$C public final class io/modelcontextprotocol/kotlin/sdk/types/ListPromptsRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/PaginatedRequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ListPromptsRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; } public final class io/modelcontextprotocol/kotlin/sdk/types/ListPromptsResult : io/modelcontextprotocol/kotlin/sdk/types/PaginatedResult, io/modelcontextprotocol/kotlin/sdk/types/ServerResult { @@ -2739,7 +2739,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourceTemplate public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourceTemplatesRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/PaginatedRequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ListResourceTemplatesRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; } public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourceTemplatesResult : io/modelcontextprotocol/kotlin/sdk/types/PaginatedResult, io/modelcontextprotocol/kotlin/sdk/types/ServerResult { @@ -2810,7 +2810,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourcesRequest public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourcesRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/PaginatedRequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ListResourcesRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; } public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourcesResult : io/modelcontextprotocol/kotlin/sdk/types/PaginatedResult, io/modelcontextprotocol/kotlin/sdk/types/ServerResult { @@ -2880,7 +2880,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListRootsRequest$Com public final class io/modelcontextprotocol/kotlin/sdk/types/ListRootsRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ListRootsRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; } public final class io/modelcontextprotocol/kotlin/sdk/types/ListRootsResult : io/modelcontextprotocol/kotlin/sdk/types/ClientResult { @@ -3014,7 +3014,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListToolsRequest$Com public final class io/modelcontextprotocol/kotlin/sdk/types/ListToolsRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/PaginatedRequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ListToolsRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; } public final class io/modelcontextprotocol/kotlin/sdk/types/ListToolsResult : io/modelcontextprotocol/kotlin/sdk/types/PaginatedResult, io/modelcontextprotocol/kotlin/sdk/types/ServerResult { @@ -3440,7 +3440,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/PingRequest$Companio public final class io/modelcontextprotocol/kotlin/sdk/types/PingRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/PingRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; } public final class io/modelcontextprotocol/kotlin/sdk/types/PingRequest_dslKt { @@ -3791,7 +3791,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ReadResourceRequest$ public final class io/modelcontextprotocol/kotlin/sdk/types/ReadResourceRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/ReadResourceRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getUri ()Ljava/lang/String; public final fun setUri (Ljava/lang/String;)V } @@ -4754,7 +4754,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/SetLevelRequest$Comp public final class io/modelcontextprotocol/kotlin/sdk/types/SetLevelRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/SetLevelRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getLoggingLevel ()Lio/modelcontextprotocol/kotlin/sdk/types/LoggingLevel; public final fun setLoggingLevel (Lio/modelcontextprotocol/kotlin/sdk/types/LoggingLevel;)V } @@ -4920,7 +4920,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/SubscribeRequest$Com public final class io/modelcontextprotocol/kotlin/sdk/types/SubscribeRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/SubscribeRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getUri ()Ljava/lang/String; public final fun setUri (Ljava/lang/String;)V } @@ -5688,7 +5688,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/UnsubscribeRequest$C public final class io/modelcontextprotocol/kotlin/sdk/types/UnsubscribeRequestBuilder : io/modelcontextprotocol/kotlin/sdk/types/RequestBuilder { public fun ()V public fun build ()Lio/modelcontextprotocol/kotlin/sdk/types/UnsubscribeRequest; - public synthetic fun build$kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; + public synthetic fun build$io_modelcontextprotocol_kotlin_sdk_core ()Lio/modelcontextprotocol/kotlin/sdk/types/Request; public final fun getUri ()Ljava/lang/String; public final fun setUri (Ljava/lang/String;)V } From 19091d35284316f69a0f7505ddb27e5cabf57186 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 12:13:30 +0200 Subject: [PATCH 086/178] chore(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.5.0 to 0.5.1 in the kotlinx group (#873) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotlinx group with 1 update: [org.jetbrains.kotlinx:kotlinx-collections-immutable](https://github.com/Kotlin/kotlinx.collections.immutable). Updates `org.jetbrains.kotlinx:kotlinx-collections-immutable` from 0.5.0 to 0.5.1
      Release notes

      Sourced from org.jetbrains.kotlinx:kotlinx-collections-immutable's releases.

      v0.5.1

      • Fixed PersistentOrderedMapBuilder returning a previously built map from build() after updating an entry value through MutableMap.MutableEntry.setValue #253, #274
      • Fixed an assertion failure in PersistentOrderedSetBuilder.build() after interleaved build and remove/removeAll calls #251
      • Provided a JPMS module descriptor for the JVM artifact — module kotlinx.collections.immutable compiled into META-INF/versions/9, the artifact stays Java 8-compatible #268

      Full changelog: https://github.com/Kotlin/kotlinx.collections.immutable/compare/v0.5.0...v0.5.1

      Changelog

      Sourced from org.jetbrains.kotlinx:kotlinx-collections-immutable's changelog.

      0.5.1

      • Fixed PersistentOrderedMapBuilder returning a previously built map from build() after updating an entry value through MutableMap.MutableEntry.setValue #253, #274
      • Fixed an assertion failure in PersistentOrderedSetBuilder.build() after interleaved build and remove/removeAll calls #251
      • Provided a JPMS module descriptor for the JVM artifact — module kotlinx.collections.immutable compiled into META-INF/versions/9, the artifact stays Java 8-compatible #268
      Commits
      • ad741d1 Release v0.5.1
      • cb4cf67 Applied artifacts validator plugin (#271)
      • e9ca796 Restore the direct links write in the ordered map builder entry (#274)
      • 6822eed Fix the pull request exclusion in the VCS trigger branch filter (#276)
      • 8201f28 Surface pull request branches on CI for manually started builds (#273)
      • f3dec4f Fix ordered set builder cache after removeAll (#251)
      • 96bf012 Provide a JPMS module descriptor for the JVM artifact (#268)
      • 81382a1 Migrate ABI validation to the Kotlin Gradle plugin (#264)
      • 694d34b Invalidate ordered map builder after entry value updates (#253)
      • 1d6fda3 Fix the method-rename examples in the 0.5.0 changelog entry (#266)
      • See full diff in compare view

      [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.jetbrains.kotlinx:kotlinx-collections-immutable&package-manager=gradle&previous-version=0.5.0&new-version=0.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
      Dependabot commands and options
      You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
      Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e7f4683..0d9b5de 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ netty = "4.2.15.Final" # libraries version awaitility = "4.3.0" -collections-immutable = "0.5.0" +collections-immutable = "0.5.1" coroutines = "1.11.0" kotest = "6.2.1" kotlinx-io = "0.9.1" From ea3940ce477c9672b43447b9aedaa9fd98612df5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 12:39:14 +0200 Subject: [PATCH 087/178] chore(deps): bump io.modelcontextprotocol:kotlin-sdk-client from 0.13.0 to 0.14.0 in /samples/kotlin-mcp-client (#875) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.modelcontextprotocol:kotlin-sdk-client](https://github.com/modelcontextprotocol/kotlin-sdk) from 0.13.0 to 0.14.0.
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index b5167d9..fab3459 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -2,7 +2,7 @@ anthropic = "2.45.0" kotlin = "2.4.0" ktor = "3.5.1" -mcp-kotlin = "0.13.0" +mcp-kotlin = "0.14.0" shadow = "9.4.3" slf4j = "2.0.18" From 04e6d56fd6c5df0dea86cea303b121f3dd3d7ef0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:28:48 +0200 Subject: [PATCH 088/178] chore(deps): bump mcp-kotlin from 0.13.0 to 0.14.0 in /samples/kotlin-mcp-server (#876) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.13.0 to 0.14.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.13.0 to 0.14.0
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.13.0 to 0.14.0
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 5a6217e..6c6ff89 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.4.0" ktor = "3.5.1" -mcp-kotlin = "0.13.0" +mcp-kotlin = "0.14.0" slf4j = "2.0.18" shadow = "9.4.3" From 14c848db417b4c884990af2ce69d1a8bac6e40a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:29:15 +0200 Subject: [PATCH 089/178] chore(deps): bump mcp-kotlin from 0.13.0 to 0.14.0 in /samples/kotlinlang-mcp-server (#877) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.13.0 to 0.14.0. Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.13.0 to 0.14.0
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.13.0 to 0.14.0
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Updates `io.modelcontextprotocol:kotlin-sdk-testing` from 0.13.0 to 0.14.0
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index c521eba..766b5ab 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.4.0" ktor = "3.5.1" -mcp-kotlin = "0.13.0" +mcp-kotlin = "0.14.0" serialization = "1.11.0" coroutines = "1.11.0" logback = "1.5.37" From 7ea602a5bf259379c027c315e08b94269db0340e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:29:38 +0200 Subject: [PATCH 090/178] chore(deps): bump mcp-kotlin from 0.13.0 to 0.14.0 in /samples/simple-streamable-server (#878) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.13.0 to 0.14.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.13.0 to 0.14.0
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.13.0 to 0.14.0
      Commits
      • fc7916f release: 0.14.0 (#867)
      • 57e546d feat: SEP-1686 Tasks (#844)
      • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
      • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
      • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
      • 0221b8d fix(client): close stdio read sources during shutdown (#798)
      • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
      • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
      • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
      • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
      • Additional commits viewable in compare view

      Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index e3f8f6a..21db581 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.4.0" ktor = "3.5.1" junit = "6.1.1" -mcp-kotlin = "0.13.0" +mcp-kotlin = "0.14.0" slf4j = "2.0.18" shadow = "9.4.3" From 91f7390a95dc7265b1202ad5226aaa8fd1d348a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 14:09:53 +0200 Subject: [PATCH 091/178] chore(deps): bump the other-dependencies group across 5 directories with 2 updates (#882) Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java) and [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 1 update in the /samples/kotlinlang-mcp-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 1 update in the /samples/weather-stdio-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Updates `com.anthropic:anthropic-java` from 2.45.0 to 2.48.0
      Release notes

      Sourced from com.anthropic:anthropic-java's releases.

      v2.48.0

      2.48.0 (2026-07-02)

      Full Changelog: v2.47.1...v2.48.0

      Features

      • api: add agent-memory-2026-07-22 beta header (6603879)

      v2.47.1

      2.47.1 (2026-07-01)

      Full Changelog: v2.47.0...v2.47.1

      Chores

      • api: remove some nonfunctional types from the SDKs (2f92a48)

      v2.47.0

      2.47.0 (2026-06-30)

      Full Changelog: v2.46.0...v2.47.0

      Features

      • api: add support for Managed Agents event delta streaming, agent overrides, reverse pagination, vault credential injection scoping, and agent and deployment webhook events (5eed04b)

      v2.46.0

      2.46.0 (2026-06-30)

      Full Changelog: v2.45.0...v2.46.0

      Features

      • api: add support for claude-sonnet-5 (444f054)
      Changelog

      Sourced from com.anthropic:anthropic-java's changelog.

      2.48.0 (2026-07-02)

      Full Changelog: v2.47.1...v2.48.0

      Features

      • api: add agent-memory-2026-07-22 beta header (6603879)

      2.47.1 (2026-07-01)

      Full Changelog: v2.47.0...v2.47.1

      Chores

      • api: remove some nonfunctional types from the SDKs (2f92a48)

      2.47.0 (2026-06-30)

      Full Changelog: v2.46.0...v2.47.0

      Features

      • api: add support for Managed Agents event delta streaming, agent overrides, reverse pagination, vault credential injection scoping, and agent and deployment webhook events (5eed04b)

      2.46.0 (2026-06-30)

      Full Changelog: v2.45.0...v2.46.0

      Features

      • api: add support for claude-sonnet-5 (444f054)
      Commits
      • db3e617 release: 2.48.0
      • a462333 feat(api): add agent-memory-2026-07-22 beta header
      • 3c6c77b release: 2.47.1
      • 0d315e6 chore(api): remove some nonfunctional types from the SDKs
      • 2093447 release: 2.47.0
      • 4bf9078 feat(api): add support for Managed Agents event delta streaming, agent overri...
      • 1c9486b codegen metadata
      • fab7574 release: 2.46.0
      • f0b5297 feat(api): add support for claude-sonnet-5
      • See full diff in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in compare view

      Updates `com.gradleup.shadow` from 9.4.3 to 9.5.1
      Release notes

      Sourced from com.gradleup.shadow's releases.

      9.5.1

      Fixed

      • Fix eager calls for toolchainSpec in Kotlin DSL.
        This fixes the regression when using toolchain without targetCompatibility in Kotlin DSL.

      9.5.0

      Added

      • Check DuplicatesStrategy for merging transformers. (#2026)
        This will log warnings when an incompatible DuplicatesStrategy (e.g., EXCLUDE) is applied in Gradle configuration for built-in ResourceTransformers.
      • Add KotlinModuleMetadataTransformer. (#2073)
      • Add R8 as an opt-in minimize { r8 { ... } } tool for shrinking the final shadowed JAR. (#2077)

      Changed

      • Bump min Gradle requirement to 9.2.0. (#2057)
      • Remove afterEvaluate when adding variants. (#2056)
      • Deprecate enableKotlinModuleRemapping for ShadowJar. (#2073)
        Apply KotlinModuleMetadataTransformer explicitly to support relocating inside Kotlin module metadata files.
      • Deprecate everything under ShadowCopyAction. (#2083)

      Fixed

      • Fix the conflicts when using afterEvaluate with other plugins. (#2055)
      Commits
      • c33612d Prepare version 9.5.1
      • 485e412 Fix eager calls for toolchainSpec in Kotlin DSL (#2087)
      • d062fa2 Fix DuplicatesStrategyCheckerTest resource loading on Windows (#2085)
      • e71a2c1 Add description for shadow configuration (#2084)
      • 7ba43b0 Prepare next development version
      • 6e00cb7 Prepare version 9.5.0
      • ca03909 Deprecate everything under ShadowCopyAction (#2083)
      • 7d7da27 Revert "Mark CONSTANT_TIME_FOR_ZIP_ENTRIES as const (#2074)"
      • da18cc0 Deprecate enableKotlinModuleRemapping for ShadowJar (#2073)
      • ec6e55a Replace system properties with buildConfig consts (#2082)
      • Additional commits viewable in Date: Mon, 6 Jul 2026 14:39:33 +0200 Subject: [PATCH 092/178] chore(deps): bump mcp-kotlin from 0.13.0 to 0.14.0 in /samples/weather-stdio-server (#879) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.13.0 to 0.14.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.13.0 to 0.14.0
        Commits
        • fc7916f release: 0.14.0 (#867)
        • 57e546d feat: SEP-1686 Tasks (#844)
        • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
        • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
        • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
        • 0221b8d fix(client): close stdio read sources during shutdown (#798)
        • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
        • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
        • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
        • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
        • Additional commits viewable in compare view

        Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.13.0 to 0.14.0
        Commits
        • fc7916f release: 0.14.0 (#867)
        • 57e546d feat: SEP-1686 Tasks (#844)
        • 35da063 fix: bound request body size in SSE and Streamable HTTP transports (#839)
        • bbf77ba chore(deps): bump @​types/node from 26.0.0 to 26.0.1 in /integration-test/src/...
        • d2b1509 chore(deps): bump the other-dependencies group across 5 directories with 5 up...
        • 0221b8d fix(client): close stdio read sources during shutdown (#798)
        • 19db4b0 fix(client): gate completion/complete on the completions capability (#846)
        • 64cf29f chore(deps): bump gradle-wrapper from 9.6.0 to 9.6.1 (#856)
        • cd91652 fix: validate Origin against localhost by default in DNS rebinding protection...
        • 4103b87 chore(deps): bump org.jetbrains.kotlinx:kotlinx-io-core from 0.9.0 to 0.9.1 i...
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index ee81756..67fec97 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ coroutines = "1.11.0" kotlin = "2.4.0" ktor = "3.5.1" logging = "8.0.4" -mcp-kotlin = "0.13.0" +mcp-kotlin = "0.14.0" shadow = "9.5.1" slf4j = "2.0.18" From 905d4f975e415a1113922465ef8013d9eedfdb21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 13:00:40 +0000 Subject: [PATCH 093/178] chore(deps): bump the all-dependencies group across 1 directory with 2 updates (#880) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 2 updates in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [tsx](https://github.com/privatenumber/tsx). Updates `@types/node` from 26.0.1 to 26.1.0
        Commits

        Updates `tsx` from 4.22.4 to 4.23.0
        Release notes

        Sourced from tsx's releases.

        v4.23.0

        4.23.0 (2026-07-03)

        Bug Fixes

        Features


        This release is also available on:

        v4.22.5

        4.22.5 (2026-07-02)

        Bug Fixes

        • isolate hook state per async module.register() registration (a305f36)

        This release is also available on:

        Commits
        • 1dfad37 docs: cite esbuild's extension-resolution model in node notes
        • 257bbbb fix: avoid redundant filesystem probes during module resolution
        • c178197 feat: add multi-scenario startup benchmark suite
        • 51800ac docs: add Node internals knowledge base (notes/node)
        • a305f36 fix: isolate hook state per async module.register() registration
        • ca501a9 chore: upgrade skills-npm to v1.2.0
        • 596cd1f test: cover __dirname, __filename, & require.cache in CJS TS file
        • 75d9bf0 test: lock in lenient ESM for ambiguous and CJS-typed packages
        • 1472f3e test: cover ESM-syntax dependency with omitted "type" field
        • See full diff in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 16 ++++++++-------- .../src/jvmTest/typescript/package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index befd50e..4d0c500 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,9 +15,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.0.1", + "@types/node": "^26.1.0", "cors": "^2.8.6", - "tsx": "^4.22.4", + "tsx": "^4.23.0", "typescript": "^6.0.3" } }, @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.1.tgz", - "integrity": "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.0.tgz", + "integrity": "sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==", "dev": true, "license": "MIT", "dependencies": { @@ -1680,9 +1680,9 @@ } }, "node_modules/tsx": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", - "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.0.tgz", + "integrity": "sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index aa8d9db..bf81140 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,9 +16,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.0.1", + "@types/node": "^26.1.0", "cors": "^2.8.6", - "tsx": "^4.22.4", + "tsx": "^4.23.0", "typescript": "^6.0.3" } } From 7937390b4787f758c82c369541374d050fbdcd9b Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Thu, 9 Jul 2026 17:03:01 +0200 Subject: [PATCH 094/178] test: create the server session before connecting the client (#885) `ChannelTransportTest` connected both sides concurrently, which is racy. `ChannelTransport` starts delivering inbound messages when its read loop launches, which happens before `start()` marks the transport `Operational`. The two run on different dispatchers, so the client's `initialize` could reach the server read loop first and the session's `InitializeResult` was then rejected by the send state gate with `Transport is not ready`. Measured ~3 failures in 600 rounds. `createSession()` does not await the handshake, so creating the session first is enough to order the two. This also matches the usage shown in `createLinkedPair()`'s KDoc. Not addressed here: the transport itself should not deliver inbound messages before it is `Operational`. Fixing that needs a post-`Operational` hook on `AbstractClientTransport` that the read loop awaits. --- .../kotlin/sdk/testing/ChannelTransportTest.kt | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/testing/ChannelTransportTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/testing/ChannelTransportTest.kt index ea246db..4d798ce 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/testing/ChannelTransportTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/testing/ChannelTransportTest.kt @@ -6,7 +6,6 @@ import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi import io.modelcontextprotocol.kotlin.sdk.client.Client import io.modelcontextprotocol.kotlin.sdk.server.Server import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions -import io.modelcontextprotocol.kotlin.sdk.server.ServerSession import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest import io.modelcontextprotocol.kotlin.sdk.types.InitializeResult @@ -16,9 +15,6 @@ import io.modelcontextprotocol.kotlin.sdk.types.ListResourcesResult import io.modelcontextprotocol.kotlin.sdk.types.Method import io.modelcontextprotocol.kotlin.sdk.types.Resource import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.joinAll -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlin.test.Test @@ -43,18 +39,9 @@ class ChannelTransportTest { clientInfo = Implementation(name = "test client", version = "1.0"), ) - val serverSessionResult = CompletableDeferred() + val serverSession = server.createSession(serverTransport) + client.connect(clientTransport) - listOf( - launch { - client.connect(clientTransport) - }, - launch { - serverSessionResult.complete(server.createSession(serverTransport)) - }, - ).joinAll() - - val serverSession = serverSessionResult.await() serverSession.setRequestHandler(Method.Defined.Initialize) { _, _ -> InitializeResult( protocolVersion = LATEST_PROTOCOL_VERSION, From beb340006498a73f83205e431344c0ff70687984 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Wed, 15 Jul 2026 12:33:29 +0200 Subject: [PATCH 095/178] feat(core): concurrent inbound dispatch behind an initialization gate (#884) Make inbound message handling concurrent after the initialization handshake, so a slow or peer-awaiting handler no longer blocks other messages on the same connection fixes #176, #572 ## Motivation and Context Inbound messages were processed serially on the transport read loop. One slow or peer-awaiting request handler (sampling, elicitation, roots) blocked every later message on that connection, including the responses and `notifications/cancelled` those handlers depend on which could deadlock request/response flows. ## How Has This Been Tested? New and old tests ## Breaking Changes - after the handshake, inbound handlers may run concurrently (processing stays serial during initialization). There is no opt-out flag by design, concurrency is bounded by `maxConcurrentHandlers` / `maxInFlightHandlers`. - `ProtocolOptions` / `ClientOptions` / `ServerOptions` gain new parameters with defaults - `RequestHandlerExtra` is now a coroutine-context element and is no longer user-constructible ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../kotlin/sdk/client/ClientTest.kt | 38 +- .../ProtocolConcurrencyIntegrationTest.kt | 306 ++++++++++ .../sdk/server/ClientConnectionLoggingTest.kt | 22 +- .../sdk/server/ServerSessionInitializeTest.kt | 2 + kotlin-sdk-client/api/kotlin-sdk-client.api | 4 +- .../kotlin/sdk/client/Client.kt | 10 +- kotlin-sdk-core/api/kotlin-sdk-core.api | 21 +- .../kotlin/sdk/shared/Protocol.kt | 569 +++++++++++++++--- .../kotlin/sdk/types/methods.kt | 9 + .../kotlin/sdk/types/serializers.kt | 9 +- .../sdk/shared/ProtocolConcurrencyTest.kt | 524 ++++++++++++++++ .../kotlin/sdk/shared/ProtocolOptionsTest.kt | 16 + .../ProtocolOutboundCancellationTest.kt | 167 +++++ .../kotlin/sdk/shared/ProtocolTest.kt | 197 ++++-- .../kotlin/sdk/shared/ProtocolTestFakes.kt | 112 ++++ .../sdk/shared/ProtocolConcurrencyJvmTest.kt | 114 ++++ kotlin-sdk-server/api/kotlin-sdk-server.api | 5 +- .../kotlin/sdk/server/Server.kt | 9 +- .../kotlin/sdk/server/ServerSession.kt | 8 + .../server/StreamableHttpServerTransport.kt | 191 +++++- .../StreamableHttpServerTransportTest.kt | 326 ++++++++++ 21 files changed, 2465 insertions(+), 194 deletions(-) create mode 100644 integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ProtocolConcurrencyIntegrationTest.kt create mode 100644 kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyTest.kt create mode 100644 kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOptionsTest.kt create mode 100644 kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOutboundCancellationTest.kt create mode 100644 kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTestFakes.kt create mode 100644 kotlin-sdk-core/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyJvmTest.kt diff --git a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt index 5dfcf61..54d25ee 100644 --- a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt +++ b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt @@ -24,6 +24,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest import io.modelcontextprotocol.kotlin.sdk.types.InitializeResult import io.modelcontextprotocol.kotlin.sdk.types.IntegerSchema import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION @@ -52,6 +53,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.UntitledSingleSelectEnumSchema import io.modelcontextprotocol.kotlin.sdk.types.UrlElicitationRequiredException import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.cancel import kotlinx.coroutines.delay import kotlinx.coroutines.joinAll @@ -71,6 +73,7 @@ import kotlin.test.assertIs import kotlin.test.assertNull import kotlin.test.assertTrue import kotlin.test.fail +import kotlin.time.Duration.Companion.seconds class ClientTest { @Test @@ -543,6 +546,15 @@ class ClientTest { val serverSession = serverSessionResult.await() + // Register the tap after createSession so it chains onto the session's subscription instead + // of pre-empting the handshake. + val cancelledOnWire = CompletableDeferred() + serverTransport.onMessage { message -> + if (message is JSONRPCNotification && message.method == Method.Defined.NotificationsCancelled.value) { + cancelledOnWire.complete(Unit) + } + } + serverSession.setRequestHandler(Method.Defined.ResourcesList) { _, _ -> // Simulate delay def.complete(Unit) @@ -568,6 +580,7 @@ class ClientTest { def.await() runCatching { job.cancel("Cancelled by test") } defCancel.await() + cancelledOnWire.await() defTimeOut.await() } @@ -606,17 +619,9 @@ class ClientTest { val serverSession = serverSessionResult.await() serverSession.setRequestHandler(Method.Defined.ResourcesList) { _, _ -> - // Simulate a delayed response - // Wait ~100ms unless canceled - try { - withTimeout(100L) { - // Just delay here, if timeout is 0 on the client side, this won't return in time - delay(100) - } - } catch (_: Exception) { - // If aborted, just rethrow or return early - } - ListResourcesResult(resources = emptyList()) + // Never respond: the handler runs on a real dispatcher while the 1 ms timeout runs on the + // virtual test clock, so a real-time delay could race it. Parking keeps the test deterministic. + awaitCancellation() } // Request with 1 msec timeout should fail immediately @@ -895,8 +900,8 @@ class ClientTest { ), ) - // Track notifications - var rootListChangedNotificationReceived = false + // The handler runs on Dispatchers.Default after concurrent dispatch is enabled; await the deferred. + val rootListChangedReceived = CompletableDeferred() val serverSessionResult = CompletableDeferred() @@ -915,16 +920,13 @@ class ClientTest { serverSession.setNotificationHandler( Method.Defined.NotificationsRootsListChanged, ) { - rootListChangedNotificationReceived = true + rootListChangedReceived.complete(Unit) CompletableDeferred(Unit) } client.sendRootsListChanged() - assertTrue( - rootListChangedNotificationReceived, - "Notification should be sent when sendRootsListChanged is called", - ) + withTimeout(5.seconds) { rootListChangedReceived.await() } } @Test diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ProtocolConcurrencyIntegrationTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ProtocolConcurrencyIntegrationTest.kt new file mode 100644 index 0000000..d8d64ec --- /dev/null +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/ProtocolConcurrencyIntegrationTest.kt @@ -0,0 +1,306 @@ +package io.modelcontextprotocol.kotlin.sdk.integration + +import io.kotest.matchers.shouldBe +import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi +import io.modelcontextprotocol.kotlin.sdk.client.Client +import io.modelcontextprotocol.kotlin.sdk.client.ClientOptions +import io.modelcontextprotocol.kotlin.sdk.server.Server +import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions +import io.modelcontextprotocol.kotlin.sdk.server.ServerSession +import io.modelcontextprotocol.kotlin.sdk.shared.InMemoryTransport +import io.modelcontextprotocol.kotlin.sdk.shared.currentRequestHandlerExtra +import io.modelcontextprotocol.kotlin.sdk.testing.ChannelTransport +import io.modelcontextprotocol.kotlin.sdk.types.CallToolRequest +import io.modelcontextprotocol.kotlin.sdk.types.CallToolRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.CallToolResult +import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.CreateMessageRequest +import io.modelcontextprotocol.kotlin.sdk.types.CreateMessageRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.CreateMessageResult +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.InitializedNotification +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCError +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse +import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION +import io.modelcontextprotocol.kotlin.sdk.types.ListRootsRequest +import io.modelcontextprotocol.kotlin.sdk.types.ListRootsResult +import io.modelcontextprotocol.kotlin.sdk.types.ListToolsRequest +import io.modelcontextprotocol.kotlin.sdk.types.ListToolsResult +import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.RequestId +import io.modelcontextprotocol.kotlin.sdk.types.Role +import io.modelcontextprotocol.kotlin.sdk.types.SamplingMessage +import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.TextContent +import io.modelcontextprotocol.kotlin.sdk.types.toJSON +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.CopyOnWriteArrayList +import java.util.concurrent.atomic.AtomicReference +import kotlin.coroutines.cancellation.CancellationException +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.time.Duration.Companion.seconds + +/** + * End-to-end tests for concurrent inbound dispatch enabled after the MCP handshake. + * + * Handlers run on a real [kotlinx.coroutines.Dispatchers.Default], so these use [runBlocking] with + * explicit [withTimeout] guards. A virtual test clock would false-fire timeouts against cross-thread + * real dispatchers. + */ +@OptIn(ExperimentalMcpApi::class) +class ProtocolConcurrencyIntegrationTest { + + private fun rootsClient(): Client = Client( + clientInfo = Implementation(name = "test client", version = "1.0"), + options = ClientOptions( + capabilities = ClientCapabilities(roots = ClientCapabilities.Roots(listChanged = null)), + ), + ) + + private fun toolsServer(): Server = Server( + serverInfo = Implementation(name = "test server", version = "1.0"), + options = ServerOptions( + capabilities = ServerCapabilities(tools = ServerCapabilities.Tools(listChanged = null)), + ), + ) + + // ChannelTransport delivers inbound messages as soon as its read loop starts, which is before + // start() marks it operational. Creating the session first keeps the client's initialize from + // landing on a transport that would reject the session's response. + private suspend fun connect( + client: Client, + clientTransport: ChannelTransport, + server: Server, + serverTransport: ChannelTransport, + ): ServerSession { + val serverSession = server.createSession(serverTransport) + client.connect(clientTransport) + return serverSession + } + + // The motivating deadlock over real serial read loops: a server tool handler makes a + // server-to-client request (roots/list) while still handling the client's tools/call. + @Test + fun `server tool handler can call roots list mid-handling without deadlock`() = runBlocking { + val client = rootsClient() + val server = toolsServer() + val (clientTransport, serverTransport) = ChannelTransport.createLinkedPair() + + val serverSession = connect(client, clientTransport, server, serverTransport) + + // Register the tools/call handler directly on the session so it can call back to the client + // mid-handling. Before concurrent dispatch this would deadlock: the server read loop is + // blocked by the tool handler and can never deliver the roots/list response. + serverSession.setRequestHandler(Method.Defined.ToolsCall) { _, _ -> + val roots = serverSession.request(ListRootsRequest()) + CallToolResult(content = listOf(TextContent(text = "roots=${roots.roots.size}"))) + } + + val result = withTimeout(10.seconds) { + client.callTool(CallToolRequest(CallToolRequestParams("needs-roots"))) + } + val text = (result as CallToolResult).content.filterIsInstance().single().text + text shouldBe "roots=0" + + client.close() + server.close() + } + + // Client-side mirror: a client sampling handler makes a client-to-server request (tools/list) + // while still handling the server's sampling/createMessage. + @Test + fun `client sampling handler can call the server mid-handling without deadlock`() = runBlocking { + val client = Client( + clientInfo = Implementation(name = "test client", version = "1.0"), + options = ClientOptions( + capabilities = ClientCapabilities(sampling = ClientCapabilities.Sampling()), + ), + ) + val server = toolsServer() + val (clientTransport, serverTransport) = ChannelTransport.createLinkedPair() + + client.setRequestHandler(Method.Defined.SamplingCreateMessage) { _, _ -> + val tools = client.request(ListToolsRequest()) + CreateMessageResult( + role = Role.Assistant, + content = TextContent(text = "tools=${tools.tools.size}"), + model = "test-model", + ) + } + + val serverSession = connect(client, clientTransport, server, serverTransport) + + val result = withTimeout(10.seconds) { + serverSession.request( + CreateMessageRequest( + CreateMessageRequestParams( + maxTokens = 100, + messages = listOf(SamplingMessage(role = Role.User, content = TextContent(text = "hi"))), + ), + ), + ) + } + val text = result.content.filterIsInstance().single().text + text shouldBe "tools=0" + + client.close() + server.close() + } + + // Nested-cancel cascade: cancelling the client's tools/call must reach the server tool handler + // over the wire and cascade into its nested roots/list request, cancelling the parked + // client-side roots handler. No tools/call response is ever sent. + @Test + fun `cancelling a tool call cascades into its nested roots list request`() = runBlocking { + val client = rootsClient() + val server = toolsServer() + val (clientTransport, serverTransport) = ChannelTransport.createLinkedPair() + + val capturedToolCallId = AtomicReference(null) + val toolHandlerCancelled = CompletableDeferred() + val rootsHandlerEntered = CompletableDeferred() + val rootsHandlerCancelled = CompletableDeferred() + val parkForever = CompletableDeferred() + val unexpectedToolCallResponse = CompletableDeferred() + + // Tap the server->client direction (client transport inbound) to prove no tools/call + // response is ever delivered once the call is cancelled. + clientTransport.onMessage { message -> + if (message is JSONRPCResponse && message.id == capturedToolCallId.get()) { + unexpectedToolCallResponse.complete(Unit) + } + } + + val serverSession = connect(client, clientTransport, server, serverTransport) + + // Client roots handler parks until cancelled and records the cancellation. + client.setRequestHandler(Method.Defined.RootsList) { _, _ -> + rootsHandlerEntered.complete(Unit) + try { + parkForever.await() + } catch (e: CancellationException) { + rootsHandlerCancelled.complete(e) + throw e + } + } + + // Tool handler makes a nested server->client request and records its own cancellation. + serverSession.setRequestHandler(Method.Defined.ToolsCall) { _, _ -> + val extra = currentRequestHandlerExtra()!! + capturedToolCallId.set(extra.requestId) + try { + extra.sendRequest(ListRootsRequest()) + } catch (e: CancellationException) { + toolHandlerCancelled.complete(e) + throw e + } + CallToolResult(content = listOf(TextContent(text = "unreachable"))) + } + + val call = launch { client.callTool(CallToolRequest(CallToolRequestParams("nested"))) } + + withTimeout(10.seconds) { rootsHandlerEntered.await() } + call.cancel(CancellationException("user aborted")) + + withTimeout(10.seconds) { toolHandlerCancelled.await() } + withTimeout(10.seconds) { rootsHandlerCancelled.await() } + + // The server suppresses the response for a cancelled request, so none is ever sent. + assertFalse( + unexpectedToolCallResponse.isCompleted, + "no tools/call response should be delivered after the call was cancelled", + ) + + client.close() + server.close() + } + + // Init gate plus context element in a high-level handler: initialize and tools/list are + // pipelined before notifications/initialized and answered serially in order. After the + // handshake a high-level addTool handler can observe currentRequestHandlerExtra(). + @Test + fun `pipelined initialize and tools list are processed serially then context element is available`(): Unit = + runBlocking { + val server = toolsServer() + server.addTool(name = "ctx-tool", description = "returns its request id") { + val extra = currentRequestHandlerExtra() + checkNotNull(extra) { "currentRequestHandlerExtra() must be non-null inside a tool handler" } + CallToolResult(content = listOf(TextContent(text = extra.requestId.asText()))) + } + + val (clientTransport, serverTransport) = InMemoryTransport.createLinkedPair() + + val arrivalOrder = CopyOnWriteArrayList() + val pending = ConcurrentHashMap>() + clientTransport.onMessage { message -> + val id = when (message) { + is JSONRPCResponse -> message.id + is JSONRPCError -> message.id + else -> null + } + if (id != null) { + arrivalOrder.add(id) + pending[id]?.complete(message) + } + } + + // Drive the client side manually over the raw transport. + server.createSession(serverTransport) + + val initRequest = InitializeRequest( + InitializeRequestParams( + protocolVersion = LATEST_PROTOCOL_VERSION, + capabilities = ClientCapabilities(), + clientInfo = Implementation(name = "raw-client", version = "1.0"), + ), + ).toJSON() + val toolsListRequest = ListToolsRequest().toJSON() + + val initAnswered = pending.expect(initRequest.id) + val toolsListAnswered = pending.expect(toolsListRequest.id) + + // Pipelined before notifications/initialized: both handled in the serial dispatch phase. + clientTransport.send(initRequest) + clientTransport.send(toolsListRequest) + + withTimeout(10.seconds) { initAnswered.await() } + withTimeout(10.seconds) { toolsListAnswered.await() } + + // Deterministic serial ordering: initialize answered before tools/list. + assertEquals( + listOf(initRequest.id, toolsListRequest.id), + arrivalOrder.toList(), + "pipelined requests must be answered in arrival order", + ) + + // Complete the handshake, then call the high-level tool. + clientTransport.send(InitializedNotification().toJSON()) + + val toolCallRequest = CallToolRequest(CallToolRequestParams("ctx-tool")).toJSON() + val toolCallAnswered = pending.expect(toolCallRequest.id) + clientTransport.send(toolCallRequest) + + val toolCallResponse = withTimeout(10.seconds) { toolCallAnswered.await() } as JSONRPCResponse + val text = (toolCallResponse.result as CallToolResult).content.filterIsInstance().single().text + // The handler echoed its request id, proving currentRequestHandlerExtra() was available. + text shouldBe toolCallRequest.id.asText() + } + + private fun ConcurrentHashMap>.expect( + id: RequestId, + ): CompletableDeferred = CompletableDeferred().also { put(id, it) } + + private fun RequestId.asText(): String = when (this) { + is RequestId.StringId -> value + is RequestId.NumberId -> value.toString() + } +} diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionLoggingTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionLoggingTest.kt index 81a3b41..a1cf797 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionLoggingTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionLoggingTest.kt @@ -1,5 +1,7 @@ package io.modelcontextprotocol.kotlin.sdk.server +import io.kotest.assertions.nondeterministic.continually +import io.kotest.assertions.nondeterministic.eventually import io.kotest.matchers.collections.shouldBeEmpty import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.shouldBe @@ -17,6 +19,9 @@ import kotlinx.serialization.json.JsonPrimitive import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource +import java.util.concurrent.CopyOnWriteArrayList +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds class ClientConnectionLoggingTest : AbstractServerFeaturesTest() { @@ -56,7 +61,7 @@ class ClientConnectionLoggingTest : AbstractServerFeaturesTest() { @ParameterizedTest @EnumSource(LoggingLevel::class) fun `notification should filter logging messages below level`(minLevel: LoggingLevel): Unit = runBlocking { - val receivedMessages = mutableListOf() + val receivedMessages = CopyOnWriteArrayList() client.setNotificationHandler(Method.Defined.NotificationsMessage) { receivedMessages.add(it) CompletableDeferred(Unit) @@ -79,8 +84,10 @@ class ClientConnectionLoggingTest : AbstractServerFeaturesTest() { client.callTool(CallToolRequest(CallToolRequestParams("test-notification-filtered"))) + // Handlers dispatch on Dispatchers.Default after the handshake, so await the expected count + // before asserting order. val expectedLevels = LoggingLevel.entries.filter { it >= minLevel } - receivedMessages shouldHaveSize expectedLevels.size + eventually(5.seconds) { receivedMessages shouldHaveSize expectedLevels.size } receivedMessages.map { it.params.level } shouldBe expectedLevels } @@ -115,7 +122,7 @@ class ClientConnectionLoggingTest : AbstractServerFeaturesTest() { @ParameterizedTest @EnumSource(LoggingLevel::class) fun `sendLoggingMessage should filter messages below level`(minLevel: LoggingLevel): Unit = runBlocking { - val receivedMessages = mutableListOf() + val receivedMessages = CopyOnWriteArrayList() client.setNotificationHandler(Method.Defined.NotificationsMessage) { receivedMessages.add(it) CompletableDeferred(Unit) @@ -138,14 +145,16 @@ class ClientConnectionLoggingTest : AbstractServerFeaturesTest() { client.callTool(CallToolRequest(CallToolRequestParams("test-logging-level"))) + // Handlers dispatch on Dispatchers.Default after the handshake, so await the expected count + // before asserting order. val expectedLevels = LoggingLevel.entries.filter { it >= minLevel } - receivedMessages shouldHaveSize expectedLevels.size + eventually(5.seconds) { receivedMessages shouldHaveSize expectedLevels.size } receivedMessages.map { it.params.level } shouldBe expectedLevels } @Test fun `sendLoggingMessage should send no messages when level is set to highest`(): Unit = runBlocking { - val receivedMessages = mutableListOf() + val receivedMessages = CopyOnWriteArrayList() client.setNotificationHandler(Method.Defined.NotificationsMessage) { receivedMessages.add(it) CompletableDeferred(Unit) @@ -167,6 +176,7 @@ class ClientConnectionLoggingTest : AbstractServerFeaturesTest() { } client.callTool(CallToolRequest(CallToolRequestParams("test-logging-highest"))) - receivedMessages.shouldBeEmpty() + // Handlers dispatch asynchronously, so hold for a window to confirm nothing ever arrives. + continually(500.milliseconds) { receivedMessages.shouldBeEmpty() } } } diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt index 5031a9c..82cf91a 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt @@ -65,6 +65,8 @@ class ServerSessionInitializeTest { assertEquals("test-client", session.clientVersion?.name) } + // Both initialize requests arrive before notifications/initialized, in the serial dispatch + // phase, so processing and response order stay deterministic. @Test fun `should reject duplicate initialize request`() = runTest { val session = createSession() diff --git a/kotlin-sdk-client/api/kotlin-sdk-client.api b/kotlin-sdk-client/api/kotlin-sdk-client.api index 1493a30..d856f5b 100644 --- a/kotlin-sdk-client/api/kotlin-sdk-client.api +++ b/kotlin-sdk-client/api/kotlin-sdk-client.api @@ -52,8 +52,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/client/ClientKt { public final class io/modelcontextprotocol/kotlin/sdk/client/ClientOptions : io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOptions { public fun ()V - public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;Z)V - public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;ZLkotlin/coroutines/CoroutineContext;)V + public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;ZLkotlin/coroutines/CoroutineContext;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun getCapabilities ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities; } diff --git a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt index 59f2b7e..3352104 100644 --- a/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt +++ b/kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/Client.kt @@ -73,11 +73,13 @@ import kotlinx.collections.immutable.minus import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toPersistentSet import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Dispatchers import kotlinx.serialization.SerializationException import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.buildJsonArray +import kotlin.coroutines.CoroutineContext import kotlin.coroutines.cancellation.CancellationException private val logger = KotlinLogging.logger {} @@ -87,11 +89,16 @@ private val logger = KotlinLogging.logger {} * * @property capabilities The capabilities this client supports. * @param enforceStrictCapabilities Whether to strictly enforce capabilities when interacting with the server. + * @param handlerCoroutineContext Coroutine context for inbound handlers. See [ProtocolOptions.handlerCoroutineContext]. */ public class ClientOptions( public val capabilities: ClientCapabilities = ClientCapabilities(), enforceStrictCapabilities: Boolean = true, -) : ProtocolOptions(enforceStrictCapabilities = enforceStrictCapabilities) + handlerCoroutineContext: CoroutineContext = Dispatchers.Default, +) : ProtocolOptions( + enforceStrictCapabilities = enforceStrictCapabilities, + handlerCoroutineContext = handlerCoroutineContext, +) /** * Initializes and connects an MCP client using the provided clientInfo [Implementation], client options, @@ -216,6 +223,7 @@ public open class Client(private val clientInfo: Implementation, options: Client serverInstructions = result.instructions notification(InitializedNotification()) + enableConcurrentDispatch() } catch (error: Throwable) { logger.error(error) { "Failed to initialize client: ${error.message}" } close() diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index 1935e9a..28d6737 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -59,6 +59,7 @@ public abstract class io/modelcontextprotocol/kotlin/sdk/shared/Protocol { public abstract fun assertRequestHandlerCapability (Lio/modelcontextprotocol/kotlin/sdk/types/Method;)V public final fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun connect (Lio/modelcontextprotocol/kotlin/sdk/shared/Transport;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + protected final fun enableConcurrentDispatch ()V public final fun getFallbackNotificationHandler ()Lkotlin/jvm/functions/Function2; public final fun getFallbackRequestHandler ()Lkotlin/jvm/functions/Function3; public final fun getNotificationHandlers ()Ljava/util/Map; @@ -71,6 +72,7 @@ public abstract class io/modelcontextprotocol/kotlin/sdk/shared/Protocol { public static synthetic fun notification$default (Lio/modelcontextprotocol/kotlin/sdk/shared/Protocol;Lio/modelcontextprotocol/kotlin/sdk/types/Notification;Lio/modelcontextprotocol/kotlin/sdk/types/RequestId;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public fun onClose ()V public fun onError (Ljava/lang/Throwable;)V + protected fun onInitializedNotification ()V public final fun removeNotificationHandler (Lio/modelcontextprotocol/kotlin/sdk/types/Method;)V public final fun removeRequestHandler (Lio/modelcontextprotocol/kotlin/sdk/types/Method;)V public final fun request (Lio/modelcontextprotocol/kotlin/sdk/types/Request;Lio/modelcontextprotocol/kotlin/sdk/shared/RequestOptions;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -84,15 +86,18 @@ public abstract class io/modelcontextprotocol/kotlin/sdk/shared/Protocol { public final class io/modelcontextprotocol/kotlin/sdk/shared/ProtocolKt { public static final field IMPLEMENTATION_NAME Ljava/lang/String; + public static final fun currentRequestHandlerExtra (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun getDEFAULT_REQUEST_TIMEOUT ()J } public class io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOptions { - public synthetic fun (ZJILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (ZJLkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (ZJLkotlin/coroutines/CoroutineContext;IIILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (ZJLkotlin/coroutines/CoroutineContext;IILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun getEnforceStrictCapabilities ()Z + public final fun getHandlerCoroutineContext ()Lkotlin/coroutines/CoroutineContext; public final fun getTimeout-UwyO8pc ()J public final fun setEnforceStrictCapabilities (Z)V + public final fun setHandlerCoroutineContext (Lkotlin/coroutines/CoroutineContext;)V public final fun setTimeout-LRDsOJo (J)V } @@ -107,8 +112,16 @@ public final class io/modelcontextprotocol/kotlin/sdk/shared/ReadBufferKt { public static final fun serializeMessage (Lio/modelcontextprotocol/kotlin/sdk/types/JSONRPCMessage;)Ljava/lang/String; } -public final class io/modelcontextprotocol/kotlin/sdk/shared/RequestHandlerExtra { - public fun ()V +public final class io/modelcontextprotocol/kotlin/sdk/shared/RequestHandlerExtra : kotlin/coroutines/AbstractCoroutineContextElement { + public static final field Key Lio/modelcontextprotocol/kotlin/sdk/shared/RequestHandlerExtra$Key; + public final fun getMethod ()Lio/modelcontextprotocol/kotlin/sdk/types/Method; + public final fun getRequestId ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestId; + public final fun sendNotification (Lio/modelcontextprotocol/kotlin/sdk/types/Notification;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun sendRequest (Lio/modelcontextprotocol/kotlin/sdk/types/Request;Lio/modelcontextprotocol/kotlin/sdk/shared/RequestOptions;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun sendRequest$default (Lio/modelcontextprotocol/kotlin/sdk/shared/RequestHandlerExtra;Lio/modelcontextprotocol/kotlin/sdk/types/Request;Lio/modelcontextprotocol/kotlin/sdk/shared/RequestOptions;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; +} + +public final class io/modelcontextprotocol/kotlin/sdk/shared/RequestHandlerExtra$Key : kotlin/coroutines/CoroutineContext$Key { } public final class io/modelcontextprotocol/kotlin/sdk/shared/RequestOptions : io/modelcontextprotocol/kotlin/sdk/shared/TransportSendOptions { diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt index 50dc356..3515b4a 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt @@ -27,15 +27,33 @@ import kotlinx.atomicfu.AtomicRef import kotlinx.atomicfu.atomic import kotlinx.atomicfu.getAndUpdate import kotlinx.atomicfu.update +import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.PersistentMap +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentMapOf import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Deferred -import kotlinx.coroutines.TimeoutCancellationException -import kotlinx.coroutines.withTimeout +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.job +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Semaphore +import kotlinx.coroutines.sync.withPermit +import kotlinx.coroutines.withContext +import kotlinx.coroutines.withTimeoutOrNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.encodeToJsonElement +import kotlin.coroutines.AbstractCoroutineContextElement +import kotlin.coroutines.ContinuationInterceptor +import kotlin.coroutines.CoroutineContext import kotlin.coroutines.cancellation.CancellationException import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -53,17 +71,26 @@ public typealias ProgressCallback = (Progress) -> Unit /** * Additional initialization options. * - * @property enforceStrictCapabilities whether to restrict emitted requests to only those that the - * remote side has indicated it can handle through its advertised capabilities. - * This does NOT affect checking of _local_ side capabilities, as it is considered a logic error - * to mis-specify those. - * Currently defaults to `false` for backwards compatibility with SDK versions that did not advertise - * capabilities correctly; in the future, this will default to `true`. + * [handlerCoroutineContext] is read once when [Protocol.connect] attaches a transport and stays + * fixed until the next [Protocol.connect]. + * + * @property enforceStrictCapabilities whether to restrict emitted requests to only those the remote + * side advertised support for. Local-side capability checks are unaffected. Defaults to `false` for + * backward compatibility with SDK versions that did not advertise capabilities correctly. * @property timeout default timeout for outgoing requests + * @property handlerCoroutineContext coroutine context used to run inbound request and notification + * handlers once initialization has completed. Must contain a real dispatching + * [kotlin.coroutines.ContinuationInterceptor]. `Dispatchers.Unconfined` and unconfined test + * dispatchers are unsupported, since handler resumptions would then run on the transport read loop + * and reintroduce head-of-line blocking. Any [kotlinx.coroutines.Job] in this context is ignored. */ public open class ProtocolOptions( public var enforceStrictCapabilities: Boolean = false, public var timeout: Duration = DEFAULT_REQUEST_TIMEOUT, + public var handlerCoroutineContext: CoroutineContext = Dispatchers.Default, + // Internal handler-concurrency bounds, read once at connect and not part of the public surface. + internal var maxConcurrentHandlers: Int = DEFAULT_MAX_CONCURRENT_HANDLERS, + internal var maxInFlightHandlers: Int = DEFAULT_MAX_IN_FLIGHT_HANDLERS, ) /** @@ -71,6 +98,12 @@ public open class ProtocolOptions( */ public val DEFAULT_REQUEST_TIMEOUT: Duration = 60.seconds +/** Default cap on concurrently executing inbound handlers per connection. */ +internal const val DEFAULT_MAX_CONCURRENT_HANDLERS: Int = 64 + +/** Default cap on launched-but-not-completed inbound handlers per connection. */ +internal const val DEFAULT_MAX_IN_FLIGHT_HANDLERS: Int = 256 + /** * Options that can be given per request. * @@ -121,7 +154,7 @@ public class RequestOptions( override fun hashCode(): Int { var result = super.hashCode() - result = 31 * result + (onProgress?.hashCode() ?: 0) + result = 31 * result + onProgress.hashCode() result = 31 * result + timeout.hashCode() return result } @@ -132,11 +165,70 @@ public class RequestOptions( /** * Extra data given to request handlers. + * + * One instance exists per in-flight inbound request. It is passed as the second parameter to + * low-level handlers registered via [Protocol.setRequestHandler] **and** installed into the + * handler coroutine's [CoroutineContext], so code nested anywhere under the handler can reach it + * via [currentRequestHandlerExtra] without parameter plumbing. + * + * @property requestId the JSON-RPC id of the request being handled + * @property method the request's method */ -public class RequestHandlerExtra +public class RequestHandlerExtra internal constructor( + public val requestId: RequestId, + public val method: Method, + private val protocol: Protocol, + internal val capturedTransport: Transport, +) : AbstractCoroutineContextElement(Key) { + + /** Context key for retrieving the extra from a handler coroutine's context. */ + public companion object Key : CoroutineContext.Key + + /** + * Sends a notification tagged with `relatedRequestId = `[requestId], letting transports + * associate it with the request being handled (e.g. route it onto the request's SSE stream). + */ + public suspend fun sendNotification(notification: Notification) { + protocol.notification(notification, relatedRequestId = requestId) + } + + /** + * Sends a request to the peer tagged with `relatedRequestId = `[requestId]. + * + * Mirrors [Protocol.request]; cancellation of the handler coroutine propagates into this call. + */ + public suspend fun sendRequest(request: Request, options: RequestOptions? = null): T { + val base = options ?: RequestOptions() + return protocol.request( + request, + RequestOptions( + relatedRequestId = requestId, + resumptionToken = base.resumptionToken, + onResumptionToken = base.onResumptionToken, + onProgress = base.onProgress, + timeout = base.timeout, + ), + ) + } +} + +/** The [RequestHandlerExtra] of the MCP request being handled by the current coroutine, or `null` outside a handler. */ +public suspend fun currentRequestHandlerExtra(): RequestHandlerExtra? = currentCoroutineContext()[RequestHandlerExtra] internal val COMPLETED = CompletableDeferred(Unit).also { it.complete(Unit) } +/** Cap on how many recently-cancelled outbound request ids are remembered to quiet late responses/progress. */ +private const val CANCELLED_REQUEST_IDS_REMEMBERED = 256 + +// Bypass set: exempt from both bound tiers so the connection cannot self-block. +// Responses are not listed — they are handled inline before dispatch. +private val CONTROL_METHODS: Set = setOf( + Method.Defined.Ping.value, + Method.Defined.NotificationsCancelled.value, + Method.Defined.NotificationsProgress.value, + Method.Defined.NotificationsInitialized.value, +) + /** * Implements MCP protocol framing on top of a pluggable transport, including * features like request/response linking, notifications, and progress. @@ -144,9 +236,11 @@ internal val COMPLETED = CompletableDeferred(Unit).also { it.complete(Unit) } * @property options protocol-level configuration; `null` falls back to defaults */ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptions?) { + private val connectionRef: AtomicRef = atomic(null) + /** The active transport, or `null` if not connected. */ - public var transport: Transport? = null - private set + public val transport: Transport? + get() = connectionRef.value?.transport private val _requestHandlers: AtomicRef RequestResult?>> = @@ -184,6 +278,21 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio public val progressHandlers: Map get() = _progressHandlers.value + private val recentlyCancelledRequestIds: AtomicRef> = + atomic(persistentListOf()) + + /** Remembers a locally-cancelled outbound request id so its late response/progress is quieted. */ + private fun rememberCancelledRequestId(id: RequestId) { + recentlyCancelledRequestIds.update { current -> + val appended = current.adding(id) + if (appended.size > CANCELLED_REQUEST_IDS_REMEMBERED) appended.removingAt(0) else appended + } + } + + /** Whether [id] was recently cancelled locally (see [rememberCancelledRequestId]). */ + private fun isRecentlyCancelled(id: RequestId?): Boolean = + id != null && recentlyCancelledRequestIds.value.contains(id) + /** * Callback for when the connection is closed for any reason. * @@ -213,6 +322,11 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio public var fallbackNotificationHandler: (suspend (notification: JSONRPCNotification) -> Unit)? = null init { + setNotificationHandler(Method.Defined.NotificationsCancelled) { notification -> + handleCancelledNotification(notification) + COMPLETED + } + setNotificationHandler(Method.Defined.NotificationsProgress) { notification -> onProgress(notification) COMPLETED @@ -223,15 +337,64 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio } } + /** + * Enables concurrent dispatch of inbound messages on the current connection. + * + * Called by subclasses when the MCP initialization phase completes (the client after the + * initialize exchange; the server session on receiving `notifications/initialized`). Until + * then, inbound messages are handled inline in arrival order. Reset by [connect]. + */ + protected fun enableConcurrentDispatch() { + val connection = connectionRef.value ?: return + connection.concurrentDispatchEnabled.value = true + } + + /** + * Router hook invoked whenever `notifications/initialized` is received, before handler lookup. + * + * Runs regardless of which notification handler is registered for the method, so replacing the + * handler via [setNotificationHandler] cannot disable subclass initialization logic. + */ + protected open fun onInitializedNotification() {} + /** * Attaches to the given transport, starts it, and starts listening for messages. * - * The Protocol object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward. + * The Protocol object assumes ownership of the Transport, replacing any callbacks that have + * already been set, and expects that it is the only user of the Transport instance going forward. + * + * @throws IllegalStateException if this Protocol is already connected; call [close] first. */ public open suspend fun connect(transport: Transport) { - this.transport = transport + val maxConcurrent = options?.maxConcurrentHandlers ?: DEFAULT_MAX_CONCURRENT_HANDLERS + val maxInFlight = options?.maxInFlightHandlers ?: DEFAULT_MAX_IN_FLIGHT_HANDLERS + require(maxConcurrent > 0) { "maxConcurrentHandlers must be positive, but was $maxConcurrent" } + require(maxInFlight >= maxConcurrent) { + "maxInFlightHandlers ($maxInFlight) must be >= maxConcurrentHandlers ($maxConcurrent)" + } + val handlerContext = (options?.handlerCoroutineContext ?: Dispatchers.Default).minusKey(Job) + val interceptor = handlerContext[ContinuationInterceptor] + if (interceptor === Dispatchers.Unconfined || + interceptor?.let { it::class.simpleName?.contains("Unconfined") } == true + ) { + logger.warn { + "handlerCoroutineContext uses an unconfined dispatcher ($interceptor); " + + "handler resumptions will run on the transport read loop and may block unrelated messages" + } + } + val connection = Connection( + transport = transport, + handlerScope = CoroutineScope(SupervisorJob() + handlerContext + CoroutineName("McpProtocol")), + executionSemaphore = Semaphore(maxConcurrent), + maxInFlightHandlers = maxInFlight, + ) + if (!connectionRef.compareAndSet(null, connection)) { + connection.handlerScope.cancel() + error("Protocol is already connected; close() the current connection before connecting a new transport") + } + transport.onClose { - doClose() + doClose(connection) } transport.onError { @@ -239,24 +402,42 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio } transport.onMessage { message -> + if (connectionRef.value !== connection) { + logger.trace { "Dropping message received after close: ${message::class.simpleName}" } + return@onMessage + } when (message) { is JSONRPCResponse -> onResponse(message, null) - is JSONRPCRequest -> onRequest(message) - is JSONRPCNotification -> onNotification(message) + is JSONRPCRequest -> dispatchRequest(connection, message) + is JSONRPCNotification -> dispatchNotification(connection, message) is JSONRPCError -> onResponse(null, message) is JSONRPCEmptyMessage -> Unit } } logger.info { "Starting transport" } - transport.start() + try { + transport.start() + } catch (cause: Throwable) { + // Roll back so the Protocol can be reconnected after a failed start; idempotent with + // a transport-initiated doClose (both CAS on the same connection). + if (connectionRef.compareAndSet(connection, null)) { + connection.handlerScope.cancel() + } + throw cause + } } - private fun doClose() { - val handlersToNotify = _responseHandlers.value.values.toList() - _responseHandlers.getAndSet(persistentMapOf()) + private fun doClose(connection: Connection) { + // A stale onClose from a previous transport must not tear down the successor connection. + if (!connectionRef.compareAndSet(connection, null)) { + logger.trace { "Ignoring close signal from a stale transport" } + return + } + val handlersToNotify = _responseHandlers.getAndSet(persistentMapOf()).values.toList() _progressHandlers.getAndSet(persistentMapOf()) - transport = null + connection.inFlightRequestJobs.getAndSet(persistentMapOf()) + connection.handlerScope.cancel() onClose() val error = McpException(RPCError.ErrorCode.CONNECTION_CLOSED, "Connection closed") @@ -265,6 +446,110 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio } } + private suspend fun dispatchRequest(connection: Connection, request: JSONRPCRequest) { + if (!connection.concurrentDispatchEnabled.value) { + // Serial phase (before the peer completes MCP initialization): inline, in arrival + // order — the delivering coroutine awaits the handler. + onRequest(request, connection, trackCancellation = false) + return + } + val bypass = request.method in CONTROL_METHODS + if (!bypass && !tryAdmit(connection)) { + rejectOverloadedRequest(connection, request) + return + } + // UNDISPATCHED starts the handler synchronously in the delivering coroutine, preserving + // arrival order, then moves to handlerCoroutineContext at its first suspension. + connection.handlerScope.launch(start = CoroutineStart.UNDISPATCHED) { + // Register before any suspension point so a following notifications/cancelled can find + // and cancel even a handler still parked on admission. + registerInFlight(connection, request.id, coroutineContext.job) + try { + if (bypass) { + onRequest(request, connection, trackCancellation = true) + } else { + connection.executionSemaphore.withPermit { + onRequest(request, connection, trackCancellation = true) + } + } + } finally { + if (!bypass) connection.inFlightCount.decrementAndGet() + } + } + } + + private suspend fun dispatchNotification(connection: Connection, notification: JSONRPCNotification) { + if (notification.method == Method.Defined.NotificationsInitialized.value) { + onInitializedNotification() + } + if (!connection.concurrentDispatchEnabled.value) { + onNotification(notification) + return + } + val bypass = notification.method in CONTROL_METHODS + if (!bypass && !tryAdmit(connection)) { + val dropped = IllegalStateException( + "Dropped notification ${notification.method}: too many in-flight messages", + ) + logger.warn { dropped.message } + onError(dropped) + return + } + connection.handlerScope.launch(start = CoroutineStart.UNDISPATCHED) { + try { + if (bypass) { + onNotification(notification) + } else { + connection.executionSemaphore.withPermit { onNotification(notification) } + } + } finally { + if (!bypass) connection.inFlightCount.decrementAndGet() + } + } + } + + private fun tryAdmit(connection: Connection): Boolean { + while (true) { + val current = connection.inFlightCount.value + if (current >= connection.maxInFlightHandlers) return false + if (connection.inFlightCount.compareAndSet(current, current + 1)) return true + } + } + + private suspend fun rejectOverloadedRequest(connection: Connection, request: JSONRPCRequest) { + logger.warn { + "Rejecting request ${request.method} (id: ${request.id}): " + + "in-flight handler limit (${connection.maxInFlightHandlers}) reached" + } + try { + connection.transport.send( + JSONRPCError( + id = request.id, + error = RPCError( + code = RPCError.ErrorCode.INTERNAL_ERROR, + message = "Server is busy: too many in-flight messages", + ), + ), + ) + } catch (e: CancellationException) { + throw e + } catch (cause: Throwable) { + logger.error(cause) { "Failed to send busy rejection for request id: ${request.id}" } + onError(cause) + } + } + + private fun handleCancelledNotification(notification: CancelledNotification) { + val connection = connectionRef.value ?: return + val requestId = notification.params.requestId + val job = connection.inFlightRequestJobs.value[requestId] + if (job == null) { + logger.trace { "Ignoring cancellation for unknown or already-completed request: $requestId" } + return + } + job.cancel("Cancelled by peer: ${notification.params.reason ?: "unknown"}") + } + private suspend fun onNotification(notification: JSONRPCNotification) { logger.trace { "Received notification: ${notification.method}" } @@ -284,15 +569,16 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio } } - private suspend fun onRequest(request: JSONRPCRequest) { + private suspend fun onRequest(request: JSONRPCRequest, connection: Connection, trackCancellation: Boolean) { logger.trace { "Received request: ${request.method} (id: ${request.id})" } val handler = requestHandlers[request.method] ?: fallbackRequestHandler + val capturedTransport = connection.transport if (handler === null) { logger.trace { "No handler found for request: ${request.method}" } try { - transport?.send( + capturedTransport.send( JSONRPCError( id = request.id, error = RPCError( @@ -310,36 +596,77 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio return } - try { - val result = handler(request, RequestHandlerExtra()) - logger.trace { "Request handled successfully: ${request.method} (id: ${request.id})" } + val extra = RequestHandlerExtra( + requestId = request.id, + method = Method.from(request.method), + protocol = this, + capturedTransport = capturedTransport, + ) - transport?.send( - JSONRPCResponse( - id = request.id, - result = result ?: EmptyResult(), - ), - ) + // Registration in the in-flight registry already happened in dispatchRequest's launch + // block (synchronously, pre-suspension). Here we only need the job for suppression checks. + val handlerJob = if (trackCancellation) currentCoroutineContext().job else null + + withContext(extra) { + try { + val result = handler(request, extra) + logger.trace { "Request handled successfully: ${request.method} (id: ${request.id})" } + if (handlerJob?.isCancelled == true) { + logger.trace { "Suppressing response for request cancelled by peer (id: ${request.id})" } + return@withContext + } + capturedTransport.send( + JSONRPCResponse( + id = request.id, + result = result ?: EmptyResult(), + ), + ) + } catch (e: CancellationException) { + // Intentional exception to the always-rethrow-CE convention, only at this boundary. + if (handlerJob == null) throw e // serial phase: inline dispatch is not response-suppressed + if (handlerJob.isCancelled) throw e // genuine peer or close cancel: suppress the response + // CE escaped a live handler job (e.g. a leaked inner withTimeout). Answer + // INTERNAL_ERROR so the peer does not hang until its own timeout. + respondWithError(capturedTransport, request, e) + } catch (cause: Throwable) { + if (handlerJob?.isCancelled == true) { + logger.trace { "Suppressing error response for request cancelled by peer (id: ${request.id})" } + return@withContext + } + respondWithError(capturedTransport, request, cause) + } + } + } + + private fun registerInFlight(connection: Connection, id: RequestId, job: Job) { + val previous = connection.inFlightRequestJobs.getAndUpdate { current -> current.putting(id, job) }[id] + if (previous != null) { + logger.warn { "Duplicate in-flight request id $id; replacing the previous handler job" } + } + job.invokeOnCompletion { + // Identity guard: never evict a successor job registered under a reused id. + connection.inFlightRequestJobs.update { current -> + if (current[id] === job) current.removing(id) else current + } + } + } + + private suspend fun respondWithError(transport: Transport, request: JSONRPCRequest, cause: Throwable) { + logger.error(cause) { "Error handling request: ${request.method} (id: ${request.id})" } + try { + val rpcError = if (cause is McpException) { + RPCError(code = cause.code, message = cause.message.orEmpty(), data = cause.data) + } else { + RPCError(code = RPCError.ErrorCode.INTERNAL_ERROR, message = cause.message ?: "Internal error") + } + transport.send(JSONRPCError(id = request.id, error = rpcError)) } catch (e: CancellationException) { throw e - } catch (cause: Throwable) { - logger.error(cause) { "Error handling request: ${request.method} (id: ${request.id})" } - - try { - val rpcError = if (cause is McpException) { - RPCError(code = cause.code, message = cause.message.orEmpty(), data = cause.data) - } else { - RPCError(code = RPCError.ErrorCode.INTERNAL_ERROR, message = cause.message ?: "Internal error") - } - transport?.send(JSONRPCError(id = request.id, error = rpcError)) - } catch (e: CancellationException) { - throw e - } catch (sendError: Throwable) { - logger.error(sendError) { - "Failed to send error response for request: ${request.method} (id: ${request.id})" - } - // Optionally implement fallback behavior here + } catch (sendError: Throwable) { + logger.error(sendError) { + "Failed to send error response for request: ${request.method} (id: ${request.id})" } + onError(sendError) } } @@ -354,6 +681,10 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio val handler = _progressHandlers.value[progressToken] if (handler == null) { + if (isRecentlyCancelled(progressToken)) { + logger.trace { "Ignoring progress for a locally cancelled request: $progressToken" } + return + } val error = Error( "Received a progress notification for an unknown token: ${McpJson.encodeToString(notification)}", ) @@ -370,7 +701,7 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio val oldResponseHandlers = _responseHandlers.getAndUpdate { current -> if (messageId != null && messageId in current) { - current.remove(messageId) + current.removing(messageId) } else { current } @@ -379,8 +710,12 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio val handler = oldResponseHandlers[messageId] if (handler != null) { - messageId?.let { msg -> _progressHandlers.update { it.remove(msg) } } + messageId?.let { msg -> _progressHandlers.update { it.removing(msg) } } } else { + if (isRecentlyCancelled(messageId)) { + logger.trace { "Ignoring response for a locally cancelled request: $messageId" } + return + } onError( IllegalStateException( "Received a response for an unknown message ID: ${McpJson.encodeToString(error ?: response)}", @@ -438,7 +773,8 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio public suspend fun request(request: Request, options: RequestOptions? = null): T { logger.trace { "Sending request: ${request.method}" } val result = CompletableDeferred() - val transport = transport ?: error("Not connected") + val connection = connectionRef.value ?: error("Not connected") + val transport = connection.transport if (this@Protocol.options?.enforceStrictCapabilities == true) { assertCapabilityForMethod(request.method) @@ -448,7 +784,7 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio options?.onProgress?.let { progressHandler -> logger.trace { "Registering progress handler for request id: $id" } _progressHandlers.update { current -> - current.put(id, progressHandler) + current.putting(id, progressHandler) } val paramsObject = (this.params as? JsonObject) ?: JsonObject(emptyMap()) @@ -467,10 +803,10 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio val jsonRpcRequestId = jsonRpcRequest.id _responseHandlers.update { current -> - current.put(jsonRpcRequestId) { response, error -> + current.putting(jsonRpcRequestId) { response, error -> if (error != null) { result.completeExceptionally(error) - return@put + return@putting } try { @@ -482,42 +818,84 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio } } - val cancel: suspend (Throwable) -> Unit = { reason: Throwable -> - _responseHandlers.update { current -> current.remove(jsonRpcRequestId) } - _progressHandlers.update { current -> current.remove(jsonRpcRequestId) } + if (connectionRef.value !== connection) { + // Connection closed or replaced during registration; nothing would complete this handler. + _responseHandlers.update { it.removing(jsonRpcRequestId) } + _progressHandlers.update { it.removing(jsonRpcRequestId) } + throw McpException(RPCError.ErrorCode.CONNECTION_CLOSED, "Connection closed") + } - val notification = CancelledNotification( - params = CancelledNotificationParams( - requestId = jsonRpcRequestId, - reason = reason.message ?: "Unknown", - ), - ) + val cancelPending: suspend (reason: Throwable, notifyPeer: Boolean) -> Unit = { reason, notifyPeer -> + // Remember before removing: a racing onResponse/onProgress that sees the handler gone + // must also see the id, or it reports a late message as unknown. Order is load-bearing. + rememberCancelledRequestId(jsonRpcRequestId) + _responseHandlers.update { current -> current.removing(jsonRpcRequestId) } + _progressHandlers.update { current -> current.removing(jsonRpcRequestId) } - val jsonRpcNotification = notification.toJSON() - - transport.send(jsonRpcNotification, options) + if (notifyPeer) { + val notification = CancelledNotification( + params = CancelledNotificationParams( + requestId = jsonRpcRequestId, + reason = reason.message ?: "Unknown", + ), + ) + transport.send(notification.toJSON(), options) + } result.completeExceptionally(reason) } + // The MCP spec forbids cancelling `initialize`; local cleanup still runs, + // but no notifications/cancelled goes on the wire (timeout and cancel paths alike). + val notifyPeerOnCancel = request.method != Method.Defined.Initialize + val timeout = options?.timeout ?: DEFAULT_REQUEST_TIMEOUT try { - withTimeout(timeout) { + val response = withTimeoutOrNull(timeout) { logger.trace { "Sending request message with id: $jsonRpcRequestId" } - this@Protocol.transport?.send(jsonRpcRequest, options) + transport.send(jsonRpcRequest, options) + result.await() } - return result.await() - } catch (cause: TimeoutCancellationException) { - logger.error { "Request timed out after ${timeout.inWholeMilliseconds}ms: ${request.method}" } - cancel( - McpException( + if (response == null) { + // Our own request timeout expired. An outer withTimeout's cancellation propagates + // through withTimeoutOrNull instead of returning null and is handled by the catch below. + logger.error { "Request timed out after ${timeout.inWholeMilliseconds}ms: ${request.method}" } + val timeoutError = McpException( code = RPCError.ErrorCode.REQUEST_TIMEOUT, message = "Request timed out", data = JsonObject(mutableMapOf("timeout" to JsonPrimitive(timeout.inWholeMilliseconds))), - ), - ) - result.cancel(cause) + ) + withContext(NonCancellable) { + try { + cancelPending(timeoutError, notifyPeerOnCancel) + } catch (e: Throwable) { + logger.warn(e) { "Failed to notify peer about timed-out request" } + onError(e) + } + } + result.cancel() + throw timeoutError + } + return response + } catch (cause: CancellationException) { + // Plain caller cancellation, or an outer withTimeout that propagated through + // withTimeoutOrNull (only our own deadline returns null there). NonCancellable so the + // cancellation notification still goes out even though the caller's job is cancelled. + // A secondary send failure must never replace the original CancellationException. + withContext(NonCancellable) { + try { + cancelPending(cause, notifyPeerOnCancel) + } catch (e: Throwable) { + logger.warn(e) { "Failed to notify peer about cancelled request" } + onError(e) + } + } throw cause + } finally { + // Backstop for the failed-send path. The success, timeout and cancellation paths already + // removed these handlers, so this only bites when the outbound send failed. + _responseHandlers.update { it.removing(jsonRpcRequestId) } + _progressHandlers.update { it.removing(jsonRpcRequestId) } } } @@ -538,6 +916,11 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio * Registers a handler to invoke when this protocol object receives a request with the given method. * * Note that this will replace any previous request handler for the same method. + * + * Handlers may run concurrently after initialization and are cancelled cooperatively, so always + * re-throw [CancellationException]. Replacing a built-in control-method handler (`ping`, + * `notifications/cancelled`, `notifications/progress`, `notifications/initialized`) with slow + * code degrades connection liveness. */ public inline fun setRequestHandler( method: Method, @@ -556,7 +939,7 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio val wrapped = wrapRequestHandler(method, block) _requestHandlers.update { current -> - current.put(method.value) { jSONRPCRequest, extraHandler -> + current.putting(method.value) { jSONRPCRequest, extraHandler -> val request = jSONRPCRequest.fromJSON() val response = wrapped(request as T, extraHandler) response @@ -582,17 +965,23 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio * Removes the request handler for the given method. */ public fun removeRequestHandler(method: Method) { - _requestHandlers.update { current -> current.remove(method.value) } + _requestHandlers.update { current -> current.removing(method.value) } } /** * Registers a handler to invoke when this protocol object receives a notification with the given method. * * Note that this will replace any previous notification handler for the same method. + * + * Handlers may run concurrently after initialization and are cancelled cooperatively, so always + * re-throw [CancellationException]. Replacing a built-in control-method handler (`ping`, + * `notifications/cancelled`, `notifications/progress`, `notifications/initialized`) with slow + * code degrades connection liveness. Replacing `notifications/cancelled` in particular disables + * inbound request cancellation entirely, since that handler is what cancels the running job. */ public fun setNotificationHandler(method: Method, handler: (notification: T) -> Deferred) { _notificationHandlers.update { current -> - current.put(method.value) { + current.putting(method.value) { @Suppress("UNCHECKED_CAST") handler(it.fromJSON() as T) } @@ -603,6 +992,22 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio * Removes the notification handler for the given method. */ public fun removeNotificationHandler(method: Method) { - _notificationHandlers.update { current -> current.remove(method.value) } + _notificationHandlers.update { current -> current.removing(method.value) } + } + + private class Connection( + val transport: Transport, + val handlerScope: CoroutineScope, + val executionSemaphore: Semaphore, + val maxInFlightHandlers: Int, + ) { + /** Init gate: inbound dispatch is inline/serial until this flips. */ + val concurrentDispatchEnabled = atomic(false) + + /** Admission tier: launched-but-not-completed handler jobs (running + parked). */ + val inFlightCount = atomic(0) + + /** In-flight request handler jobs, for `notifications/cancelled`. */ + val inFlightRequestJobs: AtomicRef> = atomic(persistentMapOf()) } } diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt index 19f4da5..90403e8 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt @@ -53,4 +53,13 @@ public sealed interface Method { */ @Serializable public data class Custom(override val value: String) : Method + + public companion object { + private val definedByValue: Map by lazy { + Defined.entries.associateBy { it.value } + } + + /** Resolves a wire method string to a [Defined] entry when known, [Custom] otherwise. */ + internal fun from(value: String): Method = definedByValue[value] ?: Custom(value) + } } diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt index ab85e6d..6eab14a 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt @@ -59,18 +59,11 @@ internal object MethodSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("io.modelcontextprotocol.kotlin.sdk.types.Method", PrimitiveKind.STRING) - private val definedMethods: Map by lazy { - Method.Defined.entries.associateBy { it.value } - } - override fun serialize(encoder: Encoder, value: Method) { encoder.encodeString(value.value) } - override fun deserialize(decoder: Decoder): Method { - val decodedString = decoder.decodeString() - return definedMethods[decodedString] ?: Method.Custom(decodedString) - } + override fun deserialize(decoder: Decoder): Method = Method.from(decoder.decodeString()) } // ============================================================================ diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyTest.kt new file mode 100644 index 0000000..b3c95ac --- /dev/null +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyTest.kt @@ -0,0 +1,524 @@ +package io.modelcontextprotocol.kotlin.sdk.shared + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain +import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult +import io.modelcontextprotocol.kotlin.sdk.types.InitializedNotification +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse +import io.modelcontextprotocol.kotlin.sdk.types.McpException +import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.PingRequest +import io.modelcontextprotocol.kotlin.sdk.types.RPCError +import io.modelcontextprotocol.kotlin.sdk.types.RequestId +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.async +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.int +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.put +import kotlin.coroutines.cancellation.CancellationException +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds + +class ProtocolConcurrencyTest { + + private fun TestScope.newProtocol(): TestProtocol = + TestProtocol(ProtocolOptions(handlerCoroutineContext = StandardTestDispatcher(testScheduler))) + + @Test + fun `a suspended slow handler does not block a later fast request`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + protocol.fallbackRequestHandler = { request, _ -> + if (request.method == "test/slow") delay(10.seconds) + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/slow")) + transport.deliver(JSONRPCRequest(id = RequestId(2L), method = "test/fast")) + runCurrent() + + responsesOn(transport).map { it.id } shouldBe listOf(RequestId(2L)) + + advanceTimeBy(11.seconds) + runCurrent() + responsesOn(transport).map { it.id } shouldBe listOf(RequestId(2L), RequestId(1L)) + } + + @Test + fun `dispatch is serial until concurrent dispatch is enabled`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + // gate NOT flipped + + protocol.fallbackRequestHandler = { request, _ -> + if (request.method == "test/slow") delay(10.seconds) + EmptyResult() + } + + val delivery = launch { + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/slow")) + transport.deliver(JSONRPCRequest(id = RequestId(2L), method = "test/fast")) + } + runCurrent() + // inline handling: the delivering coroutine is parked inside the slow handler + delivery.isCompleted shouldBe false + responsesOn(transport) shouldBe emptyList() + + advanceTimeBy(11.seconds) + runCurrent() + delivery.isCompleted shouldBe true + responsesOn(transport).map { it.id } shouldBe listOf(RequestId(1L), RequestId(2L)) + } + + // the hook fires before handler lookup and cannot be disabled by a user handler + @Test + fun `initialized notification invokes the router hook even when a user handler is registered`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + + var userHandlerCalled = false + protocol.setNotificationHandler(Method.Defined.NotificationsInitialized) { + userHandlerCalled = true + COMPLETED + } + transport.deliver(JSONRPCNotification(method = Method.Defined.NotificationsInitialized.value)) + runCurrent() + + protocol.initializedNotificationCount shouldBe 1 + userHandlerCalled shouldBe true + } + + @Test + fun `cancelled notification cancels the in-flight handler and suppresses the response`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val entered = CompletableDeferred() + val sawCancellation = CompletableDeferred() + protocol.fallbackRequestHandler = { _, _ -> + entered.complete(Unit) + try { + delay(10.seconds) + } catch (e: CancellationException) { + sawCancellation.complete(Unit) + throw e + } + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(5L), method = "test/slow")) + runCurrent() + entered.await() + + transport.deliver(cancelledNotification(requestId = RequestId(5L), reason = "user gave up")) + runCurrent() + sawCancellation.await() + advanceUntilIdle() + + responsesOn(transport) shouldBe emptyList() + errorsOn(transport) shouldBe emptyList() // JSONRPCError messages on the wire + protocol.errors shouldBe emptyList() + } + + @Test + fun `cancelled notification for an unknown id is a silent no-op`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + transport.deliver(cancelledNotification(requestId = RequestId(404L), reason = "nope")) + advanceUntilIdle() + + protocol.errors shouldBe emptyList() + } + + @Test + fun `handler leaking CancellationException without being cancelled produces INTERNAL_ERROR`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + protocol.fallbackRequestHandler = { _, _ -> throw CancellationException("leaked") } + + transport.deliver(JSONRPCRequest(id = RequestId(6L), method = "test/leak")) + advanceUntilIdle() + + val error = errorsOn(transport).single() + error.id shouldBe RequestId(6L) + error.error.code shouldBe RPCError.ErrorCode.INTERNAL_ERROR + } + + // suppression race variants + @Test + fun `handler that swallows cancellation and returns normally still gets no response`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val entered = CompletableDeferred() + protocol.fallbackRequestHandler = { _, _ -> + entered.complete(Unit) + try { + delay(10.seconds) + } catch (_: CancellationException) { + // swallow (anti-pattern) and return normally + } + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(7L), method = "test/swallow")) + runCurrent() + entered.await() + transport.deliver(cancelledNotification(requestId = RequestId(7L), reason = "stop")) + advanceUntilIdle() + + responsesOn(transport) shouldBe emptyList() + } + + @Test + fun `handler throwing non-CE while cancelled gets no error response`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val entered = CompletableDeferred() + protocol.fallbackRequestHandler = { _, _ -> + entered.complete(Unit) + try { + delay(10.seconds) + } catch (_: CancellationException) { + throw IllegalStateException("boom") + } + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(8L), method = "test/throw")) + runCurrent() + entered.await() + transport.deliver(cancelledNotification(requestId = RequestId(8L), reason = "stop")) + advanceUntilIdle() + + errorsOn(transport) shouldBe emptyList() + protocol.errors shouldBe emptyList() + } + + @Test + fun `suspension-free notification handlers observe strict arrival order`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val seen = mutableListOf() + protocol.fallbackNotificationHandler = { notification -> + seen.add((notification.params as JsonObject).getValue("i").jsonPrimitive.int) + } + + repeat(20) { i -> + transport.deliver( + JSONRPCNotification(method = "test/event", params = buildJsonObject { put("i", i) }), + ) + } + advanceUntilIdle() + + seen shouldBe (0 until 20).toList() + } + + @Test + fun `reconnect resets the dispatch gate to serial`() = runTest { + val protocol = newProtocol() + val transport1 = RecordingTransport() + protocol.connect(transport1) + protocol.enableConcurrency() + protocol.close() + + val transport2 = RecordingTransport() + protocol.connect(transport2) + protocol.fallbackRequestHandler = { request, _ -> + if (request.method == "test/slow") delay(10.seconds) + EmptyResult() + } + + val delivery = launch { + transport2.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/slow")) + transport2.deliver(JSONRPCRequest(id = RequestId(2L), method = "test/fast")) + } + runCurrent() + delivery.isCompleted shouldBe false // serial again: gate reset + advanceTimeBy(11.seconds) + runCurrent() + responsesOn(transport2).map { it.id } shouldBe listOf(RequestId(1L), RequestId(2L)) + } + + @Test + fun `close cancels in-flight handlers suppresses responses and fails pending outbound requests`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val entered = CompletableDeferred() + val sawCancellation = CompletableDeferred() + protocol.fallbackRequestHandler = { _, _ -> + entered.complete(Unit) + try { + delay(10.seconds) + } catch (e: CancellationException) { + sawCancellation.complete(Unit) + throw e + } + EmptyResult() + } + transport.deliver(JSONRPCRequest(id = RequestId(9L), method = "test/slow")) + runCurrent() + entered.await() + + // shouldThrow inside the async so its failure does not cancel the (non-supervisor) test scope. + val pending = async { shouldThrow { protocol.request(PingRequest()) } } + transport.awaitRequest() // outbound ping on the wire + + protocol.close() + runCurrent() + + sawCancellation.await() + responsesOn(transport) shouldBe emptyList() + val thrown = pending.await() + thrown.code shouldBe RPCError.ErrorCode.CONNECTION_CLOSED + } + + @Test + fun `message delivered after close is dropped without crash or response`() = runTest { + val protocol = newProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + protocol.close() + + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/anything")) + advanceUntilIdle() + + responsesOn(transport) shouldBe emptyList() + errorsOn(transport) shouldBe emptyList() + } + + @Test + fun `at most maxConcurrentHandlers handlers run concurrently while control messages bypass`() = runTest { + val protocol = TestProtocol( + ProtocolOptions( + handlerCoroutineContext = StandardTestDispatcher(testScheduler), + maxConcurrentHandlers = 2, + ), + ) + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + var entered = 0 + val release = CompletableDeferred() + protocol.fallbackRequestHandler = { _, _ -> + entered += 1 + release.await() + EmptyResult() + } + + repeat(4) { i -> transport.deliver(JSONRPCRequest(id = RequestId(i.toLong()), method = "test/slow")) } + runCurrent() + entered shouldBe 2 // exactly two running, two parked on the semaphore + + // ping (bypass) is answered while saturated + transport.deliver(JSONRPCRequest(id = RequestId(100L), method = Method.Defined.Ping.value)) + runCurrent() + responsesOn(transport).map { it.id } shouldBe listOf(RequestId(100L)) + + // responses (bypass, inline) are processed while saturated + val pending = async { protocol.request(PingRequest()) } + runCurrent() + val outbound = transport.awaitRequest() + transport.deliver(JSONRPCResponse(id = outbound.id, result = EmptyResult())) + runCurrent() + pending.isCompleted shouldBe true + + release.complete(Unit) + advanceUntilIdle() + entered shouldBe 4 + responsesOn(transport) shouldHaveSize 5 + } + + @Test + fun `flood beyond maxInFlightHandlers is rejected fail-fast and the read loop never suspends`() = runTest { + val protocol = TestProtocol( + ProtocolOptions( + handlerCoroutineContext = StandardTestDispatcher(testScheduler), + maxConcurrentHandlers = 1, + maxInFlightHandlers = 4, + ), + ) + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val release = CompletableDeferred() + protocol.fallbackRequestHandler = { _, _ -> + release.await() + EmptyResult() + } + + // 10 requests delivered back-to-back; delivery must complete without advancing + // virtual time — i.e. the read loop was never suspended on admission. + val delivery = launch { + repeat(10) { i -> transport.deliver(JSONRPCRequest(id = RequestId(i.toLong()), method = "test/slow")) } + } + runCurrent() + delivery.isCompleted shouldBe true + + // 4 admitted (1 running + 3 parked), 6 rejected immediately + val busyErrors = errorsOn(transport) + busyErrors shouldHaveSize 6 + busyErrors.forEach { + it.error.code shouldBe RPCError.ErrorCode.INTERNAL_ERROR + it.error.message shouldBe "Server is busy: too many in-flight messages" + } + + // ping still answered at full saturation + transport.deliver(JSONRPCRequest(id = RequestId(100L), method = Method.Defined.Ping.value)) + runCurrent() + responsesOn(transport).map { it.id } shouldBe listOf(RequestId(100L)) + + release.complete(Unit) + advanceUntilIdle() + responsesOn(transport) shouldHaveSize 5 // ping + the 4 admitted + } + + @Test + fun `overflowing notifications are dropped and reported via onError`() = runTest { + val protocol = TestProtocol( + ProtocolOptions( + handlerCoroutineContext = StandardTestDispatcher(testScheduler), + maxConcurrentHandlers = 1, + maxInFlightHandlers = 2, + ), + ) + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + // parks one handler with a request: holds the sole execution permit and one in-flight slot + val release = CompletableDeferred() + protocol.fallbackRequestHandler = { _, _ -> + release.await() + EmptyResult() + } + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/hog")) + runCurrent() + + // notification 1 is admitted (parked on the semaphore, behind the hogged permit); + // notification 2 overflows the admission cap and is dropped instead of parked. + val notificationRelease = CompletableDeferred() + protocol.fallbackNotificationHandler = { notificationRelease.await() } + transport.deliver(JSONRPCNotification(method = "test/event")) + transport.deliver(JSONRPCNotification(method = "test/event")) + runCurrent() + + protocol.errors shouldHaveSize 1 + protocol.errors.single().message.orEmpty() shouldContain "too many in-flight messages" + errorsOn(transport) shouldBe emptyList() // no wire error for dropped notifications + + release.complete(Unit) + notificationRelease.complete(Unit) + advanceUntilIdle() + } + + @Test + fun `cancelling saturating handlers releases permits and lets parked handlers run`() = runTest { + val protocol = TestProtocol( + ProtocolOptions( + handlerCoroutineContext = StandardTestDispatcher(testScheduler), + maxConcurrentHandlers = 1, + ), + ) + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val secondCompleted = CompletableDeferred() + protocol.fallbackRequestHandler = { request, _ -> + if (request.method == "test/hog") { + delay(1000.seconds) // cancellable park + error("unreachable") + } + secondCompleted.complete(Unit) + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/hog")) // holds the permit + transport.deliver(JSONRPCRequest(id = RequestId(2L), method = "test/next")) // parked on the semaphore + runCurrent() + secondCompleted.isCompleted shouldBe false + + // cancel the hog THROUGH the bypass while saturated + transport.deliver(cancelledNotification(requestId = RequestId(1L), reason = "make room")) + advanceUntilIdle() + + secondCompleted.isCompleted shouldBe true + responsesOn(transport).map { it.id } shouldBe listOf(RequestId(2L)) // hog suppressed, next answered + } + + @Test + fun `a parked handler can itself be cancelled before it ever runs`() = runTest { + val protocol = TestProtocol( + ProtocolOptions( + handlerCoroutineContext = StandardTestDispatcher(testScheduler), + maxConcurrentHandlers = 1, + ), + ) + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + protocol.fallbackRequestHandler = { request, _ -> + if (request.method == "test/hog") { + delay(1000.seconds) // cancellable park + error("unreachable") + } + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/hog")) // holds the permit + transport.deliver(JSONRPCRequest(id = RequestId(2L), method = "test/next")) // parked on the semaphore + runCurrent() + + // cancel the parked handler before it ever acquires the permit, then cancel the hog too + transport.deliver(cancelledNotification(requestId = RequestId(2L), reason = "give up while parked")) + transport.deliver(cancelledNotification(requestId = RequestId(1L), reason = "make room")) + advanceUntilIdle() + + // no response for id=2 at all: its withPermit acquire was cancelled before onRequest ever ran + responsesOn(transport) shouldBe emptyList() + errorsOn(transport) shouldBe emptyList() + } +} diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOptionsTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOptionsTest.kt new file mode 100644 index 0000000..81bf24a --- /dev/null +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOptionsTest.kt @@ -0,0 +1,16 @@ +package io.modelcontextprotocol.kotlin.sdk.shared + +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.Dispatchers +import kotlin.test.Test + +class ProtocolOptionsTest { + + @Test + fun `defaults expose concurrency knobs`() { + val options = ProtocolOptions() + options.handlerCoroutineContext shouldBe Dispatchers.Default + options.maxConcurrentHandlers shouldBe 64 + options.maxInFlightHandlers shouldBe 256 + } +} diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOutboundCancellationTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOutboundCancellationTest.kt new file mode 100644 index 0000000..38ad556 --- /dev/null +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolOutboundCancellationTest.kt @@ -0,0 +1,167 @@ +package io.modelcontextprotocol.kotlin.sdk.shared + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain +import io.modelcontextprotocol.kotlin.sdk.types.CancelledNotificationParams +import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse +import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION +import io.modelcontextprotocol.kotlin.sdk.types.McpException +import io.modelcontextprotocol.kotlin.sdk.types.McpJson +import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.PingRequest +import io.modelcontextprotocol.kotlin.sdk.types.RPCError +import io.modelcontextprotocol.kotlin.sdk.types.RequestId +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.async +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.withTimeout +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.long +import kotlin.coroutines.cancellation.CancellationException +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds + +class ProtocolOutboundCancellationTest { + + @Test + fun `request times out awaiting the response and sends CancelledNotification with timeout reason`() = runTest { + val protocol = TestProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + + val inFlight = async { + shouldThrow { + protocol.request(PingRequest(), RequestOptions(timeout = 5.seconds)) + } + } + val sent = transport.awaitRequest() // request is on the wire; peer never responds + advanceTimeBy(6.seconds) + runCurrent() + + val thrown = inFlight.await() + thrown.code shouldBe RPCError.ErrorCode.REQUEST_TIMEOUT + thrown.data?.jsonObject?.get("timeout")?.jsonPrimitive?.long shouldBe 5.seconds.inWholeMilliseconds + + val cancelledJson = transport.sentWithOptions + .map { it.first } + .filterIsInstance() + .single { it.method == Method.Defined.NotificationsCancelled.value } + val cancelledParams = McpJson.decodeFromJsonElement(cancelledJson.params!!) + cancelledParams.requestId shouldBe sent.id + cancelledParams.reason.shouldNotBeNull() shouldContain "timed out" + } + + @Test + fun `outer withTimeout around request propagates the original timeout exception and notifies the peer`() = runTest { + val protocol = TestProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + + val inFlight = async { + shouldThrow { + withTimeout(1.seconds) { + protocol.request(PingRequest()) + } + } + } + transport.awaitRequest() // request is on the wire; peer never responds + advanceTimeBy(2.seconds) + runCurrent() + inFlight.await() + + transport.sentWithOptions.map { it.first }.filterIsInstance() + .filter { it.method == Method.Defined.NotificationsCancelled.value } shouldHaveSize 1 + } + + @Test + fun `caller cancellation sends CancelledNotification and rethrows the original exception`() = runTest { + val protocol = TestProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + + val cancelled = CompletableDeferred() + val job = launch { + try { + protocol.request(PingRequest()) + } catch (e: CancellationException) { + cancelled.complete(e) + throw e + } + } + transport.awaitRequest() + job.cancelAndJoin() + + cancelled.await() + val wire = transport.sentWithOptions.map { it.first }.filterIsInstance() + .filter { it.method == Method.Defined.NotificationsCancelled.value } + wire shouldHaveSize 1 + } + + @Test + fun `cancelling the initialize request performs local cleanup but sends no CancelledNotification`() = runTest { + val protocol = TestProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + + val job = launch { + protocol.request( + InitializeRequest( + InitializeRequestParams( + protocolVersion = LATEST_PROTOCOL_VERSION, + capabilities = ClientCapabilities(), + clientInfo = Implementation(name = "t", version = "1"), + ), + ), + ) + } + val sent = transport.awaitRequest() + sent.method shouldBe Method.Defined.Initialize.value + job.cancelAndJoin() + + transport.sentWithOptions.map { it.first }.filterIsInstance() + .filter { it.method == Method.Defined.NotificationsCancelled.value } shouldHaveSize 0 + protocol.responseHandlers shouldBe emptyMap() + } + + @Test + fun `late response for a cancelled request is ignored silently`() = runTest { + val protocol = TestProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + + val job = launch { protocol.request(PingRequest()) } + val sent = transport.awaitRequest() + job.cancelAndJoin() + + transport.deliver(JSONRPCResponse(id = sent.id, result = EmptyResult())) + + protocol.errors shouldHaveSize 0 // no "unknown message ID" onError + } + + @Test + fun `response for a genuinely unknown id still reports onError`() = runTest { + val protocol = TestProtocol() + val transport = RecordingTransport() + protocol.connect(transport) + + transport.deliver(JSONRPCResponse(id = RequestId(999L), result = EmptyResult())) + + protocol.errors shouldHaveSize 1 + } +} diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTest.kt index b726c2f..2846ccc 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTest.kt @@ -5,6 +5,9 @@ import io.kotest.matchers.collections.shouldContainExactly import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe +import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.types.shouldBeInstanceOf import io.modelcontextprotocol.kotlin.sdk.types.CustomRequest import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage @@ -13,11 +16,16 @@ import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse import io.modelcontextprotocol.kotlin.sdk.types.McpJson import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.PingRequest +import io.modelcontextprotocol.kotlin.sdk.types.ProgressNotification +import io.modelcontextprotocol.kotlin.sdk.types.ProgressNotificationParams +import io.modelcontextprotocol.kotlin.sdk.types.ProgressToken import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceRequest import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.RequestId import io.modelcontextprotocol.kotlin.sdk.types.RequestMeta import kotlinx.coroutines.async -import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObjectBuilder @@ -30,6 +38,7 @@ import kotlinx.serialization.json.jsonPrimitive import kotlin.coroutines.cancellation.CancellationException import kotlin.test.BeforeTest import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds class ProtocolTest { private lateinit var protocol: TestProtocol @@ -185,64 +194,174 @@ class ProtocolTest { transport.deliver(JSONRPCResponse(sent.id, EmptyResult())) inFlight.await() } -} -private class TestProtocol : Protocol(null) { - val errors = mutableListOf() + @Test + fun `request handler receives enriched extra and ambient context element`() = runTest { + protocol.connect(transport) - override fun onError(error: Throwable) { - errors.add(error) + var seenByParameter: RequestHandlerExtra? = null + var seenAmbient: RequestHandlerExtra? = null + protocol.fallbackRequestHandler = { _, extra -> + seenByParameter = extra + seenAmbient = currentRequestHandlerExtra() + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(7L), method = "custom/echo")) + + seenByParameter shouldNotBe null + seenByParameter?.requestId shouldBe RequestId(7L) + seenByParameter?.method shouldBe Method.Custom("custom/echo") + // the SAME instance flows through both delivery paths + seenAmbient shouldBe seenByParameter } - override fun assertCapabilityForMethod(method: Method) { - // noop - } - override fun assertNotificationCapability(method: Method) { - // noop - } - override fun assertRequestHandlerCapability(method: Method) { - // noop - } -} + @Test + fun `extra method resolves defined methods to Defined entries`() = runTest { + protocol.connect(transport) -private class RecordingTransport : Transport { - private val sentMessages = Channel(Channel.UNLIMITED) - private var onMessageCallback: (suspend (JSONRPCMessage) -> Unit)? = null - private var onCloseCallback: (() -> Unit)? = null + var seenMethod: Method? = null + protocol.setRequestHandler(Method.Defined.Ping) { _, extra -> + seenMethod = extra.method + EmptyResult() + } + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "ping")) - override suspend fun start() { - // noop + seenMethod shouldBe Method.Defined.Ping } - override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) { - sentMessages.send(message) + @Test + fun `extra sendNotification stamps relatedRequestId`() = runTest { + protocol.connect(transport) + + protocol.fallbackRequestHandler = { _, extra -> + extra.sendNotification( + ProgressNotification( + ProgressNotificationParams(progressToken = ProgressToken(1L), progress = 0.5), + ), + ) + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(42L), method = "custom/progressing")) + + val sent = transport.sentWithOptions.first { it.first is JSONRPCNotification } + sent.second?.relatedRequestId shouldBe RequestId(42L) } - override suspend fun close() { - onCloseCallback?.invoke() + @Test + fun `extra sendRequest stamps relatedRequestId and preserves caller options`() = runTest { + protocol.connect(transport) + + protocol.fallbackRequestHandler = { _, extra -> + extra.sendRequest( + PingRequest(), + RequestOptions(resumptionToken = "tok", onProgress = { }, timeout = 30.seconds), + ) + EmptyResult() + } + + // The serial phase runs the handler inline inside deliver(), and the handler suspends + // awaiting the nested request's response — drive delivery from a child coroutine. + val delivery = launch { + transport.deliver(JSONRPCRequest(id = RequestId(42L), method = "custom/nested")) + } + + val outbound = transport.awaitRequest() + val recorded = transport.sentWithOptions + .first { (it.first as? JSONRPCRequest)?.id == outbound.id } + .second + val options = recorded.shouldBeInstanceOf() + options.relatedRequestId shouldBe RequestId(42L) + options.resumptionToken shouldBe "tok" + options.timeout shouldBe 30.seconds + options.onProgress shouldNotBe null + + transport.deliver(JSONRPCResponse(id = outbound.id, result = EmptyResult())) + delivery.join() } - override fun onClose(block: () -> Unit) { - onCloseCallback = block + @Test + fun `currentRequestHandlerExtra returns null outside handlers`() = runTest { + currentRequestHandlerExtra() shouldBe null } - override fun onError(block: (Throwable) -> Unit) { - // noop + @Test + fun `connect while already connected throws IllegalStateException`() = runTest { + protocol.connect(transport) + shouldThrow { + protocol.connect(RecordingTransport()) + } } - override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) { - onMessageCallback = block + @Test + fun `stale onClose from a previous transport does not tear down the successor connection`() = runTest { + protocol.connect(transport) + val staleCloseCallback = transport.closeCallback ?: error("onClose not registered") + + protocol.close() // disconnect first transport (fires its own doClose) + val second = RecordingTransport() + protocol.connect(second) // reconnect + + staleCloseCallback() // late duplicate close signal from transport #1 + + // successor connection must still be alive + protocol.transport shouldBe second } - suspend fun awaitRequest(): JSONRPCRequest { - val message = sentMessages.receive() - return message as? JSONRPCRequest - ?: error("Expected JSONRPCRequest but received ${message::class.simpleName}") + @Test + fun `failed transport start rolls back the connection and allows reconnect`() = runTest { + val failing = object : Transport { + override suspend fun start(): Unit = error("boom") + override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {} + override suspend fun close() {} + override fun onClose(block: () -> Unit) {} + override fun onError(block: (Throwable) -> Unit) {} + override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) {} + } + shouldThrow { protocol.connect(failing) } + protocol.transport shouldBe null // rolled back + protocol.connect(transport) // reconnect succeeds, no "already connected" + protocol.transport shouldBe transport } - suspend fun deliver(message: JSONRPCMessage) { - val callback = onMessageCallback ?: error("onMessage callback not registered") - callback(message) + @Test + fun `request cleans up its handlers when the transport send fails`() = runTest { + // Send fails without closing the connection, so the leak is not masked by doClose(). + val failingSend = object : Transport { + override suspend fun start() {} + override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?): Unit = + throw IllegalStateException("send failed") + override suspend fun close() {} + override fun onClose(block: () -> Unit) {} + override fun onError(block: (Throwable) -> Unit) {} + override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) {} + } + protocol.connect(failingSend) + + shouldThrow { + protocol.request(PingRequest(), RequestOptions(onProgress = {})) + } + + protocol.responseHandlers.size shouldBe 0 + protocol.progressHandlers.size shouldBe 0 + } + + @Test + fun `connect rejects non-positive maxConcurrentHandlers`() = runTest { + val error = shouldThrow { + TestProtocol(ProtocolOptions(maxConcurrentHandlers = 0)).connect(RecordingTransport()) + } + error.message.shouldNotBeNull() shouldContain "maxConcurrentHandlers" + } + + @Test + fun `connect rejects maxInFlightHandlers below maxConcurrentHandlers`() = runTest { + val error = shouldThrow { + TestProtocol(ProtocolOptions(maxConcurrentHandlers = 4, maxInFlightHandlers = 0)) + .connect(RecordingTransport()) + } + error.message.shouldNotBeNull() shouldContain "maxInFlightHandlers" } } diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTestFakes.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTestFakes.kt new file mode 100644 index 0000000..9e8dd60 --- /dev/null +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolTestFakes.kt @@ -0,0 +1,112 @@ +package io.modelcontextprotocol.kotlin.sdk.shared + +import io.modelcontextprotocol.kotlin.sdk.types.CancelledNotificationParams +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCError +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse +import io.modelcontextprotocol.kotlin.sdk.types.McpJson +import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.RequestId +import kotlinx.coroutines.channels.Channel +import kotlinx.serialization.json.encodeToJsonElement + +/** + * Shared [Protocol] test double: records [onError] calls, counts `notifications/initialized` + * router-hook invocations, and no-ops all capability assertions. + * + * The concurrency gate is flipped only via [enableConcurrency]; nothing in this double flips it + * implicitly, so tests keep today's serial semantics unless they opt in. + */ +internal class TestProtocol(options: ProtocolOptions? = null) : Protocol(options) { + val errors = mutableListOf() + var initializedNotificationCount = 0 + + fun enableConcurrency() { + enableConcurrentDispatch() + } + + override fun onInitializedNotification() { + initializedNotificationCount++ + // deliberately does NOT flip the gate — tests control the flip explicitly + } + + override fun onError(error: Throwable) { + errors.add(error) + } + + override fun assertCapabilityForMethod(method: Method) { + // noop + } + override fun assertNotificationCapability(method: Method) { + // noop + } + public override fun assertRequestHandlerCapability(method: Method) { + // noop + } +} + +/** Shared [Transport] test double: records every sent message (with its options) and replays inbound ones. */ +internal class RecordingTransport : Transport { + val sentMessages = Channel(Channel.UNLIMITED) + private var onMessageCallback: (suspend (JSONRPCMessage) -> Unit)? = null + private var onCloseCallback: (() -> Unit)? = null + + val sentWithOptions = mutableListOf>() + + var closeCallback: (() -> Unit)? = null + private set + + override suspend fun start() { + // noop + } + + override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) { + sentWithOptions.add(message to options) + sentMessages.send(message) + } + + override suspend fun close() { + onCloseCallback?.invoke() + } + + override fun onClose(block: () -> Unit) { + closeCallback = block + onCloseCallback = block + } + + override fun onError(block: (Throwable) -> Unit) { + // noop + } + + override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) { + onMessageCallback = block + } + + suspend fun awaitRequest(): JSONRPCRequest { + while (true) { + val message = sentMessages.receive() + if (message is JSONRPCRequest) return message + } + } + + /** Cross-thread-safe reader used by real-dispatcher tests; [sentWithOptions] is single-thread only. */ + suspend fun awaitSent(): JSONRPCMessage = sentMessages.receive() + + suspend fun deliver(message: JSONRPCMessage) { + val callback = onMessageCallback ?: error("onMessage callback not registered") + callback(message) + } +} + +internal fun responsesOn(transport: RecordingTransport): List = + transport.sentWithOptions.map { it.first }.filterIsInstance() + +internal fun errorsOn(transport: RecordingTransport): List = + transport.sentWithOptions.map { it.first }.filterIsInstance() + +internal fun cancelledNotification(requestId: RequestId, reason: String): JSONRPCNotification = JSONRPCNotification( + method = Method.Defined.NotificationsCancelled.value, + params = McpJson.encodeToJsonElement(CancelledNotificationParams(requestId = requestId, reason = reason)), +) diff --git a/kotlin-sdk-core/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyJvmTest.kt b/kotlin-sdk-core/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyJvmTest.kt new file mode 100644 index 0000000..60658f8 --- /dev/null +++ b/kotlin-sdk-core/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/ProtocolConcurrencyJvmTest.kt @@ -0,0 +1,114 @@ +package io.modelcontextprotocol.kotlin.sdk.shared + +import io.kotest.matchers.shouldBe +import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse +import io.modelcontextprotocol.kotlin.sdk.types.RequestId +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.int +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.put +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds + +/** + * Real-dispatcher counterparts to [ProtocolConcurrencyTest]. + * + * These run under [runBlocking] (real time, real threads on [Dispatchers.Default]) rather than + * `runTest`: a virtual-time scheduler auto-advances past the `withTimeout` guards and cannot + * observe genuine cross-thread parallelism, so the concurrency assertions could pass vacuously. + */ +class ProtocolConcurrencyJvmTest { + + @Test + fun `fast request completes while a slow handler is parked on Dispatchers Default`() = runBlocking { + val protocol = TestProtocol(ProtocolOptions(handlerCoroutineContext = Dispatchers.Default)) + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + val slowEntered = CompletableDeferred() + val releaseSlow = CompletableDeferred() + protocol.fallbackRequestHandler = { request, _ -> + if (request.method == "test/slow") { + slowEntered.complete(Unit) + releaseSlow.await() + } + EmptyResult() + } + + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/slow")) + withTimeout(5.seconds) { slowEntered.await() } + transport.deliver(JSONRPCRequest(id = RequestId(2L), method = "test/fast")) + + val fast = withTimeout(5.seconds) { transport.awaitSent() } + (fast as JSONRPCResponse).id shouldBe RequestId(2L) + + releaseSlow.complete(Unit) + val slow = withTimeout(5.seconds) { transport.awaitSent() } + (slow as JSONRPCResponse).id shouldBe RequestId(1L) + Unit + } + + @Test + fun `dispatch stays serial before the gate flips on Dispatchers Default`() = runBlocking { + val protocol = TestProtocol(ProtocolOptions(handlerCoroutineContext = Dispatchers.Default)) + val transport = RecordingTransport() + protocol.connect(transport) + // gate NOT flipped + + val slowEntered = CompletableDeferred() + val releaseSlow = CompletableDeferred() + protocol.fallbackRequestHandler = { request, _ -> + if (request.method == "test/slow") { + slowEntered.complete(Unit) + releaseSlow.await() + } + EmptyResult() + } + + // A single delivering coroutine models the transport read loop: the second deliver cannot + // start until the first returns, so a parked slow handler blocks the fast request. + val delivery = launch { + transport.deliver(JSONRPCRequest(id = RequestId(1L), method = "test/slow")) + transport.deliver(JSONRPCRequest(id = RequestId(2L), method = "test/fast")) + } + withTimeout(5.seconds) { slowEntered.await() } + + // The delivering coroutine is parked inside the slow handler; fast was never delivered. + transport.sentMessages.tryReceive().isFailure shouldBe true + + releaseSlow.complete(Unit) + val first = withTimeout(5.seconds) { transport.awaitSent() } + (first as JSONRPCResponse).id shouldBe RequestId(1L) + val second = withTimeout(5.seconds) { transport.awaitSent() } + (second as JSONRPCResponse).id shouldBe RequestId(2L) + delivery.join() + } + + @Test + fun `suspension-free notification handlers keep arrival order on Dispatchers Default`() = runBlocking { + val protocol = TestProtocol(ProtocolOptions(handlerCoroutineContext = Dispatchers.Default)) + val transport = RecordingTransport() + protocol.connect(transport) + protocol.enableConcurrency() + + // safe: appended only from the delivering coroutine (UNDISPATCHED, suspension-free) + val seen = mutableListOf() + protocol.fallbackNotificationHandler = { notification -> + seen.add((notification.params as JsonObject).getValue("i").jsonPrimitive.int) + } + repeat(100) { i -> + transport.deliver(JSONRPCNotification(method = "test/event", params = buildJsonObject { put("i", i) })) + } + seen shouldBe (0 until 100).toList() + } +} diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.api b/kotlin-sdk-server/api/kotlin-sdk-server.api index 6094b7c..51ac279 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.api @@ -169,8 +169,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/ServerOptions : io/ public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;)V public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Z)V public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;ZLio/modelcontextprotocol/kotlin/sdk/utils/ResourceTemplateMatcherFactory;)V - public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;ZLio/modelcontextprotocol/kotlin/sdk/utils/ResourceTemplateMatcherFactory;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;ZLio/modelcontextprotocol/kotlin/sdk/utils/ResourceTemplateMatcherFactory;Lkotlin/coroutines/CoroutineContext;)V + public synthetic fun (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;ZLio/modelcontextprotocol/kotlin/sdk/utils/ResourceTemplateMatcherFactory;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun getCapabilities ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities; public final fun getResourceTemplateMatcherFactory ()Lio/modelcontextprotocol/kotlin/sdk/utils/ResourceTemplateMatcherFactory; } @@ -198,6 +198,7 @@ public class io/modelcontextprotocol/kotlin/sdk/server/ServerSession : io/modelc public fun onClose ()V public final fun onClose (Lkotlin/jvm/functions/Function0;)V public final fun onInitialized (Lkotlin/jvm/functions/Function0;)V + protected fun onInitializedNotification ()V public final fun ping (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun sendElicitationComplete (Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun sendLoggingMessage (Lio/modelcontextprotocol/kotlin/sdk/types/LoggingMessageNotification;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt index c0d3e84..51a2389 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt @@ -53,9 +53,11 @@ import io.modelcontextprotocol.kotlin.sdk.utils.ResourceTemplateMatcher import io.modelcontextprotocol.kotlin.sdk.utils.ResourceTemplateMatcherFactory import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.put +import kotlin.coroutines.CoroutineContext import kotlin.jvm.JvmOverloads import kotlin.time.ExperimentalTime @@ -69,12 +71,17 @@ private val logger = KotlinLogging.logger {} * Forwarded to [ProtocolOptions.enforceStrictCapabilities]. * @property resourceTemplateMatcherFactory The factory used to create [ResourceTemplateMatcher] instances * for matching resource URIs against registered templates. Defaults to [PathSegmentTemplateMatcher.factory]. + * @param handlerCoroutineContext Coroutine context for inbound handlers. See [ProtocolOptions.handlerCoroutineContext]. */ public class ServerOptions( public val capabilities: ServerCapabilities, enforceStrictCapabilities: Boolean = true, public val resourceTemplateMatcherFactory: ResourceTemplateMatcherFactory = PathSegmentTemplateMatcher.factory, -) : ProtocolOptions(enforceStrictCapabilities = enforceStrictCapabilities) { + handlerCoroutineContext: CoroutineContext = Dispatchers.Default, +) : ProtocolOptions( + enforceStrictCapabilities = enforceStrictCapabilities, + handlerCoroutineContext = handlerCoroutineContext, +) { @JvmOverloads public constructor( capabilities: ServerCapabilities, diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt index d215bd5..880f1cf 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt @@ -108,10 +108,18 @@ public open class ServerSession( } } + override fun onInitializedNotification() { + // Enable concurrency before the user's onInitialized callback, which runs synchronously. + enableConcurrentDispatch() + } + internal val clientConnection: ClientConnection = ClientConnectionImpl(this) /** * Registers a callback to be invoked when the server has completed initialization. + * + * The callback must be synchronous and fast: it runs on the message-dispatch path for + * `notifications/initialized`, after concurrent dispatch has been enabled for the session. */ public fun onInitialized(block: () -> Unit) { val old = _onInitialized 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 c213350..1f8ac39 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 @@ -15,10 +15,12 @@ import io.ktor.server.sse.ServerSSESession import io.ktor.util.collections.ConcurrentMap import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions +import io.modelcontextprotocol.kotlin.sdk.types.CancelledNotificationParams import io.modelcontextprotocol.kotlin.sdk.types.DEFAULT_NEGOTIATED_PROTOCOL_VERSION import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCEmptyMessage import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCError import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCNotification import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse import io.modelcontextprotocol.kotlin.sdk.types.McpJson @@ -27,6 +29,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.RPCError import io.modelcontextprotocol.kotlin.sdk.types.RPCError.ErrorCode.REQUEST_TIMEOUT import io.modelcontextprotocol.kotlin.sdk.types.RequestId import io.modelcontextprotocol.kotlin.sdk.types.SUPPORTED_PROTOCOL_VERSIONS +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.job @@ -175,6 +178,20 @@ public class StreamableHttpServerTransport(private val configuration: Configurat private val requestToStreamMapping: ConcurrentMap = ConcurrentMap() private val requestToResponseMapping: ConcurrentMap = ConcurrentMap() + /** + * JSON-response mode only: one entry per in-flight POST, completed by [send] with the collected + * responses once every request delivered by that POST has been answered. [handlePostRequest] + * awaits it so the HTTP exchange stays open while handlers run concurrently. + */ + private val pendingJsonResponses: ConcurrentMap>> = ConcurrentMap() + + /** + * JSON-response mode only: request ids retired by an inbound cancellation while their POST is + * still awaiting. Treated as settled-without-response so the POST's "a response for every id" + * completion condition is not blocked by a request that will never be answered. + */ + private val cancelledRequestIds: ConcurrentMap = ConcurrentMap() + private val sessionMutex = Mutex() private val streamMutex = Mutex() @@ -241,54 +258,117 @@ public class StreamableHttpServerTransport(private val configuration: Configurat return } + val isTerminated = message is JSONRPCResponse || message is JSONRPCError + + // In JSON mode request-related notifications have no per-request SSE stream. Route them to the + // standalone GET stream before the lookup below, so a notification for an already-retired + // request is delivered there instead of becoming a spurious error. + if (configuration.enableJsonResponse && !isTerminated) { + val standaloneStream = streamsMapping[STANDALONE_SSE_STREAM_ID] + standaloneStream?.let { emitOnStream(STANDALONE_SSE_STREAM_ID, it.session, message) } + return + } + val streamId = requestToStreamMapping[routingRequestId] - ?: error("No connection established for request id $routingRequestId") + if (streamId == null) { + // Request already retired (completed, cancelled, or the JSON POST disconnected). In JSON + // mode a late terminal response is undeliverable and dropped. In SSE mode an unknown id + // is a real routing error. + if (configuration.enableJsonResponse) return + error("No connection established for request id $routingRequestId") + } val activeStream = streamsMapping[streamId] if (!configuration.enableJsonResponse) { activeStream?.let { stream -> emitOnStream(streamId, stream.session, message) } - } - - val isTerminated = message is JSONRPCResponse || message is JSONRPCError - if (!isTerminated) { - if (configuration.enableJsonResponse) { - // In JSON response mode there is no per-request SSE stream, so route notifications - // that are logically associated with a request to the standalone GET SSE stream. - val standaloneStream = streamsMapping[STANDALONE_SSE_STREAM_ID] - standaloneStream?.let { emitOnStream(STANDALONE_SSE_STREAM_ID, it.session, message) } - } - return + if (!isTerminated) return } requestToResponseMapping[responseRequestId!!] = message - val relatedIds = requestToStreamMapping.filterValues { it == streamId }.keys - - if (relatedIds.any { it !in requestToResponseMapping }) return streamMutex.withLock { - if (activeStream == null) error("No connection established for request ID: $routingRequestId") + // The request may have been retired (disconnect or cancellation cleanup) between recording + // the response above and acquiring the lock. Reclaim the stray mapping and drop it. + if (routingRequestId !in requestToStreamMapping) { + requestToResponseMapping.remove(routingRequestId) + return + } + // Recomputed under the lock. Handlers may respond concurrently, and the sender that + // observes the last settled request also retires the ids, so a losing sender sees an + // empty set. A cancelled request counts as settled even though it produces no response. + val relatedIds = requestToStreamMapping.filterValues { it == streamId }.keys + if (relatedIds.isEmpty() || + relatedIds.any { it !in requestToResponseMapping && it !in cancelledRequestIds } + ) { + return + } if (configuration.enableJsonResponse) { - activeStream.call.response.header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) - sessionId?.let { activeStream.call.response.header(MCP_SESSION_ID_HEADER, it) } - val responses = relatedIds.mapNotNull { requestToResponseMapping[it] } - val payload = if (responses.size == 1) { - responses.first() - } else { - responses + // Hand the collected responses to the POST suspended in [handlePostRequest], which + // completes the HTTP exchange. A null pendingPost means the POST was already retired + // (disconnect or cancellation), so the responses are undeliverable and dropped quietly. + val pendingPost = pendingJsonResponses.remove(streamId) + if (pendingPost == null) { + cleanUpRequests(relatedIds) + return } - activeStream.call.respond(payload) + val responses = relatedIds.mapNotNull { requestToResponseMapping[it] } + cleanUpRequests(relatedIds) + pendingPost.complete(responses) } else { - activeStream.session?.close() + // A null stream means the per-request SSE connection closed before the response + // settled, so the ids are retired rather than leaked. + activeStream?.session?.close() + cleanUpRequests(relatedIds) } + } + } - // Clean up - relatedIds.forEach { requestId -> - requestToResponseMapping.remove(requestId) - requestToStreamMapping.remove(requestId) + private fun cleanUpRequests(ids: Collection) { + ids.forEach { requestId -> + requestToResponseMapping.remove(requestId) + requestToStreamMapping.remove(requestId) + cancelledRequestIds.remove(requestId) + } + } + + /** + * Scans a delivered POST body for `notifications/cancelled` and retires each referenced request + * that is awaiting on a JSON-mode POST. No-op unless [Configuration.enableJsonResponse]. + */ + private suspend fun retireCancelledJsonRequests(messages: List) { + if (!configuration.enableJsonResponse) return + val cancelledIds = messages.asSequence() + .filterIsInstance() + .filter { it.method == Method.Defined.NotificationsCancelled.value } + .mapNotNull { notification -> + val params = notification.params ?: return@mapNotNull null + runCatching { + McpJson.decodeFromJsonElement(params).requestId + }.getOrNull() } + .toList() + cancelledIds.forEach { retireCancelledJsonRequest(it) } + } + + /** + * Marks a request cancelled by the peer as settled without a response and completes its POST once + * every request that POST delivered is settled (answered or cancelled). Without this, a cancelled + * request leaves the POST awaiting a response that, by design, is never sent. + */ + private suspend fun retireCancelledJsonRequest(requestId: RequestId) { + streamMutex.withLock { + val streamId = requestToStreamMapping[requestId] ?: return + cancelledRequestIds[requestId] = Unit + val relatedIds = requestToStreamMapping.filterValues { it == streamId }.keys + val allSettled = relatedIds.all { it in requestToResponseMapping || it in cancelledRequestIds } + if (!allSettled) return + val pendingPost = pendingJsonResponses.remove(streamId) ?: return + val responses = relatedIds.mapNotNull { requestToResponseMapping[it] } + cleanUpRequests(relatedIds) + pendingPost.complete(responses) } } @@ -304,6 +384,10 @@ public class StreamableHttpServerTransport(private val configuration: Configurat streamsMapping.clear() requestToStreamMapping.clear() requestToResponseMapping.clear() + cancelledRequestIds.clear() + // Release any POST calls suspended awaiting JSON responses. + pendingJsonResponses.values.forEach { it.cancel() } + pendingJsonResponses.clear() invokeOnCloseCallback() } } @@ -339,7 +423,12 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } /** - * Handles POST requests containing JSON-RPC messages + * Handles POST requests containing JSON-RPC messages. + * + * In JSON-response mode this suspends until a response has been produced for every request in + * the POST body, then completes the HTTP exchange with the collected JSON (a single object for + * one request, an array for a batch). Bodies without requests are acknowledged with 202 + * immediately. In SSE mode the responses are emitted onto the per-request SSE stream instead. */ public suspend fun handlePostRequest(session: ServerSSESession?, call: ApplicationCall) { try { @@ -407,6 +496,9 @@ public class StreamableHttpServerTransport(private val configuration: Configurat if (!hasRequest) { call.respondNullable(status = HttpStatusCode.Accepted, message = null) messages.forEach { message -> _onMessage(message) } + // A cancellation may target a request still awaiting delivery on a JSON-mode POST; + // retire it so that POST completes instead of waiting for a response that never comes. + retireCancelledJsonRequests(messages) return } @@ -429,13 +521,50 @@ public class StreamableHttpServerTransport(private val configuration: Configurat maybeSendPrimingEvent(streamId, session, clientProtocolVersion) } + val pendingPost = if (configuration.enableJsonResponse) { + CompletableDeferred>() + } else { + null + } + streamMutex.withLock { streamsMapping[streamId] = SessionContext(session, call) messages.filterIsInstance().forEach { requestToStreamMapping[it.id] = streamId } + pendingPost?.let { pendingJsonResponses[streamId] = it } } call.coroutineContext.job.invokeOnCompletion { streamsMapping.remove(streamId) } - messages.forEach { message -> _onMessage(message) } + if (pendingPost == null) { + // SSE mode: responses are emitted onto this call's SSE stream by send(). + messages.forEach { message -> _onMessage(message) } + return + } + + // JSON-response mode. Handlers may run concurrently, so returning from delivery no longer + // implies the responses were produced. Suspend until send() has collected a response for + // every request in this POST. A client disconnect or transport close cancels this call. + try { + messages.forEach { message -> _onMessage(message) } + retireCancelledJsonRequests(messages) + val responses = pendingPost.await() + sessionId?.let { call.response.header(MCP_SESSION_ID_HEADER, it) } + if (responses.isEmpty()) { + // Every request in this POST was cancelled before producing a response; there is + // nothing to return, so acknowledge with 202 rather than an empty JSON body. + call.respondNullable(status = HttpStatusCode.Accepted, message = null) + } else { + call.response.header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) + val payload = if (responses.size == 1) responses.first() else responses + call.respond(payload) + } + } finally { + // On cancellation or failure, retire this POST's ids so a late response is dropped + // quietly at the send() boundary instead of leaking mappings. Idempotent no-ops on + // the success path (send() or retirement already cleaned up). + pendingJsonResponses.remove(streamId) + pendingPost.cancel() + cleanUpRequests(messages.filterIsInstance().map { it.id }) + } } catch (e: CancellationException) { throw e } catch (e: Exception) { diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt index d7dec4e..172889a 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt @@ -19,14 +19,19 @@ import io.ktor.http.HttpHeaders import io.ktor.http.HttpStatusCode import io.ktor.http.contentType import io.ktor.serialization.kotlinx.json.json +import io.ktor.server.application.ApplicationCall import io.ktor.server.application.install import io.ktor.server.routing.post import io.ktor.server.routing.routing +import io.ktor.server.sse.ServerSSESession import io.ktor.server.testing.ApplicationTestBuilder import io.ktor.server.testing.testApplication +import io.ktor.sse.ServerSentEvent import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.readLine import io.ktor.utils.io.readUTF8Line +import io.modelcontextprotocol.kotlin.sdk.types.CancelledNotification +import io.modelcontextprotocol.kotlin.sdk.types.CancelledNotificationParams import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult import io.modelcontextprotocol.kotlin.sdk.types.Implementation @@ -46,6 +51,16 @@ import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities import io.modelcontextprotocol.kotlin.sdk.types.Tool import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema import io.modelcontextprotocol.kotlin.sdk.types.toJSON +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.async +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.withTimeout import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.put @@ -53,11 +68,13 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import java.util.concurrent.atomic.AtomicBoolean +import kotlin.coroutines.CoroutineContext import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertFalse import kotlin.test.assertNotNull +import kotlin.time.Duration.Companion.seconds import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation import io.ktor.server.plugins.contentnegotiation.ContentNegotiation as ServerContentNegotiation @@ -349,6 +366,306 @@ class StreamableHttpServerTransportTest { assertEquals("second", secondMeta?.get("label")?.jsonPrimitive?.content)*/ } + @Test + fun `json response waits for a response produced after message delivery returns`() = testApplication { + configTestServer() + + val client = createTestClient() + + val transport = StreamableHttpServerTransport( + StreamableHttpServerTransport.Configuration(enableJsonResponse = true), + ) + // Simulates concurrent dispatch: message delivery returns before the handler responds. + val handlerScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + try { + transport.onMessage { message -> + if (message is JSONRPCRequest) { + if (message.method == Method.Defined.Initialize.value) { + transport.send(JSONRPCResponse(message.id, EmptyResult())) + } else { + handlerScope.launch { + delay(100) + transport.send(JSONRPCResponse(message.id, EmptyResult())) + } + } + } + } + + configureTransportEndpoint(transport) + + val initResponse = client.post(path) { + addStreamableHeaders() + setBody(buildInitializeRequestPayload()) + } + initResponse.status shouldBe HttpStatusCode.OK + + val request = JSONRPCRequest(id = RequestId("async-1"), method = Method.Defined.ToolsList.value) + val response = withTimeout(10.seconds) { + client.post(path) { + addStreamableHeaders() + header(MCP_SESSION_ID_HEADER, initResponse.headers[MCP_SESSION_ID_HEADER]) + setBody(encodeMessages(listOf(request))) + } + } + + response.status shouldBe HttpStatusCode.OK + response.body() shouldBe JSONRPCResponse(request.id) + } finally { + handlerScope.cancel() + } + } + + @Test + fun `json response for a batch waits until every asynchronously produced response is ready`() = testApplication { + configTestServer() + + val client = createTestClient() + + val transport = StreamableHttpServerTransport( + StreamableHttpServerTransport.Configuration(enableJsonResponse = true), + ) + val firstRequest = JSONRPCRequest(id = RequestId("slow"), method = Method.Defined.ToolsList.value) + val secondRequest = JSONRPCRequest(id = RequestId("fast"), method = Method.Defined.ResourcesList.value) + + // Simulates concurrent dispatch with out-of-order completion: the second request responds + // first; the POST must stay open until the slower first response settles too. + val handlerScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + try { + transport.onMessage { message -> + if (message is JSONRPCRequest) { + if (message.method == Method.Defined.Initialize.value) { + transport.send(JSONRPCResponse(message.id, EmptyResult())) + } else { + handlerScope.launch { + delay(if (message.id == firstRequest.id) 200 else 50) + transport.send(JSONRPCResponse(message.id, EmptyResult())) + } + } + } + } + + configureTransportEndpoint(transport) + + val initResponse = client.post(path) { + addStreamableHeaders() + setBody(buildInitializeRequestPayload()) + } + initResponse.status shouldBe HttpStatusCode.OK + + val response = withTimeout(10.seconds) { + client.post(path) { + addStreamableHeaders() + header(MCP_SESSION_ID_HEADER, initResponse.headers[MCP_SESSION_ID_HEADER]) + setBody(encodeMessages(listOf(firstRequest, secondRequest))) + } + } + + response.status shouldBe HttpStatusCode.OK + val responses = response.body>() + responses.map { it.id }.toSet() shouldBe setOf(firstRequest.id, secondRequest.id) + } finally { + handlerScope.cancel() + } + } + + @Test + fun `json response POST completes with 202 when its only request is cancelled`() = testApplication { + configTestServer() + + val client = createTestClient() + + val transport = StreamableHttpServerTransport( + StreamableHttpServerTransport.Configuration(enableJsonResponse = true), + ) + val requestDelivered = CompletableDeferred() + // Concurrent dispatch: delivery returns before a response is produced. This request is never + // answered here, modelling a handler cancelled by notifications/cancelled. + transport.onMessage { message -> + if (message is JSONRPCRequest) { + if (message.method == Method.Defined.Initialize.value) { + transport.send(JSONRPCResponse(message.id, EmptyResult())) + } else { + requestDelivered.complete(Unit) + } + } + } + + configureTransportEndpoint(transport) + + val clientScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + try { + val initResponse = client.post(path) { + addStreamableHeaders() + setBody(buildInitializeRequestPayload()) + } + initResponse.status shouldBe HttpStatusCode.OK + val sessionId = initResponse.headers[MCP_SESSION_ID_HEADER] + + val request = JSONRPCRequest(id = RequestId("cancel-me"), method = Method.Defined.ToolsList.value) + val requestPost = clientScope.async { + client.post(path) { + addStreamableHeaders() + header(MCP_SESSION_ID_HEADER, sessionId) + setBody(encodeMessages(listOf(request))) + } + } + + // The request must be registered in-flight before it can be cancelled. + withTimeout(5.seconds) { requestDelivered.await() } + + val cancellation = CancelledNotification( + CancelledNotificationParams(requestId = request.id, reason = "client cancelled"), + ) + val cancelResponse = client.post(path) { + addStreamableHeaders() + header(MCP_SESSION_ID_HEADER, sessionId) + setBody(encodeMessages(listOf(cancellation.toJSON()))) + } + cancelResponse.status shouldBe HttpStatusCode.Accepted + + // Without retirement of the cancelled id this await never completes and the timeout fires. + val response = withTimeout(10.seconds) { requestPost.await() } + response.status shouldBe HttpStatusCode.Accepted + } finally { + clientScope.cancel() + } + } + + @Test + fun `json response for a batch returns only the non-cancelled responses`() = testApplication { + configTestServer() + + val client = createTestClient() + + val transport = StreamableHttpServerTransport( + StreamableHttpServerTransport.Configuration(enableJsonResponse = true), + ) + val answeredA = JSONRPCRequest(id = RequestId("a"), method = Method.Defined.ToolsList.value) + val answeredB = JSONRPCRequest(id = RequestId("b"), method = Method.Defined.ToolsList.value) + val cancelledC = JSONRPCRequest(id = RequestId("c"), method = Method.Defined.ToolsList.value) + + val cancelledDelivered = CompletableDeferred() + val handlerScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + try { + transport.onMessage { message -> + if (message is JSONRPCRequest) { + when { + message.method == Method.Defined.Initialize.value -> + transport.send(JSONRPCResponse(message.id, EmptyResult())) + + message.id == answeredA.id || message.id == answeredB.id -> + handlerScope.launch { transport.send(JSONRPCResponse(message.id, EmptyResult())) } + + message.id == cancelledC.id -> cancelledDelivered.complete(Unit) + } + } + } + + configureTransportEndpoint(transport) + + val initResponse = client.post(path) { + addStreamableHeaders() + setBody(buildInitializeRequestPayload()) + } + initResponse.status shouldBe HttpStatusCode.OK + val sessionId = initResponse.headers[MCP_SESSION_ID_HEADER] + + val batchPost = handlerScope.async { + client.post(path) { + addStreamableHeaders() + header(MCP_SESSION_ID_HEADER, sessionId) + setBody(encodeMessages(listOf(answeredA, answeredB, cancelledC))) + } + } + + withTimeout(5.seconds) { cancelledDelivered.await() } + + val cancellation = CancelledNotification(CancelledNotificationParams(requestId = cancelledC.id)) + client.post(path) { + addStreamableHeaders() + header(MCP_SESSION_ID_HEADER, sessionId) + setBody(encodeMessages(listOf(cancellation.toJSON()))) + }.status shouldBe HttpStatusCode.Accepted + + val response = withTimeout(10.seconds) { batchPost.await() } + response.status shouldBe HttpStatusCode.OK + val responses = response.body>() + responses.map { it.id }.toSet() shouldBe setOf(answeredA.id, answeredB.id) + } finally { + handlerScope.cancel() + } + } + + @Test + fun `json response send for a retired request id is dropped without error`() = runTest { + val transport = StreamableHttpServerTransport(enableJsonResponse = true) + // No stream is mapped for this id (already retired by disconnect/cancellation cleanup); + // a late terminal response must be dropped quietly, not raise "No connection established". + transport.send(JSONRPCResponse(RequestId("retired"), EmptyResult())) + } + + @Test + fun `sse response send for an unknown request id still errors`() = runTest { + val transport = StreamableHttpServerTransport(enableJsonResponse = false) + assertFailsWith { + transport.send(JSONRPCResponse(RequestId("unknown"), EmptyResult())) + } + } + + @Test + fun `sse terminal response is dropped without leaking when the per-request stream is gone`() = testApplication { + configTestServer() + val client = createTestClient() + + val transport = StreamableHttpServerTransport( + StreamableHttpServerTransport.Configuration(enableJsonResponse = false), + ) + transport.setSessionIdGenerator(null) // stateless: accept requests without an init handshake + val requestId = RequestId("held-request") + val delivered = CompletableDeferred() + val release = CompletableDeferred() + transport.onMessage { message -> + if (message is JSONRPCRequest) { + delivered.complete(Unit) + release.await() // keep the POST and its stream mapping alive until the test releases it + } + } + + application { + routing { + post(path) { + transport.handlePostRequest(FakeServerSSESession(call, call.coroutineContext), call) + } + } + } + + val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + try { + val post = scope.async { + client.post(path) { + addStreamableHeaders() + setBody( + encodeMessages( + listOf(JSONRPCRequest(id = requestId, method = Method.Defined.ToolsList.value)), + ), + ) + } + } + withTimeout(5.seconds) { delivered.await() } + + // Drop the per-request SSE stream while the request is still mapped in-flight; the handler's + // terminal response is now undeliverable and must be dropped quietly rather than raise + // "No connection established" (which would also strand the request mappings). + transport.closeSseStream(requestId) + transport.send(JSONRPCResponse(requestId, EmptyResult())) + + post.cancel() + } finally { + release.complete(Unit) + scope.cancel() + } + } + @ParameterizedTest @MethodSource("invalidPayloads") fun `POST with a null or empty body returns an error`(payload: String?) = testApplication { @@ -694,3 +1011,12 @@ class StreamableHttpServerTransportTest { } } } + +/** No-op [ServerSSESession] double that lets a POST route drive [StreamableHttpServerTransport] in SSE mode. */ +private class FakeServerSSESession( + override val call: ApplicationCall, + override val coroutineContext: CoroutineContext, +) : ServerSSESession { + override suspend fun send(event: ServerSentEvent) {} + override suspend fun close() {} +} From 76987a211b08e0d42f688f7e038eeb449a9ab385 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:21:41 +0200 Subject: [PATCH 096/178] chore(deps): bump the all-dependencies group across 1 directory with 3 updates (#891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 3 updates in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [tsx](https://github.com/privatenumber/tsx) and [typescript](https://github.com/microsoft/TypeScript). Updates `@types/node` from 26.1.0 to 26.1.1
        Commits

        Updates `tsx` from 4.23.0 to 4.23.1
        Release notes

        Sourced from tsx's releases.

        v4.23.1

        4.23.1 (2026-07-13)

        Bug Fixes

        • support tsImport after global preload (8d4ffc2)
        • watch: avoid clearing piped output (95d0672)
        • watch: treat script and dependency paths literally (79fddde)

        Performance Improvements

        • index transform cache lazily (e818ad6)
        • load esbuild lazily in CLI (d067938)
        • map Node TypeScript formats directly (cdcc623)
        • use sync module hooks on Node v22.22.3+ (f8992f1)

        This release is also available on:

        Commits
        • 79fddde fix(watch): treat script and dependency paths literally
        • e818ad6 perf: index transform cache lazily
        • cdcc623 perf: map Node TypeScript formats directly
        • d067938 perf: load esbuild lazily in CLI
        • 95d0672 fix(watch): avoid clearing piped output
        • 6fd4607 docs: add per-page metadata
        • f4176d8 docs: generate sitemap
        • 8d4ffc2 fix: support tsImport after global preload
        • f0e89b2 docs: document Node's public type-stripping API vs internal loader path
        • f8992f1 perf: use sync module hooks on Node v22.22.3+
        • See full diff in compare view

        Updates `typescript` from 6.0.3 to 7.0.2
        Commits
        Maintainer changes

        This version was pushed to npm by microsoft1es, a new releaser for typescript since your current version.


        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 391 +++++++++++++++++- .../src/jvmTest/typescript/package.json | 6 +- 2 files changed, 379 insertions(+), 18 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 4d0c500..c9d73bf 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,10 +15,10 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.1.0", + "@types/node": "^26.1.1", "cors": "^2.8.6", - "tsx": "^4.23.0", - "typescript": "^6.0.3" + "tsx": "^4.23.1", + "typescript": "^7.0.2" } }, "node_modules/@esbuild/aix-ppc64": { @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.0.tgz", - "integrity": "sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==", + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", "dev": true, "license": "MIT", "dependencies": { @@ -623,6 +623,346 @@ "@types/node": "*" } }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -1680,9 +2020,9 @@ } }, "node_modules/tsx": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.0.tgz", - "integrity": "sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz", + "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1713,17 +2053,38 @@ } }, "node_modules/typescript": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", - "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", "dev": true, "license": "Apache-2.0", "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "tsc": "bin/tsc" }, "engines": { - "node": ">=14.17" + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" } }, "node_modules/undici-types": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index bf81140..0cbee82 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,9 +16,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.1.0", + "@types/node": "^26.1.1", "cors": "^2.8.6", - "tsx": "^4.23.0", - "typescript": "^6.0.3" + "tsx": "^4.23.1", + "typescript": "^7.0.2" } } From 8f104268c787e3af2e37b625d45b08b80299d429 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 16:51:27 +0200 Subject: [PATCH 097/178] chore(deps): bump the kotest group across 1 directory with 3 updates (#888) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotest group with 3 updates in the / directory: [io.kotest:kotest-assertions-core](https://github.com/kotest/kotest), [io.kotest:kotest-assertions-json](https://github.com/kotest/kotest) and [io.kotest:kotest-assertions-ktor](https://github.com/kotest/kotest). Updates `io.kotest:kotest-assertions-core` from 6.2.1 to 6.2.2
        Release notes

        Sourced from io.kotest:kotest-assertions-core's releases.

        v6.2.2

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/v6.2.1...v6.2.2

        Commits
        • 4e55e4c Update dependency io.projectreactor.tools:blockhound to v1.0.17.RELEASE (#6164)
        • 3e0202f fix: attach Fail fast scope tracker for each root test case in instance per s...
        • 134c12b Update dependency io.mockk:mockk to v1.14.11 (#6163)
        • 01c7429 fix(kotest-assertions-core): Handle null map values in shouldBeEqualUsingFiel...
        • 44887a5 fix(kotest-framework-engine): Use display-name rendering for ignored tests in...
        • b68ef3e disable return-value-checker for releases (#6165)
        • 86a7d93 Fix typo in proptest config docs (#6155)
        • 1677bd5 Add documentation for OffsetDateTime tolerance matcher (#6161)
        • 47f3efc Document instant-based ZonedDateTime plusOrMinus comparison (#6159)
        • See full diff in compare view

        Updates `io.kotest:kotest-assertions-json` from 6.2.1 to 6.2.2
        Release notes

        Sourced from io.kotest:kotest-assertions-json's releases.

        v6.2.2

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/v6.2.1...v6.2.2

        Commits
        • 4e55e4c Update dependency io.projectreactor.tools:blockhound to v1.0.17.RELEASE (#6164)
        • 3e0202f fix: attach Fail fast scope tracker for each root test case in instance per s...
        • 134c12b Update dependency io.mockk:mockk to v1.14.11 (#6163)
        • 01c7429 fix(kotest-assertions-core): Handle null map values in shouldBeEqualUsingFiel...
        • 44887a5 fix(kotest-framework-engine): Use display-name rendering for ignored tests in...
        • b68ef3e disable return-value-checker for releases (#6165)
        • 86a7d93 Fix typo in proptest config docs (#6155)
        • 1677bd5 Add documentation for OffsetDateTime tolerance matcher (#6161)
        • 47f3efc Document instant-based ZonedDateTime plusOrMinus comparison (#6159)
        • See full diff in compare view

        Updates `io.kotest:kotest-assertions-ktor` from 6.2.1 to 6.2.2
        Release notes

        Sourced from io.kotest:kotest-assertions-ktor's releases.

        v6.2.2

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/v6.2.1...v6.2.2

        Commits
        • 4e55e4c Update dependency io.projectreactor.tools:blockhound to v1.0.17.RELEASE (#6164)
        • 3e0202f fix: attach Fail fast scope tracker for each root test case in instance per s...
        • 134c12b Update dependency io.mockk:mockk to v1.14.11 (#6163)
        • 01c7429 fix(kotest-assertions-core): Handle null map values in shouldBeEqualUsingFiel...
        • 44887a5 fix(kotest-framework-engine): Use display-name rendering for ignored tests in...
        • b68ef3e disable return-value-checker for releases (#6165)
        • 86a7d93 Fix typo in proptest config docs (#6155)
        • 1677bd5 Add documentation for OffsetDateTime tolerance matcher (#6161)
        • 47f3efc Document instant-based ZonedDateTime plusOrMinus comparison (#6159)
        • See full diff in compare view

        Updates `io.kotest:kotest-assertions-json` from 6.2.1 to 6.2.2
        Release notes

        Sourced from io.kotest:kotest-assertions-json's releases.

        v6.2.2

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/v6.2.1...v6.2.2

        Commits
        • 4e55e4c Update dependency io.projectreactor.tools:blockhound to v1.0.17.RELEASE (#6164)
        • 3e0202f fix: attach Fail fast scope tracker for each root test case in instance per s...
        • 134c12b Update dependency io.mockk:mockk to v1.14.11 (#6163)
        • 01c7429 fix(kotest-assertions-core): Handle null map values in shouldBeEqualUsingFiel...
        • 44887a5 fix(kotest-framework-engine): Use display-name rendering for ignored tests in...
        • b68ef3e disable return-value-checker for releases (#6165)
        • 86a7d93 Fix typo in proptest config docs (#6155)
        • 1677bd5 Add documentation for OffsetDateTime tolerance matcher (#6161)
        • 47f3efc Document instant-based ZonedDateTime plusOrMinus comparison (#6159)
        • See full diff in compare view

        Updates `io.kotest:kotest-assertions-ktor` from 6.2.1 to 6.2.2
        Release notes

        Sourced from io.kotest:kotest-assertions-ktor's releases.

        v6.2.2

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/v6.2.1...v6.2.2

        Commits
        • 4e55e4c Update dependency io.projectreactor.tools:blockhound to v1.0.17.RELEASE (#6164)
        • 3e0202f fix: attach Fail fast scope tracker for each root test case in instance per s...
        • 134c12b Update dependency io.mockk:mockk to v1.14.11 (#6163)
        • 01c7429 fix(kotest-assertions-core): Handle null map values in shouldBeEqualUsingFiel...
        • 44887a5 fix(kotest-framework-engine): Use display-name rendering for ignored tests in...
        • b68ef3e disable return-value-checker for releases (#6165)
        • 86a7d93 Fix typo in proptest config docs (#6155)
        • 1677bd5 Add documentation for OffsetDateTime tolerance matcher (#6161)
        • 47f3efc Document instant-based ZonedDateTime plusOrMinus comparison (#6159)
        • See full diff in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0d9b5de..035058d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ netty = "4.2.15.Final" awaitility = "4.3.0" collections-immutable = "0.5.1" coroutines = "1.11.0" -kotest = "6.2.1" +kotest = "6.2.2" kotlinx-io = "0.9.1" ktor = "3.5.1" logging = "8.0.4" From dbd34ff327c654e3811326192cc0bceb2543992e Mon Sep 17 00:00:00 2001 From: Klyne Chrysler Date: Thu, 16 Jul 2026 00:38:21 +0800 Subject: [PATCH 098/178] close stateless streamable http session after request completion (#872) fixes #786 stateless streamable http endpoint never closed its per request session, so the session registry and notification subscriptions grew forever. now the session is closed in a finally block after each request, which triggers the existing cleanup. also removed the per request server.onClose logging callback that accumulated on shared servers. added tests proving sessions are removed after normal and rejected requests. jvmTest, ktlint, detekt, apiCheck all pass. no public api changes. Co-authored-by: Pavel Gorgulov --- .../kotlin/sdk/server/KtorServer.kt | 14 ++- ...elessStreamableHttpSessionLifecycleTest.kt | 100 ++++++++++++++++++ 2 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StatelessStreamableHttpSessionLifecycleTest.kt 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 ec0652b..73ef258 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 @@ -380,11 +380,17 @@ private suspend fun RoutingContext.mcpStatelessStreamableHttpEndpoint( logger.info { "New stateless StreamableHttp connection established without sessionId" } val server = block() - server.onClose { logger.info { "Server connection closed without sessionId" } } - server.createSession(transport) + val session = server.createSession(transport) - transport.handleRequest(null, this.call) - logger.debug { "Server connected to transport without sessionId" } + try { + transport.handleRequest(null, this.call) + logger.debug { "Server connected to transport without sessionId" } + } finally { + // A stateless session serves exactly one request: close it so the server's + // session registry and notification subscriptions do not grow unboundedly. + session.close() + logger.debug { "Stateless session closed after request completion" } + } } private suspend fun RoutingContext.mcpPostEndpoint(transportManager: TransportManager) { diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StatelessStreamableHttpSessionLifecycleTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StatelessStreamableHttpSessionLifecycleTest.kt new file mode 100644 index 0000000..3646faf --- /dev/null +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StatelessStreamableHttpSessionLifecycleTest.kt @@ -0,0 +1,100 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.kotest.assertions.nondeterministic.eventually +import io.kotest.matchers.maps.shouldBeEmpty +import io.kotest.matchers.shouldBe +import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.header +import io.ktor.client.request.post +import io.ktor.client.request.setBody +import io.ktor.http.ContentType +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpStatusCode +import io.ktor.http.contentType +import io.ktor.server.testing.testApplication +import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION +import io.modelcontextprotocol.kotlin.sdk.types.McpJson +import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.toJSON +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds + +/** + * Verifies that the stateless Streamable HTTP endpoint does not leak server sessions: + * every session created to serve a single request must be closed and removed from the + * session registry once that request completes (https://github.com/modelcontextprotocol/kotlin-sdk/issues/786). + */ +class StatelessStreamableHttpSessionLifecycleTest { + + private fun testServer(): Server = Server( + Implementation("test-server", "1.0"), + ServerOptions(capabilities = ServerCapabilities()), + ) + + @Test + fun `stateless endpoint removes session after each request`() = testApplication { + val server = testServer() + application { + mcpStatelessStreamableHttp { server } + } + + repeat(5) { + val response = client.post("/mcp") { + addStreamableHeaders() + setBody(initializeRequestBody()) + } + response.status shouldBe HttpStatusCode.OK + } + + eventually(5.seconds) { + server.sessions.shouldBeEmpty() + } + } + + @Test + fun `stateless endpoint removes session when the request is rejected`() = testApplication { + val server = testServer() + application { + mcpStatelessStreamableHttp { server } + } + + // Missing "text/event-stream" in Accept makes the transport reject the request. + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Accept, ContentType.Application.Json.toString()) + contentType(ContentType.Application.Json) + setBody(initializeRequestBody()) + } + response.status shouldBe HttpStatusCode.NotAcceptable + + eventually(5.seconds) { + server.sessions.shouldBeEmpty() + } + } + + private fun HttpRequestBuilder.addStreamableHeaders() { + header(HttpHeaders.Host, "localhost") + header( + HttpHeaders.Accept, + listOf(ContentType.Application.Json, ContentType.Text.EventStream).joinToString(", "), + ) + contentType(ContentType.Application.Json) + } + + private fun initializeRequestBody(): String { + val request = InitializeRequest( + InitializeRequestParams( + protocolVersion = LATEST_PROTOCOL_VERSION, + capabilities = ClientCapabilities(), + clientInfo = Implementation(name = "test-client", version = "1.0.0"), + ), + ).toJSON() + + return McpJson.encodeToString(JSONRPCMessage.serializer(), request) + } +} From e464e69a081aea36cb5d11393e6f2ae4d4eb9c9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 23:43:10 +0200 Subject: [PATCH 099/178] chore(deps): bump io.netty:netty-bom from 4.2.15.Final to 4.2.16.Final in the infrastructure group across 1 directory (#889) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the infrastructure group with 1 update in the / directory: [io.netty:netty-bom](https://github.com/netty/netty). Updates `io.netty:netty-bom` from 4.2.15.Final to 4.2.16.Final
        Release notes

        Sourced from io.netty:netty-bom's releases.

        netty-4.2.16.Final

        What's Changed

        ... (truncated)

        Commits
        • 3703d79 [maven-release-plugin] prepare release netty-4.2.16.Final
        • 63bbb2c Update rust toolchain - add required parameters
        • ac06c1b Update rust toolchain
        • 5b68c61 Merge branches from forks (#17063)
        • de5d276 Update lz4-java to 1.11.1 (#17061)
        • da22048 Pin github actions to reduce risk (#17043)
        • 0332676 Fix maxAllocation for brotli-encoded content in HttpContentDecompressor (#17037)
        • 7364401 Support QPACK sensitivity detector for Never Indexed header fields (#17026)
        • 06faf18 Allow WebSocket extension negotiation to be disabled per response (#17030)
        • bc4b983 Implement Adaptive Cumulator (#16731)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 035058d..235f0e9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kover = "0.9.8" ktlint = "14.2.0" knit = "0.5.1" mavenPublish = "0.37.0" -netty = "4.2.15.Final" +netty = "4.2.16.Final" # libraries version awaitility = "4.3.0" From c984bc7a327dd251d42cea0b7cdbb1ecf7ffb561 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:39:09 +0200 Subject: [PATCH 100/178] chore(deps): bump ch.qos.logback:logback-classic from 1.5.37 to 1.5.38 (#890) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.37 to 1.5.38.
        Release notes

        Sourced from ch.qos.logback:logback-classic's releases.

        Logback 1.5.38

        2026-07-09 Release of logback version 1.5.38

        • In HardenedObjectInputStream, fixed a typo preventing Throwable objects from being white-filtered. This issue was reported in [PR #1045](qos-ch/logback#1045) by t0rchwo0d.

        • A bitwise identical binary of this version can be reproduced by building from source code at commit d04984a41fce42977466f45a2f076f0ee5cc4207 associated with the tag v_1.5.38. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

        Commits
        • d04984a prepare release 1.5.38
        • 4fffda6 updateversion of maven-gpg-plugin
        • 7ee48a1 Fixed a typo where java,lang.Throwable was written with a comma instead of a ...
        • 84580a2 remove license profile
        • f817c8d start work on 1.5.28-SNAPSHOT
        • See full diff in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 235f0e9..8591f0d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" slf4j = "2.0.18" -logback = "1.5.37" +logback = "1.5.38" junit = "5.14.4" [libraries] From 5cb76fd0401dc33ff279520456dfee62033f363e Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Thu, 16 Jul 2026 15:41:46 +0200 Subject: [PATCH 101/178] fix(core): clear recently-cancelled request ids on connection close (#892) Clear the recently-cancelled request id buffer in `doClose` so connection teardown fully resets per-request bookkeeping. ## Motivation and Context Follow-up to #884. `doClose` already resets `_responseHandlers`, `_progressHandlers`, and `inFlightRequestJobs`, but left `recentlyCancelledRequestIds` populated across a close. This aligns teardown to clear all Protocol-scoped per-request state. Not a correctness bug: the buffer is bounded (256) and self-evicting, request ids are random UUIDs so stale entries cannot false-match a new connection, and the post-close `onMessage` guard drops late messages from the old transport before the buffer is consulted. The change removes the lone asymmetry in `doClose`. ## How Has This Been Tested? - `./gradlew :kotlin-sdk-core:compileKotlinJvm` - `./gradlew :kotlin-sdk-core:jvmTest --tests "*ProtocolTest*"` ## Breaking Changes None. ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [ ] I have added appropriate error handling - [ ] I have added or updated documentation as needed ## Additional context `recentlyCancelledRequestIds` is Protocol-scoped (like `_responseHandlers`/`_progressHandlers`), so it is reset in `doClose` rather than on the per-connection `Connection` object. --- .../kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt index 3515b4a..0c82f5e 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt @@ -436,6 +436,7 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio } val handlersToNotify = _responseHandlers.getAndSet(persistentMapOf()).values.toList() _progressHandlers.getAndSet(persistentMapOf()) + recentlyCancelledRequestIds.getAndSet(persistentListOf()) connection.inFlightRequestJobs.getAndSet(persistentMapOf()) connection.handlerScope.cancel() onClose() From 309d88fe1d4c3e2553553031290b001d65587fef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 13:58:22 +0200 Subject: [PATCH 102/178] chore(deps): bump the other-dependencies group across 2 directories with 3 updates (#897) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 2 updates in the /samples/kotlinlang-mcp-server directory: [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) and [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 2 updates in the /samples/simple-streamable-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow) and [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework). Updates `ch.qos.logback:logback-classic` from 1.5.37 to 1.5.38
        Release notes

        Sourced from ch.qos.logback:logback-classic's releases.

        Logback 1.5.38

        2026-07-09 Release of logback version 1.5.38

        • In HardenedObjectInputStream, fixed a typo preventing Throwable objects from being white-filtered. This issue was reported in [PR #1045](qos-ch/logback#1045) by t0rchwo0d.

        • A bitwise identical binary of this version can be reproduced by building from source code at commit d04984a41fce42977466f45a2f076f0ee5cc4207 associated with the tag v_1.5.38. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

        Commits
        • d04984a prepare release 1.5.38
        • 4fffda6 updateversion of maven-gpg-plugin
        • 7ee48a1 Fixed a typo where java,lang.Throwable was written with a comma instead of a ...
        • 84580a2 remove license profile
        • f817c8d start work on 1.5.28-SNAPSHOT
        • See full diff in compare view

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.0
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.0
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.0
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `org.junit.jupiter:junit-jupiter` from 6.1.1 to 6.1.2
        Release notes

        Sourced from org.junit.jupiter:junit-jupiter's releases.

        JUnit 6.1.2 = Platform 6.1.2 + Jupiter 6.1.2 + Vintage 6.1.2

        See Release Notes.

        Full Changelog: https://github.com/junit-team/junit-framework/compare/r6.1.1...r6.1.2

        Commits
        • b685426 Release 6.1.2
        • ae244a6 Remove blanket outputDirectoryCreator from SuiteEngineTests (#5793)
        • 43bd154 Finalize 6.1.2 release notes
        • 0cd9510 Fix order of release note sections
        • a1507cb Add initial 6.1.2 release notes to release notes index
        • 9326641 Fix NoTestsDiscoveredException for suites containing only dynamic tests (#5839)
        • 2ef1123 Create initial 6.1.2 release notes from template
        • 83fa9ab Back to snapshots for further development
        • See full diff in compare view

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.0
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
        Dependabot commands and options
        You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 4 ++-- samples/simple-streamable-server/gradle/libs.versions.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 029aae2..047c0bf 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -4,8 +4,8 @@ ktor = "3.5.1" mcp-kotlin = "0.14.0" serialization = "1.11.0" coroutines = "1.11.0" -logback = "1.5.37" -shadow = "9.5.1" +logback = "1.5.38" +shadow = "9.6.0" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 376bc9b..bbf7120 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] kotlin = "2.4.0" ktor = "3.5.1" -junit = "6.1.1" +junit = "6.1.2" mcp-kotlin = "0.14.0" slf4j = "2.0.18" -shadow = "9.5.1" +shadow = "9.6.0" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } From 0ea42519ed6e83ef3d8e3ef928e1f0df6e96115c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 15:46:44 +0200 Subject: [PATCH 103/178] chore(deps): bump org.jetbrains.kotlin.jvm from 2.4.0 to 2.4.10 in /samples/kotlin-mcp-client (#899) Bumps [org.jetbrains.kotlin.jvm](https://github.com/JetBrains/kotlin) from 2.4.0 to 2.4.10.
        Release notes

        Sourced from org.jetbrains.kotlin.jvm's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.jvm's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index f674a64..732dfbd 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] anthropic = "2.48.0" -kotlin = "2.4.0" +kotlin = "2.4.10" ktor = "3.5.1" mcp-kotlin = "0.14.0" shadow = "9.5.1" From 078e739424af944089cfab48a0a0ed271f161950 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:49:15 +0200 Subject: [PATCH 104/178] chore(deps): bump org.jetbrains.kotlinx.kover from 0.9.8 to 0.9.9 in the gradle-plugins group across 1 directory (#902) Bumps the gradle-plugins group with 1 update in the / directory: [org.jetbrains.kotlinx.kover](https://github.com/Kotlin/kotlinx-kover). Updates `org.jetbrains.kotlinx.kover` from 0.9.8 to 0.9.9
        Release notes

        Sourced from org.jetbrains.kotlinx.kover's releases.

        0.9.9

        Kover Gradle Plugin

        Bugfixes

        Changelog

        Sourced from org.jetbrains.kotlinx.kover's changelog.

        0.9.9 / 2026-07-17

        Kover Gradle Plugin

        Bugfixes

        Commits

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8591f0d..6d3c5a8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ binaryCompatibilityValidatorPlugin = "0.18.1" detekt = "2.0.0-alpha.5" dokka = "2.2.0" kotlin = "2.4.0" -kover = "0.9.8" +kover = "0.9.9" ktlint = "14.2.0" knit = "0.5.1" mavenPublish = "0.37.0" From 737b46f03299f038270b30176fc3b2f849770266 Mon Sep 17 00:00:00 2001 From: Takuya Akamatsu Date: Wed, 22 Jul 2026 01:17:16 +0900 Subject: [PATCH 105/178] feat(server): validate accepted elicitation content against the requested schema (#896) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Validate accepted form-mode elicitation `content` against the `requestedSchema` on the server, rejecting mismatches with an `INVALID_PARAMS` error. fixes #895 ## Motivation and Context `createElicitation` returned accepted content to server code as-is. The specification's form-mode security guidance says "Servers SHOULD validate received data matches the requested schema" ([2025-11-25, Form Mode Security](https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation#form-mode-security)). Comparable validation already exists in the TypeScript SDK's `elicitInput` and Python's `elicit_with_validation` helper. Details and design notes are in #895. ## How Has This Been Tested? New unit tests for the validator and integration tests over an in-memory client–server pair. ## Breaking Changes No API changes. Behavioral note: an accepted form-mode response that does not match the requested schema now fails `createElicitation` with `McpException` (`INVALID_PARAMS`) instead of being returned to the caller. ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed Co-authored-by: Pavel Gorgulov --- .../kotlin/sdk/client/ClientTest.kt | 97 ++++ .../kotlin/sdk/server/ClientConnection.kt | 22 +- .../sdk/server/ElicitationValidation.kt | 174 +++++++ .../kotlin/sdk/server/ServerSession.kt | 7 +- .../sdk/server/ElicitationValidationTest.kt | 438 ++++++++++++++++++ 5 files changed, 735 insertions(+), 3 deletions(-) create mode 100644 kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidation.kt create mode 100644 kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidationTest.kt diff --git a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt index 54d25ee..099329d 100644 --- a/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt +++ b/integration-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt @@ -1124,6 +1124,103 @@ class ClientTest { assertEquals(elicitationResultContent, result.content) } + @Test + fun `should reject accepted elicitation content that does not match requested schema`() = runTest { + val requestedSchema = ElicitRequestParams.RequestedSchema( + properties = mapOf("name" to StringSchema()), + required = listOf("name"), + ) + val (client, serverSession) = setupElicitationPair { + ElicitResult(action = ElicitResult.Action.Accept, content = buildJsonObject { put("name", 42) }) + } + + val exception = assertFailsWith { + serverSession.createElicitation(message = "mismatch", requestedSchema = requestedSchema) + } + assertTrue( + exception.message.orEmpty() + .startsWith("Elicitation response content does not match requested schema: "), + "Unexpected message: ${exception.message}", + ) + assertTrue("'name' must be string" in exception.message.orEmpty(), "Unexpected message: ${exception.message}") + + client.close() + } + + @Test + fun `should reject accepted elicitation without content when schema has required properties`() = runTest { + val requestedSchema = ElicitRequestParams.RequestedSchema( + properties = mapOf("name" to StringSchema()), + required = listOf("name"), + ) + val (client, serverSession) = setupElicitationPair { + ElicitResult(action = ElicitResult.Action.Accept, content = null) + } + + val exception = assertFailsWith { + serverSession.createElicitation(message = "no content", requestedSchema = requestedSchema) + } + assertTrue( + "must have required property 'name'" in exception.message.orEmpty(), + "Unexpected message: ${exception.message}", + ) + + client.close() + } + + @Test + fun `should accept elicitation without content when schema has no required properties`() = runTest { + val requestedSchema = ElicitRequestParams.RequestedSchema( + properties = mapOf("name" to StringSchema()), + ) + val (client, serverSession) = setupElicitationPair { + ElicitResult(action = ElicitResult.Action.Accept, content = null) + } + + val result = serverSession.createElicitation(message = "no required", requestedSchema = requestedSchema) + + assertEquals(ElicitResult.Action.Accept, result.action) + assertNull(result.content) + + client.close() + } + + @Test + fun `should pass through declined elicitation without validation`() = runTest { + val requestedSchema = ElicitRequestParams.RequestedSchema( + properties = mapOf("name" to StringSchema()), + required = listOf("name"), + ) + val (client, serverSession) = setupElicitationPair { + ElicitResult(action = ElicitResult.Action.Decline) + } + + val result = serverSession.createElicitation(message = "decline", requestedSchema = requestedSchema) + + assertEquals(ElicitResult.Action.Decline, result.action) + assertNull(result.content) + + client.close() + } + + @Test + fun `should pass through cancelled elicitation without validation`() = runTest { + val requestedSchema = ElicitRequestParams.RequestedSchema( + properties = mapOf("name" to StringSchema()), + required = listOf("name"), + ) + val (client, serverSession) = setupElicitationPair { + ElicitResult(action = ElicitResult.Action.Cancel) + } + + val result = serverSession.createElicitation(message = "cancel", requestedSchema = requestedSchema) + + assertEquals(ElicitResult.Action.Cancel, result.action) + assertNull(result.content) + + client.close() + } + @Test fun `should apply elicitation defaults for missing fields in empty content`() = runTest { val schema = defaultsTestSchema() diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt index 343774b..21e0925 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt @@ -10,12 +10,14 @@ import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestParams import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestURLParams import io.modelcontextprotocol.kotlin.sdk.types.ElicitResult import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotification +import io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject import io.modelcontextprotocol.kotlin.sdk.types.EmptyResult import io.modelcontextprotocol.kotlin.sdk.types.IncludeContext import io.modelcontextprotocol.kotlin.sdk.types.ListRootsRequest import io.modelcontextprotocol.kotlin.sdk.types.ListRootsResult import io.modelcontextprotocol.kotlin.sdk.types.LoggingLevel import io.modelcontextprotocol.kotlin.sdk.types.LoggingMessageNotification +import io.modelcontextprotocol.kotlin.sdk.types.McpException import io.modelcontextprotocol.kotlin.sdk.types.PingRequest import io.modelcontextprotocol.kotlin.sdk.types.PromptListChangedNotification import io.modelcontextprotocol.kotlin.sdk.types.Request @@ -95,12 +97,17 @@ public interface ClientConnection { * Sends a message to the client requesting elicitation. * This typically results in a form being displayed to the end user. * + * Accepted content is validated against [requestedSchema]. If content is absent, an empty + * object is used for validation only, so declared `required` properties still apply. The + * returned [ElicitResult] is not modified. + * * @param message The message for the elicitation to display. - * @param requestedSchema The schema requested by the client for the elicitation result. + * @param requestedSchema The schema the server requests for the elicitation result. * Influences the form displayed to the user. * @param options Optional request options. * @return The result of the elicitation request. * @throws IllegalStateException If the server or client does not support elicitation. + * @throws McpException If an accepted response does not match [requestedSchema]. */ public suspend fun createElicitation( message: String, @@ -130,10 +137,15 @@ public interface ClientConnection { * Sends a message to the client requesting elicitation. * This typically results in a form being displayed to the user. * + * For form-mode requests, accepted content is validated against the requested schema. If + * content is absent, an empty object is used for validation only, so declared `required` + * properties still apply. The returned [ElicitResult] is not modified. + * * @param request The elicitation request parameters. * @param options Optional request options. * @return The result of the elicitation request. * @throws IllegalStateException If the server or client does not support elicitation. + * @throws McpException If an accepted form-mode response does not match its requested schema. */ public suspend fun createElicitation(request: ElicitRequest, options: RequestOptions? = null): ElicitResult @@ -256,7 +268,13 @@ internal class ClientConnectionImpl(private val session: ServerSession) : Client } } logger.trace { "ElicitRequest: $request" } - return request(request, options) + val result: ElicitResult = request(request, options) + if (params is ElicitRequestFormParams && result.action == ElicitResult.Action.Accept) { + // Peer-response backstop: accepted form content is client-supplied. Absent content is + // validated as an empty object so declared `required` properties still apply. + validateElicitationContent(params.requestedSchema, result.content ?: EmptyJsonObject) + } + return result } override suspend fun createElicitation( diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidation.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidation.kt new file mode 100644 index 0000000..d976d34 --- /dev/null +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidation.kt @@ -0,0 +1,174 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.modelcontextprotocol.kotlin.sdk.types.BooleanSchema +import io.modelcontextprotocol.kotlin.sdk.types.DoubleSchema +import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.IntegerSchema +import io.modelcontextprotocol.kotlin.sdk.types.LegacyTitledEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.McpException +import io.modelcontextprotocol.kotlin.sdk.types.PrimitiveSchemaDefinition +import io.modelcontextprotocol.kotlin.sdk.types.RPCError +import io.modelcontextprotocol.kotlin.sdk.types.StringSchema +import io.modelcontextprotocol.kotlin.sdk.types.TitledMultiSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.TitledSingleSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.UntitledMultiSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.UntitledSingleSelectEnumSchema +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.booleanOrNull +import kotlinx.serialization.json.doubleOrNull +import kotlinx.serialization.json.longOrNull +import kotlin.math.floor + +/** + * Validates accepted form-mode elicitation [content] against the supported constraints in + * [requestedSchema]: types, `required`, numeric bounds, string lengths, enum membership, and item + * counts. Undeclared properties are permitted. + * [StringSchema.format] values are treated as annotations and are not asserted. + * + * @throws McpException with [RPCError.ErrorCode.INVALID_PARAMS] listing the detected violations + * (at most one per property). + */ +internal fun validateElicitationContent(requestedSchema: ElicitRequestParams.RequestedSchema, content: JsonObject) { + val errors = buildList { + for (name in requestedSchema.required.orEmpty()) { + if (name !in content) add("must have required property '$name'") + } + for ((name, schema) in requestedSchema.properties) { + val value = content[name] ?: continue + checkProperty(name, schema, value)?.let(::add) + } + } + if (errors.isNotEmpty()) { + throw McpException( + code = RPCError.ErrorCode.INVALID_PARAMS, + message = "Elicitation response content does not match requested schema: ${errors.joinToString(", ")}", + ) + } +} + +private fun checkProperty(name: String, schema: PrimitiveSchemaDefinition, value: JsonElement): String? = + when (schema) { + is StringSchema -> { + val string = stringValue(value) ?: return "'$name' must be string" + val minLength = schema.minLength + val maxLength = schema.maxLength + val length = codePointCount(string) + when { + minLength != null && length < minLength -> + "'$name' must NOT have fewer than $minLength characters" + + maxLength != null && length > maxLength -> + "'$name' must NOT have more than $maxLength characters" + + else -> null + } + } + + is IntegerSchema -> { + val integer = integerValue(value) ?: return "'$name' must be integer" + checkRange(name, integer, schema.minimum?.toLong(), schema.maximum?.toLong()) + } + + is DoubleSchema -> { + val number = doubleValue(value) ?: return "'$name' must be number" + checkRange(name, number, schema.minimum, schema.maximum) + } + + is BooleanSchema -> if (booleanValue(value) == null) "'$name' must be boolean" else null + + is UntitledSingleSelectEnumSchema -> checkEnum(name, value, schema.enumValues) + + is TitledSingleSelectEnumSchema -> checkEnum(name, value, schema.oneOf.map { it.const }) + + is LegacyTitledEnumSchema -> checkEnum(name, value, schema.enumValues) + + is UntitledMultiSelectEnumSchema -> + checkMultiSelect(name, value, schema.items.enumValues, schema.minItems, schema.maxItems) + + is TitledMultiSelectEnumSchema -> + checkMultiSelect(name, value, schema.items.anyOf.map { it.const }, schema.minItems, schema.maxItems) + } + +// Keep Double statically typed so comparisons use IEEE 754 semantics; generic Comparable ordering +// treats -0.0 as less than 0.0. +private fun checkRange( + name: String, + value: Long, + minimum: Long?, + maximum: Long?, +): String? = when { + minimum != null && value < minimum -> "'$name' must be >= $minimum" + maximum != null && value > maximum -> "'$name' must be <= $maximum" + else -> null +} + +private fun checkRange( + name: String, + value: Double, + minimum: Double?, + maximum: Double?, +): String? = when { + minimum != null && value < minimum -> "'$name' must be >= $minimum" + maximum != null && value > maximum -> "'$name' must be <= $maximum" + else -> null +} + +private fun checkEnum(name: String, value: JsonElement, allowed: List): String? { + val string = stringValue(value) ?: return "'$name' must be string" + return if (string in allowed) null else "'$name' must be equal to one of the allowed values" +} + +private fun checkMultiSelect( + name: String, + value: JsonElement, + allowed: List, + minItems: Int?, + maxItems: Int?, +): String? { + val array = value as? JsonArray ?: return "'$name' must be array" + if (minItems != null && array.size < minItems) return "'$name' must NOT have fewer than $minItems items" + if (maxItems != null && array.size > maxItems) return "'$name' must NOT have more than $maxItems items" + for (element in array) { + val item = stringValue(element) ?: return "'$name' items must be string" + if (item !in allowed) return "'$name' items must be equal to one of the allowed values" + } + return null +} + +// JSON distinguishes the string "42" from the number 42; kotlinx's JsonPrimitive accessors parse +// string content too, so every helper checks isString to preserve that distinction. + +private fun stringValue(value: JsonElement): String? = (value as? JsonPrimitive)?.takeIf { it.isString }?.content + +private fun integerValue(value: JsonElement): Long? { + val primitive = (value as? JsonPrimitive)?.takeIf { !it.isString } ?: return null + primitive.longOrNull?.let { return it } + // JSON Schema's "integer" also matches numbers with a zero fractional part (e.g. 5.0, 1e2). + // Values that do not parse as Long are evaluated using their finite Double representation. + val number = primitive.doubleOrNull ?: return null + return if (number.isFinite() && number == floor(number)) number.toLong() else null +} + +private fun doubleValue(value: JsonElement): Double? = + (value as? JsonPrimitive)?.takeIf { !it.isString }?.doubleOrNull?.takeIf { it.isFinite() } + +private fun booleanValue(value: JsonElement): Boolean? = + (value as? JsonPrimitive)?.takeIf { !it.isString }?.booleanOrNull + +// JSON Schema string lengths count Unicode code points (RFC 8259 characters), not UTF-16 units, +// so a surrogate pair is one character. +private fun codePointCount(string: String): Int { + var count = 0 + var index = 0 + while (index < string.length) { + if (string[index].isHighSurrogate() && index + 1 < string.length && string[index + 1].isLowSurrogate()) { + index++ + } + index++ + count++ + } + return count +} diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt index 880f1cf..f20d3e1 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt @@ -421,12 +421,17 @@ public open class ServerSession( * Sends a message to the client requesting an elicitation. * This typically results in a form being displayed to the end user. * + * Accepted content is validated against [requestedSchema]. If content is absent, an empty + * object is used for validation only, so declared `required` properties still apply. The + * returned [ElicitResult] is not modified. + * * @param message The message for the elicitation to display. - * @param requestedSchema The schema requested by the client for the elicitation result. + * @param requestedSchema The schema the server requests for the elicitation result. * Influences the form displayed to the user. * @param options Optional request options. * @return The result of the elicitation request. * @throws IllegalStateException If the server or client does not support elicitation. + * @throws McpException If an accepted response does not match [requestedSchema]. */ public suspend fun createElicitation( message: String, diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidationTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidationTest.kt new file mode 100644 index 0000000..b218b47 --- /dev/null +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ElicitationValidationTest.kt @@ -0,0 +1,438 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.modelcontextprotocol.kotlin.sdk.types.BooleanSchema +import io.modelcontextprotocol.kotlin.sdk.types.DoubleSchema +import io.modelcontextprotocol.kotlin.sdk.types.ElicitRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.EnumOption +import io.modelcontextprotocol.kotlin.sdk.types.IntegerSchema +import io.modelcontextprotocol.kotlin.sdk.types.LegacyTitledEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.McpException +import io.modelcontextprotocol.kotlin.sdk.types.McpJson +import io.modelcontextprotocol.kotlin.sdk.types.PrimitiveSchemaDefinition +import io.modelcontextprotocol.kotlin.sdk.types.RPCError +import io.modelcontextprotocol.kotlin.sdk.types.StringSchema +import io.modelcontextprotocol.kotlin.sdk.types.StringSchemaFormat +import io.modelcontextprotocol.kotlin.sdk.types.TitledMultiSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.TitledSingleSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.UntitledMultiSelectEnumSchema +import io.modelcontextprotocol.kotlin.sdk.types.UntitledSingleSelectEnumSchema +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.add +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import kotlinx.serialization.json.putJsonArray +import kotlinx.serialization.json.putJsonObject +import org.junit.jupiter.api.assertDoesNotThrow +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertTrue + +/** + * Unit tests for [validateElicitationContent]: pure-function checks of accepted form-mode + * content against the requested schema. + * + * End-to-end tests for the `createElicitation` round trip live in the `integration-test` + * module under `io.modelcontextprotocol.kotlin.sdk.client`. + */ +class ElicitationValidationTest { + + private fun schema(vararg properties: Pair, required: List? = null) = + ElicitRequestParams.RequestedSchema(properties = mapOf(*properties), required = required) + + private fun assertRejected( + schema: ElicitRequestParams.RequestedSchema, + content: JsonObject, + expectedError: String, + ) { + val exception = assertFailsWith { validateElicitationContent(schema, content) } + assertEquals(RPCError.ErrorCode.INVALID_PARAMS, exception.code) + val message = exception.message.orEmpty() + assertTrue( + message.startsWith("Elicitation response content does not match requested schema: "), + "Unexpected message prefix: $message", + ) + assertTrue(expectedError in message, "Expected '$expectedError' in: $message") + } + + @Test + fun `validate content matching schema passes`() { + assertDoesNotThrow { + validateElicitationContent( + schema( + "name" to StringSchema(minLength = 1, maxLength = 10), + "age" to IntegerSchema(minimum = 0, maximum = 120), + "score" to DoubleSchema(minimum = 0.0, maximum = 1.0), + "subscribed" to BooleanSchema(), + "color" to UntitledSingleSelectEnumSchema(enumValues = listOf("red", "green")), + "size" to TitledSingleSelectEnumSchema( + oneOf = listOf(EnumOption("s", "Small"), EnumOption("l", "Large")), + ), + "tags" to UntitledMultiSelectEnumSchema( + items = UntitledMultiSelectEnumSchema.Items(enumValues = listOf("a", "b", "c")), + minItems = 1, + maxItems = 2, + ), + required = listOf("name", "age"), + ), + buildJsonObject { + put("name", "octocat") + put("age", 42) + put("score", 0.5) + put("subscribed", true) + put("color", "red") + put("size", "l") + putJsonArray("tags") { add("a") } + }, + ) + } + } + + @Test + fun `validate missing required property fails`() { + assertRejected( + schema("name" to StringSchema(), required = listOf("name")), + JsonObject(emptyMap()), + "must have required property 'name'", + ) + } + + @Test + fun `validate empty content with no required properties passes`() { + assertDoesNotThrow { + validateElicitationContent(schema("name" to StringSchema()), JsonObject(emptyMap())) + } + } + + @Test + fun `validate wrong type for string property fails`() { + assertRejected( + schema("name" to StringSchema()), + buildJsonObject { put("name", 42) }, + "'name' must be string", + ) + } + + @Test + fun `validate string length constraints fail`() { + assertRejected( + schema("name" to StringSchema(minLength = 3)), + buildJsonObject { put("name", "ab") }, + "'name' must NOT have fewer than 3 characters", + ) + assertRejected( + schema("name" to StringSchema(maxLength = 3)), + buildJsonObject { put("name", "abcd") }, + "'name' must NOT have more than 3 characters", + ) + } + + @Test + fun `validate json string is not accepted for integer boolean or number`() { + // JsonPrimitive("42") is the JSON string "42", not the number 42; the validator must not + // parse string content as a number. + assertRejected( + schema("age" to IntegerSchema()), + buildJsonObject { put("age", "42") }, + "'age' must be integer", + ) + assertRejected( + schema("score" to DoubleSchema()), + buildJsonObject { put("score", "1.5") }, + "'score' must be number", + ) + assertRejected( + schema("subscribed" to BooleanSchema()), + buildJsonObject { put("subscribed", "true") }, + "'subscribed' must be boolean", + ) + } + + @Test + fun `validate integer outside minimum and maximum fails`() { + assertRejected( + schema("age" to IntegerSchema(minimum = 0)), + buildJsonObject { put("age", -1) }, + "'age' must be >= 0", + ) + assertRejected( + schema("age" to IntegerSchema(maximum = 120)), + buildJsonObject { put("age", 200) }, + "'age' must be <= 120", + ) + } + + @Test + fun `validate non-integral value for integer property fails`() { + assertRejected( + schema("age" to IntegerSchema()), + buildJsonObject { put("age", 3.5) }, + "'age' must be integer", + ) + } + + @Test + fun `validate integral number forms are accepted for integer property`() { + // JSON Schema's "integer" matches numbers with a zero fractional part. + assertDoesNotThrow { + validateElicitationContent( + schema("age" to IntegerSchema(minimum = 0, maximum = 200)), + buildJsonObject { put("age", 5.0) }, + ) + } + } + + @Test + fun `validate exponent form is accepted for integer property`() { + val content = McpJson.parseToJsonElement("""{"age": 1e2}""") as JsonObject + assertDoesNotThrow { + validateElicitationContent( + schema("age" to IntegerSchema(minimum = 0, maximum = 200)), + content, + ) + } + } + + @Test + fun `validate number outside range fails`() { + assertRejected( + schema("score" to DoubleSchema(maximum = 1.0)), + buildJsonObject { put("score", 1.5) }, + "'score' must be <= 1.0", + ) + } + + @Test + fun `validate integral value is accepted for number property`() { + assertDoesNotThrow { + validateElicitationContent( + schema("score" to DoubleSchema(minimum = 0.0)), + buildJsonObject { put("score", 5) }, + ) + } + } + + @Test + fun `validate string length counts unicode code points`() { + // JSON Schema string length counts RFC 8259 characters: one emoji is one character + // even when it is two UTF-16 units. + assertDoesNotThrow { + validateElicitationContent( + schema("emoji" to StringSchema(maxLength = 1)), + buildJsonObject { put("emoji", "😀") }, + ) + } + assertRejected( + schema("emoji" to StringSchema(minLength = 2)), + buildJsonObject { put("emoji", "😀") }, + "'emoji' must NOT have fewer than 2 characters", + ) + } + + @Test + fun `validate string format is treated as an annotation`() { + assertDoesNotThrow { + validateElicitationContent( + schema("email" to StringSchema(format = StringSchemaFormat.Email)), + buildJsonObject { put("email", "not-an-email") }, + ) + } + } + + @Test + fun `validate negative zero satisfies an inclusive zero bound`() { + // IEEE 754 comparison: -0.0 == 0.0, so an inclusive minimum of 0.0 admits -0.0. + assertDoesNotThrow { + validateElicitationContent( + schema("score" to DoubleSchema(minimum = 0.0)), + buildJsonObject { put("score", -0.0) }, + ) + } + } + + @Test + fun `validate enum value not in allowed set fails`() { + assertRejected( + schema("color" to UntitledSingleSelectEnumSchema(enumValues = listOf("red", "green"))), + buildJsonObject { put("color", "blue") }, + "'color' must be equal to one of the allowed values", + ) + assertRejected( + schema("size" to TitledSingleSelectEnumSchema(oneOf = listOf(EnumOption("s", "Small")))), + buildJsonObject { put("size", "xl") }, + "'size' must be equal to one of the allowed values", + ) + assertRejected( + schema("legacy" to LegacyTitledEnumSchema(enumValues = listOf("a", "b"))), + buildJsonObject { put("legacy", "c") }, + "'legacy' must be equal to one of the allowed values", + ) + } + + @Test + fun `validate multi-select constraints fail`() { + val tags = UntitledMultiSelectEnumSchema( + items = UntitledMultiSelectEnumSchema.Items(enumValues = listOf("a", "b", "c")), + minItems = 1, + maxItems = 2, + ) + assertRejected( + schema("tags" to tags), + buildJsonObject { put("tags", "a") }, + "'tags' must be array", + ) + assertRejected( + schema("tags" to tags), + buildJsonObject { + putJsonArray("tags") { + add("a") + add(42) + } + }, + "'tags' items must be string", + ) + assertRejected( + schema("tags" to tags), + buildJsonObject { + putJsonArray("tags") { + add("a") + add("z") + } + }, + "'tags' items must be equal to one of the allowed values", + ) + assertRejected( + schema("tags" to tags), + buildJsonObject { putJsonArray("tags") {} }, + "'tags' must NOT have fewer than 1 items", + ) + assertRejected( + schema("tags" to tags), + buildJsonObject { + putJsonArray("tags") { + add("a") + add("b") + add("c") + } + }, + "'tags' must NOT have more than 2 items", + ) + } + + @Test + fun `validate titled multi-select membership uses option consts`() { + val sizes = TitledMultiSelectEnumSchema( + items = TitledMultiSelectEnumSchema.Items( + anyOf = listOf(EnumOption("s", "Small"), EnumOption("l", "Large")), + ), + ) + assertDoesNotThrow { + validateElicitationContent( + schema("sizes" to sizes), + buildJsonObject { putJsonArray("sizes") { add("s") } }, + ) + } + assertRejected( + schema("sizes" to sizes), + buildJsonObject { putJsonArray("sizes") { add("Small") } }, + "'sizes' items must be equal to one of the allowed values", + ) + } + + @Test + fun `validate json null is rejected with the type error for each schema kind`() { + // JsonNull is a JsonPrimitive whose content is "null"; it must fail the type check, not + // accidentally parse as a value. + assertRejected( + schema("name" to StringSchema()), + buildJsonObject { put("name", JsonNull) }, + "'name' must be string", + ) + assertRejected( + schema("age" to IntegerSchema()), + buildJsonObject { put("age", JsonNull) }, + "'age' must be integer", + ) + assertRejected( + schema("subscribed" to BooleanSchema()), + buildJsonObject { put("subscribed", JsonNull) }, + "'subscribed' must be boolean", + ) + } + + @Test + fun `validate non-primitive value is rejected for scalar schemas`() { + assertRejected( + schema("name" to StringSchema()), + buildJsonObject { putJsonArray("name") { add("x") } }, + "'name' must be string", + ) + assertRejected( + schema("age" to IntegerSchema()), + buildJsonObject { putJsonObject("age") {} }, + "'age' must be integer", + ) + } + + @Test + fun `validate number below minimum fails`() { + assertRejected( + schema("score" to DoubleSchema(minimum = 0.0)), + buildJsonObject { put("score", -0.5) }, + "'score' must be >= 0.0", + ) + } + + @Test + fun `validate non-finite value for number property fails`() { + // McpJson is lenient, so an unquoted NaN literal can arrive off the wire; it decodes to + // the same primitive as Double.NaN here. + assertRejected( + schema("score" to DoubleSchema(minimum = 0.0, maximum = 1.0)), + buildJsonObject { put("score", Double.NaN) }, + "'score' must be number", + ) + } + + @Test + fun `validate required property not declared in properties is still required`() { + // JSON Schema's `required` is independent of `properties`. + assertRejected( + schema("name" to StringSchema(), required = listOf("name", "consent")), + buildJsonObject { put("name", "octocat") }, + "must have required property 'consent'", + ) + } + + @Test + fun `validate properties not declared in schema pass`() { + // JSON Schema default: without an additionalProperties restriction, undeclared keys are permitted. + assertDoesNotThrow { + validateElicitationContent( + schema("name" to StringSchema(), required = listOf("name")), + buildJsonObject { + put("name", "octocat") + put("undeclared", 42) + }, + ) + } + } + + @Test + fun `validate reports every violation in one error`() { + val exception = assertFailsWith { + validateElicitationContent( + schema( + "name" to StringSchema(), + "age" to IntegerSchema(), + required = listOf("name"), + ), + buildJsonObject { put("age", "old") }, + ) + } + val message = exception.message.orEmpty() + assertTrue("must have required property 'name'" in message, message) + assertTrue("'age' must be integer" in message, message) + } +} From 9ef4f80f85ade12128d4f07b311e93eaf3c244e4 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 21 Jul 2026 18:37:21 +0200 Subject: [PATCH 106/178] fix(server): reject duplicate feature names on registration (#883) Reject duplicate feature registration instead of silently overwriting the existing entry. ## Motivation and Context `FeatureRegistry.add`/`addAll` silently replaced a feature registered under the same key and emitted a spurious `list_changed` notification. Tool/prompt names and resource URIs are unique identifiers in MCP, and the TypeScript SDK already rejects duplicates at registration time (`Tool X is already registered`). - `addTool`/`addPrompt`/`addResource`/`addResourceTemplate` now throw `IllegalArgumentException` on a duplicate name/URI; the existing registration stays intact and no notification is emitted. - `addTools`/`addPrompts`/`addResources` are all-or-nothing: batches with intra-batch duplicates or conflicts with existing keys are rejected without registering anything. - To replace a feature, remove it first (`removeTool` + `addTool`), matching the TypeScript SDK's remove-then-re-register path. No new public API. ## How Has This Been Tested? New `FeatureRegistryTest` unit suite (duplicate rejection, batch atomicity, no notification on rejection, re-add after remove) plus integration tests for tools, prompts, resources, and resource templates. The check also surfaced a real duplicate `addResource` in `AbstractResourceIntegrationTest`, fixed here. `jvmTest` (all modules), `apiCheck`, `ktlintCheck`, and `detekt` pass locally. ## Breaking Changes No public API signature changes (`apiCheck` passes against the existing dump). Behavioral: registering a duplicate name/URI now throws `IllegalArgumentException` instead of silently overwriting; remove the feature first to replace it. ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../kotlin/AbstractResourceIntegrationTest.kt | 17 --- .../sdk/server/ServerBulkFeaturesTest.kt | 74 ++++++++++++ .../kotlin/sdk/server/ServerPromptsTest.kt | 23 ++++ .../sdk/server/ServerResourceTemplateTest.kt | 19 ++++ .../kotlin/sdk/server/ServerResourcesTest.kt | 21 ++++ .../sdk/server/ServerToolsNotificationTest.kt | 22 ++++ .../kotlin/sdk/server/ServerToolsTest.kt | 39 +++++++ .../kotlin/sdk/server/FeatureRegistry.kt | 40 +++++-- .../kotlin/sdk/server/FeatureRegistryTest.kt | 106 ++++++++++++++++++ 9 files changed, 333 insertions(+), 28 deletions(-) create mode 100644 kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistryTest.kt diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractResourceIntegrationTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractResourceIntegrationTest.kt index da7d85b..ab2a854 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractResourceIntegrationTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractResourceIntegrationTest.kt @@ -77,23 +77,6 @@ abstract class AbstractResourceIntegrationTest : KotlinTestBase() { ) } - server.addResource( - uri = testResourceUri, - name = testResourceName, - description = testResourceDescription, - mimeType = "text/plain", - ) { request -> - ReadResourceResult( - contents = listOf( - TextResourceContents( - text = testResourceContent, - uri = request.params.uri, - mimeType = "text/plain", - ), - ), - ) - } - server.addResource( uri = binaryResourceUri, name = binaryResourceName, diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerBulkFeaturesTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerBulkFeaturesTest.kt index 1eb828f..52f6908 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerBulkFeaturesTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerBulkFeaturesTest.kt @@ -1,5 +1,6 @@ package io.modelcontextprotocol.kotlin.sdk.server +import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.collections.shouldBeEmpty import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder import io.kotest.matchers.collections.shouldHaveSize @@ -57,6 +58,39 @@ class ServerBulkFeaturesTest : AbstractServerFeaturesTest() { tools.map { it.name } shouldContainExactlyInAnyOrder listOf("existing", "new-a", "new-b") } + @Test + fun `addTools should throw and register nothing when a tool is already registered`() = runTest { + server.addTool("existing", "Existing") { CallToolResult(emptyList()) } + + shouldThrow { + server.addTools( + listOf( + RegisteredTool(Tool("new-a", ToolSchema())) { CallToolResult(emptyList()) }, + RegisteredTool(Tool("existing", ToolSchema())) { CallToolResult(emptyList()) }, + ), + ) + } + + val tools = client.listTools().tools + + tools shouldHaveSize 1 + tools.map { it.name } shouldContainExactlyInAnyOrder listOf("existing") + } + + @Test + fun `addTools should throw when batch contains duplicate names`() = runTest { + shouldThrow { + server.addTools( + listOf( + RegisteredTool(Tool("dup", ToolSchema())) { CallToolResult(emptyList()) }, + RegisteredTool(Tool("dup", ToolSchema())) { CallToolResult(emptyList()) }, + ), + ) + } + + client.listTools().tools.shouldBeEmpty() + } + // ── addPrompts ───────────────────────────────────────────────────────────── @Test @@ -89,6 +123,25 @@ class ServerBulkFeaturesTest : AbstractServerFeaturesTest() { prompts.map { it.name } shouldContainExactlyInAnyOrder listOf("existing-prompt", "new-p") } + @Test + fun `addPrompts should throw and register nothing when a prompt is already registered`() = runTest { + server.addPrompt("existing-prompt", "Existing") { GetPromptResult(messages = emptyList()) } + + shouldThrow { + server.addPrompts( + listOf( + RegisteredPrompt(Prompt("new-p")) { GetPromptResult(messages = emptyList()) }, + RegisteredPrompt(Prompt("existing-prompt")) { GetPromptResult(messages = emptyList()) }, + ), + ) + } + + val prompts = client.listPrompts().prompts + + prompts shouldHaveSize 1 + prompts.map { it.name } shouldContainExactlyInAnyOrder listOf("existing-prompt") + } + // ── addResources ─────────────────────────────────────────────────────────── @Test @@ -123,6 +176,27 @@ class ServerBulkFeaturesTest : AbstractServerFeaturesTest() { resources.map { it.uri } shouldContainExactlyInAnyOrder listOf("test://existing-res", "test://new-res") } + @Test + fun `addResources should throw and register nothing when a resource is already registered`() = runTest { + server.addResource("test://existing-res", "Existing", "Existing resource") { + ReadResourceResult(emptyList()) + } + + shouldThrow { + server.addResources( + listOf( + RegisteredResource(Resource("test://new-res", "New")) { ReadResourceResult(emptyList()) }, + RegisteredResource(Resource("test://existing-res", "Dup")) { ReadResourceResult(emptyList()) }, + ), + ) + } + + val resources = client.listResources().resources + + resources shouldHaveSize 1 + resources.map { it.uri } shouldContainExactlyInAnyOrder listOf("test://existing-res") + } + // ── Partial-batch remove ─────────────────────────────────────────────────── @Test diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerPromptsTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerPromptsTest.kt index d7ae46d..44b1e42 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerPromptsTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerPromptsTest.kt @@ -1,5 +1,8 @@ package io.modelcontextprotocol.kotlin.sdk.server +import io.kotest.matchers.string.shouldContain +import io.modelcontextprotocol.kotlin.sdk.types.GetPromptRequest +import io.modelcontextprotocol.kotlin.sdk.types.GetPromptRequestParams import io.modelcontextprotocol.kotlin.sdk.types.GetPromptResult import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.Method @@ -110,6 +113,26 @@ class ServerPromptsTest : AbstractServerFeaturesTest() { assertFalse(promptListChangedNotificationReceived, "No notification should be sent when prompt doesn't exist") } + @Test + fun `addPrompt should throw when prompt with same name is already registered`() = runTest { + server.addPrompt(Prompt("test-prompt", "Original Prompt", null)) { + GetPromptResult(description = "original", messages = emptyList()) + } + + val exception = assertThrows { + server.addPrompt(Prompt("test-prompt", "Duplicate Prompt", null)) { + GetPromptResult(description = "duplicate", messages = emptyList()) + } + } + exception.message.orEmpty() shouldContain "Prompt \"test-prompt\" is already registered" + + // The original registration is intact + val prompts = client.listPrompts().prompts + assertEquals(1, prompts.size, "Only the original prompt should be registered") + val result = client.getPrompt(GetPromptRequest(GetPromptRequestParams("test-prompt"))) + assertEquals("original", result.description) + } + @Test fun `removePrompt should throw when prompts capability is not supported`() = runTest { var promptListChangedNotificationReceived = false diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourceTemplateTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourceTemplateTest.kt index c8ace19..8405469 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourceTemplateTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourceTemplateTest.kt @@ -5,6 +5,7 @@ import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.maps.shouldContainKey import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.ListResourceTemplatesRequest import io.modelcontextprotocol.kotlin.sdk.types.McpException @@ -162,6 +163,24 @@ class ServerResourceTemplateTest : AbstractServerFeaturesTest() { removed shouldBe false } + @Test + fun `addResourceTemplate should throw when template with same uriTemplate is already registered`() { + server.addResourceTemplate("test://items/{id}", "Item") { _, _ -> + ReadResourceResult(emptyList()) + } + + val exception = assertThrows { + server.addResourceTemplate("test://items/{id}", "Duplicate Item") { _, _ -> + ReadResourceResult(emptyList()) + } + } + exception.message.orEmpty() shouldContain "ResourceTemplate \"test://items/{id}\" is already registered" + + // The original registration is intact + server.resourceTemplates shouldHaveSize 1 + server.resourceTemplates[0].name shouldBe "Item" + } + @Test fun `addResourceTemplate should throw when resources capability is not supported`() { val noResourcesServer = Server( diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourcesTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourcesTest.kt index fafc3c8..a830788 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourcesTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerResourcesTest.kt @@ -1,7 +1,10 @@ package io.modelcontextprotocol.kotlin.sdk.server +import io.kotest.matchers.string.shouldContain import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceRequest +import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceRequestParams import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceResult import io.modelcontextprotocol.kotlin.sdk.types.ResourceListChangedNotification import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities @@ -115,6 +118,24 @@ class ServerResourcesTest : AbstractServerFeaturesTest() { ) } + @Test + fun `addResource should throw when resource with same uri is already registered`() = runTest { + server.addResource("test://resource", "Original", "Original resource") { + ReadResourceResult(listOf(TextResourceContents(text = "original", uri = "test://resource"))) + } + + val exception = assertThrows { + server.addResource("test://resource", "Duplicate", "Duplicate resource") { + ReadResourceResult(listOf(TextResourceContents(text = "duplicate", uri = "test://resource"))) + } + } + exception.message.orEmpty() shouldContain "Resource \"test://resource\" is already registered" + + // The original registration is intact + val result = client.readResource(ReadResourceRequest(ReadResourceRequestParams("test://resource"))) + assertEquals("original", (result.contents.single() as TextResourceContents).text) + } + @Test fun `removeResource should throw when resources capability is not supported`() = runTest { // Create server without resources capability diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsNotificationTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsNotificationTest.kt index 3572082..9ac744b 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsNotificationTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsNotificationTest.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.test.runTest import org.awaitility.kotlin.await import org.awaitility.kotlin.untilAsserted import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -81,6 +82,27 @@ class ServerToolsNotificationTest : AbstractServerFeaturesTest() { } } + @Test + fun `addTool should not send notification when duplicate is rejected`() = runTest { + // Track notifications + val notifications = mutableListOf() + client.setNotificationHandler( + Method.Defined.NotificationsToolsListChanged, + ) { notification -> + notifications.add(notification) + CompletableDeferred(Unit) + } + + server.addTool("test-tool", "Test Tool") { CallToolResult(emptyList()) } + assertThrows { + server.addTool("test-tool", "Duplicate Tool") { CallToolResult(emptyList()) } + } + // Close the server to stop processing further events and flush notifications + server.close() + + assertEquals(1, notifications.size, "Only the first registration should send a notification") + } + @Test fun `notification should not be send when removed tool does not exists`() = runTest { // Track notifications diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsTest.kt index 54c998e..1b3df91 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerToolsTest.kt @@ -1,5 +1,8 @@ package io.modelcontextprotocol.kotlin.sdk.server +import io.kotest.matchers.string.shouldContain +import io.modelcontextprotocol.kotlin.sdk.types.CallToolRequest +import io.modelcontextprotocol.kotlin.sdk.types.CallToolRequestParams import io.modelcontextprotocol.kotlin.sdk.types.CallToolResult import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.Method @@ -108,6 +111,42 @@ class ServerToolsTest : AbstractServerFeaturesTest() { assertTrue(result, "Tool with non-conforming name should have been registered and removable") } + @Test + fun `addTool should throw when tool with same name is already registered`() = runTest { + server.addTool("test-tool", "Original Tool") { + CallToolResult(listOf(TextContent("Original result"))) + } + + val exception = assertThrows { + server.addTool("test-tool", "Duplicate Tool") { + CallToolResult(listOf(TextContent("Duplicate result"))) + } + } + exception.message.orEmpty() shouldContain "Tool \"test-tool\" is already registered" + + // The original registration is intact + val tools = client.listTools().tools + assertEquals(1, tools.size, "Only the original tool should be registered") + val result = client.callTool(CallToolRequest(CallToolRequestParams("test-tool"))) + assertEquals("Original result", (result.content.single() as TextContent).text) + } + + @Test + fun `addTool should succeed after removing existing tool`() = runTest { + server.addTool("test-tool", "Original Tool") { + CallToolResult(listOf(TextContent("Original result"))) + } + + server.removeTool("test-tool") + server.addTool("test-tool", "Replacement Tool") { + CallToolResult(listOf(TextContent("Replacement result"))) + } + + assertEquals(1, client.listTools().tools.size, "Re-adding after removal should not duplicate the tool") + val result = client.callTool(CallToolRequest(CallToolRequestParams("test-tool"))) + assertEquals("Replacement result", (result.content.single() as TextContent).text) + } + @Test fun `removeTool should throw when tools capability is not supported`() = runTest { var toolListChangedNotificationReceived = false diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistry.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistry.kt index 0ed6558..142d59c 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistry.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistry.kt @@ -20,9 +20,12 @@ internal interface FeatureListener { * A generic registry for managing features of a specified type. This class provides thread-safe * operations for adding, removing, and retrieving features from the registry. * + * Feature keys are unique: [add] and [addAll] reject keys that are already registered. + * To replace a feature, [remove] it first and add the new one. + * * @param T The type of the feature, constrained to implement the [Feature] interface. * @param featureType A string description of the type of feature being managed. - * Used primarily for logging purposes. + * Used for logging and error messages. */ internal class FeatureRegistry(private val featureType: String) { @@ -44,11 +47,11 @@ internal class FeatureRegistry(private val featureType: String) { private val listeners = atomic(persistentListOf()) internal fun addListener(listener: FeatureListener) { - listeners.update { it.add(listener) } + listeners.update { it.adding(listener) } } internal fun removeListener(listener: FeatureListener) { - listeners.update { it.remove(listener) } + listeners.update { it.removing(listener) } } /** @@ -58,27 +61,42 @@ internal class FeatureRegistry(private val featureType: String) { */ internal fun add(feature: T) { logger.info { "Adding $featureType: \"${feature.key}\"" } - val oldMap = registry.getAndUpdate { current -> current.put(feature.key, feature) } - val oldFeature = oldMap[feature.key] + registry.update { current -> + require(!current.containsKey(feature.key)) { + "$featureType \"${feature.key}\" is already registered. Remove it first to replace it." + } + current.putting(feature.key, feature) + } logger.info { "Added $featureType: \"${feature.key}\"" } - notifyFeatureUpdated(oldFeature, feature) + notifyFeatureUpdated(null, feature) } /** * Adds the given list of features to the registry. Each feature is mapped by its key - * and added to the current registry. + * and added to the current registry. The operation is all-or-nothing: if any key is + * rejected, no features are added. * * @param features The list of features to add to the registry. */ internal fun addAll(features: List) { logger.info { "Adding ${featureType}s: ${features.size}" } - val oldMap = registry.getAndUpdate { current -> current.putAll(features.associateBy { it.key }) } + val newEntries = features.associateBy { it.key } + require(newEntries.size == features.size) { + val duplicated = features.groupingBy { it.key }.eachCount().filterValues { it > 1 }.keys + "Duplicate $featureType keys in batch: $duplicated" + } + registry.update { current -> + val conflicting = newEntries.keys.filter { current.containsKey(it) } + require(conflicting.isEmpty()) { + "${featureType}s already registered: $conflicting. Remove them first to replace them." + } + current.puttingAll(newEntries) + } logger.info { "Added ${featureType}s: ${features.size}" } for (feature in features) { - val oldFeature = oldMap[feature.key] - notifyFeatureUpdated(oldFeature, feature) + notifyFeatureUpdated(null, feature) } } @@ -90,7 +108,7 @@ internal class FeatureRegistry(private val featureType: String) { */ internal fun remove(key: FeatureKey): Boolean { logger.info { "Removing $featureType: \"$key\"" } - val oldMap = registry.getAndUpdate { current -> current.remove(key) } + val oldMap = registry.getAndUpdate { current -> current.removing(key) } val removedFeature = oldMap[key] val removed = removedFeature != null diff --git a/kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistryTest.kt b/kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistryTest.kt new file mode 100644 index 0000000..c6bf72b --- /dev/null +++ b/kotlin-sdk-server/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/FeatureRegistryTest.kt @@ -0,0 +1,106 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.kotest.matchers.shouldBe +import kotlin.test.Test +import kotlin.test.assertFailsWith + +private data class TestFeature(override val key: FeatureKey, val payload: String = "") : Feature + +private class RecordingListener : FeatureListener { + val updatedKeys = mutableListOf() + + override fun onFeatureUpdated(featureKey: String) { + updatedKeys.add(featureKey) + } +} + +class FeatureRegistryTest { + + private val registry = FeatureRegistry("Tool") + private val listener = RecordingListener() + + init { + registry.addListener(listener) + } + + @Test + fun `add should register feature and notify listener`() { + val feature = TestFeature("a") + + registry.add(feature) + + registry.values shouldBe mapOf("a" to feature) + listener.updatedKeys shouldBe listOf("a") + } + + @Test + fun `add should throw when key is already registered`() { + registry.add(TestFeature("a")) + + val exception = assertFailsWith { + registry.add(TestFeature("a", payload = "override")) + } + + exception.message shouldBe "Tool \"a\" is already registered. Remove it first to replace it." + } + + @Test + fun `add should keep original feature and not notify when duplicate is rejected`() { + val original = TestFeature("a", payload = "original") + registry.add(original) + + assertFailsWith { + registry.add(TestFeature("a", payload = "override")) + } + + registry.values shouldBe mapOf("a" to original) + listener.updatedKeys shouldBe listOf("a") + } + + @Test + fun `addAll should register all features and notify per feature`() { + val a = TestFeature("a") + val b = TestFeature("b") + + registry.addAll(listOf(a, b)) + + registry.values shouldBe mapOf("a" to a, "b" to b) + listener.updatedKeys shouldBe listOf("a", "b") + } + + @Test + fun `addAll should throw on duplicate keys within batch and register nothing`() { + val exception = assertFailsWith { + registry.addAll(listOf(TestFeature("a"), TestFeature("b"), TestFeature("a"))) + } + + exception.message shouldBe "Duplicate Tool keys in batch: [a]" + registry.values shouldBe emptyMap() + listener.updatedKeys shouldBe emptyList() + } + + @Test + fun `addAll should throw when any key is already registered and register nothing`() { + val existing = TestFeature("existing") + registry.add(existing) + + val exception = assertFailsWith { + registry.addAll(listOf(TestFeature("new"), TestFeature("existing", payload = "override"))) + } + + exception.message shouldBe "Tools already registered: [existing]. Remove them first to replace them." + registry.values shouldBe mapOf("existing" to existing) + listener.updatedKeys shouldBe listOf("existing") + } + + @Test + fun `add should succeed after the existing feature is removed`() { + registry.add(TestFeature("a", payload = "original")) + registry.remove("a") + + registry.add(TestFeature("a", payload = "replacement")) + + registry.values shouldBe mapOf("a" to TestFeature("a", payload = "replacement")) + listener.updatedKeys shouldBe listOf("a", "a", "a") + } +} From a7bb0ea73ffd0f5b92ab877caa90a99517eb210f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 20:46:05 +0200 Subject: [PATCH 107/178] chore(deps): bump actions/setup-node from 6 to 7 in the all-actions group across 1 directory (#898) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-actions group with 1 update in the / directory: [actions/setup-node](https://github.com/actions/setup-node). Updates `actions/setup-node` from 6 to 7
        Release notes

        Sourced from actions/setup-node's releases.

        v7.0.0

        What's Changed

        Enhancements:

        Bug fixes:

        Documentation updates:

        Dependency update:

        New Contributors

        Full Changelog: https://github.com/actions/setup-node/compare/v6...v7.0.0

        v6.5.0

        What's Changed

        Full Changelog: https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0

        v6.4.0

        What's Changed

        Dependency updates:

        New Contributors

        Full Changelog: https://github.com/actions/setup-node/compare/v6...v6.4.0

        v6.3.0

        What's Changed

        Enhancements:

        ... (truncated)

        Commits
        • 8207627 Migrate to ESM and upgrade dependencies (#1574)
        • 04be95c Add cache-primary-key and cache-matched-key as outputs (#1577)
        • 7c2c68d docs: Update caching recommendations to mitigate cache poisoning risks (#1567)
        • 6a61c03 Merge pull request #1569 from jasongin/update-actions-cache-5.1.0
        • 30eb73b Resolve high-severity audit issues
        • 4e1a87a Update dist
        • 360237f Strict equality
        • 4f8aac5 Bump @​actions/cache to 5.1.0, log cache write denied
        • f4a67bb Only use mirrorToken in getManifest if it's provided (#1548)
        • 0355742 Remove dummy NODE_AUTH_TOKEN export (#1558)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/gradle-publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2b6e415..147163c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,7 +53,7 @@ jobs: - name: Set up Node.js if: matrix.os == 'ubuntu-latest' - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '22' # increase only after https://github.com/nodejs/node/issues/56645 will be fixed diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index f9df053..058e041 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -25,7 +25,7 @@ jobs: distribution: 'temurin' - name: Set up Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '22' # increase only after https://github.com/nodejs/node/issues/56645 will be fixed From 152a1c88ee774f2bd21ff40e587477e5337931f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 01:29:46 +0200 Subject: [PATCH 108/178] chore(deps): bump body-parser from 2.2.2 to 2.3.0 in /integration-test/src/jvmTest/typescript (#907) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [body-parser](https://github.com/expressjs/body-parser) from 2.2.2 to 2.3.0.
        Release notes

        Sourced from body-parser's releases.

        v2.3.0

        Important: Security

        What's Changed

        New Contributors

        Full Changelog: https://github.com/expressjs/body-parser/compare/v2.2.2...v2.3.0

        Changelog

        Sourced from body-parser's changelog.

        2.3.0 / 2026-06-15

        • Security fix for GHSA-v422-hmwv-36x6
        • fix: use static exports instead of lazy getters to improve ESM compatibility
        • feat: add subpath exports for individual parsers
        • fix: improve limit option validation (#698)
          • Invalid limit values (e.g. unparseable strings or NaN) now throw instead of being silently ignored, which previously disabled size limit enforcement
          • null and undefined fall back to the default 100kb limit
        • deps:
          • content-type@^2.0.0
          • http-errors@^2.0.1
          • iconv-lite^0.7.2
          • qs@^6.15.2
          • raw-body@^3.0.2
          • type-is@^2.1.0
        Commits
        • d0f2ace 2.3.0 (#735)
        • 7d03f2f chore: updated deps to latest (#733)
        • 8024ba7 build(deps): bump actions/checkout from 6.0.2 to 6.0.3 (#732)
        • 32b4ed4 build(deps): bump github/codeql-action from 4.35.3 to 4.36.1 (#731)
        • ff0f6b9 docs: update outdated reference to MDN docs (#730)
        • 14d001a refactor: switch to const/let and enable eslint no-var rule (#729)
        • 37f36a2 deps: update content-type and type-is (#728)
        • e1c244b build(deps): bump github/codeql-action from 4.35.1 to 4.35.3 (#723)
        • e01087f build(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1 (#724)
        • a7698d3 build(deps): bump actions/setup-node from 6.3.0 to 6.4.0 (#725)
        • Additional commits viewable in compare view

        [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=body-parser&package-manager=npm_and_yarn&previous-version=2.2.2&new-version=2.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
        Dependabot commands and options
        You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/modelcontextprotocol/kotlin-sdk/network/alerts).
        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index c9d73bf..83b03fb 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1010,20 +1010,20 @@ } }, "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", - "content-type": "^1.0.5", + "content-type": "^2.0.0", "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" }, "engines": { "node": ">=18" @@ -1033,6 +1033,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -2039,17 +2052,34 @@ } }, "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", "license": "MIT", "dependencies": { - "content-type": "^1.0.5", + "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/typescript": { From 031a90c8a107beaaebb7f604d93544ae13a9e23c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 09:27:20 +0200 Subject: [PATCH 109/178] chore(deps): bump ip-address and express-rate-limit in /integration-test/src/jvmTest/typescript (#906) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ip-address](https://github.com/beaugunderson/ip-address) and [express-rate-limit](https://github.com/express-rate-limit/express-rate-limit). These dependencies needed to be updated together. Updates `ip-address` from 10.1.0 to 10.2.0
        Commits
        • 80fccaa 10.2.0
        • abaeb4d Type Address4.addressMinusSuffix as non-nilable (closes #143)
        • 2878c29 Preserve subnet prefix through Address6.to4() (closes #123) (#203)
        • 586666e Reject trailing junk in Address6.fromURL (closes #158) (#202)
        • 80bc76e Validate static factories instead of silently overflowing (#201)
        • 98927be Clarify isValid() accepts CIDRs with host bits set (#81)
        • a0eb073 Fix getScope() and broaden getType() classification (closes #122) (#200)
        • ec52105 Add networkForm() for CIDR network-address strings (#199)
        • a9443a7 Add isMapped4() predicate for IPv4-mapped IPv6 addresses (closes #62) (#198)
        • f01d742 Add address-property predicates (private, ULA, loopback, link-local, etc.) (#...
        • Additional commits viewable in compare view

        Updates `express-rate-limit` from 8.3.1 to 8.6.0
        Release notes

        Sourced from express-rate-limit's releases.

        v8.6.0

        You can view the changelog here.

        v8.5.2

        You can view the changelog here.

        v8.5.1

        You can view the changelog here.

        v8.5.0

        You can view the changelog here.

        v8.4.1

        You can view the changelog here.

        v8.4.0

        You can view the changelog here.

        v8.3.2

        You can view the changelog here.

        Commits
        • fffb3c4 8.6.0
        • f366b2d docs: debugging guide, time constants, & v8.6.0 changelog (#652)
        • 593ddd2 fix: make debug output easier to read (#653)
        • ef8c129 fix: Pin safe version of @​asyncapi/specs dev dep (#659)
        • 7b05e0d feat: add time constants to support more readable values for windowMs (#655)
        • 863e730 chore(deps-dev): bump the development-dependencies group with 3 updates (#657)
        • e0e711e fix: correct wording in usage documentation for express-rate-limit (#656)
        • fcd3aa7 chore(deps-dev): bump the development-dependencies group with 3 updates (#651)
        • 99d4298 feat: use debug for debug logging (#641)
        • 23e4dde feat: Run validations once each (#650)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 83b03fb..b778fbb 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1362,12 +1362,13 @@ } }, "node_modules/express-rate-limit": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.3.1.tgz", - "integrity": "sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.6.0.tgz", + "integrity": "sha512-XKJXDsASUOo0LLtFwW5hCcQGH0N4WQc/Rn8/Pvoia+TJFOkkFPvrtW9lZOeeNcxQJspvOIERMwiRLsVFlhHEkA==", "license": "MIT", "dependencies": { - "ip-address": "10.1.0" + "debug": "^4.4.3", + "ip-address": "^10.2.0" }, "engines": { "node": ">= 16" @@ -1588,9 +1589,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "license": "MIT", "engines": { "node": ">= 12" From 9308473745711b40784cdbc89b6f7ada64c550bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 12:26:55 +0200 Subject: [PATCH 110/178] chore(deps): bump fast-uri from 3.1.2 to 3.1.4 in /integration-test/src/jvmTest/typescript (#910) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.2 to 3.1.4.
        Release notes

        Sourced from fast-uri's releases.

        v3.1.4

        ⚠️ Security Release

        Fix for https://github.com/fastify/fast-uri/security/advisories/GHSA-v2hh-gcrm-f6hx

        Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4

        v3.1.3

        ⚠️ Security Release

        Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.3

        Commits

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index b778fbb..0c70662 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1387,9 +1387,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "funding": [ { "type": "github", From b6cb547d582a89c4e51ac4ae4e29ab1d53dd7ff3 Mon Sep 17 00:00:00 2001 From: King Star Date: Wed, 22 Jul 2026 21:53:01 +0800 Subject: [PATCH 111/178] fix(server): preserve id on duplicate initialize errors (#868) ## Summary Fixes #866. ## Changes - Preserve the parsed JSON-RPC request id when Streamable HTTP rejects a duplicate `initialize` request. - Keep pre-parse and transport-level rejection paths unchanged when the request id is not available. - Extend the duplicate-initialize regression test to assert the error response id as well as the HTTP status. ## Verification ```bash ./gradlew :kotlin-sdk-server:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.server.StreamableHttpServerTransportTest.second initialization request returns JSON-RPC error with request id' ./gradlew :kotlin-sdk-server:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.server.StreamableHttpServerTransportTest' ./gradlew :kotlin-sdk-server:jvmTest ./gradlew :kotlin-sdk-server:ktlintCheck :kotlin-sdk-server:detekt ``` Co-authored-by: Pavel Gorgulov --- .../server/StreamableHttpServerTransport.kt | 18 ++++++++++++------ .../StreamableHttpServerTransportTest.kt | 9 +++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) 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 1f8ac39..3b02835 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 @@ -459,9 +459,10 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } val messages = parseBody(call) ?: return - val isInitializationRequest = messages.any { - it is JSONRPCRequest && it.method == Method.Defined.Initialize.value + val initializationRequest = messages.filterIsInstance().firstOrNull { + it.method == Method.Defined.Initialize.value } + val isInitializationRequest = initializationRequest != null if (isInitializationRequest) { if (initialized.load() && sessionId != null) { @@ -469,6 +470,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat HttpStatusCode.BadRequest, RPCError.ErrorCode.INVALID_REQUEST, "Invalid Request: Server already initialized", + initializationRequest.id, ) return } @@ -506,8 +508,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat // For initialize requests, get from request params. // For other requests, get from header (already validated). val clientProtocolVersion = if (isInitializationRequest) { - val initRequest = messages.first() as JSONRPCRequest - (initRequest.params as? JsonObject)?.get("protocolVersion") + (initializationRequest.params as? JsonObject)?.get("protocolVersion") ?.let { McpJson.decodeFromJsonElement(it) } ?: DEFAULT_NEGOTIATED_PROTOCOL_VERSION } else { @@ -913,7 +914,12 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } } -internal suspend fun ApplicationCall.reject(status: HttpStatusCode, code: Int, message: String) { +internal suspend fun ApplicationCall.reject( + status: HttpStatusCode, + code: Int, + message: String, + id: RequestId? = null, +) { this.response.status(status) - this.respond(JSONRPCError(id = null, error = RPCError(code = code, message = message))) + this.respond(JSONRPCError(id = id, error = RPCError(code = code, message = message))) } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt index 172889a..0d99f51 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt @@ -38,6 +38,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.Implementation import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequestParams import io.modelcontextprotocol.kotlin.sdk.types.InitializedNotification +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCError import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse @@ -163,7 +164,7 @@ class StreamableHttpServerTransportTest { } @Test - fun `second initialization request returns an HTTP error`() = testApplication { + fun `second initialization request returns JSON-RPC error with request id`() = testApplication { configTestServer() val client = createTestClient() @@ -186,13 +187,17 @@ class StreamableHttpServerTransportTest { firstResponse.status shouldBe HttpStatusCode.OK + val secondRequest = buildInitializeRequestPayload().copy(id = RequestId("second-init")) val secondResponse = client.post(path) { addStreamableHeaders() header("mcp-session-id", firstResponse.headers[MCP_SESSION_ID_HEADER]) - setBody(payload) + setBody(secondRequest) } secondResponse.status shouldBe HttpStatusCode.BadRequest + val error = secondResponse.body() + error.id shouldBe secondRequest.id + error.error.message shouldBe "Invalid Request: Server already initialized" } @Test From cab669b108b0297201e08f5bd703f4e2476c9525 Mon Sep 17 00:00:00 2001 From: King Star Date: Thu, 23 Jul 2026 00:12:12 +0800 Subject: [PATCH 112/178] fix: classify malformed request params as invalid params (#886) ## Summary Classify typed request deserialization failures as JSON-RPC `Invalid Params` instead of `Internal error`. Fixes #830. ## Changes - translate `SerializationException` from typed request decoding to `-32602` - return a stable `Invalid params` message without serialization internals - cover malformed `initialize` requests through session and Streamable HTTP paths ## Scope and risk The catch is limited to request parameter deserialization after the JSON-RPC method has been resolved. Envelope parsing, unknown methods, handler failures, and successful requests keep their existing behavior. ## Verification ```bash ./gradlew :integration-test:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.server.ServerSessionInitializeTest' ./gradlew :kotlin-sdk-server:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.server.StreamableHttpServerTransportTest' ./gradlew :kotlin-sdk-core:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.shared.ProtocolTest' ./gradlew ktlintCheck apiCheck ``` Co-authored-by: Pavel Gorgulov --- .../sdk/server/ServerSessionInitializeTest.kt | 40 +++++++++++++++++++ .../kotlin/sdk/shared/Protocol.kt | 11 ++++- .../StreamableHttpServerTransportTest.kt | 31 ++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt index 82cf91a..38b169a 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSessionInitializeTest.kt @@ -7,9 +7,11 @@ import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequestParams import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCError import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCResponse import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION import io.modelcontextprotocol.kotlin.sdk.types.RPCError +import io.modelcontextprotocol.kotlin.sdk.types.RequestId import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities import io.modelcontextprotocol.kotlin.sdk.types.toJSON import kotlinx.coroutines.CompletableDeferred @@ -18,9 +20,13 @@ import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withContext +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import kotlinx.serialization.json.putJsonObject import org.junit.jupiter.api.Test import java.util.concurrent.CopyOnWriteArrayList import kotlin.test.assertEquals +import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue @@ -41,6 +47,18 @@ class ServerSessionInitializeTest { ), ) + private fun createMalformedInitializeRequest(): JSONRPCRequest = JSONRPCRequest( + id = RequestId(1), + method = "initialize", + params = buildJsonObject { + putJsonObject("capabilities") {} + putJsonObject("clientInfo") { + put("name", "repro") + put("version", "0.1.0") + } + }, + ) + @Test fun `should handle first initialize request successfully`() = runTest { val session = createSession() @@ -67,6 +85,28 @@ class ServerSessionInitializeTest { // Both initialize requests arrive before notifications/initialized, in the serial dispatch // phase, so processing and response order stay deterministic. + @Test + fun `should classify malformed initialize params as invalid params`() = runTest { + val session = createSession() + val (clientTransport, serverTransport) = InMemoryTransport.createLinkedPair() + + val responseDone = CompletableDeferred() + clientTransport.onMessage { message -> + if (message is JSONRPCError) { + responseDone.complete(message) + } + } + + session.connect(serverTransport) + clientTransport.send(createMalformedInitializeRequest()) + + val response = responseDone.await() + assertEquals(RPCError.ErrorCode.INVALID_PARAMS, response.error.code) + assertFalse(response.error.message.contains("kotlinx.serialization")) + assertNull(session.clientCapabilities) + assertNull(session.clientVersion) + } + @Test fun `should reject duplicate initialize request`() = runTest { val session = createSession() diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt index 0c82f5e..908e524 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt @@ -48,6 +48,7 @@ import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull +import kotlinx.serialization.SerializationException import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.encodeToJsonElement @@ -941,7 +942,15 @@ public abstract class Protocol(@PublishedApi internal val options: ProtocolOptio _requestHandlers.update { current -> current.putting(method.value) { jSONRPCRequest, extraHandler -> - val request = jSONRPCRequest.fromJSON() + val request = try { + jSONRPCRequest.fromJSON() + } catch (cause: SerializationException) { + throw McpException( + code = RPCError.ErrorCode.INVALID_PARAMS, + message = "Invalid params", + cause = cause, + ) + } val response = wrapped(request as T, extraHandler) response } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt index 0d99f51..bb522d6 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt @@ -47,6 +47,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.ListResourcesResult import io.modelcontextprotocol.kotlin.sdk.types.ListToolsResult import io.modelcontextprotocol.kotlin.sdk.types.McpJson import io.modelcontextprotocol.kotlin.sdk.types.Method +import io.modelcontextprotocol.kotlin.sdk.types.RPCError import io.modelcontextprotocol.kotlin.sdk.types.RequestId import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities import io.modelcontextprotocol.kotlin.sdk.types.Tool @@ -225,6 +226,36 @@ class StreamableHttpServerTransportTest { initResponse.headers[MCP_SESSION_ID_HEADER] shouldBe null } + @Test + fun `malformed initialize params return invalid params over streamable http`() = testApplication { + val mcpPath = "/mcp" + + application { + mcpStreamableHttp(mcpPath, enableDnsRebindingProtection = false) { + Server( + Implementation("test-server", "1.0.0"), + ServerOptions(capabilities = ServerCapabilities()), + ) + } + } + + val client = createTestClient() + + val response = client.post(mcpPath) { + addStreamableHeaders() + setBody( + """ + {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"repro","version":"0.1.0"}}} + """.trimIndent(), + ) + } + + response.status shouldBe HttpStatusCode.OK + val error = response.body() + error.error.code shouldBe RPCError.ErrorCode.INVALID_PARAMS + error.error.message.contains("kotlinx.serialization") shouldBe false + } + @Test fun `request with unsupported protocol version returns an HTTP error`() = testApplication { configTestServer() From a06d699d6c9dfdf8321e5cbb3f5aebcb0016b6f6 Mon Sep 17 00:00:00 2001 From: UnscientificJsZhai <73090853+UnscientificJsZhai@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:37:37 +0800 Subject: [PATCH 113/178] feat: SSE heartbeat (#761) ## Summary Adds optional SSE heartbeat configuration for streamable HTTP MCP server connections. This lets `Application.mcpStreamableHttp` callers pass Ktor's `Heartbeat` configuration for SSE streams, including heartbeat period and event payload. Heartbeats remain disabled by default, preserving the existing stream behavior unless the new option is explicitly provided. ## Motivation and Context Some MCP clients need heartbeat messages on SSE connections to keep the connection alive. Without those heartbeats, the client may proactively disconnect from the MCP server. MCP server developers need a way to configure an SSE heartbeat mechanism so they can avoid unexpected client disconnects. In my case, my MCP server was consistently disconnected by Gemini CLI. I worked around the issue with some fallback approaches, but I believe the best implementation is to add heartbeat support by using Ktor's built-in API. ## Implementation Notes - Added a function overload of `Application.mcpStreamableHttp` to introduce heartbeat parameter `sseHeartbeatConfig: (Heartbeat.() -> Unit)?`. - Applied the configuration inside the Ktor `sse { ... }` block before handling the existing streamable HTTP transport request. - Updated the server API dump for the new public API surface. ## How Has This Been Tested? Added `StreamableHttpHeartbeatIntegrationTest` covering: - Configured GET SSE streams apply the provided heartbeat configuration. - GET SSE streams do not send default heartbeats when `sseHeartbeatConfig` is omitted. - Configured GET SSE streams emit heartbeat events repeatedly. - Legacy MCP over SSE APIs do not expose the new heartbeat configuration. Verified locally with: ```bash ./gradlew :integration-test:jvmTest --tests "io.modelcontextprotocol.kotlin.sdk.integration.streamablehttp.StreamableHttpHeartbeatIntegrationTest" ``` Result: `BUILD SUCCESSFUL`. ## Breaking Changes None. This change adds a new `Application.mcpStreamableHttp` overload that accepts `sseHeartbeatConfig: (Heartbeat.() -> Unit)?` while keeping the existing overload unchanged. Existing callers continue to compile and keep the previous behavior: SSE heartbeats are not sent unless the new overload is used with an explicit heartbeat configuration. ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed ## Additional context Heartbeat behavior is delegated to Ktor's SSE heartbeat support, so applications can use the same configuration semantics they would use in native Ktor SSE routes. Related issue: [SSE needs a heartbeat #344 ](https://github.com/modelcontextprotocol/kotlin-sdk/issues/344) --------- Co-authored-by: Pavel Gorgulov --- .../AbstractStreamableHttpIntegrationTest.kt | 8 +- .../StreamableHttpHeartbeatIntegrationTest.kt | 174 ++++++++++++++++++ kotlin-sdk-server/api/kotlin-sdk-server.api | 4 +- .../kotlin/sdk/server/KtorServer.kt | 7 + 4 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpHeartbeatIntegrationTest.kt diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/AbstractStreamableHttpIntegrationTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/AbstractStreamableHttpIntegrationTest.kt index 9bc0c17..535393e 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/AbstractStreamableHttpIntegrationTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/AbstractStreamableHttpIntegrationTest.kt @@ -3,6 +3,7 @@ package io.modelcontextprotocol.kotlin.sdk.integration.streamablehttp import io.ktor.server.cio.CIOApplicationEngine import io.ktor.server.engine.EmbeddedServer import io.ktor.server.engine.embeddedServer +import io.ktor.server.sse.Heartbeat import io.modelcontextprotocol.kotlin.sdk.server.Server import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions import io.modelcontextprotocol.kotlin.sdk.server.mcpStreamableHttp @@ -17,7 +18,10 @@ import io.ktor.server.cio.CIO as ServerCIO open class AbstractStreamableHttpIntegrationTest { - suspend fun initTestServer(name: String? = null): StreamableHttpTestServer { + suspend fun initTestServer( + name: String? = null, + sseHeartbeatConfig: (Heartbeat.() -> Unit)? = null, + ): StreamableHttpTestServer { val mcpServer = Server( Implementation(name = name ?: DEFAULT_SERVER_NAME, version = VERSION), ServerOptions( @@ -52,7 +56,7 @@ open class AbstractStreamableHttpIntegrationTest { host = URL, port = PORT, ) { - mcpStreamableHttp { mcpServer } + mcpStreamableHttp(sseHeartbeatConfig = sseHeartbeatConfig) { mcpServer } } return StreamableHttpTestServer( diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpHeartbeatIntegrationTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpHeartbeatIntegrationTest.kt new file mode 100644 index 0000000..8019557 --- /dev/null +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/streamablehttp/StreamableHttpHeartbeatIntegrationTest.kt @@ -0,0 +1,174 @@ +package io.modelcontextprotocol.kotlin.sdk.integration.streamablehttp + +import io.kotest.matchers.shouldBe +import io.ktor.client.HttpClient +import io.ktor.client.plugins.sse.SSE +import io.ktor.client.request.header +import io.ktor.client.request.post +import io.ktor.client.request.prepareGet +import io.ktor.client.request.setBody +import io.ktor.client.statement.bodyAsChannel +import io.ktor.http.ContentType +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpStatusCode +import io.ktor.http.contentType +import io.ktor.sse.ServerSentEvent +import io.ktor.utils.io.ByteReadChannel +import io.ktor.utils.io.readUTF8Line +import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest +import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequestParams +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCRequest +import io.modelcontextprotocol.kotlin.sdk.types.LATEST_PROTOCOL_VERSION +import io.modelcontextprotocol.kotlin.sdk.types.toJSON +import io.modelcontextprotocol.kotlin.test.utils.actualPort +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeoutOrNull +import kotlinx.serialization.json.Json +import kotlin.test.Test +import kotlin.test.assertNotNull +import kotlin.time.Duration.Companion.milliseconds +import io.ktor.client.engine.cio.CIO as ClientCIO + +private const val SESSION_ID_HEADER = "mcp-session-id" +private const val PROTOCOL_VERSION_HEADER = "mcp-protocol-version" +private const val DEFAULT_HEARTBEAT_LINE = ": heartbeat" +private const val CUSTOM_HEARTBEAT_LINE = ": mcp-heartbeat" + +class StreamableHttpHeartbeatIntegrationTest : AbstractStreamableHttpIntegrationTest() { + + @Test + fun `GET SSE stream emits configured heartbeat`(): Unit = runBlocking(Dispatchers.IO) { + var server: StreamableHttpTestServer? = null + var httpClient: HttpClient? = null + + try { + server = initTestServer("heartbeat-test") { + period = 50.milliseconds + event = ServerSentEvent(comments = "mcp-heartbeat") + } + val mcpUrl = "http://$URL:${server.ktorServer.actualPort()}/mcp" + httpClient = HttpClient(ClientCIO) { install(SSE) } + val sessionId = initializeSession(httpClient, mcpUrl) + + httpClient.prepareGet(mcpUrl) { + addSseHeaders(sessionId) + }.execute { response -> + response.status shouldBe HttpStatusCode.OK + response.headers[SESSION_ID_HEADER] shouldBe sessionId + + response.bodyAsChannel().readLineMatching(CUSTOM_HEARTBEAT_LINE) shouldBe CUSTOM_HEARTBEAT_LINE + } + } finally { + httpClient?.close() + server?.ktorServer?.stopSuspend(1000, 2000) + } + } + + @Test + fun `GET SSE stream does not emit heartbeat by default`(): Unit = runBlocking(Dispatchers.IO) { + var server: StreamableHttpTestServer? = null + var httpClient: HttpClient? = null + + try { + server = initTestServer("no-heartbeat-test") + val mcpUrl = "http://$URL:${server.ktorServer.actualPort()}/mcp" + httpClient = HttpClient(ClientCIO) { install(SSE) } + val sessionId = initializeSession(httpClient, mcpUrl) + + httpClient.prepareGet(mcpUrl) { + addSseHeaders(sessionId) + }.execute { response -> + response.status shouldBe HttpStatusCode.OK + response.headers[SESSION_ID_HEADER] shouldBe sessionId + + response.bodyAsChannel().readLineMatching(timeoutMillis = 150) { line -> + line.isHeartbeatSseLine() + } shouldBe null + } + } finally { + httpClient?.close() + server?.ktorServer?.stopSuspend(1000, 2000) + } + } + + @Test + fun `GET SSE stream emits configured heartbeat repeatedly`(): Unit = runBlocking(Dispatchers.IO) { + var server: StreamableHttpTestServer? = null + var httpClient: HttpClient? = null + + try { + server = initTestServer("repeating-heartbeat-test") { + period = 50.milliseconds + event = ServerSentEvent(comments = "mcp-heartbeat") + } + val mcpUrl = "http://$URL:${server.ktorServer.actualPort()}/mcp" + httpClient = HttpClient(ClientCIO) { install(SSE) } + val sessionId = initializeSession(httpClient, mcpUrl) + + httpClient.prepareGet(mcpUrl) { + addSseHeaders(sessionId) + }.execute { response -> + response.status shouldBe HttpStatusCode.OK + response.headers[SESSION_ID_HEADER] shouldBe sessionId + + val channel = response.bodyAsChannel() + channel.readLineMatching(CUSTOM_HEARTBEAT_LINE) shouldBe CUSTOM_HEARTBEAT_LINE + channel.readLineMatching(CUSTOM_HEARTBEAT_LINE) shouldBe CUSTOM_HEARTBEAT_LINE + } + } finally { + httpClient?.close() + server?.ktorServer?.stopSuspend(1000, 2000) + } + } + + private suspend fun initializeSession(client: HttpClient, mcpUrl: String): String { + val response = client.post(mcpUrl) { + contentType(ContentType.Application.Json) + header( + HttpHeaders.Accept, + "${ContentType.Application.Json}, ${ContentType.Text.EventStream}", + ) + setBody(Json.encodeToString(buildInitPayload())) + } + + response.status shouldBe HttpStatusCode.OK + return assertNotNull(response.headers[SESSION_ID_HEADER]) + } + + private fun buildInitPayload(): JSONRPCRequest = InitializeRequest( + InitializeRequestParams( + protocolVersion = LATEST_PROTOCOL_VERSION, + capabilities = ClientCapabilities(), + clientInfo = Implementation(name = "heartbeat-test-client", version = "1.0.0"), + ), + ).toJSON() + + private fun io.ktor.client.request.HttpRequestBuilder.addSseHeaders(sessionId: String) { + header(HttpHeaders.Accept, ContentType.Text.EventStream.toString()) + header(SESSION_ID_HEADER, sessionId) + header(PROTOCOL_VERSION_HEADER, LATEST_PROTOCOL_VERSION) + } + + private suspend fun ByteReadChannel.readLineMatching(expectedLine: String, timeoutMillis: Long = 2_000): String? = + readLineMatching(timeoutMillis) { line -> line == expectedLine } + + private suspend fun ByteReadChannel.readLineMatching( + timeoutMillis: Long = 2_000, + matches: (String) -> Boolean, + ): String? = withTimeoutOrNull(timeoutMillis.milliseconds) { + var line = readUTF8Line() + while (line != null) { + if (matches(line)) return@withTimeoutOrNull line + line = readUTF8Line() + } + null + } + + private fun String.isHeartbeatSseLine(): Boolean = this == DEFAULT_HEARTBEAT_LINE || + this == CUSTOM_HEARTBEAT_LINE || + (startsWith(":") && contains("heartbeat", ignoreCase = true)) || + (startsWith("event:") && contains("heartbeat", ignoreCase = true)) +} diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.api b/kotlin-sdk-server/api/kotlin-sdk-server.api index 51ac279..1ec2efd 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.api @@ -59,8 +59,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/KtorServerKt { 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 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 final fun mcpStreamableHttp (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 synthetic fun mcpStreamableHttp$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 final fun mcpStreamableHttp (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/server/EventStore;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun mcpStreamableHttp$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;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V } public final class io/modelcontextprotocol/kotlin/sdk/server/RegisteredPrompt : io/modelcontextprotocol/kotlin/sdk/server/Feature { 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 73ef258..5fc3d22 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 @@ -20,8 +20,10 @@ import io.ktor.server.routing.get import io.ktor.server.routing.post import io.ktor.server.routing.route import io.ktor.server.routing.routing +import io.ktor.server.sse.Heartbeat import io.ktor.server.sse.SSE import io.ktor.server.sse.ServerSSESession +import io.ktor.server.sse.heartbeat import io.ktor.server.sse.sse import io.ktor.utils.io.KtorDsl import io.modelcontextprotocol.kotlin.sdk.types.RPCError @@ -162,6 +164,7 @@ private fun Application.mcpStreamableHttp( allowedHosts: List?, allowedOrigins: List?, configuration: StreamableHttpServerTransport.Configuration, + sseHeartbeatConfig: (Heartbeat.() -> Unit)?, block: RoutingContext.() -> Server, ) { installMcpContentNegotiation() @@ -185,6 +188,7 @@ private fun Application.mcpStreamableHttp( sse { val transport = existingStreamableTransport(call, transportManager) ?: return@sse + sseHeartbeatConfig?.let { config -> heartbeat(config) } transport.handleRequest(this, call) } @@ -227,6 +231,7 @@ private fun Application.mcpStreamableHttp( * With custom `allowedHosts`, `null` skips origin validation. * @param eventStore An optional [EventStore] instance to enable resumable event stream functionality. * Allows storing and replaying events. + * @param sseHeartbeatConfig The heartbeat configuration option for SSE connections. `null` means no heartbeat is sent. * @param block factory block with access to the [RoutingContext] (for reading request headers) * that creates and returns the [Server] to handle the connection. */ @@ -237,6 +242,7 @@ public fun Application.mcpStreamableHttp( allowedHosts: List? = null, allowedOrigins: List? = null, eventStore: EventStore? = null, + sseHeartbeatConfig: (Heartbeat.() -> Unit)? = null, block: RoutingContext.() -> Server, ) { mcpStreamableHttp( @@ -248,6 +254,7 @@ public fun Application.mcpStreamableHttp( eventStore = eventStore, enableJsonResponse = true, ), + sseHeartbeatConfig = sseHeartbeatConfig, block = block, ) } From 82fe56e1e857c992d7de18c3ea90fad040deebf7 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Mon, 27 Jul 2026 13:39:49 +0200 Subject: [PATCH 114/178] fix(server): preserve Streamable HTTP response status and body (#911) Streamable HTTP responses now keep their status when the client accepts only `text/event-stream`. ## How Has This Been Tested? New `StreamableHttpResponseDeliveryTest` ## Breaking Changes None ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../kotlin/sdk/server/KtorServer.kt | 23 +++-- .../server/StreamableHttpServerTransport.kt | 27 +++-- .../StreamableHttpResponseDeliveryTest.kt | 99 +++++++++++++++++++ .../StreamableHttpServerTransportTest.kt | 63 +++++++++++- 4 files changed, 191 insertions(+), 21 deletions(-) create mode 100644 kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpResponseDeliveryTest.kt 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 5fc3d22..8220a8b 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 @@ -1,6 +1,7 @@ package io.modelcontextprotocol.kotlin.sdk.server import io.github.oshai.kotlinlogging.KotlinLogging +import io.ktor.http.HttpHeaders import io.ktor.http.HttpMethod import io.ktor.http.HttpStatusCode import io.ktor.server.application.Application @@ -282,18 +283,10 @@ private fun Application.mcpStatelessStreamableHttp( ) } get { - call.reject( - HttpStatusCode.MethodNotAllowed, - RPCError.ErrorCode.CONNECTION_CLOSED, - "Method not allowed.", - ) + call.rejectUnsupportedMethod() } delete { - call.reject( - HttpStatusCode.MethodNotAllowed, - RPCError.ErrorCode.CONNECTION_CLOSED, - "Method not allowed.", - ) + call.rejectUnsupportedMethod() } } } @@ -419,6 +412,16 @@ private suspend fun RoutingContext.mcpPostEndpoint(transportManager: TransportMa logger.trace { "Message handled for sessionId: $sessionId" } } +/** A stateless endpoint serves POST only, offering neither an SSE stream to open nor a session to delete. */ +private suspend fun ApplicationCall.rejectUnsupportedMethod() { + response.header(HttpHeaders.Allow, HttpMethod.Post.value) + reject( + HttpStatusCode.MethodNotAllowed, + RPCError.ErrorCode.CONNECTION_CLOSED, + "Method not allowed.", + ) +} + private fun ApplicationRequest.sessionId(): String? = header(MCP_SESSION_ID_HEADER) private suspend fun existingStreamableTransport( 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 3b02835..15d0b4c 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 @@ -10,7 +10,7 @@ import io.ktor.server.request.header import io.ktor.server.request.httpMethod import io.ktor.server.response.header import io.ktor.server.response.respond -import io.ktor.server.response.respondNullable +import io.ktor.server.response.respondText import io.ktor.server.sse.ServerSSESession import io.ktor.util.collections.ConcurrentMap import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport @@ -474,12 +474,13 @@ public class StreamableHttpServerTransport(private val configuration: Configurat ) return } - if (!validateProtocolVersion(call)) return + if (!validateProtocolVersion(call, initializationRequest.id)) return if (messages.size > 1) { call.reject( HttpStatusCode.BadRequest, RPCError.ErrorCode.INVALID_REQUEST, "Invalid Request: Only one initialization request is allowed", + initializationRequest.id, ) return } @@ -491,12 +492,13 @@ public class StreamableHttpServerTransport(private val configuration: Configurat sessionId?.let { onSessionInitialized?.invoke(it) } } } else { - if (!validateSession(call) || !validateProtocolVersion(call)) return + val requestId = messages.filterIsInstance().firstOrNull()?.id + if (!validateSession(call, requestId) || !validateProtocolVersion(call, requestId)) return } val hasRequest = messages.any { it is JSONRPCRequest } if (!hasRequest) { - call.respondNullable(status = HttpStatusCode.Accepted, message = null) + call.respond(HttpStatusCode.Accepted) messages.forEach { message -> _onMessage(message) } // A cancellation may target a request still awaiting delivery on a JSON-mode POST; // retire it so that POST completes instead of waiting for a response that never comes. @@ -552,7 +554,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat if (responses.isEmpty()) { // Every request in this POST was cancelled before producing a response; there is // nothing to return, so acknowledge with 202 rather than an empty JSON body. - call.respondNullable(status = HttpStatusCode.Accepted, message = null) + call.respond(HttpStatusCode.Accepted) } else { call.response.header(HttpHeaders.ContentType, ContentType.Application.Json.toString()) val payload = if (responses.size == 1) responses.first() else responses @@ -645,7 +647,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat if (!validateSession(call) || !validateProtocolVersion(call)) return sessionId?.let { onSessionClosed?.invoke(it) } close() - call.respondNullable(status = HttpStatusCode.OK, message = null) + call.respond(HttpStatusCode.OK) } /** @@ -734,7 +736,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } } - private suspend fun validateSession(call: ApplicationCall): Boolean { + private suspend fun validateSession(call: ApplicationCall, id: RequestId? = null): Boolean { if (sessionIdGenerator == null) return true if (!initialized.load()) { @@ -742,6 +744,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat HttpStatusCode.BadRequest, RPCError.ErrorCode.CONNECTION_CLOSED, "Bad Request: Server not initialized", + id, ) return false } @@ -753,6 +756,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat HttpStatusCode.BadRequest, RPCError.ErrorCode.CONNECTION_CLOSED, "Bad Request: Mcp-Session-Id header is required", + id, ) return false } @@ -765,13 +769,14 @@ public class StreamableHttpServerTransport(private val configuration: Configurat HttpStatusCode.NotFound, REQUEST_TIMEOUT, "Session not found", + id, ) false } } } - private suspend fun validateProtocolVersion(call: ApplicationCall): Boolean { + private suspend fun validateProtocolVersion(call: ApplicationCall, id: RequestId? = null): Boolean { val version = call.request.headers[MCP_PROTOCOL_VERSION_HEADER] ?: return true return when (version) { @@ -784,6 +789,7 @@ public class StreamableHttpServerTransport(private val configuration: Configurat ", ", ) })", + id, ) false } @@ -914,12 +920,13 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } } +/** Writes an already serialized body so a client accepting only `text/event-stream` still receives [status]. */ internal suspend fun ApplicationCall.reject( status: HttpStatusCode, code: Int, message: String, id: RequestId? = null, ) { - this.response.status(status) - this.respond(JSONRPCError(id = id, error = RPCError(code = code, message = message))) + val error = JSONRPCError(id = id, error = RPCError(code = code, message = message)) + respondText(McpJson.encodeToString(error), ContentType.Application.Json, status) } diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpResponseDeliveryTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpResponseDeliveryTest.kt new file mode 100644 index 0000000..fc076eb --- /dev/null +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpResponseDeliveryTest.kt @@ -0,0 +1,99 @@ +package io.modelcontextprotocol.kotlin.sdk.server + +import io.kotest.matchers.shouldBe +import io.ktor.client.request.delete +import io.ktor.client.request.get +import io.ktor.client.request.header +import io.ktor.client.request.post +import io.ktor.client.request.setBody +import io.ktor.client.statement.HttpResponse +import io.ktor.client.statement.bodyAsText +import io.ktor.http.ContentType +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpMethod +import io.ktor.http.HttpStatusCode +import io.ktor.http.contentType +import io.ktor.server.testing.testApplication +import io.modelcontextprotocol.kotlin.sdk.types.Implementation +import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCError +import io.modelcontextprotocol.kotlin.sdk.types.McpJson +import io.modelcontextprotocol.kotlin.sdk.types.RPCError +import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities +import kotlin.test.Test + +/** + * A client opening the standalone stream sends `Accept: text/event-stream`, which matches no JSON + * converter. Responses rendered through ContentNegotiation used to reach such a client as an empty + * 406 with the intended status discarded. + */ +class StreamableHttpResponseDeliveryTest { + + private val eventStream = ContentType.Text.EventStream.toString() + + private fun testServer(): Server = Server( + Implementation("test-server", "1.0"), + ServerOptions(capabilities = ServerCapabilities()), + ) + + @Test + fun `stateless GET is rejected with 405 and advertises POST`() = testApplication { + application { mcpStatelessStreamableHttp { testServer() } } + + val response = client.get("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Accept, eventStream) + } + + response.assertMethodNotAllowed() + } + + @Test + fun `stateless DELETE is rejected with 405 and advertises POST`() = testApplication { + application { mcpStatelessStreamableHttp { testServer() } } + + val response = client.delete("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Accept, eventStream) + } + + response.assertMethodNotAllowed() + } + + @Test + fun `stateful DELETE for an unknown session returns 404`() = testApplication { + application { mcpStreamableHttp { testServer() } } + + val response = client.delete("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Accept, eventStream) + header(MCP_SESSION_ID_HEADER, "unknown-session") + } + + response.status shouldBe HttpStatusCode.NotFound + response.decodeError().error.message shouldBe "Session not found" + } + + @Test + fun `POST carrying no request is acknowledged with a bodiless 202`() = testApplication { + application { mcpStatelessStreamableHttp { testServer() } } + + val response = client.post("/mcp") { + header(HttpHeaders.Host, "localhost") + header(HttpHeaders.Accept, "${ContentType.Application.Json}, $eventStream") + contentType(ContentType.Application.Json) + setBody("""{"jsonrpc":"2.0","method":"notifications/initialized"}""") + } + + response.status shouldBe HttpStatusCode.Accepted + response.bodyAsText() shouldBe "" + } + + private suspend fun HttpResponse.assertMethodNotAllowed() { + status shouldBe HttpStatusCode.MethodNotAllowed + headers[HttpHeaders.Allow] shouldBe HttpMethod.Post.value + contentType()?.withoutParameters() shouldBe ContentType.Application.Json + decodeError().error.code shouldBe RPCError.ErrorCode.CONNECTION_CLOSED + } + + private suspend fun HttpResponse.decodeError(): JSONRPCError = McpJson.decodeFromString(bodyAsText()) +} diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt index bb522d6..e5c51e9 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt @@ -216,14 +216,16 @@ class StreamableHttpServerTransportTest { configureTransportEndpoint(transport) + val payload = buildInitializeRequestPayload() val initResponse = client.post(path) { addStreamableHeaders() header("mcp-protocol-version", "1900-01-01") - setBody(buildInitializeRequestPayload()) + setBody(payload) } initResponse.status shouldBe HttpStatusCode.BadRequest initResponse.headers[MCP_SESSION_ID_HEADER] shouldBe null + initResponse.body().id shouldBe payload.id } @Test @@ -297,6 +299,65 @@ class StreamableHttpServerTransportTest { } response.status shouldBe HttpStatusCode.BadRequest + response.body().id shouldBe RequestId("test-1") + } + + @Test + fun `batch with an initialization request echoes the initialize id when rejected`() = testApplication { + configTestServer() + + val client = createTestClient() + + val transport = StreamableHttpServerTransport(enableJsonResponse = true) + transport.onMessage { } + + configureTransportEndpoint(transport) + + val initPayload = buildInitializeRequestPayload() + val response = client.post(path) { + addStreamableHeaders() + setBody( + encodeMessages( + listOf( + initPayload, + JSONRPCRequest(id = RequestId("extra"), method = Method.Defined.ToolsList.value), + ), + ), + ) + } + + response.status shouldBe HttpStatusCode.BadRequest + val error = response.body() + error.error.message shouldBe "Invalid Request: Only one initialization request is allowed" + error.id shouldBe initPayload.id + } + + @Test + fun `non-init request before initialization echoes the request id`() = testApplication { + configTestServer() + + val client = createTestClient() + + val transport = StreamableHttpServerTransport(enableJsonResponse = true) + transport.onMessage { } + + configureTransportEndpoint(transport) + + val response = client.post(path) { + addStreamableHeaders() + setBody( + encodeMessages( + listOf( + JSONRPCRequest(id = RequestId("before-init"), method = Method.Defined.ToolsList.value), + ), + ), + ) + } + + response.status shouldBe HttpStatusCode.BadRequest + val error = response.body() + error.error.message shouldBe "Bad Request: Server not initialized" + error.id shouldBe RequestId("before-init") } @Test From 2b494b763730e3886f415a211ed82ac8fdaf9244 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 14:09:25 +0200 Subject: [PATCH 115/178] chore(deps): bump the other-dependencies group across 5 directories with 3 updates (#914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java) and [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 2 updates in the /samples/kotlinlang-mcp-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow) and [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback). Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Bumps the other-dependencies group with 1 update in the /samples/weather-stdio-server directory: [com.gradleup.shadow](https://github.com/GradleUp/shadow). Updates `com.anthropic:anthropic-java` from 2.48.0 to 2.52.0
        Release notes

        Sourced from com.anthropic:anthropic-java's releases.

        v2.52.0

        2.52.0 (2026-07-24)

        Full Changelog: v2.51.0...v2.52.0

        Features

        • api: add claude-opus-5 model (fb245bd)
        • api: add tool addition/removal blocks and tool_change events (fb245bd)
        • api: expand client-side fallback credit token types and add server-side fallbacks default option (fb245bd)

        v2.51.0

        2.51.0 (2026-07-23)

        Full Changelog: v2.50.0...v2.51.0

        Features

        • api: add new stop reason 'model_context_window_exceeded' (f4b644e)

        Bug Fixes

        • refer to the CLI as ant in NoCredentialsException (#170) (1bc2be9)

        v2.50.0

        2.50.0 (2026-07-22)

        Full Changelog: v2.49.1...v2.50.0

        Features

        • api: add support for Managed Agents model effort, initial session events, and threads delta streaming (e312432)

        v2.49.1

        2.49.1 (2026-07-21)

        Full Changelog: v2.49.0...v2.49.1

        Chores

        • api: add support for new refusal category (40db9c7)
        • client: docs updates (5b25c27)
        • docs: small updates (99a2a8c)
        • docs: small updates (adc11f5)
        • internal: codegen related update (9d85f79)

        v2.49.0

        2.49.0 (2026-07-16)

        ... (truncated)

        Changelog

        Sourced from com.anthropic:anthropic-java's changelog.

        2.52.0 (2026-07-24)

        Full Changelog: v2.51.0...v2.52.0

        Features

        • api: add claude-opus-5 model (fb245bd)
        • api: add tool addition/removal blocks and tool_change events (fb245bd)
        • api: expand client-side fallback credit token types and add server-side fallbacks default option (fb245bd)

        2.51.0 (2026-07-23)

        Full Changelog: v2.50.0...v2.51.0

        Features

        • api: add new stop reason 'model_context_window_exceeded' (f4b644e)

        Bug Fixes

        • refer to the CLI as ant in NoCredentialsException (#170) (1bc2be9)

        2.50.0 (2026-07-22)

        Full Changelog: v2.49.1...v2.50.0

        Features

        • api: add support for Managed Agents model effort, initial session events, and threads delta streaming (e312432)

        2.49.1 (2026-07-21)

        Full Changelog: v2.49.0...v2.49.1

        Chores

        • api: add support for new refusal category (40db9c7)
        • client: docs updates (5b25c27)
        • docs: small updates (99a2a8c)
        • docs: small updates (adc11f5)
        • internal: codegen related update (9d85f79)

        2.49.0 (2026-07-16)

        Full Changelog: v2.48.0...v2.49.0

        Features

        • api: add support for dreaming (836ee60)

        ... (truncated)

        Commits
        • 55ff755 release: 2.52.0
        • 917b495 feat(api): add claude-opus-5 model
        • 4124b5e release: 2.51.0
        • 684e2a8 feat(api): add new stop reason 'model_context_window_exceeded'
        • 2fbb806 fix: refer to the CLI as ant in NoCredentialsException (#170)
        • 8bfe5af release: 2.50.0
        • 46da3ef feat(api): add support for Managed Agents model effort, initial session event...
        • abe2641 release: 2.49.1
        • 847a8c1 chore(api): add support for new refusal category
        • 0d9869f chore(internal): codegen related update
        • Additional commits viewable in compare view

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.5.1 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.6.0 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.6.0 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `ch.qos.logback:logback-classic` from 1.5.38 to 1.6.0
        Release notes

        Sourced from ch.qos.logback:logback-classic's releases.

        Logback 1.6.0

        2026-07-23 Release of logback version 1.6.0

        • Removed certain deprecated variables, methods, and classes. For the list of removed members see release_1.6.0.txt.

        • In AsyncAppenderBase, the put(ILoggingEvent) method now has the protected modifier to allow access from derived classes. This change was requested by Thomas Skjølberg in pr#1053.

        • Bump SLF4J dependency to version 2.0.18.

        • See also the overview of the 1.6.x series.

        • A bit-wise identical binary of this version can be reproduced by building from source code at commit b07adf36019b51a10f824fdd94009985c587b1d3 associated with the tag v_1.6.0. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

        Commits
        • b07adf3 synronized logback-access with future 2.0.14
        • 8381cdc prepare release 1.6.0
        • 15db759 notes on removed deprecated classes, methods and variables.
        • 90ced5a revert removal of support for packaing data
        • 64c5d3f Packaging data is no longer supported. It was rarely used.
        • 5474044 fix failing tests
        • ac484c2 in version 1.6.x target JDK 11
        • 01eaa90 start work on version 1.6.0-SNAPSHOT
        • d5e658c Allow subclasses to use put(ILoggingEvent) by making method access protected
        • 94ba1a0 improve message in case of version mismatch
        • Additional commits viewable in compare view

        Updates `com.gradleup.shadow` from 9.6.0 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed

        • Rename ShadowDslMarker to ShadowDsl. (#2091)
        • POTENTIALLY BREAKING: Apply @ShadowDsl to ShadowJar, ResourceTransformer, DependencyFilter, and Relocator. (#2090)
          This restricts nested DSL configuration blocks from implicitly calling outer receiver APIs in Kotlin script files.

        Fixed

        • Validate ZIP entry names to prevent Zip Slip path traversal.
        • Avoid resolving unused R8 dependency. (#2101)
        Commits

        Updates `com.gradleup.shadow` from 9.6.0 to 9.6.1
        Release notes

        Sourced from com.gradleup.shadow's releases.

        9.6.1

        Changed

        • Use GradleException for expected build failures. (#2113)

        Fixed

        • Preserve repeated lines in R8 rule files when using minimize { r8 { ... } }. (#2115)

        9.6.0

        Added

        • Extract R8 rules from dependency JARs when using minimize { r8 { ... } }. (#2089)

        Changed Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 4 ++-- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 4 ++-- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 732dfbd..921a7b2 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,9 +1,9 @@ [versions] -anthropic = "2.48.0" +anthropic = "2.52.0" kotlin = "2.4.10" ktor = "3.5.1" mcp-kotlin = "0.14.0" -shadow = "9.5.1" +shadow = "9.6.1" slf4j = "2.0.18" [libraries] diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 6cdd81f..230336b 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin = "2.4.0" ktor = "3.5.1" mcp-kotlin = "0.14.0" slf4j = "2.0.18" -shadow = "9.5.1" +shadow = "9.6.1" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 047c0bf..363c373 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -4,8 +4,8 @@ ktor = "3.5.1" mcp-kotlin = "0.14.0" serialization = "1.11.0" coroutines = "1.11.0" -logback = "1.5.38" -shadow = "9.6.0" +logback = "1.6.0" +shadow = "9.6.1" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index bbf7120..abd1290 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -4,7 +4,7 @@ ktor = "3.5.1" junit = "6.1.2" mcp-kotlin = "0.14.0" slf4j = "2.0.18" -shadow = "9.6.0" +shadow = "9.6.1" [libraries] ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 67fec97..69b8d1c 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -4,7 +4,7 @@ kotlin = "2.4.0" ktor = "3.5.1" logging = "8.0.4" mcp-kotlin = "0.14.0" -shadow = "9.5.1" +shadow = "9.6.1" slf4j = "2.0.18" [libraries] From 94745e617cada0b89e084dd4ffd5010f26174e54 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 14:52:31 +0200 Subject: [PATCH 116/178] chore(deps): bump the kotest group across 1 directory with 3 updates (#915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotest group with 3 updates in the / directory: [io.kotest:kotest-assertions-core](https://github.com/kotest/kotest), [io.kotest:kotest-assertions-json](https://github.com/kotest/kotest) and [io.kotest:kotest-assertions-ktor](https://github.com/kotest/kotest). Updates `io.kotest:kotest-assertions-core` from 6.2.2 to 6.2.3
        Release notes

        Sourced from io.kotest:kotest-assertions-core's releases.

        v6.2.3

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/6.2.2...v6.2.3

        Commits

        Updates `io.kotest:kotest-assertions-json` from 6.2.2 to 6.2.3
        Release notes

        Sourced from io.kotest:kotest-assertions-json's releases.

        v6.2.3

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/6.2.2...v6.2.3

        Commits

        Updates `io.kotest:kotest-assertions-ktor` from 6.2.2 to 6.2.3
        Release notes

        Sourced from io.kotest:kotest-assertions-ktor's releases.

        v6.2.3

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/6.2.2...v6.2.3

        Commits

        Updates `io.kotest:kotest-assertions-json` from 6.2.2 to 6.2.3
        Release notes

        Sourced from io.kotest:kotest-assertions-json's releases.

        v6.2.3

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/6.2.2...v6.2.3

        Commits

        Updates `io.kotest:kotest-assertions-ktor` from 6.2.2 to 6.2.3
        Release notes

        Sourced from io.kotest:kotest-assertions-ktor's releases.

        v6.2.3

        What's Changed

        New Contributors

        Full Changelog: https://github.com/kotest/kotest/compare/6.2.2...v6.2.3

        Commits

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6d3c5a8..d648750 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ netty = "4.2.16.Final" awaitility = "4.3.0" collections-immutable = "0.5.1" coroutines = "1.11.0" -kotest = "6.2.2" +kotest = "6.2.3" kotlinx-io = "0.9.1" ktor = "3.5.1" logging = "8.0.4" From 7fa438ce00e1bdb2fb1cc22d3efacb07dafa448e Mon Sep 17 00:00:00 2001 From: "Andre.Kalberer" <83852559+AndreKalberer@users.noreply.github.com> Date: Mon, 27 Jul 2026 06:29:51 -0700 Subject: [PATCH 117/178] feat(client): send MCP standard POST headers (#894) ## Problem SEP-2243 requires Streamable HTTP clients to mirror applicable JSON-RPC request metadata into standard HTTP headers. The Kotlin client currently sends `Mcp-Protocol-Version` and session metadata but does not emit `Mcp-Method` or `Mcp-Name`. ## Solution - Add `Mcp-Method` for JSON-RPC requests and notifications. - Add `Mcp-Name` from a string `params.name`, falling back to a string `params.uri`. - Omit both headers for JSON-RPC responses. - Add focused transport tests for name-, URI-, notification-, and response-based behavior. ## Validation - `.\gradlew.bat :kotlin-sdk-client:jvmTest --tests "io.modelcontextprotocol.kotlin.sdk.client.streamable.http.StreamableHttpClientTransportTest"` - `.\gradlew.bat :kotlin-sdk-client:ktlintCheck :kotlin-sdk-client:detekt :kotlin-sdk-client:apiCheck` - `git diff --check` Closes #787 AI assistance was used while preparing this PR. I reviewed the final change, ran the validation listed above, and take responsibility for it. --------- Co-authored-by: Pavel Gorgulov --- .../client/StreamableHttpClientTransport.kt | 39 ++++++++ .../http/StreamableHttpClientTransportTest.kt | 94 +++++++++++++++++++ 2 files changed, 133 insertions(+) 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 a63c1d2..6df352a 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 @@ -43,6 +43,10 @@ import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.ExperimentalEncodingApi import kotlin.math.pow import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -51,6 +55,10 @@ import kotlin.time.Duration.Companion.seconds private const val MCP_SESSION_ID_HEADER = "mcp-session-id" private const val MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version" private const val MCP_RESUMPTION_TOKEN_HEADER = "Last-Event-ID" +private const val MCP_METHOD_HEADER = "Mcp-Method" +private const val MCP_NAME_HEADER = "Mcp-Name" +private const val MCP_BASE64_PREFIX = "=?base64?" +private const val MCP_BASE64_SUFFIX = "?=" /** * Default maximum size, in characters, of a single inline SSE event assembled from a POST response. @@ -167,6 +175,7 @@ public class StreamableHttpClientTransport( val jsonBody = McpJson.encodeToString(message) val response = client.post(url) { applyCommonHeaders(this) + applyStandardPostHeaders(this, message) headers.append(HttpHeaders.Accept, "${ContentType.Application.Json}, ${ContentType.Text.EventStream}") contentType(ContentType.Application.Json) setBody(jsonBody) @@ -390,6 +399,36 @@ public class StreamableHttpClientTransport( } } + private fun applyStandardPostHeaders(builder: HttpRequestBuilder, message: JSONRPCMessage) { + val (method, params) = when (message) { + is JSONRPCRequest -> message.method to message.params + is JSONRPCNotification -> message.method to message.params + else -> return + } + + builder.headers { + append(MCP_METHOD_HEADER, method) + + val paramsObject = params as? JsonObject ?: return@headers + val mcpName = paramsObject.stringValue("name") ?: paramsObject.stringValue("uri") + mcpName?.let { append(MCP_NAME_HEADER, it.encodeMcpHeaderValue()) } + } + } + + private fun JsonObject.stringValue(key: String): String? = + (get(key) as? JsonPrimitive)?.takeIf { it.isString }?.content + + @OptIn(ExperimentalEncodingApi::class) + private fun String.encodeMcpHeaderValue(): String { + val containsUnsafeCharacters = any { it != '\t' && it.code !in 0x20..0x7e } + val hasEdgeWhitespace = firstOrNull()?.isWhitespace() == true || lastOrNull()?.isWhitespace() == true + val matchesBase64Sentinel = startsWith(MCP_BASE64_PREFIX) && endsWith(MCP_BASE64_SUFFIX) + + if (!containsUnsafeCharacters && !hasEdgeWhitespace && !matchesBase64Sentinel) return this + + return "$MCP_BASE64_PREFIX${Base64.Default.encode(encodeToByteArray())}$MCP_BASE64_SUFFIX" + } + private suspend fun collectSse( session: ClientSSESession, replayMessageId: RequestId?, diff --git a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt index ef55867..d9aaf7a 100644 --- a/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt +++ b/kotlin-sdk-client/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/streamable/http/StreamableHttpClientTransportTest.kt @@ -246,6 +246,100 @@ class StreamableHttpClientTransportTest { transport.close() } + @Test + fun `should send MCP method and name headers from name`() = runTest { + val transport = createTransport { request -> + assertEquals("tools/call", request.headers["Mcp-Method"]) + assertEquals("read_file", request.headers["Mcp-Name"]) + respond(content = "", status = HttpStatusCode.Accepted) + } + + transport.start() + transport.send( + JSONRPCRequest( + id = "test-id", + method = "tools/call", + params = buildJsonObject { + put("name", JsonPrimitive("read_file")) + put("arguments", buildJsonObject { put("path", JsonPrimitive("README.md")) }) + }, + ), + ) + transport.close() + } + + @Test + fun `should send MCP name header from URI`() = runTest { + val transport = createTransport { request -> + assertEquals("resources/read", request.headers["Mcp-Method"]) + assertEquals("file:///README.md", request.headers["Mcp-Name"]) + respond(content = "", status = HttpStatusCode.Accepted) + } + + transport.start() + transport.send( + JSONRPCRequest( + id = "test-id", + method = "resources/read", + params = buildJsonObject { put("uri", JsonPrimitive("file:///README.md")) }, + ), + ) + transport.close() + } + + @Test + fun `should encode MCP name header values when required`() = runTest { + val cases = listOf( + "Hello, 世界" to "=?base64?SGVsbG8sIOS4lueVjA==?=", + " padded " to "=?base64?IHBhZGRlZCA=?=", + "line1\nline2" to "=?base64?bGluZTEKbGluZTI=?=", + "=?base64?literal?=" to "=?base64?PT9iYXNlNjQ/bGl0ZXJhbD89?=", + ) + + cases.forEachIndexed { index, (name, expectedHeader) -> + val transport = createTransport { request -> + assertEquals(expectedHeader, request.headers["Mcp-Name"]) + respond(content = "", status = HttpStatusCode.Accepted) + } + + transport.start() + transport.send( + JSONRPCRequest( + id = "test-id-$index", + method = "tools/call", + params = buildJsonObject { put("name", JsonPrimitive(name)) }, + ), + ) + transport.close() + } + } + + @Test + fun `should send MCP method header for notifications`() = runTest { + val transport = createTransport { request -> + assertEquals("notifications/tools/list_changed", request.headers["Mcp-Method"]) + assertNull(request.headers["Mcp-Name"]) + respond(content = "", status = HttpStatusCode.Accepted) + } + + transport.start() + transport.send(JSONRPCNotification(method = "notifications/tools/list_changed")) + transport.close() + } + + @Test + fun `should omit MCP standard headers for responses`() = runTest { + val transport = createTransport { request -> + assertNull(request.headers["Mcp-Method"]) + assertNull(request.headers["Mcp-Name"]) + respond(content = "", status = HttpStatusCode.Accepted) + } + + transport.start() + transport.send(JSONRPCResponse(id = RequestId.StringId("test-id"))) + transport.close() + } + // Engine doesn't support SSECapability: https://youtrack.jetbrains.com/issue/KTOR-8177/MockEngine-Add-SSE-support @Ignore @Test From 24c3cd3a6943556d7cd6c9024fd7860ff7b2dd13 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 28 Jul 2026 14:51:21 +0200 Subject: [PATCH 118/178] fix(server): match Accept header as media ranges (#912) The header is now parsed into media ranges (`parseHeaderValue` + `ContentType.match`) ## Breaking Changes none ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- .../server/StreamableHttpServerTransport.kt | 22 +++- .../StreamableHttpServerTransportTest.kt | 107 ++++++++++++++++++ 2 files changed, 127 insertions(+), 2 deletions(-) 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 15d0b4c..dcba848 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 @@ -1,9 +1,11 @@ package io.modelcontextprotocol.kotlin.sdk.server +import io.ktor.http.BadContentTypeFormatException import io.ktor.http.ContentType import io.ktor.http.HttpHeaders import io.ktor.http.HttpMethod import io.ktor.http.HttpStatusCode +import io.ktor.http.parseHeaderValue import io.ktor.server.application.ApplicationCall import io.ktor.server.request.contentType import io.ktor.server.request.header @@ -864,8 +866,24 @@ public class StreamableHttpServerTransport(private val configuration: Configurat } } - private fun String?.accepts(mime: ContentType): Boolean = - this?.lowercase()?.contains(mime.toString().lowercase()) == true + /** + * Reports whether the `Accept` header admits [mime]. + * + * Comparison is over parsed media ranges rather than raw substrings, so wildcards are honored + * and a near miss such as `application/jsonp` no longer passes as `application/json`. An absent + * header states no preference and admits any type. + */ + private fun String?.accepts(mime: ContentType): Boolean { + if (this == null) return true + return parseHeaderValue(this).any { range -> + if (range.quality <= 0.0) return@any false + try { + mime.match(ContentType.parse(range.value)) + } catch (_: BadContentTypeFormatException) { + false + } + } + } private suspend fun emitOnStream(streamId: String, session: ServerSSESession?, message: JSONRPCMessage) { val eventId = configuration.eventStore?.storeEvent(streamId, message) diff --git a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt index e5c51e9..43ff605 100644 --- a/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt +++ b/kotlin-sdk-server/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/StreamableHttpServerTransportTest.kt @@ -9,6 +9,7 @@ import io.ktor.client.call.body import io.ktor.client.plugins.logging.LogLevel import io.ktor.client.plugins.logging.Logging import io.ktor.client.request.HttpRequestBuilder +import io.ktor.client.request.get import io.ktor.client.request.header import io.ktor.client.request.post import io.ktor.client.request.prepareGet @@ -21,6 +22,7 @@ import io.ktor.http.contentType import io.ktor.serialization.kotlinx.json.json import io.ktor.server.application.ApplicationCall import io.ktor.server.application.install +import io.ktor.server.routing.get import io.ktor.server.routing.post import io.ktor.server.routing.routing import io.ktor.server.sse.ServerSSESession @@ -76,6 +78,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertFalse import kotlin.test.assertNotNull +import kotlin.test.assertTrue import kotlin.time.Duration.Companion.seconds import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation import io.ktor.server.plugins.contentnegotiation.ContentNegotiation as ServerContentNegotiation @@ -100,6 +103,26 @@ class StreamableHttpServerTransportTest { Arguments.of(sizeTestPayload.length.toLong(), HttpStatusCode.BadRequest), Arguments.of(sizeTestPayload.length.toLong() + 1, HttpStatusCode.BadRequest), ) + + @JvmStatic + fun postAcceptHeaderCases(): List = listOf( + Arguments.of("application/json, text/event-stream", HttpStatusCode.OK), + Arguments.of("Application/JSON;q=0.9, TEXT/Event-Stream;charset=utf-8", HttpStatusCode.OK), + Arguments.of("*/*", HttpStatusCode.OK), + Arguments.of("application/*, text/*", HttpStatusCode.OK), + Arguments.of(null, HttpStatusCode.OK), + Arguments.of("application/json", HttpStatusCode.NotAcceptable), + Arguments.of("text/event-stream", HttpStatusCode.NotAcceptable), + Arguments.of("application/jsonp, text/event-stream-bogus", HttpStatusCode.NotAcceptable), + Arguments.of("application/json, text/event-stream;q=0", HttpStatusCode.NotAcceptable), + ) + + @JvmStatic + fun getAcceptHeaderCases() = listOf( + "application/json", + "text/event-stream-bogus", + "text/event-stream;q=0", + ) } private val path = "/transport" @@ -130,6 +153,90 @@ class StreamableHttpServerTransportTest { assertFalse(onMessageCalled.get(), "Transport should not deliver messages when headers are invalid") } + @ParameterizedTest + @MethodSource("postAcceptHeaderCases") + fun `POST Accept header is matched as media ranges`(acceptHeader: String?, expectedStatus: HttpStatusCode) = + testApplication { + configTestServer() + + // Bare client: the ContentNegotiation plugin would supply an Accept header of its own, + // leaving the absent-header case untestable. + val client = createClient {} + + val transport = StreamableHttpServerTransport(enableJsonResponse = true) + val onMessageCalled = AtomicBoolean(false) + transport.onMessage { message -> + onMessageCalled.set(true) + if (message is JSONRPCRequest) { + transport.send(JSONRPCResponse(message.id, EmptyResult())) + } + } + + configureTransportEndpoint(transport) + + val response = client.post(path) { + contentType(ContentType.Application.Json) + acceptHeader?.let { header(HttpHeaders.Accept, it) } + setBody(McpJson.encodeToString(JSONRPCMessage.serializer(), buildInitializeRequestPayload())) + } + + assertEquals(expectedStatus, response.status) + assertEquals( + expectedStatus == HttpStatusCode.OK, + onMessageCalled.get(), + "Only a request that clears the Accept gate may reach the transport", + ) + } + + @Test + fun `POST with an unparsable Accept header is rejected without failing the request`() = testApplication { + configTestServer() + + val client = createClient {} + + val transport = StreamableHttpServerTransport(enableJsonResponse = true) + val onMessageCalled = AtomicBoolean(false) + transport.onMessage { + onMessageCalled.set(true) + } + + configureTransportEndpoint(transport) + + val response = client.post(path) { + contentType(ContentType.Application.Json) + header(HttpHeaders.Accept, "not-a-media-type") + setBody(McpJson.encodeToString(JSONRPCMessage.serializer(), buildInitializeRequestPayload())) + } + + // The exact code is decided by content negotiation once the transport has rejected the request. + assertTrue(response.status.value in 400..499, "Expected a client error, got ${response.status}") + assertFalse(onMessageCalled.get(), "Transport should not deliver messages when headers are invalid") + } + + @ParameterizedTest + @MethodSource("getAcceptHeaderCases") + fun `GET whose Accept header admits no event-stream range is rejected`(acceptHeader: String) = testApplication { + configTestServer() + + val client = createClient {} + + val transport = StreamableHttpServerTransport(enableJsonResponse = true) + + application { + routing { + get(path) { + transport.handleGetRequest(FakeServerSSESession(call, call.coroutineContext), call) + } + } + } + + val response = client.get(path) { + header(HttpHeaders.Accept, acceptHeader) + } + + assertEquals(HttpStatusCode.NotAcceptable, response.status) + } + @Test fun `initialization request establishes session and returns json response`() = testApplication { configTestServer() From dab340f9bff1662cc2975d675ec14550d14adcc5 Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 28 Jul 2026 15:43:24 +0200 Subject: [PATCH 119/178] fix(server): drop inert eventStore from stateless Streamable HTTP (#909) Removes the `eventStore` parameter from `mcpStatelessStreamableHttp`, where it was never read or written. closes #908 ## Breaking Changes Source-breaking only ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed --- kotlin-sdk-server/api/kotlin-sdk-server.api | 2 + .../kotlin/sdk/server/KtorServer.kt | 39 ++++++++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/kotlin-sdk-server/api/kotlin-sdk-server.api b/kotlin-sdk-server/api/kotlin-sdk-server.api index 1ec2efd..d8e4c7a 100644 --- a/kotlin-sdk-server/api/kotlin-sdk-server.api +++ b/kotlin-sdk-server/api/kotlin-sdk-server.api @@ -58,7 +58,9 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/KtorServerKt { 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 (Lio/ktor/server/application/Application;Ljava/lang/String;ZLjava/util/List;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/server/EventStore;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V public static synthetic fun mcpStreamableHttp$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;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V } 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 8220a8b..3127499 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 @@ -270,7 +270,6 @@ private fun Application.mcpStatelessStreamableHttp( block: RoutingContext.() -> Server, ) { installMcpContentNegotiation() - install(SSE) routing { route(path) { @@ -297,10 +296,11 @@ private fun Application.mcpStatelessStreamableHttp( * over _stateless_ [Streamable HTTP Transport](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http) * * Sets up an HTTP POST endpoint at [path]. GET and DELETE requests return 405 Method Not Allowed. - * Simple request/response pairs are returned as JSON (not SSE streams). + * Every request/response pair is returned as JSON, so this endpoint opens no SSE stream and + * offers no resumability. Use [mcpStreamableHttp] when either is required. * * Automatically installs [ContentNegotiation][io.ktor.server.plugins.contentnegotiation.ContentNegotiation] - * with [McpJson][io.modelcontextprotocol.kotlin.sdk.types.McpJson] and [SSE]. + * with [McpJson][io.modelcontextprotocol.kotlin.sdk.types.McpJson]. * * @param path The URL path where the server listens for incoming JSON-RPC requests. Defaults to "/mcp". * @param enableDnsRebindingProtection Determines whether DNS rebinding protection is enabled. Defaults to `true`. @@ -309,7 +309,6 @@ private fun Application.mcpStatelessStreamableHttp( * @param allowedOrigins A list of allowed `Origin` header values, compared by hostname only * (scheme and port are ignored). Requests without an `Origin` header are allowed. * If `null`, origin validation is disabled. - * @param eventStore An optional [EventStore] implementation to provide resumability and event replay support. * @param block factory block with access to the [RoutingContext] (for reading request headers) * that creates and returns the [Server] to handle the connection. */ @@ -319,7 +318,6 @@ public fun Application.mcpStatelessStreamableHttp( enableDnsRebindingProtection: Boolean = true, allowedHosts: List? = null, allowedOrigins: List? = null, - eventStore: EventStore? = null, block: RoutingContext.() -> Server, ) { mcpStatelessStreamableHttp( @@ -328,13 +326,42 @@ public fun Application.mcpStatelessStreamableHttp( allowedHosts = allowedHosts, allowedOrigins = allowedOrigins, configuration = StreamableHttpServerTransport.Configuration( - eventStore = eventStore, enableJsonResponse = true, ), block = block, ) } +/** + * 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, From 76b8e7d63aac39fe41e03684e3b91a6c3724a8da Mon Sep 17 00:00:00 2001 From: Pavel Gorgulov Date: Tue, 28 Jul 2026 16:41:12 +0200 Subject: [PATCH 120/178] release: 0.15.0 (#918) Bump version to 0.15.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 434144d..a5655c3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,4 @@ kotlin.daemon.jvmargs=-Xmx4G kotlin.native.ignoreDisabledTargets=true group=io.modelcontextprotocol -version=0.14.0 +version=0.15.0 From b133d7ecdd42a498d09dc3e60094fae94e1e899c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 13:48:11 +0200 Subject: [PATCH 121/178] chore(deps): bump ch.qos.logback:logback-classic from 1.5.38 to 1.6.1 (#916) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.38 to 1.6.1.
        Release notes

        Sourced from ch.qos.logback:logback-classic's releases.

        Logback 1.6.1

        2026-07-28 Release of logback version 1.6.1

        • In TimeBasedRollingPolicy, when the file option is set, the intermediate file renamed before asynchronous compression now receives the target archive name without the compression suffix (e.g. .gz, .zip, .xz). Previously it used a nanotime-based .tmp suffix. This makes the file easier to identify if compression fails during rollover. (See also the following paragraph.)

        • On GZ, ZIP, or XZ compression failure, the original (uncompressed) log file is no longer deleted. Compression strategies now delete the source file only after successful compression and emit a warning that the original was left intact.

        • ConsoleAppender with now probes JLine's org.jline.jansi.AnsiConsole first and falls back to the legacy FuseSource org.fusesource.jansi.AnsiConsole class. This keeps ANSI coloring working after Jansi moved under the JLine project. The optional org.jline:jansi-core artifact is declared as a dependency alongside the existing FuseSource jansi dependency. A preferredJansiClassName property was added for tests. This issue was reported in issues/1043 by seonwoo_jung who also provided the relevant PR.

        • LayoutWrappingEncoder now reports an error at start() when no layout is set and guards encode() against a null layout. Previously, a missing layout (for example after an ignored // branch) allowed the encoder to start and then fail with a NullPointerException on every event, resulting in silent log loss. This issue was reported in issues/1046 by seonwoo_jung who also provided the relevant PR.

        • FileCollisionAnalyser now detects file collisions involving nested appenders of SiftingAppender. When the nested file or fileNamePattern does not textually reference the discriminator key (e.g. ${userId}), a warning is issued at configuration time naming the appender, the key, and the shared target. This closes a gap where statically declared file appenders were checked but sifted nested appenders were not. This enhancement was contributed in [PR #1041](qos-ch/logback#1041) by seonwoo_jung.

        • More defensive handling in SyslogOutputStream and SyslogAppenderBase: the close() method now ensures that resources are closed, writes and flushes check that the underlying resources are in a valid state and fallback to no-op otherwise.

        • A bit-wise identical binary of this version can be reproduced by building from source code at commit 57759f433000a133088ef0441038963134437fbd associated with the tag v_1.6.1. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

        • See https://logback.qos.ch/news.html#1.6.1 for the original text.

        Logback 1.6.0

        2026-07-23 Release of logback version 1.6.0

        • Removed certain deprecated variables, methods, and classes. For the list of removed members see release_1.6.0.txt.

        • In AsyncAppenderBase, the put(ILoggingEvent) method now has the protected modifier to allow access from derived classes. This change was requested by Thomas Skjølberg in pr#1053.

        • Bump SLF4J dependency to version 2.0.18.

        • See also the overview of the 1.6.x series.

        • A bit-wise identical binary of this version can be reproduced by building from source code at commit b07adf36019b51a10f824fdd94009985c587b1d3 associated with the tag v_1.6.0. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

        Commits
        • 57759f4 prepare release 1.6.1
        • 175f99f fix imports
        • 4b8773e add compressionFailureLeavesOriginalFileIntact test for XZ compression
        • cafaf11 do not delete original file if compression fails
        • ee50125 let the temporary file before compression be target file without the .gz or ....
        • 5626acc minor refactoring
        • d97da4f minor refactoring
        • 159c045 more defensive coding in SyslogOutputStream and in SyslogAppenderBase
        • 9427d6b slight refactoring for clarity
        • 79c4179 slight refactoring
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d648750..6d7bbbb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" slf4j = "2.0.18" -logback = "1.5.38" +logback = "1.6.1" junit = "5.14.4" [libraries] From cce22c282aa5f9fc2bbb7c7c58f24f9c7973087f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:23:43 +0200 Subject: [PATCH 122/178] chore(deps): bump ch.qos.logback:logback-classic from 1.6.0 to 1.6.1 in /samples/kotlinlang-mcp-server in the other-dependencies group across 1 directory (#924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the other-dependencies group with 1 update in the /samples/kotlinlang-mcp-server directory: [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback). Updates `ch.qos.logback:logback-classic` from 1.6.0 to 1.6.1
        Release notes

        Sourced from ch.qos.logback:logback-classic's releases.

        Logback 1.6.1

        2026-07-28 Release of logback version 1.6.1

        • In TimeBasedRollingPolicy, when the file option is set, the intermediate file renamed before asynchronous compression now receives the target archive name without the compression suffix (e.g. .gz, .zip, .xz). Previously it used a nanotime-based .tmp suffix. This makes the file easier to identify if compression fails during rollover. (See also the following paragraph.)

        • On GZ, ZIP, or XZ compression failure, the original (uncompressed) log file is no longer deleted. Compression strategies now delete the source file only after successful compression and emit a warning that the original was left intact.

        • ConsoleAppender with now probes JLine's org.jline.jansi.AnsiConsole first and falls back to the legacy FuseSource org.fusesource.jansi.AnsiConsole class. This keeps ANSI coloring working after Jansi moved under the JLine project. The optional org.jline:jansi-core artifact is declared as a dependency alongside the existing FuseSource jansi dependency. A preferredJansiClassName property was added for tests. This issue was reported in issues/1043 by seonwoo_jung who also provided the relevant PR.

        • LayoutWrappingEncoder now reports an error at start() when no layout is set and guards encode() against a null layout. Previously, a missing layout (for example after an ignored // branch) allowed the encoder to start and then fail with a NullPointerException on every event, resulting in silent log loss. This issue was reported in issues/1046 by seonwoo_jung who also provided the relevant PR.

        • FileCollisionAnalyser now detects file collisions involving nested appenders of SiftingAppender. When the nested file or fileNamePattern does not textually reference the discriminator key (e.g. ${userId}), a warning is issued at configuration time naming the appender, the key, and the shared target. This closes a gap where statically declared file appenders were checked but sifted nested appenders were not. This enhancement was contributed in [PR #1041](qos-ch/logback#1041) by seonwoo_jung.

        • More defensive handling in SyslogOutputStream and SyslogAppenderBase: the close() method now ensures that resources are closed, writes and flushes check that the underlying resources are in a valid state and fallback to no-op otherwise.

        • A bit-wise identical binary of this version can be reproduced by building from source code at commit 57759f433000a133088ef0441038963134437fbd associated with the tag v_1.6.1. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

        • See https://logback.qos.ch/news.html#1.6.1 for the original text.

        Commits
        • 57759f4 prepare release 1.6.1
        • 175f99f fix imports
        • 4b8773e add compressionFailureLeavesOriginalFileIntact test for XZ compression
        • cafaf11 do not delete original file if compression fails
        • ee50125 let the temporary file before compression be target file without the .gz or ....
        • 5626acc minor refactoring
        • d97da4f minor refactoring
        • 159c045 more defensive coding in SyslogOutputStream and in SyslogAppenderBase
        • 9427d6b slight refactoring for clarity
        • 79c4179 slight refactoring
        • Additional commits viewable in compare view

        [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ch.qos.logback:logback-classic&package-manager=gradle&previous-version=1.6.0&new-version=1.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
        Dependabot commands and options
        You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 363c373..f059fa4 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -4,7 +4,7 @@ ktor = "3.5.1" mcp-kotlin = "0.14.0" serialization = "1.11.0" coroutines = "1.11.0" -logback = "1.6.0" +logback = "1.6.1" shadow = "9.6.1" [libraries] From 6c9ca01922ead6a2a0e7e6c29e30e549f76c0a79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:03:13 +0200 Subject: [PATCH 123/178] chore(deps): bump io.modelcontextprotocol:kotlin-sdk-client from 0.14.0 to 0.15.0 in /samples/kotlin-mcp-client (#925) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.modelcontextprotocol:kotlin-sdk-client](https://github.com/modelcontextprotocol/kotlin-sdk) from 0.14.0 to 0.15.0.
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 921a7b2..ea0043d 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -2,7 +2,7 @@ anthropic = "2.52.0" kotlin = "2.4.10" ktor = "3.5.1" -mcp-kotlin = "0.14.0" +mcp-kotlin = "0.15.0" shadow = "9.6.1" slf4j = "2.0.18" From 47938a056c87ab862e83f52a1a619956cebbcf80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:20:37 +0200 Subject: [PATCH 124/178] chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/kotlin-mcp-server (#926) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.14.0 to 0.15.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 230336b..83a262e 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.4.0" ktor = "3.5.1" -mcp-kotlin = "0.14.0" +mcp-kotlin = "0.15.0" slf4j = "2.0.18" shadow = "9.6.1" From b7f280118ded1e6a04aad60d8ff14aa7cba10d47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:39:04 +0200 Subject: [PATCH 125/178] chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/kotlinlang-mcp-server (#927) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.14.0 to 0.15.0. Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Updates `io.modelcontextprotocol:kotlin-sdk-testing` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-testing's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index f059fa4..2d48f35 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.4.0" ktor = "3.5.1" -mcp-kotlin = "0.14.0" +mcp-kotlin = "0.15.0" serialization = "1.11.0" coroutines = "1.11.0" logback = "1.6.1" From bb716cd44d6fcb205f77ad34a7cd5b7f0d6ec46d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:31:38 +0200 Subject: [PATCH 126/178] chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/simple-streamable-server (#928) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.14.0 to 0.15.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index abd1290..28ab094 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.4.0" ktor = "3.5.1" junit = "6.1.2" -mcp-kotlin = "0.14.0" +mcp-kotlin = "0.15.0" slf4j = "2.0.18" shadow = "9.6.1" From c61a7ca00c50d86ae7d67c37bf36a89c8289986c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 18:46:44 +0200 Subject: [PATCH 127/178] chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/weather-stdio-server (#929) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `mcp-kotlin` from 0.14.0 to 0.15.0. Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-client's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.14.0 to 0.15.0
        Release notes

        Sourced from io.modelcontextprotocol:kotlin-sdk-server's releases.

        0.15.0

        Description

        This release makes inbound message handling concurrent after the initialization handshake, adds SSE heartbeats and elicitation schema validation, and fixes several Streamable HTTP response and session-lifecycle bugs.

        Breaking Changes

        Concurrent inbound dispatch by @​devcrocod in #884

        Inbound messages were processed serially on the transport read loop, so one slow or peer-awaiting handler (sampling, elicitation, roots) blocked every later message on the connection, including the responses and notifications/cancelled those handlers depend on. After the handshake, handlers may now run concurrently; processing stays serial during initialization.

        • ProtocolOptions / ClientOptions / ServerOptions gain a handlerCoroutineContext parameter (defaults to Dispatchers.Default). Concurrency is bounded internally; there is no opt-out flag by design.
        • RequestHandlerExtra is now a CoroutineContext.Element and is no longer user-constructible. It exposes requestId, method, sendRequest, and sendNotification, and can be read inside a handler via the new currentRequestHandlerExtra().
        - val extra = RequestHandlerExtra()
        + val extra = currentRequestHandlerExtra()
        

        Duplicate feature names are rejected at registration by @​devcrocod in #883

        addTool/addPrompt/addResource/addResourceTemplate silently replaced an existing entry and emitted a spurious list_changed notification. They now throw IllegalArgumentException and leave the existing registration intact. The batch variants (addTools/addPrompts/addResources) are all-or-nothing. To replace a feature, remove it first.

        - server.addTool(name = "search", ...)
        // silently overwrote
        + server.removeTool("search")
        + server.addTool(name = "search", ...)
        

        eventStore removed from mcpStatelessStreamableHttp by @​devcrocod in #909

        The parameter was never read or written: a stateless endpoint answers GET with 405, so no stream exists to store or replay events on. The old overload is retained at DeprecationLevel.ERROR with a ReplaceWith migration hint. Use mcpStreamableHttp when you need resumability.

          application.mcpStatelessStreamableHttp(
              path = "/mcp",
        -     eventStore = myEventStore,
          ) { server }
        

        Features

        • Optional SSE heartbeats for Streamable HTTP servers via mcpStreamableHttp(sseHeartbeatConfig = { ... }), keeping long-lived streams alive against clients that disconnect on idle. Heartbeats stay off by default, by @​UnscientificJsZhai in #761
        • Accepted form-mode elicitation content is now validated against requestedSchema; a mismatch fails createElicitation with McpException (INVALID_PARAMS) instead of reaching server code unchecked, by @​rea9r in #896
        • The Streamable HTTP client now sends the standard Mcp-Method and Mcp-Name POST headers, by @​AndreKalberer in #894

        Fixed

        • Stateless Streamable HTTP now closes its per-request session, fixing unbounded growth of the session registry and notification subscriptions, by @​KlyneChrysler in #872
        • Streamable HTTP responses keep their status and body when the client accepts only text/event-stream, by @​devcrocod in #911

        ... (truncated)

        Commits
        • 76b8e7d release: 0.15.0 (#918)
        • dab340f fix(server): drop inert eventStore from stateless Streamable HTTP (#909)
        • 24c3cd3 fix(server): match Accept header as media ranges (#912)
        • 7fa438c feat(client): send MCP standard POST headers (#894)
        • 94745e6 chore(deps): bump the kotest group across 1 directory with 3 updates (#915)
        • 2b494b7 chore(deps): bump the other-dependencies group across 5 directories with 3 up...
        • 82fe56e fix(server): preserve Streamable HTTP response status and body (#911)
        • a06d699 feat: SSE heartbeat (#761)
        • cab669b fix: classify malformed request params as invalid params (#886)
        • b6cb547 fix(server): preserve id on duplicate initialize errors (#868)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 69b8d1c..ea351f1 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ coroutines = "1.11.0" kotlin = "2.4.0" ktor = "3.5.1" logging = "8.0.4" -mcp-kotlin = "0.14.0" +mcp-kotlin = "0.15.0" shadow = "9.6.1" slf4j = "2.0.18" From fe9843ded917460233e47fe1bf5a0a4dd9256440 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 11:56:24 +0200 Subject: [PATCH 128/178] chore(deps): bump the all-actions group across 1 directory with 3 updates (#932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-actions group with 3 updates in the / directory: [gradle/actions](https://github.com/gradle/actions), [actions/stale](https://github.com/actions/stale) and [github/codeql-action](https://github.com/github/codeql-action). Updates `gradle/actions` from 6 to 6.2.0
        Release notes

        Sourced from gradle/actions's releases.

        v6.2.0

        Highlights

        This release brings significant behaviour improvements to Enhanced caching, improvements to the generated Job Summary, and a number of correctness and security fixes.

        1. Improved cache-cleanup mechanism. Cleanup of stale files from the Gradle User Home is now faster, and no longer depends on Gradle or a JVM. It works by inspecting the local file state directly, removing the Gradle invocation from the post-build step.
        2. More granular, more stable caching. The local build cache is stored as a separate cache entry, so it can be restored and invalidated independently of the main Gradle User Home entry. Transient Gradle housekeeping files are excluded from the cache, reducing its size and improving stability.
        3. Hide obsolete Job summaries in PR commments: When a new Job summary comment is added to a PR, previous outdated Job summaries are now hidden.
        4. Improved caching report in the job summary. The cache report now uses a single, consistent layout across all cache states and providers. Provider information is integrated directly into the report, and per-entry details are available in an expandable section. (#985)
        5. Correctness and security fixes. A unique cache key is now used per run attempt, so re-runs no longer collide; the job summary shows the cache key string rather than an internal id; and bundled dependencies have been updated, including a ReDoS fix and a fast-xml CVE fix.

        What's Changed

        New Contributors

        Full Changelog: https://github.com/gradle/actions/compare/v6.1.1...v6.2.0

        v6.1.1

        This release updates various dependency versions, resolving several reported security vulnerabilities. No functional changes are included

        What's Changed

        Full Changelog: https://github.com/gradle/actions/compare/v6.1.0...v6.1.1

        v6.1.0

        New: Basic Cache Provider

        A new MIT-licensed Basic Caching provider is now available as an alternative to the proprietary Enhanced Caching provided by gradle-actions-caching. Choose Basic Caching by setting cache-provider: basic on setup-gradle or dependency-submission actions.

        • Built on @actions/cache -- fully open source

        ... (truncated)

        Commits
        • b6eebf3 [bot] Update dist directory
        • 9901393 Remove unnecessary dependency overrides (#981)
        • 20ce680 Update RELEASING.md
        • 5e2ebd0 [bot] Update dist directory
        • 9e2c1cc Resolve npm security vulnerabilities via dependency overrides (#980)
        • 657f690 [bot] Update dist directory
        • 9d6bacd Update @​actions/cache and @​actions/artifact, stop ignoring them in Dependabot...
        • 79f6b19 [bot] Update dist directory
        • 6781648 Bump the npm-dependencies group in /sources with 5 updates (#977)
        • a3b40d2 [bot] Update dist directory
        • Additional commits viewable in compare view

        Updates `actions/stale` from 10 to 11
        Release notes

        Sourced from actions/stale's releases.

        v11.0.0

        What's Changed

        Enhancement

        Dependency Update

        Full Changelog: https://github.com/actions/stale/compare/v10...v11.0.0

        v10.4.0

        What's Changed

        Bug Fix

        Dependency Updates

        New Contributors

        Full Changelog: https://github.com/actions/stale/compare/v10.3.0...v10.4.0

        v10.3.0

        What's Changed

        Bug Fix

        Dependency Updates

        New Contributors

        Full Changelog: https://github.com/actions/stale/compare/v10...v10.3.0

        v10.2.0

        What's Changed

        Bug Fix

        Dependency Updates

        New Contributors

        Full Changelog: https://github.com/actions/stale/compare/v10...v10.2.0

        ... (truncated)

        Changelog

        Sourced from actions/stale's changelog.

        Changelog

        [10.1.0]

        What's Changed

        [10.0.0]

        What's Changed

        Breaking Changes

        Enhancement

        Dependency Upgrades

        Documentation changes

        [9.1.0]

        What's Changed

        [9.0.0]

        Breaking Changes

        1. Action is now stateful: If the action ends because of operations-per-run then the next run will start from the first unprocessed issue skipping the issues processed during the previous run(s). The state is reset when all the issues are processed. This should be considered for scheduling workflow runs.
        2. Version 9 of this action updated the runtime to Node.js 20. All scripts are now run with Node.js 20 instead of Node.js 16 and are affected by any breaking changes between Node.js 16 and 20.

        ... (truncated)

        Commits
        • 4391f3d Fix 24 high severity vulnerabilities by overriding brace-expansion to 5.0.8 (...
        • eaf9131 refactor: update imports to use ES module syntax and improve test structure (...
        • See full diff in compare view

        Updates `github/codeql-action` from 4 to 4.37.4
        Release notes

        Sourced from github/codeql-action's releases.

        v4.37.4

        • This version of the CodeQL Action adds support for the tools input for the codeql-action/init step to be specified using a github-codeql-tools repository property. This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to toolcache to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for tools in the workflow definition always takes precedence unless the value of the repository property starts with !. #4037
        • Update default CodeQL bundle version to 2.26.2. #4051

        v4.37.3

        No user facing changes.

        v4.37.2

        • The new address format for the config-file input that was introduced in CodeQL Action 4.37.0 is now enabled by default. In addition to the format described there, the remote= prefix can now be used to explicitly indicate that the input refers to a remote file. All previous input formats continue to be accepted as well. #4023
        • The CodeQL Action can now make use of configured private registries in Default Setup to retrieve CodeQL configuration files from remote repositories that require authentication. This will allow customers to store their CodeQL configuration in a single repository that can then be referenced by Default Setup workflows in other repositories. We expect to roll this and other, related changes out to everyone in July. #4007

        v4.37.1

        • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.20.6 and earlier. These versions of CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise Server 3.16, and will be unsupported by the next minor release of the CodeQL Action. #3956
        • Update default CodeQL bundle version to 2.26.1. #4019

        v4.37.0

        • Update default CodeQL bundle version to 2.26.0. #3995
        • In addition to the existing input format, the config-file input for the codeql-action/init step will soon support a new [owner/]repo[@ref][:path] format. All components except the repository name are optional. If omitted, owner defaults to the same owner as the repository the analysis is running for, ref to main, and path to .github/codeql-action.yaml. Support for this format ships in this version of the CodeQL Action, but will only be enabled over the coming weeks. #3973

        v4.36.3

        No user facing changes.

        v4.36.2

        • Cache CodeQL CLI version information across Actions steps. #3943
        • Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. #3937
        • Update default CodeQL bundle version to 2.25.6. #3948

        v4.36.1

        No user facing changes.

        v4.36.0

        • Breaking change: Bump the minimum required CodeQL bundle version to 2.19.4. #3894
        • Add support for SHA-256 Git object IDs. #3893
        • Update default CodeQL bundle version to 2.25.5. #3926

        v4.35.5

        • We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. #3899
        • For performance and accuracy reasons, improved incremental analysis will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. #3791
        • If multiple inputs are provided for the GitHub-internal analysis-kinds input, only code-scanning will be enabled. The analysis-kinds input is experimental, for GitHub-internal use only, and may change without notice at any time. #3892
        • Added an experimental change which, when running a Code Scanning analysis for a PR with improved incremental analysis enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. #3880

        v4.35.4

        • Update default CodeQL bundle version to 2.25.4. #3881

        v4.35.3

        • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. #3837
        • Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. #3850
        • Best-effort connection tests for private registries now use GET requests instead of HEAD for better compatibility with various registry implementations. For NuGet feeds, the test is now always performed against the service index. #3853
        • Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. #3852
        • Update default CodeQL bundle version to 2.25.3. #3865

        ... (truncated)

        Changelog

        Sourced from github/codeql-action's changelog.

        4.37.4 - 29 Jul 2026

        • This version of the CodeQL Action adds support for the tools input for the codeql-action/init step to be specified using a github-codeql-tools repository property. This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to toolcache to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for tools in the workflow definition always takes precedence unless the value of the repository property starts with !. #4037
        • Update default CodeQL bundle version to 2.26.2. #4051

        4.37.3 - 22 Jul 2026

        No user facing changes.

        4.37.2 - 21 Jul 2026

        • The new address format for the config-file input that was introduced in CodeQL Action 4.37.0 is now enabled by default. In addition to the format described there, the remote= prefix can now be used to explicitly indicate that the input refers to a remote file. All previous input formats continue to be accepted as well. #4023
        • The CodeQL Action can now make use of configured private registries in Default Setup to retrieve CodeQL configuration files from remote repositories that require authentication. This will allow customers to store their CodeQL configuration in a single repository that can then be referenced by Default Setup workflows in other repositories. We expect to roll this and other, related changes out to everyone in July. #4007

        4.37.1 - 16 Jul 2026

        • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.20.6 and earlier. These versions of CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise Server 3.16, and will be unsupported by the next minor release of the CodeQL Action. #3956
        • Update default CodeQL bundle version to 2.26.1. #4019

        4.37.0 - 08 Jul 2026

        • Update default CodeQL bundle version to 2.26.0. #3995
        • In addition to the existing input format, the config-file input for the codeql-action/init step will soon support a new [owner/]repo[@ref][:path] format. All components except the repository name are optional. If omitted, owner defaults to the same owner as the repository the analysis is running for, ref to main, and path to .github/codeql-action.yaml. Support for this format ships in this version of the CodeQL Action, but will only be enabled over the coming weeks. #3973

        4.36.3 - 01 Jul 2026

        No user facing changes.

        Commits
        • 18420e3 Merge pull request #4043 from github/mbg/ts/changelog
        • 7e8d897 Merge pull request #4046 from github/mbg/repo-prop/code-quality
        • 2d4c474 Log !analysisKindSupported case
        • 98c05a1 Fix argument validation in rollback-changelog.ts
        • 8289a49 Ignore repository property for unsupported analysis kinds
        • 2a8731c Move config-file computation after determining the analysisKinds
        • 3434fbb Merge pull request #4044 from github/mbg/ff/promote-toolcache
        • 3013ac0 Promote AllowToolcacheInput feature
        • 74b15aa Install JS deps if needed in post-release-mergeback workflow
        • f00f809 Fix checking keys rather than values
        • Additional commits viewable in compare view

        Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
        Dependabot commands and options
        You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/apidocs.yaml | 2 +- .github/workflows/automations.yml | 4 ++-- .github/workflows/build.yml | 6 +++--- .github/workflows/codeql.yml | 6 +++--- .github/workflows/conformance.yml | 8 ++++---- .github/workflows/gradle-publish.yml | 2 +- .github/workflows/samples.yml | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/apidocs.yaml b/.github/workflows/apidocs.yaml index 510af19..8887169 100644 --- a/.github/workflows/apidocs.yaml +++ b/.github/workflows/apidocs.yaml @@ -34,7 +34,7 @@ jobs: cache: gradle - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 - name: Generate Dokka Site run: |- diff --git a/.github/workflows/automations.yml b/.github/workflows/automations.yml index 4f88d37..60a9d3b 100644 --- a/.github/workflows/automations.yml +++ b/.github/workflows/automations.yml @@ -27,7 +27,7 @@ jobs: name: Mark/unmark stale PRs and issues runs-on: ubuntu-latest steps: - - uses: actions/stale@v10 + - uses: actions/stale@v11 with: debug-only: ${{ env.DRY_RUN }} exempt-draft-pr: true @@ -66,7 +66,7 @@ jobs: name: Close stale PRs and issues runs-on: ubuntu-latest steps: - - uses: actions/stale@v10 + - uses: actions/stale@v11 with: debug-only: ${{ env.DRY_RUN }} only-labels: 'stale' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 147163c..0707d44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,7 +63,7 @@ jobs: run: npm ci - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: validate-wrappers: true add-job-summary: 'always' @@ -135,7 +135,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: validate-wrappers: true add-job-summary: 'always' @@ -177,7 +177,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: add-job-summary: 'always' cache-read-only: true diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f25ec64..368f044 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,13 +34,13 @@ jobs: java-version: ${{ env.JAVA_VERSION }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@v4.37.4 with: languages: java-kotlin build-mode: manual - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: validate-wrappers: true cache-read-only: true @@ -52,6 +52,6 @@ jobs: --no-daemon --rerun-tasks --stacktrace - name: Analyze - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@v4.37.4 with: category: '/language:java-kotlin' diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 2511286..0605b10 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -34,7 +34,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} @@ -85,7 +85,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} @@ -116,7 +116,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} @@ -155,7 +155,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index 058e041..c9dc966 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -30,7 +30,7 @@ jobs: node-version: '22' # increase only after https://github.com/nodejs/node/issues/56645 will be fixed - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 - name: Check run: ./gradlew check --no-configuration-cache diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml index 89de699..812fbb9 100644 --- a/.github/workflows/samples.yml +++ b/.github/workflows/samples.yml @@ -45,7 +45,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.2.0 with: validate-wrappers: true add-job-summary: 'always' From 4a8ffdfea998e03a0e4b27236035bb6dc030c0fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 14:07:06 +0200 Subject: [PATCH 129/178] chore(deps): bump the kotlin group across 1 directory with 2 updates (#901) Bumps the kotlin group with 2 updates in the / directory: [org.jetbrains.kotlin:kotlin-gradle-plugin](https://github.com/JetBrains/kotlin) and [org.jetbrains.kotlin:kotlin-serialization](https://github.com/JetBrains/kotlin). Updates `org.jetbrains.kotlin:kotlin-gradle-plugin` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin:kotlin-gradle-plugin's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin:kotlin-gradle-plugin's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Updates `org.jetbrains.kotlin:kotlin-serialization` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin:kotlin-serialization's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin:kotlin-serialization's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Updates `org.jetbrains.kotlin:kotlin-serialization` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin:kotlin-serialization's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin:kotlin-serialization's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6d7bbbb..051e361 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ atomicfu = "0.33.0" binaryCompatibilityValidatorPlugin = "0.18.1" detekt = "2.0.0-alpha.5" dokka = "2.2.0" -kotlin = "2.4.0" +kotlin = "2.4.10" kover = "0.9.9" ktlint = "14.2.0" knit = "0.5.1" From 9249c6929596dc129e0851e2952abfafb5e528d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 14:27:10 +0200 Subject: [PATCH 130/178] chore(deps): bump ip-address from 10.2.0 to 10.4.0 in /integration-test/src/jvmTest/typescript (#934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ip-address](https://github.com/beaugunderson/ip-address) from 10.2.0 to 10.4.0.
        Release notes

        Sourced from ip-address's releases.

        v10.4.0

        What's Changed

        Full Changelog: https://github.com/beaugunderson/ip-address/compare/v10.3.1...v10.4.0

        v10.3.1

        Full Changelog: https://github.com/beaugunderson/ip-address/compare/v10.3.0...v10.3.1

        v10.3.0

        Full Changelog: https://github.com/beaugunderson/ip-address/compare/v10.2.2...v10.3.0

        v10.2.2

        Full Changelog: https://github.com/beaugunderson/ip-address/compare/v10.2.1...v10.2.2

        v10.2.1

        Full Changelog: https://github.com/beaugunderson/ip-address/compare/v10.2.0...v10.2.1

        Commits
        • fbb8db2 10.4.0
        • 45a2b11 Validate the byte arrays Address6 is given (#217)
        • bac8810 Keep the package loadable on node 12, and enforce it (#216)
        • 9b3d848 Add a security policy and a README section on security posture
        • e84a7b3 Order the README API reference Address4, Address6, AddressError
        • 015160b Collapse each class in the README API reference
        • 34061a8 Pin checkout and setup-node to commits in the release job
        • c5fae5d Pin action-gh-release to a commit and move it to 3.0.2
        • e0ef048 Replace CircleCI with GitHub Actions
        • 5e3ceb7 Add GitHub Actions CI across Node 20, 22, 24 and 25 (#213)
        • Additional commits viewable in compare view
        Maintainer changes

        This version was pushed to npm by GitHub Actions, a new releaser for ip-address since your current version.

        Install script changes

        This version adds prepare script that runs during installation. Review the package contents before updating.


        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 0c70662..7cbfffd 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1589,9 +1589,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", "license": "MIT", "engines": { "node": ">= 12" From 7284373aa4124f1170ee3b17a20f0c61b907ff44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 18:21:38 +0200 Subject: [PATCH 131/178] chore(deps): bump @hono/node-server and @modelcontextprotocol/sdk in /integration-test/src/jvmTest/typescript (#933) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@hono/node-server](https://github.com/honojs/node-server) to 2.1.0 and updates ancestor dependency [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk). These dependencies need to be updated together. Updates `@hono/node-server` from 1.19.13 to 2.1.0
        Release notes

        Sourced from @​hono/node-server's releases.

        v2.1.0

        What's Changed

        New Contributors

        Full Changelog: https://github.com/honojs/node-server/compare/v2.0.12...v2.1.0

        v2.0.12

        What's Changed

        Full Changelog: https://github.com/honojs/node-server/compare/v2.0.11...v2.0.12

        v2.0.11

        What's Changed

        Full Changelog: https://github.com/honojs/node-server/compare/v2.0.10...v2.0.11

        v2.0.10

        Security fixes

        This release includes a fix for the following security issue:

        Unauthenticated memory-leak DoS via aborted WebSocket handshake

        Affects: upgradeWebSocket. A WebSocket upgrade request with a missing or malformed Sec-WebSocket-Key header leaked the request's IncomingMessage and left a promise pending, even though no connection was established. Since the route is reachable pre-handshake without authentication, an attacker could flood it to gradually exhaust memory. GHSA-9mqv-5hh9-4cgg


        Users of upgradeWebSocket are encouraged to upgrade to this version.

        v2.0.9

        What's Changed

        New Contributors

        ... (truncated)

        Commits
        Maintainer changes

        This version was pushed to npm by GitHub Actions, a new releaser for @​hono/node-server since your current version.


        Updates `@modelcontextprotocol/sdk` from 1.29.0 to 1.30.0
        Release notes

        Sourced from @​modelcontextprotocol/sdk's releases.

        1.30.0

        What's Changed

        New Contributors

        Full Changelog: https://github.com/modelcontextprotocol/typescript-sdk/compare/v1.29.0...1.30.0

        Commits
        • 2d889f2 chore: bump version to 1.30.0 (#2563)
        • e3f3daa Fix SSE keep-alive timer lifecycle in Streamable HTTP server transport (v1.x)...
        • bb5a718 fix(deps): widen @​hono/node-server past GHSA-frvp-7c67-39w9 (#2549)
        • 1dad263 fix: send SSE keep-alive comment frames from Streamable HTTP server transport...
        • 69749aa Validate Content-Type by parsed media type instead of substring match (v1.x) ...
        • 369513d fix: support Zod 3.25 method literals (#2368)
        • e7ee57c v1 stdio buffer limit (#2239)
        • c36e1ef Add end-to-end test suite (#2167)
        • bf1e022 chore(ci): switch publish to OIDC trusted publishing (#1839)
        • 9edbab7 fix(server): prioritize zod issues and format them (#1503)
        • See full diff in compare view
        Maintainer changes

        This version was pushed to npm by GitHub Actions, a new releaser for @​modelcontextprotocol/sdk since your current version.


        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 10 +++++----- integration-test/src/jvmTest/typescript/package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 7cbfffd..fad2995 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -8,7 +8,7 @@ "name": "mcp-typescript-test-sdk", "version": "1.0.0", "dependencies": { - "@modelcontextprotocol/sdk": "^1.29.0", + "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", "zod": "^4.4.3" }, @@ -476,12 +476,12 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", - "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", + "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.9", + "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 0cbee82..9bf2360 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -9,7 +9,7 @@ "server:http": "tsx server/http-server.ts" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.29.0", + "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", "zod": "^4.4.3" }, From dae3476f7d44dadab04da83b9e3309ce026e1266 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:15:31 +0200 Subject: [PATCH 132/178] chore(deps): bump kotlin from 2.4.0 to 2.4.10 in /samples/weather-stdio-server (#905) Bumps `kotlin` from 2.4.0 to 2.4.10. Updates `org.jetbrains.kotlin.jvm` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.jvm's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.jvm's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Updates `org.jetbrains.kotlin.plugin.serialization` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index ea351f1..5f92a6c 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] coroutines = "1.11.0" -kotlin = "2.4.0" +kotlin = "2.4.10" ktor = "3.5.1" logging = "8.0.4" mcp-kotlin = "0.15.0" From 00a27e6ceb7da85f3aac9e1d68998e2426410be5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:46:01 +0200 Subject: [PATCH 133/178] chore(deps): bump kotlin from 2.4.0 to 2.4.10 in /samples/simple-streamable-server (#904) Bumps `kotlin` from 2.4.0 to 2.4.10. Updates `org.jetbrains.kotlin.jvm` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.jvm's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.jvm's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Updates `org.jetbrains.kotlin.plugin.serialization` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 28ab094..328b154 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.4.0" +kotlin = "2.4.10" ktor = "3.5.1" junit = "6.1.2" mcp-kotlin = "0.15.0" From 046af272134af081ed2319602f294860c703e63d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:30:46 +0200 Subject: [PATCH 134/178] chore(deps): bump kotlin from 2.4.0 to 2.4.10 in /samples/kotlin-mcp-server (#900) Bumps `kotlin` from 2.4.0 to 2.4.10. Updates `org.jetbrains.kotlin.jvm` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.jvm's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.jvm's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Updates `org.jetbrains.kotlin.plugin.serialization` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 83a262e..ba4f306 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.4.0" +kotlin = "2.4.10" ktor = "3.5.1" mcp-kotlin = "0.15.0" slf4j = "2.0.18" From f1cf484e25573b8aa858633af8e0830aa9cabf45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:55:25 +0200 Subject: [PATCH 135/178] chore(deps): bump kotlin from 2.4.0 to 2.4.10 in /samples/kotlinlang-mcp-server (#903) Bumps `kotlin` from 2.4.0 to 2.4.10. Updates `org.jetbrains.kotlin.jvm` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.jvm's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.jvm's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Updates `org.jetbrains.kotlin.plugin.serialization` from 2.4.0 to 2.4.10
        Release notes

        Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

        Kotlin 2.4.10

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts

        Kotlin 2.4.10-RC2

        Changelog

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        ... (truncated)

        Changelog

        Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

        2.4.10

        Backend. Wasm

        • KT-87066 K/Wasm: Not all files are presented in compiler output directory with multimodule-closed-world and incremental compilation

        Compiler

        • KT-86939 JVM: IllegalStateException "No value for annotation parameter" when using const val in nested Java annotation array argument
        • KT-83766 K2: Wrong sourcePsi is set for SymbolPsiLiteral in SLC for annotation arguments referencing a const val
        • KT-86728 Reified type inference: expected type not propagated into inline call inside lambda with elvis operator

        Compose Compiler

        • b/522127447 Compose Compiler 2.4: classes previously inferred stable now reported runtime/Uncertain

        Klibs

        • KT-86501 Native: IrTypeAliasSymbolImpl is already bound. Signature: kotlinx.datetime/Instant|null[0] on iosSimulatorArm64

        Tools. CLI

        • KT-86930 Introduce kotlinr in the Kotlin distribution

        Tools. Gradle. BCV

        • KT-87223 Gradle, BCV: open version range in kotlinAbiValidationCompatClasspath causes kotlin-build-tools-impl to resolve to 2.4.20-Beta1 instead of 2.4.0

        Tools. Gradle. JS

        • KT-87304 jsBrowserTest fails with "exited with errors (exit code: 1)"
        • KT-86057 kotlinUpgradeYarnLock skips lock file regeneration when kotlinNpmInstall is up-to-date, causing kotlinStoreYarnLock to fail

        Tools. Gradle. Multiplatform

        • KT-87084 False positive warning for JS and Wasm compilations when CRI is enabled

        Tools. Scripts

        • KT-87076 @file:CompilerOptions("-jvm-target", ...) ignored in .main.kts scripts in Kotlin 2.4.0, falling back to JVM target 1.8
        • KT-86352 K2 scripting: FirResolvedTypeRef exception when resolving extension functions from imported scripts
        Commits
        • 5687445 Add Changelog for 2.4.10-RC2
        • ba30392 [Wasm] Support regenerate unchanged modules flag on KGP
        • 6307e73 [Wasm] Implement Xwasm-IC-generate-unchanged-modules flag
        • 39d7aee Add ChangeLog for 2.4.10-RC2
        • a2956be [Gradle] Update karma.conf.js to use 'require(...)' instead plain strings
        • 9b1361c [Gradle] KT-87223: Updated regression test
        • a4c153a [Gradle] KT-87223: Fix toochain to 2.4.0 for abiValidation compat config
        • bc04b90 Add ChangeLog for 2.4.10-RC
        • bbcb94b [CRI] explicitly disable CRI generation for non-JVM targets to avoid false-po...
        • 6c2c458 Scripting: fix jvmTarget processing from script annotations
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index 2d48f35..feecf5b 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.4.0" +kotlin = "2.4.10" ktor = "3.5.1" mcp-kotlin = "0.15.0" serialization = "1.11.0" From 455a4b30c333003b2063630bfe23b1d656181ef0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 20:46:39 +0200 Subject: [PATCH 136/178] chore(deps): bump fast-uri from 3.1.4 to 3.1.5 in /integration-test/src/jvmTest/typescript (#935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.4 to 3.1.5.
        Release notes

        Sourced from fast-uri's releases.

        v3.1.5

        ⚠️ Security Warning

        Fix for https://github.com/fastify/fast-uri/security/advisories/GHSA-7p8r-x3mc-p8w7

        Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.4...v3.1.5

        Commits

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index fad2995..1577f3d 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1387,9 +1387,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", - "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", "funding": [ { "type": "github", From 0ab49f30bea3c57dbf41f0ce4994d4ca23f37f9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 21:29:09 +0200 Subject: [PATCH 137/178] chore(deps): bump the all-dependencies group across 1 directory with 2 updates (#937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 2 updates in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [tsx](https://github.com/privatenumber/tsx). Updates `@types/node` from 26.1.1 to 26.1.2
        Commits

        Updates `tsx` from 4.23.1 to 4.23.4
        Release notes

        Sourced from tsx's releases.

        v4.23.4

        4.23.4 (2026-08-02)

        Bug Fixes

        • cli: allow async process.once() signal handlers to finish (#827) (2afc7bb)

        This release is also available on:

        v4.23.3

        4.23.3 (2026-08-02)

        Bug Fixes

        • preserve listenerCount overload semantics (#823) (b6574d4)

        This release is also available on:

        v4.23.2

        4.23.2 (2026-08-02)

        Bug Fixes

        • watch: exit with 128 + signal number when interrupted (#820) (0b00bc8)

        This release is also available on:

        Commits
        • 2afc7bb fix(cli): allow async process.once() signal handlers to finish (#827)
        • b6574d4 fix: preserve listenerCount overload semantics (#823)
        • 0b00bc8 fix(watch): exit with 128 + signal number when interrupted (#820)
        • 3216332 docs(faq): minor grammar nit (#686)
        • 5828ffe chore: require cross-spawn 7.0.6 (#815)
        • 33afa36 ci: gate releases on test workflow
        • See full diff in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 16 ++++++++-------- .../src/jvmTest/typescript/package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 1577f3d..26c6e7f 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,9 +15,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.1.1", + "@types/node": "^26.1.2", "cors": "^2.8.6", - "tsx": "^4.23.1", + "tsx": "^4.23.4", "typescript": "^7.0.2" } }, @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.1.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", - "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "version": "26.1.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz", + "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==", "dev": true, "license": "MIT", "dependencies": { @@ -2034,9 +2034,9 @@ } }, "node_modules/tsx": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz", - "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", + "version": "4.23.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.4.tgz", + "integrity": "sha512-ZiUQ8oT/KzN51mJUWPqARYqwFLFJZtGZipRkw1ynHMr9vy3eU77m5yfF3Gzm6meEg/beW+lUu3fHYgskTN2oVQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 9bf2360..240e861 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,9 +16,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.1.1", + "@types/node": "^26.1.2", "cors": "^2.8.6", - "tsx": "^4.23.1", + "tsx": "^4.23.4", "typescript": "^7.0.2" } } From 76c12274ef4795859924950f511d3c8813d81b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20=C4=B0hsan=20G=C3=B6rgel?= Date: Thu, 6 Aug 2026 00:20:07 +0300 Subject: [PATCH 138/178] feat(core): add SEP-2575 request metadata and discovery types (#893) ## Summary Part of #815. Adds the core types and codecs needed for SEP-2575: - experimental accessors for request-scoped metadata while preserving legacy request shapes and unknown `_meta` entries; - `server/discover` request/result types, cache fields, and unsupported-version error data; and - polymorphic request/result decoding with wire-format and malformed-input coverage. The discovery types match the merged draft schema in modelcontextprotocol/modelcontextprotocol#3002: `protocolVersion` and `clientCapabilities` are required, `clientInfo` is optional, and optional server information remains in result `_meta`. ## Motivation and Context SEP-2575 moves protocol and client context onto individual requests and introduces `server/discover`. The shared `RequestMeta` accessors remain nullable so legacy requests stay representable; `DiscoverRequestParams` enforces the fields required by the new discovery request. This PR stops at the core type and codec boundary. It does not add server admission, request-scoped dispatch, Streamable HTTP, authentication, subscriptions, MRTR, lifecycle hooks, or a discovery DSL. ## How Has This Been Tested? - JVM: 597/597 tests - JS Node and Chrome: 528/528 tests per target - WasmJS Node and Chrome: 528/528 tests per target - iOS Simulator arm64 and macOS arm64: 528/528 tests per target - API dump/check, ktlint, detekt, and diff checks Coverage includes required discovery metadata, optional `clientInfo`, required cache fields, unknown metadata round-trips, the legacy `resultType` fallback, unsupported-version data, and polymorphic result classification. ## Breaking Changes This adds `DiscoverRequest` as a new `ClientRequest` subtype. Consumers recompiling exhaustive `when` expressions over `ClientRequest` may need to add a branch. Existing request types and wire representations are unchanged. ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed ## Additional context `ttlMs` and `cacheScope` have Kotlin construction defaults but remain required when decoding. An absent `resultType` decodes as `"complete"` for compatibility with legacy results. Discovery result selection requires the complete required shape so unrelated result extensions are not misclassified. --------- Co-authored-by: Pavel Gorgulov --- kotlin-sdk-core/api/kotlin-sdk-core.api | 146 ++++++++ .../kotlin/sdk/types/discovery.kt | 107 ++++++ .../kotlin/sdk/types/jsonRpc.kt | 3 + .../kotlin/sdk/types/methods.kt | 1 + .../kotlin/sdk/types/request.kt | 91 +++++ .../kotlin/sdk/types/serializers.kt | 10 + .../kotlin/sdk/types/DiscoveryTest.kt | 324 ++++++++++++++++++ .../kotlin/sdk/types/RequestTest.kt | 100 ++++++ 8 files changed, 782 insertions(+) create mode 100644 kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/discovery.kt create mode 100644 kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/DiscoveryTest.kt diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index 28d6737..b3e88d8 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -390,6 +390,19 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/BooleanSchema$Compan public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/CacheScope : java/lang/Enum { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope$Companion; + public static final field Private Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope; + public static final field Public Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope; + public static fun values ()[Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/CacheScope$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequest$Companion; public fun (Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;)V @@ -1395,6 +1408,104 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CustomRequest$Compan public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$Companion; + public fun (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;)V + public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams; + public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest; + public fun equals (Ljava/lang/Object;)Z + public final fun getMeta--Khlwt8 ()Lkotlinx/serialization/json/JsonObject; + public fun getMethod ()Lio/modelcontextprotocol/kotlin/sdk/types/Method; + public fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams; + public synthetic fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestParams; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams : io/modelcontextprotocol/kotlin/sdk/types/RequestParams { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$Companion; + public synthetic fun (Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1--Khlwt8 ()Lkotlinx/serialization/json/JsonObject; + public final fun copy-hVVZdjo (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams; + public static synthetic fun copy-hVVZdjo$default (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams; + public fun equals (Ljava/lang/Object;)Z + public fun getMeta--Khlwt8 ()Lkotlinx/serialization/json/JsonObject; + public synthetic fun getMeta-VI-3G7E ()Lkotlinx/serialization/json/JsonObject; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverResult : io/modelcontextprotocol/kotlin/sdk/types/ServerResult { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$Companion; + public fun (Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;)V + public synthetic fun (Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/util/List; + public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Ljava/lang/String; + public final fun component5 ()J + public final fun component6 ()Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope; + public final fun component7 ()Lkotlinx/serialization/json/JsonObject; + public final fun copy (Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult; + public fun equals (Ljava/lang/Object;)Z + public final fun getCacheScope ()Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope; + public final fun getCapabilities ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities; + public final fun getInstructions ()Ljava/lang/String; + public fun getMeta ()Lkotlinx/serialization/json/JsonObject; + public final fun getResultType ()Ljava/lang/String; + public final fun getSupportedVersions ()Ljava/util/List; + public final fun getTtlMs ()J + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/types/DoubleSchema : io/modelcontextprotocol/kotlin/sdk/types/NumberSchemaDefinition { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DoubleSchema$Companion; public fun ()V @@ -3245,6 +3356,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Method$Defined : jav public static final field ResourcesUnsubscribe Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined; public static final field RootsList Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined; public static final field SamplingCreateMessage Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined; + public static final field ServerDiscover Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined; public static final field TasksCancel Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined; public static final field TasksGet Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined; public static final field TasksList Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined; @@ -3767,6 +3879,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/RPCError$ErrorCode { public static final field PARSE_ERROR I public static final field REQUEST_TIMEOUT I public static final field RESOURCE_NOT_FOUND I + public static final field UNSUPPORTED_PROTOCOL_VERSION I public static final field URL_ELICITATION_REQUIRED I } @@ -4012,8 +4125,12 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/RequestMeta { public static fun equals-impl (Lkotlinx/serialization/json/JsonObject;Ljava/lang/Object;)Z public static final fun equals-impl0 (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)Z public static final fun get-impl (Lkotlinx/serialization/json/JsonObject;Ljava/lang/String;)Lkotlinx/serialization/json/JsonElement; + public static final fun getClientCapabilities-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities; + public static final fun getClientInfo-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/Implementation; public final fun getJson ()Lkotlinx/serialization/json/JsonObject; + public static final fun getLogLevel-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/LoggingLevel; public static final fun getProgressToken-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/RequestId; + public static final fun getProtocolVersion-impl (Lkotlinx/serialization/json/JsonObject;)Ljava/lang/String; public static final fun getRelatedTask-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/RelatedTaskMetadata; public fun hashCode ()I public static fun hashCode-impl (Lkotlinx/serialization/json/JsonObject;)I @@ -5736,6 +5853,35 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/UnsubscribeRequestPa public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$Companion; + public fun (Ljava/util/List;Ljava/lang/String;)V + public final fun component1 ()Ljava/util/List; + public final fun component2 ()Ljava/lang/String; + public final fun copy (Ljava/util/List;Ljava/lang/String;)Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData; + public fun equals (Ljava/lang/Object;)Z + public final fun getRequested ()Ljava/lang/String; + public final fun getSupported ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/types/UntitledMultiSelectEnumSchema : io/modelcontextprotocol/kotlin/sdk/types/MultiSelectEnumSchema { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/UntitledMultiSelectEnumSchema$Companion; public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Lio/modelcontextprotocol/kotlin/sdk/types/UntitledMultiSelectEnumSchema$Items;Ljava/util/List;)V diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/discovery.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/discovery.kt new file mode 100644 index 0000000..d486b1f --- /dev/null +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/discovery.kt @@ -0,0 +1,107 @@ +package io.modelcontextprotocol.kotlin.sdk.types + +import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.Required +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.JsonObject + +/** + * Parameters for a `server/discover` request. + * + * Discovery belongs to the request-scoped lifecycle and therefore requires a protocol version and + * client capabilities in [meta]. Client information is recommended by the protocol but optional. + * Unknown metadata entries are preserved by [RequestMeta]. + * + * @property meta request-scoped protocol and client metadata + * @throws IllegalArgumentException if required request-scoped metadata is absent + * @throws SerializationException if required metadata is malformed + */ +@Serializable +@ExperimentalMcpApi +public data class DiscoverRequestParams( + @SerialName("_meta") + override val meta: RequestMeta, +) : RequestParams { + init { + requireNotNull(meta.protocolVersion) { "${RequestMetaKeys.PROTOCOL_VERSION} is required" } + requireNotNull(meta.clientCapabilities) { "${RequestMetaKeys.CLIENT_CAPABILITIES} is required" } + } +} + +/** + * Requests the protocol versions, capabilities, and metadata advertised by a server. + * + * @property params request metadata required by the request-scoped lifecycle + */ +@Serializable +@ExperimentalMcpApi +public data class DiscoverRequest(override val params: DiscoverRequestParams) : ClientRequest { + @OptIn(ExperimentalSerializationApi::class) + @EncodeDefault + override val method: Method = Method.Defined.ServerDiscover + + /** Metadata for this request. */ + public val meta: RequestMeta + get() = params.meta +} + +/** Defines where a cached discovery result may be reused. */ +@Serializable +@ExperimentalMcpApi +public enum class CacheScope { + /** The result may only be reused within the same authorization context. */ + @SerialName("private") + Private, + + /** The result may be shared across authorization contexts. */ + @SerialName("public") + Public, +} + +/** + * Result returned by `server/discover`. + * + * @property supportedVersions protocol versions supported by the server + * @property capabilities capabilities advertised by the server + * @property instructions optional guidance for clients using the server + * @property resultType discriminator for the result representation + * @property ttlMs number of milliseconds clients may treat this result as fresh + * @property cacheScope authorization boundary within which the result may be reused + * @property meta optional response metadata, including optional server information + * @throws IllegalArgumentException if [ttlMs] is negative + */ +@Serializable +@ExperimentalMcpApi +public data class DiscoverResult( + val supportedVersions: List, + val capabilities: ServerCapabilities, + val instructions: String? = null, + @EncodeDefault + val resultType: String = COMPLETE_RESULT_TYPE, + @Required + val ttlMs: Long = 0, + @Required + val cacheScope: CacheScope = CacheScope.Private, + @SerialName("_meta") + override val meta: JsonObject? = null, +) : ServerResult { + init { + require(ttlMs >= 0) { "ttlMs must be non-negative, but was $ttlMs" } + } +} + +/** + * Data returned when a request selects an unsupported protocol version. + * + * @property supported protocol versions supported by the receiver + * @property requested protocol version selected by the request + */ +@Serializable +@ExperimentalMcpApi +public data class UnsupportedProtocolVersionData(val supported: List, val requested: String) + +internal const val COMPLETE_RESULT_TYPE: String = "complete" diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt index a9d465f..7e10904 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/jsonRpc.kt @@ -269,6 +269,9 @@ public data class RPCError(val code: Int, val message: String, val data: JsonEle /** Resource not found */ public const val RESOURCE_NOT_FOUND: Int = -32002 + /** The request selected a protocol version that the receiver does not support. */ + public const val UNSUPPORTED_PROTOCOL_VERSION: Int = -32022 + /** * A URL-mode elicitation must be completed before the request can be processed. * The error [data][RPCError.data] carries the required URL-mode elicitations diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt index 90403e8..1824ad0 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/methods.kt @@ -16,6 +16,7 @@ public sealed interface Method { @Serializable public enum class Defined(override val value: String) : Method { Initialize("initialize"), + ServerDiscover("server/discover"), Ping("ping"), ResourcesList("resources/list"), ResourcesTemplatesList("resources/templates/list"), diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/request.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/request.kt index aacab9a..7d885fb 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/request.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/request.kt @@ -1,8 +1,10 @@ package io.modelcontextprotocol.kotlin.sdk.types +import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationException import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive @@ -11,6 +13,13 @@ import kotlinx.serialization.json.long import kotlinx.serialization.json.longOrNull import kotlin.jvm.JvmInline +internal object RequestMetaKeys { + const val PROTOCOL_VERSION: String = "io.modelcontextprotocol/protocolVersion" + const val CLIENT_INFO: String = "io.modelcontextprotocol/clientInfo" + const val CLIENT_CAPABILITIES: String = "io.modelcontextprotocol/clientCapabilities" + const val LOG_LEVEL: String = "io.modelcontextprotocol/logLevel" +} + /** * Metadata attached to a request's `_meta` field. * @@ -40,6 +49,88 @@ public value class RequestMeta(public val json: JsonObject) { McpJson.decodeFromJsonElement(element) } + /** + * The MCP protocol version selected for this request, or `null` when absent. + * + * This field is required by the request-scoped lifecycle introduced in protocol version + * `2026-07-28`, but remains optional here so older requests retain their wire shape. + * + * @throws SerializationException if the field is present but is not a string + */ + @ExperimentalMcpApi + public val protocolVersion: String? + get() = json[RequestMetaKeys.PROTOCOL_VERSION]?.let { element -> + if (element !is JsonPrimitive || !element.isString) { + throw SerializationException("${RequestMetaKeys.PROTOCOL_VERSION} must be a JSON string") + } + element.content + } + + /** + * Information about the client making this request, or `null` when absent. + * + * Request-scoped clients should include this field unless specifically configured not to do + * so. The self-reported value is intended for display, logging, and debugging; servers should + * not use it to change behavior or rely on it for security decisions. + * + * @throws SerializationException if the field is present but is not a valid [Implementation] + */ + @ExperimentalMcpApi + public val clientInfo: Implementation? + get() = json[RequestMetaKeys.CLIENT_INFO]?.let { element -> + try { + McpJson.decodeFromJsonElement(element) + } catch (cause: SerializationException) { + throw SerializationException( + "${RequestMetaKeys.CLIENT_INFO} must be a valid client implementation", + cause, + ) + } + } + + /** + * Capabilities declared by the client for this request, or `null` when absent. + * + * Servers using the request-scoped lifecycle must not infer capabilities from an earlier + * request. An empty object means the client supports no optional capabilities. + * + * @throws SerializationException if the field is present but is not valid [ClientCapabilities] + */ + @ExperimentalMcpApi + public val clientCapabilities: ClientCapabilities? + get() = json[RequestMetaKeys.CLIENT_CAPABILITIES]?.let { element -> + try { + McpJson.decodeFromJsonElement(element) + } catch (cause: SerializationException) { + throw SerializationException( + "${RequestMetaKeys.CLIENT_CAPABILITIES} must be a valid client capabilities object", + cause, + ) + } + } + + /** + * Minimum severity of request-associated log notifications, or `null` when absent. + * + * In the request-scoped lifecycle, absence means that the server must not emit log + * notifications for this request. + * + * @throws SerializationException if the field is present but is not a valid [LoggingLevel] + */ + @Deprecated("Per-request log levels are deprecated as of MCP protocol version 2026-07-28 (SEP-2577).") + @ExperimentalMcpApi + public val logLevel: LoggingLevel? + get() = json[RequestMetaKeys.LOG_LEVEL]?.let { element -> + try { + McpJson.decodeFromJsonElement(element) + } catch (cause: SerializationException) { + throw SerializationException( + "${RequestMetaKeys.LOG_LEVEL} must be a valid logging level", + cause, + ) + } + } + /** * Retrieves the value associated with the specified key from the JSON object. * diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt index 6eab14a..36b7e37 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/serializers.kt @@ -1,6 +1,7 @@ package io.modelcontextprotocol.kotlin.sdk.types import io.github.oshai.kotlinlogging.KotlinLogging +import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.KSerializer import kotlinx.serialization.SerializationException @@ -238,9 +239,11 @@ internal object ResourceContentsPolymorphicSerializer : // Request Serializers // ============================================================================ +@OptIn(ExperimentalMcpApi::class) private val clientRequestDeserializers: Map> by lazy { mapOf( Method.Defined.CompletionComplete.value to CompleteRequest.serializer(), + Method.Defined.ServerDiscover.value to DiscoverRequest.serializer(), Method.Defined.Initialize.value to InitializeRequest.serializer(), Method.Defined.Ping.value to PingRequest.serializer(), Method.Defined.LoggingSetLevel.value to SetLevelRequest.serializer(), @@ -417,9 +420,16 @@ private fun selectClientResultDeserializer(element: JsonElement): Deserializatio * Selects the appropriate deserializer for server results based on JSON content. * Returns null if the structure doesn't match any known server result type. */ +@OptIn(ExperimentalMcpApi::class) private fun selectServerResultDeserializer(element: JsonElement): DeserializationStrategy? { val jsonObject = element.jsonObject + val isDiscoverResult = + "supportedVersions" in jsonObject && + "capabilities" in jsonObject && + "ttlMs" in jsonObject && + "cacheScope" in jsonObject return when { + isDiscoverResult -> DiscoverResult.serializer() "protocolVersion" in jsonObject && "capabilities" in jsonObject -> InitializeResult.serializer() "completion" in jsonObject -> CompleteResult.serializer() "tools" in jsonObject -> ListToolsResult.serializer() diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/DiscoveryTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/DiscoveryTest.kt new file mode 100644 index 0000000..691af45 --- /dev/null +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/DiscoveryTest.kt @@ -0,0 +1,324 @@ +package io.modelcontextprotocol.kotlin.sdk.types + +import io.kotest.assertions.json.shouldEqualJson +import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFails +import kotlin.test.assertFailsWith +import kotlin.test.assertIs +import kotlin.test.assertNotNull +import kotlin.test.assertNull +import kotlin.test.assertTrue + +@OptIn(ExperimentalMcpApi::class) +class DiscoveryTest { + + @Test + fun `should decode server discover request from its wire shape`() { + val request = McpJson.decodeFromString( + """ + { + "method": "server/discover", + "params": { + "_meta": { + "io.modelcontextprotocol/protocolVersion": "2026-07-28", + "io.modelcontextprotocol/clientInfo": { + "name": "test-client", + "version": "1.0.0" + }, + "io.modelcontextprotocol/clientCapabilities": {} + } + } + } + """.trimIndent(), + ) + + val discover = assertIs(request) + assertEquals(Method.Defined.ServerDiscover, discover.method) + assertEquals("2026-07-28", discover.meta.protocolVersion) + assertEquals("test-client", discover.meta.clientInfo?.name) + assertEquals(ClientCapabilities(), discover.meta.clientCapabilities) + } + + @Test + fun `should decode discovery request without optional client info`() { + val request = McpJson.decodeFromString( + """ + { + "method": "server/discover", + "params": { + "_meta": { + "io.modelcontextprotocol/protocolVersion": "2026-07-28", + "io.modelcontextprotocol/clientCapabilities": {}, + "com.example/traceId": "trace-123" + } + } + } + """.trimIndent(), + ) + + val discover = assertIs(request) + assertEquals("2026-07-28", discover.meta.protocolVersion) + assertEquals(ClientCapabilities(), discover.meta.clientCapabilities) + assertNull(discover.meta.clientInfo) + assertNotNull(discover.meta["com.example/traceId"]) + McpJson.encodeToString(discover) shouldEqualJson """ + { + "method": "server/discover", + "params": { + "_meta": { + "io.modelcontextprotocol/protocolVersion": "2026-07-28", + "io.modelcontextprotocol/clientCapabilities": {}, + "com.example/traceId": "trace-123" + } + } + } + """.trimIndent() + } + + @Test + fun `should reject discovery requests without required request metadata`() { + val invalidParams = listOf( + "{}" to "_meta", + """{"_meta": {}}""" to RequestMetaKeys.PROTOCOL_VERSION, + """ + { + "_meta": { + "${RequestMetaKeys.PROTOCOL_VERSION}": "2026-07-28", + "${RequestMetaKeys.CLIENT_INFO}": { + "name": "test-client", + "version": "1.0.0" + } + } + } + """.trimIndent() to RequestMetaKeys.CLIENT_CAPABILITIES, + ) + + invalidParams.forEach { (params, missingField) -> + val failure = assertFails { + McpJson.decodeFromString( + """{"method": "server/discover", "params": $params}""", + ) + } + + assertTrue( + failure.message.orEmpty().contains(missingField), + "Expected failure to identify missing field $missingField, but was: $failure", + ) + } + } + + @Test + fun `should serialize every required discovery result field`() { + val result = DiscoverResult( + supportedVersions = listOf("2026-07-28"), + capabilities = ServerCapabilities( + tools = ServerCapabilities.Tools(listChanged = true), + ), + instructions = "Use tools intentionally.", + ) + + McpJson.encodeToString(result) shouldEqualJson """ + { + "supportedVersions": ["2026-07-28"], + "capabilities": { + "tools": {"listChanged": true} + }, + "instructions": "Use tools intentionally.", + "resultType": "complete", + "ttlMs": 0, + "cacheScope": "private" + } + """.trimIndent() + } + + @Test + fun `should encode optional server info in result metadata`() { + val result = DiscoverResult( + supportedVersions = listOf("2026-07-28"), + capabilities = ServerCapabilities(), + meta = Json.parseToJsonElement( + """ + { + "io.modelcontextprotocol/serverInfo": { + "name": "test-server", + "version": "2.0.0" + }, + "com.example/source": "edge" + } + """.trimIndent(), + ).jsonObject, + ) + + McpJson.encodeToString(result) shouldEqualJson """ + { + "supportedVersions": ["2026-07-28"], + "capabilities": {}, + "resultType": "complete", + "ttlMs": 0, + "cacheScope": "private", + "_meta": { + "io.modelcontextprotocol/serverInfo": { + "name": "test-server", + "version": "2.0.0" + }, + "com.example/source": "edge" + } + } + """.trimIndent() + assertEquals( + Json.parseToJsonElement("""{"name":"test-server","version":"2.0.0"}"""), + result.meta?.get("io.modelcontextprotocol/serverInfo"), + ) + } + + @Test + fun `should encode required defaults independently of McpJson`() { + val result = DiscoverResult( + supportedVersions = listOf("2026-07-28"), + capabilities = ServerCapabilities(), + ) + + Json.encodeToString(result) shouldEqualJson """ + { + "supportedVersions": ["2026-07-28"], + "capabilities": {}, + "resultType": "complete", + "ttlMs": 0, + "cacheScope": "private" + } + """.trimIndent() + } + + @Test + fun `should reject discovery results without required cache fields`() { + val invalidResults = listOf( + """ + { + "supportedVersions": ["2026-07-28"], + "capabilities": {}, + "cacheScope": "private" + } + """.trimIndent(), + """ + { + "supportedVersions": ["2026-07-28"], + "capabilities": {}, + "ttlMs": 0 + } + """.trimIndent(), + ) + + invalidResults.forEach { wire -> + assertFails { McpJson.decodeFromString(wire) } + assertFails { McpJson.decodeFromString(wire) } + } + } + + @Test + fun `should use complete when a discovery result omits resultType`() { + val result = McpJson.decodeFromString( + """ + { + "supportedVersions": ["2026-07-28"], + "capabilities": {}, + "ttlMs": 0, + "cacheScope": "private" + } + """.trimIndent(), + ) + + assertEquals(COMPLETE_RESULT_TYPE, assertIs(result).resultType) + } + + @Test + fun `should deserialize discovery results polymorphically`() { + val wire = + """ + { + "supportedVersions": ["2026-07-28"], + "capabilities": {}, + "resultType": "complete", + "ttlMs": 250, + "cacheScope": "public", + "_meta": { + "io.modelcontextprotocol/serverInfo": { + "name": "server", + "version": "1" + }, + "com.example/source": "edge" + } + } + """.trimIndent() + val result = McpJson.decodeFromString(wire) + + val discover = assertIs(result) + assertEquals(250, discover.ttlMs) + assertEquals(CacheScope.Public, discover.cacheScope) + assertEquals( + Json.parseToJsonElement("""{"name":"server","version":"1"}"""), + discover.meta?.get("io.modelcontextprotocol/serverInfo"), + ) + assertNotNull(discover.meta?.get("com.example/source")) + McpJson.encodeToString(discover) shouldEqualJson wire + } + + @Test + fun `should not treat supportedVersions alone as a discovery discriminator`() { + val result = McpJson.decodeFromString( + """ + { + "tools": [], + "supportedVersions": ["extension-value"] + } + """.trimIndent(), + ) + + assertIs(result) + } + + @Test + fun `should not treat an initialize extension as a discovery result`() { + val result = McpJson.decodeFromString( + """ + { + "protocolVersion": "2025-06-18", + "capabilities": {}, + "serverInfo": { + "name": "test-server", + "version": "1.0.0" + }, + "supportedVersions": ["extension-value"] + } + """.trimIndent(), + ) + + assertIs(result) + } + + @Test + fun `should reject a negative discovery ttl`() { + assertFailsWith { + DiscoverResult( + supportedVersions = listOf("2026-07-28"), + capabilities = ServerCapabilities(), + ttlMs = -1, + ) + } + } + + @Test + fun `unsupported version data should round trip without losing versions`() { + val data = UnsupportedProtocolVersionData( + supported = listOf("2026-07-28", "2025-11-25"), + requested = "2099-01-01", + ) + + val encoded = McpJson.encodeToString(data) + assertEquals(data, McpJson.decodeFromString(encoded)) + assertEquals(-32022, RPCError.ErrorCode.UNSUPPORTED_PROTOCOL_VERSION) + } +} diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/RequestTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/RequestTest.kt index 1d6da19..6087b20 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/RequestTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/types/RequestTest.kt @@ -2,20 +2,120 @@ package io.modelcontextprotocol.kotlin.sdk.types import io.kotest.assertions.json.shouldEqualJson import io.kotest.matchers.shouldBe +import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi import io.modelcontextprotocol.kotlin.test.utils.verifyDeserialization import io.modelcontextprotocol.kotlin.test.utils.verifySerialization +import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.double import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.put import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFailsWith import kotlin.test.assertIs import kotlin.test.assertNotNull import kotlin.test.assertNull +import kotlin.test.assertTrue class RequestTest { + @OptIn(ExperimentalMcpApi::class) + @Suppress("DEPRECATION") + @Test + fun `should decode typed request metadata without discarding extensions`() { + val request = McpJson.decodeFromString( + """ + { + "method": "tools/list", + "params": { + "_meta": { + "io.modelcontextprotocol/protocolVersion": "2026-07-28", + "io.modelcontextprotocol/clientInfo": { + "name": "wire-client", + "version": "1.2.3" + }, + "io.modelcontextprotocol/clientCapabilities": { + "sampling": {}, + "com.example/custom-capability": {"enabled": true} + }, + "io.modelcontextprotocol/logLevel": "warning", + "com.example/traceId": "trace-123" + } + } + } + """.trimIndent(), + ) + + val listTools = assertIs(request) + val meta = assertNotNull(listTools.params?.meta) + meta.protocolVersion shouldBe "2026-07-28" + meta.clientInfo shouldBe Implementation(name = "wire-client", version = "1.2.3") + assertNotNull(meta.clientCapabilities?.sampling) + meta.logLevel shouldBe LoggingLevel.Warning + meta["com.example/traceId"]?.jsonPrimitive?.content shouldBe "trace-123" + assertNotNull(meta.json[RequestMetaKeys.CLIENT_CAPABILITIES]?.let { it as? JsonObject }) + } + + @OptIn(ExperimentalMcpApi::class) + @Test + fun `empty client capabilities should mean no optional capabilities`() { + val json = Json.parseToJsonElement( + """{"${RequestMetaKeys.CLIENT_CAPABILITIES}": {}}""", + ) as JsonObject + + RequestMeta(json).clientCapabilities shouldBe ClientCapabilities() + } + + @OptIn(ExperimentalMcpApi::class) + @Suppress("DEPRECATION") + @Test + fun `typed request metadata should reject malformed fields`() { + val malformedValues = listOf( + RequestMetaKeys.PROTOCOL_VERSION to "{}", + RequestMetaKeys.PROTOCOL_VERSION to "null", + RequestMetaKeys.CLIENT_INFO to "\"not-an-implementation\"", + RequestMetaKeys.CLIENT_INFO to "{\"name\":\"missing-version\"}", + RequestMetaKeys.CLIENT_INFO to "null", + RequestMetaKeys.CLIENT_CAPABILITIES to "\"not-capabilities\"", + RequestMetaKeys.CLIENT_CAPABILITIES to "[]", + RequestMetaKeys.CLIENT_CAPABILITIES to "null", + RequestMetaKeys.LOG_LEVEL to "\"verbose\"", + RequestMetaKeys.LOG_LEVEL to "7", + RequestMetaKeys.LOG_LEVEL to "null", + ) + + malformedValues.forEach { (key, value) -> + val json = Json.parseToJsonElement("""{"$key":$value}""") as JsonObject + val meta = RequestMeta(json) + + val failure = assertFailsWith { + when (key) { + RequestMetaKeys.PROTOCOL_VERSION -> meta.protocolVersion + RequestMetaKeys.CLIENT_INFO -> meta.clientInfo + RequestMetaKeys.CLIENT_CAPABILITIES -> meta.clientCapabilities + else -> meta.logLevel + } + } + assertTrue(failure.message.orEmpty().contains(key)) + } + } + + @OptIn(ExperimentalMcpApi::class) + @Test + fun `legacy requests should not gain request scoped metadata`() { + val request = ListToolsRequest() + + McpJson.encodeToString(request) shouldEqualJson """ + { + "method": "tools/list" + } + """.trimIndent() + assertNull(request.params?.meta?.protocolVersion) + } + @Test fun `should expose progress token from RequestMeta`() { val stringTokenMeta = RequestMeta(buildJsonObject { put("progressToken", "sync-1") }) From 04a72353e15cf865440208797a1209139889c2f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 12:02:22 +0200 Subject: [PATCH 139/178] chore(deps): bump @hono/node-server from 1.19.13 to 2.1.0 in /integration-test/src/jvmTest/typescript (#939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@hono/node-server](https://github.com/honojs/node-server) from 1.19.13 to 2.1.0.
        Release notes

        Sourced from @​hono/node-server's releases.

        v2.1.0

        What's Changed

        New Contributors

        Full Changelog: https://github.com/honojs/node-server/compare/v2.0.12...v2.1.0

        v2.0.12

        What's Changed

        Full Changelog: https://github.com/honojs/node-server/compare/v2.0.11...v2.0.12

        v2.0.11

        What's Changed

        Full Changelog: https://github.com/honojs/node-server/compare/v2.0.10...v2.0.11

        v2.0.10

        Security fixes

        This release includes a fix for the following security issue:

        Unauthenticated memory-leak DoS via aborted WebSocket handshake

        Affects: upgradeWebSocket. A WebSocket upgrade request with a missing or malformed Sec-WebSocket-Key header leaked the request's IncomingMessage and left a promise pending, even though no connection was established. Since the route is reachable pre-handshake without authentication, an attacker could flood it to gradually exhaust memory. GHSA-9mqv-5hh9-4cgg


        Users of upgradeWebSocket are encouraged to upgrade to this version.

        v2.0.9

        What's Changed

        New Contributors

        ... (truncated)

        Commits
        Maintainer changes

        This version was pushed to npm by GitHub Actions, a new releaser for @​hono/node-server since your current version.


        [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@hono/node-server&package-manager=npm_and_yarn&previous-version=1.19.13&new-version=2.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
        Dependabot commands and options
        You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/modelcontextprotocol/kotlin-sdk/network/alerts).
        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 26c6e7f..52ba6fa 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -464,12 +464,12 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.13", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.13.tgz", - "integrity": "sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.0.tgz", + "integrity": "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==", "license": "MIT", "engines": { - "node": ">=18.14.1" + "node": ">=20" }, "peerDependencies": { "hono": "^4" From e34cb2244c5807d83b5f0caeb46ea9f9c894ad3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 12:26:30 +0200 Subject: [PATCH 140/178] chore(deps): bump hono from 4.12.27 to 4.13.1 in /integration-test/src/jvmTest/typescript (#940) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [hono](https://github.com/honojs/hono) from 4.12.27 to 4.13.1.
        Release notes

        Sourced from hono's releases.

        v4.13.1

        What's Changed

        New Contributors

        Full Changelog: https://github.com/honojs/hono/compare/v4.13.0...v4.13.1

        v4.13.0

        Hono v4.13.0 is now available!

        The highlight of this release is performance: a batch of low-level optimizations makes the core request/response path significantly faster — up to 1.25x on common routes in our benchmark. This release also adds first-class support for the HTTP QUERY method, defined in RFC 10008, a new Method Not Allowed middleware, and more.

        Performance improvements

        This release includes a series of small optimizations: skipping unnecessary Headers allocations, replacing regex tests with indexOf, allocating internal state lazily, and more.

        Here is benchmarks/fetch comparing v4.12 and v4.13 (ROUNDS=5 ./compare.sh, Bun 1.4.0, Apple Silicon — each measurement runs in a fresh process, and the variant order is reversed every round to avoid warm-up bias):

        Benchmark v4.12 v4.13 Speedup
        ping — GET / 165.83 ns 163.99 ns 1.01x
        query — GET /id/1?name=bun 674.40 ns 616.99 ns 1.09x
        json — GET /user 528.99 ns 422.44 ns 1.25x
        body — POST /json 1.16 µs 1.00 µs 1.15x

        The individual changes:

        In addition, the RegExpRouter rewrite described below makes route registration plus the first match roughly 20% faster.

        Thanks @​kibertoad for the contributions!

        First-class QUERY method support

        The QUERY method — a safe, idempotent method that carries a request body — is now a first-class citizen in Hono. You can define QUERY handlers with app.query():

        const app = new Hono()
        

        </tr></table>

        ... (truncated)

        Commits
        • cf78528 4.13.1
        • f6aa913 fix(etag): skip unsafe methods or error responses on non-* case (#5196)
        • cd31bc1 fix(utils/stream): re-acquire writer lock when pipe() throws (#4988)
        • 569b419 fix(trie-router): count every slash a pattern consumes (#5189)
        • 192768f 4.13.0
        • b0c2d90 Merge pull request #5154 from honojs/next
        • 8f07028 fix(compress): set Vary: Accept-Encoding on negotiated responses (#5137)
        • 8a0b18f feat(reg-exp-router): throw UnsupportedPathError during route registration (#...
        • 3feb355 fix(jsx): allow a function component to return an array (#5179)
        • 5d911d2 feat(utils/headers): add HTTP fields newly registered with IANA (#5153)
        • Additional commits viewable in compare view

        Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 52ba6fa..b014f88 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1538,9 +1538,9 @@ } }, "node_modules/hono": { - "version": "4.12.27", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.27.tgz", - "integrity": "sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.1.tgz", + "integrity": "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==", "license": "MIT", "engines": { "node": ">=16.9.0" From 8ceb779dd45e4a5705084fe34772231d89176c10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 13:04:29 +0200 Subject: [PATCH 141/178] chore(deps): bump the ktor group across 1 directory with 15 updates (#941) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the ktor group with 15 updates in the / directory: | Package | From | To | | --- | --- | --- | | [io.ktor:ktor-client-apache5](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-client-auth](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-client-core](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-client-logging](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-server-content-negotiation](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-client-content-negotiation](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-serialization-kotlinx-json](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-server-auth](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-server-core](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-server-sse](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-server-websockets](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-client-mock](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-server-test-host](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-client-cio](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | | [io.ktor:ktor-server-cio](https://github.com/ktorio/ktor) | `3.5.1` | `3.5.2` | Updates `io.ktor:ktor-client-apache5` from 3.5.1 to 3.5.2
        Release notes

        Sourced from io.ktor:ktor-client-apache5's releases.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Changelog

        Sourced from io.ktor:ktor-client-apache5's changelog.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Commits
        • 01c469a Release 3.5.2 (#5781)
        • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
        • 74df458 chore: fix some comments to improve readability
        • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
        • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
        • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
        • 58256cd KTOR-9743 Clarify readLine documentation
        • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
        • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
        • 7fb0844 KTOR-9585 Fix schema title trimming
        • Additional commits viewable in compare view

        Updates `io.ktor:ktor-client-auth` from 3.5.1 to 3.5.2
        Release notes

        Sourced from io.ktor:ktor-client-auth's releases.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Changelog

        Sourced from io.ktor:ktor-client-auth's changelog.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Commits
        • 01c469a Release 3.5.2 (#5781)
        • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
        • 74df458 chore: fix some comments to improve readability
        • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
        • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
        • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
        • 58256cd KTOR-9743 Clarify readLine documentation
        • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
        • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
        • 7fb0844 KTOR-9585 Fix schema title trimming
        • Additional commits viewable in compare view

        Updates `io.ktor:ktor-client-core` from 3.5.1 to 3.5.2
        Release notes

        Sourced from io.ktor:ktor-client-core's releases.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Changelog

        Sourced from io.ktor:ktor-client-core's changelog.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Commits
        • 01c469a Release 3.5.2 (#5781)
        • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
        • 74df458 chore: fix some comments to improve readability
        • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
        • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
        • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
        • 58256cd KTOR-9743 Clarify readLine documentation
        • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
        • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
        • 7fb0844 KTOR-9585 Fix schema title trimming
        • Additional commits viewable in compare view

        Updates `io.ktor:ktor-client-logging` from 3.5.1 to 3.5.2
        Release notes

        Sourced from io.ktor:ktor-client-logging's releases.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Changelog

        Sourced from io.ktor:ktor-client-logging's changelog.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Commits
        • 01c469a Release 3.5.2 (#5781)
        • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
        • 74df458 chore: fix some comments to improve readability
        • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
        • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
        • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
        • 58256cd KTOR-9743 Clarify readLine documentation
        • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
        • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
        • 7fb0844 KTOR-9585 Fix schema title trimming
        • Additional commits viewable in compare view

        Updates `io.ktor:ktor-server-content-negotiation` from 3.5.1 to 3.5.2
        Release notes

        Sourced from io.ktor:ktor-server-content-negotiation's releases.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Changelog

        Sourced from io.ktor:ktor-server-content-negotiation's changelog.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Commits
        • 01c469a Release 3.5.2 (#5781)
        • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
        • 74df458 chore: fix some comments to improve readability
        • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
        • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
        • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
        • 58256cd KTOR-9743 Clarify readLine documentation
        • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
        • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
        • 7fb0844 KTOR-9585 Fix schema title trimming
        • Additional commits viewable in compare view

        Updates `io.ktor:ktor-client-content-negotiation` from 3.5.1 to 3.5.2
        Release notes

        Sourced from io.ktor:ktor-client-content-negotiation's releases.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
        • KTOR-9671 Darwin: Semicolons in URL path are sanitized
        Changelog

        Sourced from io.ktor:ktor-client-content-negotiation's changelog.

        3.5.2

        Published 31 July 2026

        Improvements

        • KTOR-8032 RateLimit: Allow limit requests based on authentication result
        • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
        • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
        • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
        • KTOR-9759 Reject whitespace in URL hosts during parsing
        • KTOR-9681 Update kotlinx-io to 0.9.1
        • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
        • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

        Bugfixes

        • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
        • KTOR-7661 Maven + YAML config file does not work
        • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
        • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
        • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
        • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
        • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
        • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
        • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
        • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
        • KTOR-8903 Netty: Close channel connection on errors properly
        • KTOR-9707 SaveBody performance regression
        • KTOR-9703 Inefficient text reading function in DefaultTransform
        • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
        • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
        • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
        • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't... _Description has been truncated_ Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 051e361..7257a7d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ collections-immutable = "0.5.1" coroutines = "1.11.0" kotest = "6.2.3" kotlinx-io = "0.9.1" -ktor = "3.5.1" +ktor = "3.5.2" logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" From 68042497a0038253afce1093a36837b7af42699a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:59:51 +0200 Subject: [PATCH 142/178] chore(deps): bump the other-dependencies group across 5 directories with 1 update (#942) Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-client directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/kotlinlang-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/weather-stdio-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
          • Additional commits viewable in compare view

          Updates `gradle-wrapper` from 9.6.1 to 9.7.0
          Release notes

          Sourced from gradle-wrapper's releases.

          9.7.0

          The Gradle team is excited to announce Gradle 9.7.0.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating
          • Broader Configuration Cache compatibility
          • More source locations in problem reports

          Read the Release Notes

          We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

          Upgrade instructions

          Switch your build to use Gradle 9.7.0 by updating your wrapper:

          ./gradlew :wrapper --gradle-version=9.7.0 &&
          ./gradlew :wrapper
          

          See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

          For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

          Reporting problems

          If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

          We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

          9.7.0 RC3

          The Gradle team is excited to announce Gradle 9.7.0 RC3.

          Here are the highlights of this release:

          • Isolated Projects graduates to incubating

          ... (truncated)

          Commits
          • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
          • f176043 make DistributionIntegrationSpec more permissive for releases
          • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
          • 064b6d6 cleanup
          • dfe7bdc add new training to release notes
          • 7561968 add release notes for 37801
          • 68a1f35 cherrypick 38367 to release
          • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
          • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
          • Date: Mon, 10 Aug 2026 15:51:01 +0200 Subject: [PATCH 143/178] chore(deps): bump io.ktor:ktor-bom from 3.5.1 to 3.5.2 in /samples/kotlin-mcp-client (#944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.5.1 to 3.5.2.
            Release notes

            Sourced from io.ktor:ktor-bom's releases.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Changelog

            Sourced from io.ktor:ktor-bom's changelog.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Commits
            • 01c469a Release 3.5.2 (#5781)
            • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
            • 74df458 chore: fix some comments to improve readability
            • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
            • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
            • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
            • 58256cd KTOR-9743 Clarify readLine documentation
            • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
            • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
            • 7fb0844 KTOR-9585 Fix schema title trimming
            • Additional commits viewable in compare view

            Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index ea0043d..4e1f8bb 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] anthropic = "2.52.0" kotlin = "2.4.10" -ktor = "3.5.1" +ktor = "3.5.2" mcp-kotlin = "0.15.0" shadow = "9.6.1" slf4j = "2.0.18" From 05c5953a18e351795e793e76ad321c77db810388 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:11:51 +0200 Subject: [PATCH 144/178] chore(deps): bump io.ktor:ktor-bom from 3.5.1 to 3.5.2 in /samples/kotlin-mcp-server (#945) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.5.1 to 3.5.2.
            Release notes

            Sourced from io.ktor:ktor-bom's releases.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Changelog

            Sourced from io.ktor:ktor-bom's changelog.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Commits
            • 01c469a Release 3.5.2 (#5781)
            • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
            • 74df458 chore: fix some comments to improve readability
            • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
            • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
            • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
            • 58256cd KTOR-9743 Clarify readLine documentation
            • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
            • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
            • 7fb0844 KTOR-9585 Fix schema title trimming
            • Additional commits viewable in compare view

            Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index ba4f306..5f8b83f 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin = "2.4.10" -ktor = "3.5.1" +ktor = "3.5.2" mcp-kotlin = "0.15.0" slf4j = "2.0.18" shadow = "9.6.1" From df346975054ef7495f2fac0d45ddc8f3c3072b99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:43:19 +0200 Subject: [PATCH 145/178] chore(deps): bump io.ktor:ktor-bom from 3.5.1 to 3.5.2 in /samples/kotlinlang-mcp-server (#946) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.5.1 to 3.5.2.
            Release notes

            Sourced from io.ktor:ktor-bom's releases.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Changelog

            Sourced from io.ktor:ktor-bom's changelog.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Commits
            • 01c469a Release 3.5.2 (#5781)
            • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
            • 74df458 chore: fix some comments to improve readability
            • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
            • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
            • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
            • 58256cd KTOR-9743 Clarify readLine documentation
            • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
            • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
            • 7fb0844 KTOR-9585 Fix schema title trimming
            • Additional commits viewable in compare view

            Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index feecf5b..cf37f51 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin = "2.4.10" -ktor = "3.5.1" +ktor = "3.5.2" mcp-kotlin = "0.15.0" serialization = "1.11.0" coroutines = "1.11.0" From 9482283aa325a04973a890cdfb09cd6bd11df66c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:03:14 +0200 Subject: [PATCH 146/178] chore(deps): bump io.ktor:ktor-bom from 3.5.1 to 3.5.2 in /samples/simple-streamable-server (#947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.5.1 to 3.5.2.
            Release notes

            Sourced from io.ktor:ktor-bom's releases.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Changelog

            Sourced from io.ktor:ktor-bom's changelog.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Commits
            • 01c469a Release 3.5.2 (#5781)
            • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
            • 74df458 chore: fix some comments to improve readability
            • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
            • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
            • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
            • 58256cd KTOR-9743 Clarify readLine documentation
            • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
            • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
            • 7fb0844 KTOR-9585 Fix schema title trimming
            • Additional commits viewable in compare view

            Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 328b154..966a7e2 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] kotlin = "2.4.10" -ktor = "3.5.1" +ktor = "3.5.2" junit = "6.1.2" mcp-kotlin = "0.15.0" slf4j = "2.0.18" From 5ca99555006662ecf1300ca921c5744d304712f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:53:45 +0200 Subject: [PATCH 147/178] chore(deps): bump io.ktor:ktor-bom from 3.5.1 to 3.5.2 in /samples/weather-stdio-server (#948) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.ktor:ktor-bom](https://github.com/ktorio/ktor) from 3.5.1 to 3.5.2.
            Release notes

            Sourced from io.ktor:ktor-bom's releases.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Changelog

            Sourced from io.ktor:ktor-bom's changelog.

            3.5.2

            Published 31 July 2026

            Improvements

            • KTOR-8032 RateLimit: Allow limit requests based on authentication result
            • KTOR-9719 ApplicationCall.isStaticContent returns false when called from plugin interceptors
            • KTOR-8450 ContentNegotiation: it doesn't handle content type suffixes
            • KTOR-7892 SwaggerUI: Missing oauth2-redirect.html support in the plugin
            • KTOR-9759 Reject whitespace in URL hosts during parsing
            • KTOR-9681 Update kotlinx-io to 0.9.1
            • KTOR-9743 ByteReadChannel.readLineStrict: Misleading definition of limit parameter in KDocs
            • KTOR-9504 Improve KDoc for EmbeddedServer.addShutdownHook

            Bugfixes

            • KTOR-9741 CIO: request-handler coroutine leak on half-closed idle connection after ≥1MB response
            • KTOR-7661 Maven + YAML config file does not work
            • KTOR-9585 OpenAPI: JsonSchema title is truncated when it contains a dot
            • KTOR-9704 UTF-8 encoding in ktor-io bypasses JVM String.getBytes intrinsics, slowing every text response by 5-7x
            • KTOR-9588 SSE client (CIO engine) sends spurious Content-Length: 0 on body-less GET (RFC 9110 § 8.6 violation; rejected by AWS ELB)
            • KTOR-9679 ByteReadChannel.readLine corrupts multi-byte UTF-8 by splitting a character at a buffer boundary
            • KTOR-9767 ByteReadChannel.readLineTo: Return read bytes count instead of decoded characters count
            • KTOR-8992 HoconConfigLoader is not loaded when ktor-server-config-yaml on the classpath
            • KTOR-9698 OpenAPI: schema for kotlinx.serialization sealed types omits discriminator property in variant schemas
            • KTOR-9690 Netty: in-flight requests are aborted on stop(), ignoring shutdown grace period
            • KTOR-8903 Netty: Close channel connection on errors properly
            • KTOR-9707 SaveBody performance regression
            • KTOR-9703 Inefficient text reading function in DefaultTransform
            • KTOR-9711 Netty HTTP/2: a single client-canceled stream (RST_STREAM) breaks response flushing for the whole connection
            • KTOR-9688 RateLimit: No access to principal when wrapped with authentication since 3.5.1
            • KTOR-9677 Auto-reloading: server is reloaded only once since 3.5.0
            • KTOR-9683 Sockets: Canceling a SelectorManager job doesn't close it properly
            • KTOR-9671 Darwin: Semicolons in URL path are sanitized
            Commits
            • 01c469a Release 3.5.2 (#5781)
            • c965a0c KTOR-9741 Prevent CIO request handler leak (#5783)
            • 74df458 chore: fix some comments to improve readability
            • 2672567 [KTOR-9704] Optimized encoding flow for UTF-8 (#5743)
            • d5680ed KTOR-5391: Document ECDSA certificate limitation for client authentication (#...
            • 9b0f356 something::javaClass.name is not the name of the class of something but `"j...
            • 58256cd KTOR-9743 Clarify readLine documentation
            • 088bd60 KTOR-9679 Fix regressions caused by adding buffering
            • 167176a KTOR-9588 Do not send Content-Length: 0 for body-less GET requests (#5620)
            • 7fb0844 KTOR-9585 Fix schema title trimming
            • Additional commits viewable in compare view

            Most Recent Ignore Conditions Applied to This Pull Request | Dependency Name | Ignore Conditions | | --- | --- | | io.ktor:ktor-bom | [>= 3.4.a, < 3.5] |
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 5f92a6c..b84a655 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] coroutines = "1.11.0" kotlin = "2.4.10" -ktor = "3.5.1" +ktor = "3.5.2" logging = "8.0.4" mcp-kotlin = "0.15.0" shadow = "9.6.1" From d6235597e07541c07a70053e516668b5b881f4d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:12:50 +0200 Subject: [PATCH 148/178] chore(deps): bump gradle-wrapper from 9.6.1 to 9.7.0 (#949) Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.6.1 to 9.7.0.
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.0

            The Gradle team is excited to announce Gradle 9.7.0.

            Here are the highlights of this release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.0 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.0 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            9.7.0 RC3

            The Gradle team is excited to announce Gradle 9.7.0 RC3.

            Here are the highlights of this release:

            • Isolated Projects graduates to incubating

            ... (truncated)

            Commits
            • 3defbfc make DistributionIntegrationSpec more permissive for releases (#38766)
            • f176043 make DistributionIntegrationSpec more permissive for releases
            • b0828da Prepare release notes for Gradle 9.7.0GA (#38756)
            • 064b6d6 cleanup
            • dfe7bdc add new training to release notes
            • 7561968 add release notes for 37801
            • 68a1f35 cherrypick 38367 to release
            • a462c95 Rebalance AllVersionsCrossVersion buckets for agents without TestDistribution...
            • 820e2b1 Update Gradle wrapper to version 9.7.0-rc-3 (#38743)
            • 75ea3d7 Update Gradle wrapper to version 9.7.0-rc-3
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.jar | Bin 48462 -> 47505 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index b1b8ef56b44f16b14dc800fa8103a6d89abb526f..eddabd2eef8d94a5437d6168ff9c87a78ff725b3 100644 GIT binary patch delta 39079 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 F{Rc_uT_ykk delta 40101 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a9db115..69dd0d0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From de2a0aafd6bf070321ed29926132dbc14b3679ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 11:28:03 +0200 Subject: [PATCH 149/178] chore(deps): bump dev.detekt:detekt-gradle-plugin from 2.0.0-alpha.5 to 2.0.0-alpha.6 (#950) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dev.detekt:detekt-gradle-plugin](https://github.com/detekt/detekt) from 2.0.0-alpha.5 to 2.0.0-alpha.6.
            Release notes

            Sourced from dev.detekt:detekt-gradle-plugin's releases.

            v2.0.0-alpha.6

            2.0.0-alpha.6 - 2026-08-04

            This is an alpha release of Detekt 2.0.0. It's built against Kotlin 2.4.10, Gradle 9.6.1, AGP 9.3.1 and is tested against JDK 25.

            Notable Changes

            • detekt-rules-ktlint-wrapper now targets JVM 17, in preparation for the next ktlint major release which requires JVM 17+, the rest of detekt still targets JVM 8+ - #9453

            Changelog

            • feat(rules): add ignoreSealedClasses option to AbstractClassCanBeInterface - #9557
            • docs: drop stale Android compile classpath warning note - #9550
            • Recommend to use Locale.ROOT instead of Locale.US - #9532
            • Recognize params swallowed by KDoc lexer in OutdatedDocumentation - #9529
            • Fix UnusedPrivateProperty false negative for constructor properties - #9491
            • Fix MissingSuperCall false positive when annotation is in grandparent - #9469
            • Fix UseDataClass false positive for properties with a custom accessor - #9462
            • Fix a potential bug on Config.getListOrDefault - #9461
            • Fix UnusedPrivateFunction false positive for overloaded private extension functions with a Java (or generated) receiver type - #9450
            • Fix CanBeNonNullable false negative on local variables - #9432
            • Fix CognitiveComplexMethod false positive for object literal methods - #9431
            • Fix ReturnCount/ThrowsCount false positive where a guard clause following a local variable declaration was still counted (with excludeGuardClauses enabled) - #9424
            • Extend PropertyUsedBeforeDeclaration to follow private init calls - #9334
            • Add configuration ignoredFullyQualifiedNames to UnnecessaryFullyQualifiedName rule - #9301
            • Expose multiline parameter in ClassSignature - #9084

            Dependency Updates

            • Update agp to v9.3.1 - #9538
            • Update kotlin monorepo to v2.4.10 - #9518
            • Update Gradle to v9.6.1 - #9444
            • Update Gradle to v9.6.0 - #9420

            Housekeeping & Refactorings

            • Reduce scope of @Suppress("UNCHECKED_CAST") - #9459
            • Remove irrelevant test for YamlConfig - #9457
            • fix: handle trailing commas in @​Configuration annotation parsing in JS generator - #9447
            • Production code should not depend on fixtures - #9439

            Contributors

            We would like to thank the following contributors that made this release possible: @​3flex, @​BraisGabin, @​ChristophyBarth, @​FilippoVigani, @​Phoenix1808, @​ShubhamWorks02, @​cortinico, @​e5l, @​eyupcanakman, @​iuryeng, @​loganrosen, @​marpalat, @​roian6, @​sahilpatel2521, @​tonytonycoder11

            See all issues at: 2.0.0

            Commits
            • 401c64b Update github/codeql-action digest to 5595cca (#9569)
            • 7d92d70 Migrate to the OSS Community Develocity Instance (#9549)
            • 7212708 Update gradle/actions digest to 9c97196 (#9568)
            • 529f2ba Update github/codeql-action digest to d1ba80a (#9567)
            • 6df1cf1 feat(rules): add ignoreSealedClasses option to AbstractClassCanBeInterface (#...
            • 6fa04a6 Update actions/setup-java digest to b6effb0 (#9560)
            • d744c2f Update plugin com.gradle.common-custom-user-data-gradle-plugin to v2.8.0 (#9561)
            • 688c42b Update github/codeql-action digest to f205ea1 (#9559)
            • a2f4740 fix(doc): remove mention of fixed issue (#9556)
            • 1ac699e Fix UnusedPrivateProperty false negative (#9491)
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7257a7d..f8ccbd9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ # plugins version atomicfu = "0.33.0" binaryCompatibilityValidatorPlugin = "0.18.1" -detekt = "2.0.0-alpha.5" +detekt = "2.0.0-alpha.6" dokka = "2.2.0" kotlin = "2.4.10" kover = "0.9.9" From 450f9e082ce1be2584e561e09737b88aec86a372 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 12:01:50 +0200 Subject: [PATCH 150/178] chore(deps): bump the all-dependencies group across 1 directory with 2 updates (#954) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 2 updates in the /integration-test/src/jvmTest/typescript directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [tsx](https://github.com/privatenumber/tsx). Updates `@types/node` from 26.1.2 to 26.2.0
            Commits

            Updates `tsx` from 4.23.4 to 4.23.11
            Release notes

            Sourced from tsx's releases.

            v4.23.11

            4.23.11 (2026-08-07)

            Bug Fixes

            • preserve async ESM require fallback (55cbece)

            This release is also available on:

            v4.23.10

            4.23.10 (2026-08-07)

            Bug Fixes


            This release is also available on:

            v4.23.9

            4.23.9 (2026-08-06)

            Bug Fixes

            • map Node test locations (2f55884)
            • support data URLs in tsImport (b94f46f)

            This release is also available on:

            v4.23.8

            4.23.8 (2026-08-05)

            Bug Fixes

            • preserve package subpath resolution (be1315e)
            • preserve typeless ESM dependency exports (70dfc5e)

            This release is also available on:

            ... (truncated)

            Commits
            • bd3bc64 test: cover CommonJS loader source fallback
            • 55cbece fix: preserve async ESM require fallback
            • 6c5ba85 docs: document CommonJS default interop
            • ec1bcd5 fix: support nyc coverage discovery (#710)
            • b6e5b48 docs: clarify CommonJS default imports
            • 2f55884 fix: map Node test locations
            • de935d5 docs: document Node source-map stack formatting
            • b94f46f fix: support data URLs in tsImport
            • be1315e fix: preserve package subpath resolution
            • 5efba41 docs: organize transform backend research
            • Additional commits viewable in compare view

            Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
            Dependabot commands and options
            You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 16 ++++++++-------- .../src/jvmTest/typescript/package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index b014f88..fcf0b0d 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -15,9 +15,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.1.2", + "@types/node": "^26.2.0", "cors": "^2.8.6", - "tsx": "^4.23.4", + "tsx": "^4.23.11", "typescript": "^7.0.2" } }, @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.1.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz", - "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==", + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", + "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", "dev": true, "license": "MIT", "dependencies": { @@ -2034,9 +2034,9 @@ } }, "node_modules/tsx": { - "version": "4.23.4", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.4.tgz", - "integrity": "sha512-ZiUQ8oT/KzN51mJUWPqARYqwFLFJZtGZipRkw1ynHMr9vy3eU77m5yfF3Gzm6meEg/beW+lUu3fHYgskTN2oVQ==", + "version": "4.23.11", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.11.tgz", + "integrity": "sha512-Ry2oTEUnhBdeEdWIztY8kf3/nBGnPnjMLVGL0YfdRXMORuPER5NlKmayqxtxRxwB1xBN+RivRaJfe7PM1rtiyw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 240e861..f5be3b4 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -16,9 +16,9 @@ "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.1.2", + "@types/node": "^26.2.0", "cors": "^2.8.6", - "tsx": "^4.23.4", + "tsx": "^4.23.11", "typescript": "^7.0.2" } } From d9b42aed683d00243a722e11be10d003baa0a3d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 12:31:41 +0200 Subject: [PATCH 151/178] chore(deps): bump the all-actions group across 1 directory with 2 updates (#952) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-actions group with 2 updates in the / directory: [gradle/actions](https://github.com/gradle/actions) and [github/codeql-action](https://github.com/github/codeql-action). Updates `gradle/actions` from 6.2.0 to 6.3.0
            Release notes

            Sourced from gradle/actions's releases.

            v6.3.0

            Highlights

            Enhanced Caching: Windows fixes and a cache-protocol bump

            This release updates gradle-actions-caching to v1.0.0 (up from v0.7.0), which fixes two significant caching defects, both most visible on Windows:

            • Cache entries failed to store at all on Windows.. Every entry failed with Path Validation Error: Path(s) specified in the action for caching do(es) not exist, even though the Gradle User Home was fully intact. Nothing was stored, so every downstream job ran against an empty Gradle User Home. The cause was a nested, unpatched copy of @actions/glob combined with a silently swallowed require() in the bundle, which left Windows path separators unnormalized.

            • Cache cleanup deleted instrumented jars that were in use. A bug in key hashing for paths shorter than 64 characters made cleanup judge freshly created caches/jars-9 entries as unused and remove them, so the instrumented-jars entry was never saved and every job re-instrumented its classpaths.

              Also included: cache entry names are now consistent between the save and restore reports — restore previously fell back to showing the raw glob pattern (e.g. /home/runner/.gradle/caches/modules-*/files-*/*/*/*/*/) instead of dependencies.

            [!IMPORTANT] Existing cache entries are invalidated by this release. The cache protocol version was bumped to v2, so the first run after upgrading will be a cache miss and will repopulate the cache. No configuration changes are required.

            Basic caching warns instead of failing silently

            The basic (open-source) caching provider now emits a warning and reports (Entry not saved: save failed) in the Job Summary when a cache save fails, rather than reporting success (#1028).

            Dependency submission works with Isolated Projects

            dependency-submission now disables Isolated Projects via a promoted property, so dependency graph generation works on builds that enable it (#1025). Thanks to @​reinsch82 for the contribution.

            Updated defaults

            • Injected Develocity Gradle plugin: 4.4.2 → 4.5.0
            • 36 new known-good wrapper checksums added for wrapper-validation

            What's Changed

            ... (truncated)

            Commits
            • 9c97196 Bump the github-actions group across 2 directories with 9 updates (#1024)
            • 760e4a4 Bump the npm-dependencies group across 1 directory with 2 updates (#1037)
            • 73e4c42 Update gradle-actions-caching library to v1.0.0 (#1029)
            • a9d1438 Add dependabot ignore rules for TypeScript 7.x and @​types/node 25.x/26.x
            • 68f3700 [bot] Update dist directory
            • 5971332 Bump Gradle Wrapper to 9.6.1, wrapper checksums, and Develocity plugin to 4.5...
            • b5bc804 [bot] Update dist directory
            • dcbab4e Bump npm-dependencies group with TypeScript 6.0.3, @​types/node 24.x, and secu...
            • ca8d957 Move non-smoke restore-gradle-home tests back to the integ-test suite (#1032)
            • 4318659 [bot] Update dist directory
            • Additional commits viewable in compare view

            Updates `github/codeql-action` from 4.37.4 to 4.37.6
            Release notes

            Sourced from github/codeql-action's releases.

            v4.37.6

            • Changed the default filepath for the new remote file address format that was introduced in CodeQL Action 4.37.0 / 3.37.0 to .github/codeql-config.yml to align it with the suggested path that is used elsewhere. #4070

            v4.37.5

            • Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the init Action instead of falling back to downloading the bundle before extracting it. #4061
            Changelog

            Sourced from github/codeql-action's changelog.

            4.37.6 - 04 Aug 2026

            • Changed the default filepath for the new remote file address format that was introduced in CodeQL Action 4.37.0 / 3.37.0 to .github/codeql-config.yml to align it with the suggested path that is used elsewhere. #4070

            4.37.5 - 03 Aug 2026

            • Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the init Action instead of falling back to downloading the bundle before extracting it. #4061
            Commits
            • 5595cca Merge pull request #4071 from github/update-v4.37.6-6a9359a1b
            • ec9c757 Add change note for PR 4070
            • 45c8742 Update changelog for v4.37.6
            • 6a9359a Merge pull request #4070 from github/mbg/remote-address/change-file-default
            • 065cdc0 Change DEFAULT_CONFIG_FILE_NAME
            • f99dd5a Merge pull request #4066 from github/dependabot/npm_and_yarn/js-yaml-5.2.2
            • 1804b21 Merge pull request #4068 from github/mergeback/v4.37.5-to-main-d1ba80a1
            • 3020a2f Rebuild
            • 93c3a5a Update changelog and version after v4.37.5
            • d1ba80a Merge pull request #4067 from github/update-v4.37.5-1cd4d01d5
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/apidocs.yaml | 2 +- .github/workflows/build.yml | 6 +++--- .github/workflows/codeql.yml | 6 +++--- .github/workflows/conformance.yml | 8 ++++---- .github/workflows/gradle-publish.yml | 2 +- .github/workflows/samples.yml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/apidocs.yaml b/.github/workflows/apidocs.yaml index 8887169..c3967d6 100644 --- a/.github/workflows/apidocs.yaml +++ b/.github/workflows/apidocs.yaml @@ -34,7 +34,7 @@ jobs: cache: gradle - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 - name: Generate Dokka Site run: |- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0707d44..fb4f43e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,7 +63,7 @@ jobs: run: npm ci - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: validate-wrappers: true add-job-summary: 'always' @@ -135,7 +135,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: validate-wrappers: true add-job-summary: 'always' @@ -177,7 +177,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: add-job-summary: 'always' cache-read-only: true diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 368f044..44e903b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,13 +34,13 @@ jobs: java-version: ${{ env.JAVA_VERSION }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.4 + uses: github/codeql-action/init@v4.37.6 with: languages: java-kotlin build-mode: manual - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: validate-wrappers: true cache-read-only: true @@ -52,6 +52,6 @@ jobs: --no-daemon --rerun-tasks --stacktrace - name: Analyze - uses: github/codeql-action/analyze@v4.37.4 + uses: github/codeql-action/analyze@v4.37.6 with: category: '/language:java-kotlin' diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 0605b10..908107f 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -34,7 +34,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} @@ -85,7 +85,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} @@ -116,7 +116,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} @@ -155,7 +155,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index c9dc966..1cf24e4 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -30,7 +30,7 @@ jobs: node-version: '22' # increase only after https://github.com/nodejs/node/issues/56645 will be fixed - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 - name: Check run: ./gradlew check --no-configuration-cache diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml index 812fbb9..463c024 100644 --- a/.github/workflows/samples.yml +++ b/.github/workflows/samples.yml @@ -45,7 +45,7 @@ jobs: distribution: ${{ env.JAVA_DISTRIBUTION }} - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6.2.0 + uses: gradle/actions/setup-gradle@v6.3.0 with: validate-wrappers: true add-job-summary: 'always' From d67b0b7804b0acfd4e9c760699e1239df288f472 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Aug 2026 13:43:30 +0200 Subject: [PATCH 152/178] chore(deps): bump tsx from 4.23.11 to 4.23.12 in /integration-test/src/jvmTest/typescript in the all-dependencies group (#963) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group in /integration-test/src/jvmTest/typescript with 1 update: [tsx](https://github.com/privatenumber/tsx). Updates `tsx` from 4.23.11 to 4.23.12
            Release notes

            Sourced from tsx's releases.

            v4.23.12

            4.23.12 (2026-08-10)

            Bug Fixes

            • shim import.meta when tokens are split by comments or newlines (#829) (ed9d330), closes #828

            This release is also available on:

            Commits
            • ed9d330 fix: shim import.meta when tokens are split by comments or newlines (#829)
            • 651f5be test: cover CommonJS TypeScript import.meta paths
            • See full diff in compare view

            [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tsx&package-manager=npm_and_yarn&previous-version=4.23.11&new-version=4.23.12)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
            Dependabot commands and options
            You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 8 ++++---- integration-test/src/jvmTest/typescript/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index fcf0b0d..77509cc 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -17,7 +17,7 @@ "@types/express": "^5.0.6", "@types/node": "^26.2.0", "cors": "^2.8.6", - "tsx": "^4.23.11", + "tsx": "^4.23.12", "typescript": "^7.0.2" } }, @@ -2034,9 +2034,9 @@ } }, "node_modules/tsx": { - "version": "4.23.11", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.11.tgz", - "integrity": "sha512-Ry2oTEUnhBdeEdWIztY8kf3/nBGnPnjMLVGL0YfdRXMORuPER5NlKmayqxtxRxwB1xBN+RivRaJfe7PM1rtiyw==", + "version": "4.23.12", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz", + "integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==", "dev": true, "license": "MIT", "dependencies": { diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index f5be3b4..2321ffb 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -18,7 +18,7 @@ "@types/express": "^5.0.6", "@types/node": "^26.2.0", "cors": "^2.8.6", - "tsx": "^4.23.11", + "tsx": "^4.23.12", "typescript": "^7.0.2" } } From 815a70e7e7f3d9b6684ef6e132bd3f124d51585f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Aug 2026 15:54:20 +0200 Subject: [PATCH 153/178] chore(deps): bump github/codeql-action from 4.37.6 to 4.37.7 in the all-actions group across 1 directory (#962) Bumps the all-actions group with 1 update in the / directory: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.37.6 to 4.37.7
            Release notes

            Sourced from github/codeql-action's releases.

            v4.37.7

            • Update default CodeQL bundle version to 2.26.3. #4085
            Changelog

            Sourced from github/codeql-action's changelog.

            4.37.7 - 13 Aug 2026

            • Update default CodeQL bundle version to 2.26.3. #4085
            Commits
            • ff2f1c6 Merge pull request #4093 from github/update-v4.37.7-be7a3dbb8
            • 951a133 Update changelog for v4.37.7
            • be7a3db Merge pull request #4087 from github/dependabot/npm_and_yarn/npm-minor-0aa561...
            • 9310334 Merge pull request #4086 from github/mbg/thread-action-state-to-codeql
            • b4d8a54 Rebuild
            • ab5db25 Bump the npm-minor group across 1 directory with 8 updates
            • 38055a3 Drop logger from databaseInitCluster in interface
            • 1f87aed Merge pull request #4085 from github/update-bundle/codeql-bundle-v2.26.3
            • dc1b98a Make logger available to getCodeQLForCmd
            • 6f0220e Merge pull request #4084 from github/navntoft/bump-undici
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 44e903b..c697ff8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,7 +34,7 @@ jobs: java-version: ${{ env.JAVA_VERSION }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.6 + uses: github/codeql-action/init@v4.37.7 with: languages: java-kotlin build-mode: manual @@ -52,6 +52,6 @@ jobs: --no-daemon --rerun-tasks --stacktrace - name: Analyze - uses: github/codeql-action/analyze@v4.37.6 + uses: github/codeql-action/analyze@v4.37.7 with: category: '/language:java-kotlin' From 86243340578cae98eda9341f72ee211e93c28760 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:08:48 +0200 Subject: [PATCH 154/178] chore(deps): bump the kotest group across 1 directory with 3 updates (#960) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotest group with 3 updates in the / directory: [io.kotest:kotest-assertions-core](https://github.com/kotest/kotest), [io.kotest:kotest-assertions-json](https://github.com/kotest/kotest) and [io.kotest:kotest-assertions-ktor](https://github.com/kotest/kotest). Updates `io.kotest:kotest-assertions-core` from 6.2.3 to 6.2.4
            Release notes

            Sourced from io.kotest:kotest-assertions-core's releases.

            v6.2.4

            What's Changed

            New Contributors

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.3...v6.2.4

            Commits
            • 736a47b Add module-factory support to KoinExtension (#6006) (#6138)
            • cb91c7e junit testFinished improvements (#6205)
            • 5c898b4 spec tags cache (#6206)
            • 69fdc8d make ai skill available to users via claude marketplace and tie versioning to...
            • 2403f4f fix kdoc on StrictThrowableHandling (#6212)
            • f96cf2a introduce a TeamCity renderer that allows tree view and force it for our IJ p...
            • 0579271 sourceRef improvements (#6203)
            • da26f16 spring extension improvements (#6204)
            • cc5cf25 update docs to clarify that copies in shouldContainExactCopies must be 1 or...
            • 1d648f9 Update dependency io.github.classgraph:classgraph to v4.8.186 (#6201)
            • Additional commits viewable in compare view

            Updates `io.kotest:kotest-assertions-json` from 6.2.3 to 6.2.4
            Release notes

            Sourced from io.kotest:kotest-assertions-json's releases.

            v6.2.4

            What's Changed

            New Contributors

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.3...v6.2.4

            Commits
            • 736a47b Add module-factory support to KoinExtension (#6006) (#6138)
            • cb91c7e junit testFinished improvements (#6205)
            • 5c898b4 spec tags cache (#6206)
            • 69fdc8d make ai skill available to users via claude marketplace and tie versioning to...
            • 2403f4f fix kdoc on StrictThrowableHandling (#6212)
            • f96cf2a introduce a TeamCity renderer that allows tree view and force it for our IJ p...
            • 0579271 sourceRef improvements (#6203)
            • da26f16 spring extension improvements (#6204)
            • cc5cf25 update docs to clarify that copies in shouldContainExactCopies must be 1 or...
            • 1d648f9 Update dependency io.github.classgraph:classgraph to v4.8.186 (#6201)
            • Additional commits viewable in compare view

            Updates `io.kotest:kotest-assertions-ktor` from 6.2.3 to 6.2.4
            Release notes

            Sourced from io.kotest:kotest-assertions-ktor's releases.

            v6.2.4

            What's Changed

            New Contributors

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.3...v6.2.4

            Commits
            • 736a47b Add module-factory support to KoinExtension (#6006) (#6138)
            • cb91c7e junit testFinished improvements (#6205)
            • 5c898b4 spec tags cache (#6206)
            • 69fdc8d make ai skill available to users via claude marketplace and tie versioning to...
            • 2403f4f fix kdoc on StrictThrowableHandling (#6212)
            • f96cf2a introduce a TeamCity renderer that allows tree view and force it for our IJ p...
            • 0579271 sourceRef improvements (#6203)
            • da26f16 spring extension improvements (#6204)
            • cc5cf25 update docs to clarify that copies in shouldContainExactCopies must be 1 or...
            • 1d648f9 Update dependency io.github.classgraph:classgraph to v4.8.186 (#6201)
            • Additional commits viewable in compare view

            Updates `io.kotest:kotest-assertions-json` from 6.2.3 to 6.2.4
            Release notes

            Sourced from io.kotest:kotest-assertions-json's releases.

            v6.2.4

            What's Changed

            New Contributors

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.3...v6.2.4

            Commits
            • 736a47b Add module-factory support to KoinExtension (#6006) (#6138)
            • cb91c7e junit testFinished improvements (#6205)
            • 5c898b4 spec tags cache (#6206)
            • 69fdc8d make ai skill available to users via claude marketplace and tie versioning to...
            • 2403f4f fix kdoc on StrictThrowableHandling (#6212)
            • f96cf2a introduce a TeamCity renderer that allows tree view and force it for our IJ p...
            • 0579271 sourceRef improvements (#6203)
            • da26f16 spring extension improvements (#6204)
            • cc5cf25 update docs to clarify that copies in shouldContainExactCopies must be 1 or...
            • 1d648f9 Update dependency io.github.classgraph:classgraph to v4.8.186 (#6201)
            • Additional commits viewable in compare view

            Updates `io.kotest:kotest-assertions-ktor` from 6.2.3 to 6.2.4
            Release notes

            Sourced from io.kotest:kotest-assertions-ktor's releases.

            v6.2.4

            What's Changed

            New Contributors

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.3...v6.2.4

            Commits
            • 736a47b Add module-factory support to KoinExtension (#6006) (#6138)
            • cb91c7e junit testFinished improvements (#6205)
            • 5c898b4 spec tags cache (#6206)
            • 69fdc8d make ai skill available to users via claude marketplace and tie versioning to...
            • 2403f4f fix kdoc on StrictThrowableHandling (#6212)
            • f96cf2a introduce a TeamCity renderer that allows tree view and force it for our IJ p...
            • 0579271 sourceRef improvements (#6203)
            • da26f16 spring extension improvements (#6204)
            • cc5cf25 update docs to clarify that copies in shouldContainExactCopies must be 1 or...
            • 1d648f9 Update dependency io.github.classgraph:classgraph to v4.8.186 (#6201)
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f8ccbd9..6f8aaaa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ netty = "4.2.16.Final" awaitility = "4.3.0" collections-immutable = "0.5.1" coroutines = "1.11.0" -kotest = "6.2.3" +kotest = "6.2.4" kotlinx-io = "0.9.1" ktor = "3.5.2" logging = "8.0.4" From 4aa06febfcc220e1deb42411c4920185b1feb231 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 13:14:04 +0200 Subject: [PATCH 155/178] chore(deps): bump the other-dependencies group across 3 directories with 4 updates (#968) Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-client directory: [gradle-wrapper](https://github.com/gradle/gradle) and [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Bumps the other-dependencies group with 2 updates in the /samples/kotlinlang-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback). Bumps the other-dependencies group with 2 updates in the /samples/simple-streamable-server directory: [gradle-wrapper](https://github.com/gradle/gradle) and [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework). Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `com.anthropic:anthropic-java` from 2.52.0 to 2.57.0
            Release notes

            Sourced from com.anthropic:anthropic-java's releases.

            v2.57.0

            2.57.0 (2026-08-19)

            Full Changelog: v2.56.0...v2.57.0

            Features

            • api: managed agents web search config and self hosted sandbox memory (83b03c0)

            v2.56.0

            2.56.0 (2026-08-19)

            Full Changelog: v2.55.0...v2.56.0

            Features

            • api: Files and Skills APIs are now GA; add computer use and browser use toolsets (762f342)

            v2.55.0

            2.55.0 (2026-08-18)

            Full Changelog: v2.54.0...v2.55.0

            Features

            • api: additions to files and memory stores (1f89b9b)
            • api: updates to skill, files, and user profiles (a5febda)
            • client: add helpers for accessing the workspace ID in response headers (718d5c1)
            • internal: upgrade to Gradle 9 and Kotlin 2.3 with a shared version catalog (596395e)

            Bug Fixes

            • api: remove unsupported mid_conv_system content block (89bf901)
            • client: don't let null usage fields in message_delta overwrite accumulated usage (#226) (603d2f5)
            • client: keep unknown content block and delta types when accumulating a message stream (#225) (9bf944d)
            • tool-runner: forward the server-assigned container on follow-up requests (#216) (b754c45)
            • tool-runner: send the BetaToolRunner helper header (#220) (95b359c)

            Chores

            • internal: lint and format build logic sources with ktfmt (9b52a2a)
            • internal: remove leftover prism references (7624523)

            v2.54.0

            2.54.0 (2026-08-13)

            Full Changelog: v2.53.0...v2.54.0

            ... (truncated)

            Changelog

            Sourced from com.anthropic:anthropic-java's changelog.

            2.57.0 (2026-08-19)

            Full Changelog: v2.56.0...v2.57.0

            Features

            • api: managed agents web search config and self hosted sandbox memory (83b03c0)

            2.56.0 (2026-08-19)

            Full Changelog: v2.55.0...v2.56.0

            Features

            • api: Files and Skills APIs are now GA; add computer use and browser use toolsets (762f342)

            2.55.0 (2026-08-18)

            Full Changelog: v2.54.0...v2.55.0

            Features

            • api: additions to files and memory stores (1f89b9b)
            • api: updates to skill, files, and user profiles (a5febda)
            • client: add helpers for accessing the workspace ID in response headers (718d5c1)
            • internal: upgrade to Gradle 9 and Kotlin 2.3 with a shared version catalog (596395e)

            Bug Fixes

            • api: remove unsupported mid_conv_system content block (89bf901)
            • client: don't let null usage fields in message_delta overwrite accumulated usage (#226) (603d2f5)
            • client: keep unknown content block and delta types when accumulating a message stream (#225) (9bf944d)
            • tool-runner: forward the server-assigned container on follow-up requests (#216) (b754c45)
            • tool-runner: send the BetaToolRunner helper header (#220) (95b359c)

            Chores

            • internal: lint and format build logic sources with ktfmt (9b52a2a)
            • internal: remove leftover prism references (7624523)

            2.54.0 (2026-08-13)

            Full Changelog: v2.53.0...v2.54.0

            Features

            • api: add output_behavior to dream creation (create a new memory store or update the input store in place) (a49ea9a)
            • client: add StructuredOutputConfig for combining Class<T> structured outputs with other output options (#192) (8caead3)

            ... (truncated)

            Commits
            • 8f5861c release: 2.57.0
            • 71074ed feat(api): managed agents web search config and self hosted sandbox memory
            • 76e0cfa release: 2.56.0
            • ce2a502 feat(api): Files and Skills APIs are now GA; add computer use and browser use...
            • 8752d28 release: 2.55.0
            • fb31467 feat(api): updates to skill, files, and user profiles
            • ddaf1ec fix(client): don't let null usage fields in message_delta overwrite accumulat...
            • a544b28 fix(client): keep unknown content block and delta types when accumulating a m...
            • 27a08d0 fix(tool-runner): send the BetaToolRunner helper header (#220)
            • df22a59 chore(internal): lint and format build logic sources with ktfmt
            • Additional commits viewable in compare view

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `ch.qos.logback:logback-classic` from 1.6.1 to 1.6.3
            Release notes

            Sourced from ch.qos.logback:logback-classic's releases.

            Logback 1.6.3

            2026-08-14 Release of logback version 1.6.3

            • In response CVE-2026-19880, MDCBasedDiscriminator (used by SiftingAppender) now strips forward and backward slashes (/, \) from MDC values before they are used as discriminating keys. This prevents path segments from escaping into destinations controlled by an attacker. When sanitisation actually changes a value, a warning is emitted; the warning is rate-limited (a small batch, then a lull of about ten minutes).

            • Colour console support is split out into a dedicated JansiConsoleAppender. It wraps stdout or stderr with Jansi so ANSI escape sequences (for example coloured patterns) render correctly on terminals that need it, notably Windows. Prefer this class over the older path described next. See the appenders documentation.

            • The withJansi property on ConsoleAppender is deprecated. Existing configurations that still set <withJansi>true</withJansi> continue to work for compatibility, but new setups should use JansiConsoleAppender instead.

            • ConsoleAppender no longer treats the process console as an exclusive resource: stopping it does not close System.out / System.err. JansiConsoleAppender pairs each AnsiConsole.systemInstall() with systemUninstall() on stop, so repeated start/stop cycles do not leave Jansi installed or tear down streams shared with the rest of the JVM. Related behavior is covered by tests for issues/1063.

            • Invocation throttling helpers were reworked: SimpleInvocationGate is renamed FixedIntervalInvocationGate, and BatchedFixedIntervalInvocationGate allows a short burst of invocations before applying a fixed lull. The sanitisation warning above uses the batched gate.

            • The JPMS module-info for logback-core now exports the ch.qos.logback.core.property package, which had been missing from the module descriptor.

            • A bit-wise identical binary of this version can be reproduced by building from source code at commit e8e824dede022a6d7208b36cfa875b0d1b7772f3 associated with the tag v_1.6.3. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

            -- Sponsoring SLF4J/logback/reload4j at https://github.com/sponsors/qos-ch

            Logback 1.6.2

            https://github.com/user-attachments/assets/9ceaf157-b758-4188-815d-edfe4e1b4edd

            2026-08-10 Release of logback version 1.6.2

            • Configuration analysis now detects contradictory caller-data inclusion instructions. For example, an AsyncAppender, SocketAppender or SMTPAppender with includeCallerData left at the default false is incompatible with a layout or encoder pattern that uses a caller-data converter such as %C, %M, %L, %F, %l or %caller. At runtime those converters would print question marks and still incur extraction cost on a worker thread. Logback now emits a configuration-time warning when such instructions disagree. See codes.html#callerContradiction for details. This issue was reported in issues/1059 by leeychee. The initial analysis was contributed by seonwoo_jung.

            • Caller-contradiction analysis can be turned off by setting the logback.skipCallerContradictionAnalysis variable to true, either as a system property (-Dlogback.skipCallerContradictionAnalysis=true) or as a property in the configuration file:

              <property
              name="logback.skipCallerContradictionAnalysis"
              value="true"/>
              
            • SimpleSocketServer and SimpleSSLSocketServer now require an explicit client IP whitelist. On the command line, pass one or more allowed addresses (single IPs or CIDR ranges) after the configuration file. An empty whitelist means no clients are accepted. When embedding the server programmatically, register allowed addresses with addAllowedClientAddress(String) or setAllowedClientAddresses(Collection) before clients connect. See the documentation on restricting client access.

            • Added ThrowableProxyVOBuilder for assembling a ThrowableProxyVO field by field, with a corresponding ThrowableProxyVO.builder() entry point.

            • Dependency analysis handlers now run their postHandle method after child models have been processed, so checks that depend on nested appenders (such as caller-contradiction analysis) see a complete picture.

            • Updated several dependencies, including Angus Mail to 2.0.4 and Jetty (test) to 12.1.12.

            • A bit-wise identical binary of this version can be reproduced by building from source code at commit e3d78330ad1ba024fd987fd00c3ffb9cfcdb07dc associated with the tag v_1.6.2. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

            Commits
            • e8e824d prepare release 1.6.3
            • 761821b MDCBasedDiscriminator has a gated warning mechanism
            • 53ed122 update copyright year
            • c7e2db2 rename SimpleInvocationGate as FixedIntervalInvocationGate
            • b5aa931 added BatchedSimpleInvocationGate
            • 1f22af7 add javadocs to SimpleInvocationGate
            • 638ffa7 prevent forward and backward slashes to escape to other directories
            • 7d6b9a4 add missing ch.qos.logback.core.property package
            • fa25930 add an extension path in ConsoleAppender for JansiConsoleAppender
            • c73b43f deprecate the withJansi path
            • Additional commits viewable in compare view

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `org.junit.jupiter:junit-jupiter`... _Description has been truncated_ Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- .../kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties | 2 +- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 4e1f8bb..4c2f14c 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.52.0" +anthropic = "2.57.0" kotlin = "2.4.10" ktor = "3.5.2" mcp-kotlin = "0.15.0" diff --git a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties index 69dd0d0..ad7845b 100644 --- a/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-client/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index cf37f51..a113c64 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -4,7 +4,7 @@ ktor = "3.5.2" mcp-kotlin = "0.15.0" serialization = "1.11.0" coroutines = "1.11.0" -logback = "1.6.1" +logback = "1.6.3" shadow = "9.6.1" [libraries] diff --git a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties index 69dd0d0..ad7845b 100644 --- a/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlinlang-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 966a7e2..fd03619 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "2.4.10" ktor = "3.5.2" -junit = "6.1.2" +junit = "6.1.3" mcp-kotlin = "0.15.0" slf4j = "2.0.18" shadow = "9.6.1" diff --git a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties index 69dd0d0..ad7845b 100644 --- a/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/simple-streamable-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From e06014fc8333f69683c8dbc04e299194f55e2bfb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 17:18:50 +0200 Subject: [PATCH 156/178] chore(deps): bump gradle-wrapper from 9.7.0 to 9.7.1 (#969) Bumps [gradle-wrapper](https://github.com/gradle/gradle) from 9.7.0 to 9.7.1.
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69dd0d0..ad7845b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From dfdd8820da5f4f4572a2624d25f7d7d8650d131a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:50:19 +0200 Subject: [PATCH 157/178] chore(deps): bump ch.qos.logback:logback-classic from 1.6.1 to 1.6.3 (#970) Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.6.1 to 1.6.3.
            Release notes

            Sourced from ch.qos.logback:logback-classic's releases.

            Logback 1.6.3

            2026-08-14 Release of logback version 1.6.3

            • In response CVE-2026-19880, MDCBasedDiscriminator (used by SiftingAppender) now strips forward and backward slashes (/, \) from MDC values before they are used as discriminating keys. This prevents path segments from escaping into destinations controlled by an attacker. When sanitisation actually changes a value, a warning is emitted; the warning is rate-limited (a small batch, then a lull of about ten minutes).

            • Colour console support is split out into a dedicated JansiConsoleAppender. It wraps stdout or stderr with Jansi so ANSI escape sequences (for example coloured patterns) render correctly on terminals that need it, notably Windows. Prefer this class over the older path described next. See the appenders documentation.

            • The withJansi property on ConsoleAppender is deprecated. Existing configurations that still set <withJansi>true</withJansi> continue to work for compatibility, but new setups should use JansiConsoleAppender instead.

            • ConsoleAppender no longer treats the process console as an exclusive resource: stopping it does not close System.out / System.err. JansiConsoleAppender pairs each AnsiConsole.systemInstall() with systemUninstall() on stop, so repeated start/stop cycles do not leave Jansi installed or tear down streams shared with the rest of the JVM. Related behavior is covered by tests for issues/1063.

            • Invocation throttling helpers were reworked: SimpleInvocationGate is renamed FixedIntervalInvocationGate, and BatchedFixedIntervalInvocationGate allows a short burst of invocations before applying a fixed lull. The sanitisation warning above uses the batched gate.

            • The JPMS module-info for logback-core now exports the ch.qos.logback.core.property package, which had been missing from the module descriptor.

            • A bit-wise identical binary of this version can be reproduced by building from source code at commit e8e824dede022a6d7208b36cfa875b0d1b7772f3 associated with the tag v_1.6.3. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

            -- Sponsoring SLF4J/logback/reload4j at https://github.com/sponsors/qos-ch

            Logback 1.6.2

            https://github.com/user-attachments/assets/9ceaf157-b758-4188-815d-edfe4e1b4edd

            2026-08-10 Release of logback version 1.6.2

            • Configuration analysis now detects contradictory caller-data inclusion instructions. For example, an AsyncAppender, SocketAppender or SMTPAppender with includeCallerData left at the default false is incompatible with a layout or encoder pattern that uses a caller-data converter such as %C, %M, %L, %F, %l or %caller. At runtime those converters would print question marks and still incur extraction cost on a worker thread. Logback now emits a configuration-time warning when such instructions disagree. See codes.html#callerContradiction for details. This issue was reported in issues/1059 by leeychee. The initial analysis was contributed by seonwoo_jung.

            • Caller-contradiction analysis can be turned off by setting the logback.skipCallerContradictionAnalysis variable to true, either as a system property (-Dlogback.skipCallerContradictionAnalysis=true) or as a property in the configuration file:

              <property
              name="logback.skipCallerContradictionAnalysis"
              value="true"/>
              
            • SimpleSocketServer and SimpleSSLSocketServer now require an explicit client IP whitelist. On the command line, pass one or more allowed addresses (single IPs or CIDR ranges) after the configuration file. An empty whitelist means no clients are accepted. When embedding the server programmatically, register allowed addresses with addAllowedClientAddress(String) or setAllowedClientAddresses(Collection) before clients connect. See the documentation on restricting client access.

            • Added ThrowableProxyVOBuilder for assembling a ThrowableProxyVO field by field, with a corresponding ThrowableProxyVO.builder() entry point.

            • Dependency analysis handlers now run their postHandle method after child models have been processed, so checks that depend on nested appenders (such as caller-contradiction analysis) see a complete picture.

            • Updated several dependencies, including Angus Mail to 2.0.4 and Jetty (test) to 12.1.12.

            • A bit-wise identical binary of this version can be reproduced by building from source code at commit e3d78330ad1ba024fd987fd00c3ffb9cfcdb07dc associated with the tag v_1.6.2. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.

            Commits
            • e8e824d prepare release 1.6.3
            • 761821b MDCBasedDiscriminator has a gated warning mechanism
            • 53ed122 update copyright year
            • c7e2db2 rename SimpleInvocationGate as FixedIntervalInvocationGate
            • b5aa931 added BatchedSimpleInvocationGate
            • 1f22af7 add javadocs to SimpleInvocationGate
            • 638ffa7 prevent forward and backward slashes to escape to other directories
            • 7d6b9a4 add missing ch.qos.logback.core.property package
            • fa25930 add an extension path in ConsoleAppender for JansiConsoleAppender
            • c73b43f deprecate the withJansi path
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6f8aaaa..c4d4f90 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" slf4j = "2.0.18" -logback = "1.6.1" +logback = "1.6.3" junit = "5.14.4" [libraries] From cf5cca553b81fb78c9dcf444463a89793caa4e98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 20:56:55 +0200 Subject: [PATCH 158/178] chore(deps): bump github/codeql-action from 4.37.7 to 4.37.8 in the all-actions group across 1 directory (#971) Bumps the all-actions group with 1 update in the / directory: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.37.7 to 4.37.8
            Release notes

            Sourced from github/codeql-action's releases.

            v4.37.8

            No user facing changes.

            Changelog

            Sourced from github/codeql-action's changelog.

            4.37.8 - 21 Aug 2026

            No user facing changes.

            Commits
            • db488dd Merge pull request #4102 from github/update-v4.37.8-9ee088e13
            • 1845f5b Update changelog for v4.37.8
            • 9ee088e Merge pull request #4080 from github/henrymercer/studious-giggle
            • 1aef003 Address review feedback on overlay disk flags
            • 508b83b Merge main into overlay minimum disk feature branch
            • d97b342 Merge pull request #4098 from github/mbg/permission-error-as-configuration-error
            • 47fa622 Make EACCES a ConfigurationError
            • 45693cc Refactor ENOSPC check into isDiskConfigurationError function
            • c2fd8f5 Merge pull request #4081 from github/mario-campos/version-cache-to-disk
            • c56f48e Log unexpected conditions during caching CLI output
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c697ff8..84f0523 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,7 +34,7 @@ jobs: java-version: ${{ env.JAVA_VERSION }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.7 + uses: github/codeql-action/init@v4.37.8 with: languages: java-kotlin build-mode: manual @@ -52,6 +52,6 @@ jobs: --no-daemon --rerun-tasks --stacktrace - name: Analyze - uses: github/codeql-action/analyze@v4.37.7 + uses: github/codeql-action/analyze@v4.37.8 with: category: '/language:java-kotlin' From 52fc8878cd756afcd4d5f033ed8207c381b76ce3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Sep 2026 13:26:31 +0200 Subject: [PATCH 159/178] chore(deps): bump the other-dependencies group across 3 directories with 2 updates (#974) Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Bumps the other-dependencies group with 1 update in the /samples/weather-stdio-server directory: [gradle-wrapper](https://github.com/gradle/gradle). Updates `com.anthropic:anthropic-java` from 2.57.0 to 2.59.0
            Release notes

            Sourced from com.anthropic:anthropic-java's releases.

            v2.59.0

            2.59.0 (2026-08-27)

            Full Changelog: v2.58.0...v2.59.0

            Features

            • api: beta files/skills namespaces use GA shapes; drop dated beta header pins (e4e0e25)

            Bug Fixes

            • aws,bedrock: don't consume the request body while SigV4 signing (#257) (95238b1)
            • client: page backward via before_id and stop on has_more=false (81f16e7)
            • webhooks: require headers to be passed to unwrap() (4b43e22)

            Documentation

            • api: clarify pagination on the organization rate-limit list endpoints (1d0e987)

            v2.58.0

            2.58.0 (2026-08-26)

            Full Changelog: v2.57.0...v2.58.0

            Features

            • api: add updates thinking display mode (beta) (792b318)
            • api: add missing anthropic-beta values (60cc62a)
            • api: add support for Organization API endpoints (3adde69)

            Bug Fixes

            • bedrock: stop clobbering body anthropic_beta with header betas (#58) (e2609a9)
            • client: let explicit and ANTHROPIC_BASE_URL base URLs override profile base_url (#241) (7486e65)
            • client: resolve base URL in ClientOptions instead of the transport (#242) (a3e988a)
            • tools: keep the tool runner going on pause_turn (#196) (557c72d)

            Chores

            • docs: clarify skill version latest support and memory version retention (cc7fc00)
            • internal: cancel superseded CI runs (ae7cc8f)
            • internal: minor workflow reformat (36b5b98)

            Documentation

            ... (truncated)

            Changelog

            Sourced from com.anthropic:anthropic-java's changelog.

            2.59.0 (2026-08-27)

            Full Changelog: v2.58.0...v2.59.0

            Features

            • api: beta files/skills namespaces use GA shapes; drop dated beta header pins (e4e0e25)

            Bug Fixes

            • aws,bedrock: don't consume the request body while SigV4 signing (#257) (95238b1)
            • client: page backward via before_id and stop on has_more=false (81f16e7)
            • webhooks: require headers to be passed to unwrap() (4b43e22)

            Documentation

            • api: clarify pagination on the organization rate-limit list endpoints (1d0e987)

            2.58.0 (2026-08-26)

            Full Changelog: v2.57.0...v2.58.0

            Features

            • api: add updates thinking display mode (beta) (792b318)
            • api: add missing anthropic-beta values (60cc62a)
            • api: add support for Organization API endpoints (3adde69)

            Bug Fixes

            • bedrock: stop clobbering body anthropic_beta with header betas (#58) (e2609a9)
            • client: let explicit and ANTHROPIC_BASE_URL base URLs override profile base_url (#241) (7486e65)
            • client: resolve base URL in ClientOptions instead of the transport (#242) (a3e988a)
            • tools: keep the tool runner going on pause_turn (#196) (557c72d)

            Chores

            • docs: clarify skill version latest support and memory version retention (cc7fc00)
            • internal: cancel superseded CI runs (ae7cc8f)
            • internal: minor workflow reformat (36b5b98)

            Documentation

            • api: clarify session thread agent and usage.iterations compaction descriptions (beta) (2283253)
            • examples: use adaptive thinking in thinking examples (da9aaba)
            Commits
            • 8722270 release: 2.59.0
            • bc1e199 docs(api): clarify pagination on the organization rate-limit list endpoints
            • 4da20e1 fix(client): page backward via before_id and stop on has_more=false
            • b7046bc feat(api): beta files/skills namespaces use GA shapes; drop dated beta header...
            • 6531a27 fix(webhooks): require headers to be passed to unwrap()
            • 8786a45 fix(aws,bedrock): don't consume the request body while SigV4 signing (#257)
            • accd19e codegen metadata
            • 51bd492 release: 2.58.0
            • 82b2544 codegen metadata
            • 7bec4e1 feat(api): add support for Organization API endpoints
            • Additional commits viewable in compare view

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Updates `gradle-wrapper` from 9.7.0 to 9.7.1
            Release notes

            Sourced from gradle-wrapper's releases.

            9.7.1

            The Gradle team is excited to announce Gradle 9.7.1.

            This is a patch release for 9.7.0. We recommend using 9.7.1 instead of 9.7.0.

            Here are the highlights of 9.7.0 release:

            • Isolated Projects graduates to incubating
            • Broader Configuration Cache compatibility
            • Resilient Sync helps you fix broken builds
            • More source locations in problem reports

            Read the Release Notes

            We would like to thank the following community members for their contributions to this release of Gradle: Adam, Aman Gautam, Aman Kumar, Anton Dubrouski, Aurimas, gbhavya07, Josh Friend, nicklauslittle-gov, Pragati, project516, Qin Mi, Ravi, sk-reddy17, Suvrat Acharya, Yongshun Ye.

            Upgrade instructions

            Switch your build to use Gradle 9.7.1 by updating your wrapper:

            ./gradlew :wrapper --gradle-version=9.7.1 &&
            ./gradlew :wrapper
            

            See the Gradle 9.x upgrade guide to learn about deprecations, breaking changes and other considerations when upgrading.

            For Java, Groovy, Kotlin and Android compatibility, see the full compatibility notes.

            Reporting problems

            If you find a problem with this release, please file a bug on GitHub Issues adhering to our issue guidelines. If you're not sure you're encountering a bug, please use the forum.

            We hope you will build happiness with Gradle, and we look forward to your feedback via Twitter or on GitHub.

            Commits

            Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
            Dependabot commands and options
            You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- .../kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 4c2f14c..03b7ad4 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.57.0" +anthropic = "2.59.0" kotlin = "2.4.10" ktor = "3.5.2" mcp-kotlin = "0.15.0" diff --git a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties index 69dd0d0..ad7845b 100644 --- a/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/kotlin-mcp-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties index 69dd0d0..ad7845b 100644 --- a/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties +++ b/samples/weather-stdio-server/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From abce6d5367f5ee5e87be5871c6298798f53710de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:20:21 +0200 Subject: [PATCH 160/178] chore(deps): bump the all-dependencies group across 1 directory with 2 updates (#977) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 2 updates in the /integration-test/src/jvmTest/typescript directory: [zod](https://github.com/colinhacks/zod) and [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `zod` from 4.4.3 to 4.5.2
            Release notes

            Sourced from zod's releases.

            v4.5.2

            Commits:

            • a354314ac04fdd5484aa62dd5c3a4b553211a0e4 fix(docs): keep blog posts out of the docs collection (#6484)
            • d378c42aff6869f0929058a7923cd775880f5c4c ci: drop canary publishing from the release workflow (#6487)
            • 212b941791e7faae078e17645eb612824fd8f79a fix(v4): let a prototype method getter answer a bare call so vi.spyOn works (#6488)
            • e7576f542a7bc7ef3cc5eeec237714fd0e6b6e98 docs(blog): let the page show through the navbar in dark mode (#6489)
            • fedb06fafe33a66ce0b5c236ad2557e0a5a170fe fix(docs): match the blog TOC hover bar to the 2px active indicator
            • 6c932fcb2eea6eb671710ea058ca9fdc382ada89 chore: bump devcontainer image to Node 24 (#6470)
            • 6635d9dd367a664109de83c021995821f48efa29 docs(blog): soften the "method memoization" attribution
            • 019ae299cc75daa132bf1acf59086a520abf6b85 fix(docs): drop ISR on the docs route so the home page hydrates
            • 652bb438aa4c626c1cd7948c6849c4691239fca7 chore(docs): drop the scroll log from the route-change scroller
            • 571c8e8a3d73b4305f4abfdd6977773cc12f2bf5 fix(docs): render blog tabs with the stock fumadocs tab card
            • 9a193aa24b4efa3b315b91d4c56c8bc385b8513f 4.5.2

            v4.5.1

            Commits:

            • 2e862dbf89da2835e5206a8fd3d3be61afe3cf7f ci: gate the GitHub release and JSR publish on the version being live on npm
            • 8e03380510db36fa6fda979fc78a375fdea8021c 4.5.1

            v4.5.0

            Zod 4.5 is now available.

            npm install zod@latest
            

            At a glance:

            z.compile()

            You can now pre-compile any Zod schema using z.compile(schema). This dramatically speeds up parsing performance.

            import * as z from "zod";
            

            const Player = z.object({ username: z.string(), bio: z.string(), xp: z.number(), // ...20 more properties... </tr></table>

            ... (truncated)

            Commits
            • 9a193aa 4.5.2
            • 571c8e8 fix(docs): render blog tabs with the stock fumadocs tab card
            • 652bb43 chore(docs): drop the scroll log from the route-change scroller
            • 019ae29 fix(docs): drop ISR on the docs route so the home page hydrates
            • 6635d9d docs(blog): soften the "method memoization" attribution
            • 6c932fc chore: bump devcontainer image to Node 24 (#6470)
            • fedb06f fix(docs): match the blog TOC hover bar to the 2px active indicator
            • e7576f5 docs(blog): let the page show through the navbar in dark mode (#6489)
            • 212b941 fix(v4): let a prototype method getter answer a bare call so vi.spyOn works (...
            • d378c42 ci: drop canary publishing from the release workflow (#6487)
            • Additional commits viewable in compare view

            Updates `@types/node` from 26.2.0 to 26.4.0
            Commits

            Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
            Dependabot commands and options
            You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 16 ++++++++-------- .../src/jvmTest/typescript/package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 77509cc..f7769d6 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -10,12 +10,12 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", - "zod": "^4.4.3" + "zod": "^4.5.2" }, "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.2.0", + "@types/node": "^26.4.0", "cors": "^2.8.6", "tsx": "^4.23.12", "typescript": "^7.0.2" @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", - "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.0.tgz", + "integrity": "sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2165,9 +2165,9 @@ "license": "ISC" }, "node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.2.tgz", + "integrity": "sha512-XkYXCol10+ba/6F/cueWV+TezUeOqXW0hdeJt5CdXjTYeAgAQg5N03RQdJ80mhfFE72+pblvYMW4wy2Qp4Qbrg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 2321ffb..312c4f8 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -11,12 +11,12 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", - "zod": "^4.4.3" + "zod": "^4.5.2" }, "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.2.0", + "@types/node": "^26.4.0", "cors": "^2.8.6", "tsx": "^4.23.12", "typescript": "^7.0.2" From 358b2d5a1206304143b12a3732242b4eac8efa4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:46:46 +0200 Subject: [PATCH 161/178] chore(deps): bump qs from 6.15.2 to 6.16.0 in /integration-test/src/jvmTest/typescript (#979) Bumps [qs](https://github.com/ljharb/qs) from 6.15.2 to 6.16.0.
            Changelog

            Sourced from qs's changelog.

            6.16.0

            • [New] stringify: add a depth option to bound recursion depth (default Infinity)
            • [Fix] stringify: serialize Date values when a filter is provided
            • [Fix] parse: enforce arrayLimit on comma groups under []= when throwOnLimitExceeded is set
            • [Fix] parse: flatten a collection appended to an overflowed array (#571)
            • [Fix] utils: isBuffer: do not invoke a non-callable constructor.isBuffer
            • [Fix] stringify: do not let allowEmptyArrays skip cycle detection (or drop own keys) on an empty array with own properties
            • [Fix] stringify: encode dots in a top-level key with a primitive value when encodeDotInKeys is set (#562)
            • [Docs] threat model: clarify stringify deep-nesting DoS is caller-bounded
            • [Docs] clarify arrayLimit is a representation threshold, not an element-count cap
            • [Tests] parse: remove a test that pinned []= comma groups escaping arrayLimit
            • [Tests] stringify: pin current encodeDotInKeys separator-dot behavior
            • [Dev Deps] update @ljharb/eslint-config, eslint
            • [Dev Deps] update eslint, evalmd

            6.15.3

            • [Fix] parse: enforce throwOnLimitExceeded for cumulative array growth via combine/merge
            • [Fix] utils: respect encoding of surrogate pairs across chunks (#559)
            • [Robustness] parse: throw the arrayLimit error before splitting oversized comma values
            • [Robustness] utils.merge / utils.assign: avoid invoking __proto__ setter when copying own properties
            • [Robustness] utils: enforce arrayLimit consistently across merge's array paths
            • [Perf] utils: make compact O(n) via a side-channel visited-set instead of Array.indexOf
            • [Deps] update side-channel
            • [Dev Deps] update eslint, mock-property, tape
            • [Tests] parse: characterize current lenient handling of unbalanced bracket keys (#558)
            Commits
            • bb9379e v6.16.0
            • 62fd254 [Fix] stringify: serialize Date values when a filter is provided
            • 8859c37 [Fix] parse: enforce arrayLimit on comma groups under []= when `throwOn...
            • 8079adc [Tests] parse: remove a test that pinned []= comma groups escaping `array...
            • d56f48c [Fix] parse: flatten a collection appended to an overflowed array
            • e83d321 [Fix] utils: isBuffer: do not invoke a non-callable constructor.isBuffer
            • 7e87a07 [Dev Deps] update @ljharb/eslint-config, eslint
            • 9a76af2 [Dev Deps] update eslint, evalmd
            • 3a890d4 [Dev Deps] update eslint, evalmd
            • b433a9b [Fix] stringify: do not let allowEmptyArrays skip cycle detection (or dro...
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index f7769d6..f523ea3 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1229,9 +1229,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -1526,9 +1526,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -1802,12 +1802,13 @@ } }, "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", + "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" @@ -1944,14 +1945,14 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -1963,13 +1964,13 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" From d78d2d8b6fcf1ff34291c11774298b83b458f4bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 13:26:35 +0200 Subject: [PATCH 162/178] chore(deps): bump fast-uri from 3.1.5 to 3.1.7 in /integration-test/src/jvmTest/typescript (#978) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.5 to 3.1.7.
            Release notes

            Sourced from fast-uri's releases.

            v3.1.7

            ⚠️ Security Warning

            This is a security release that fixes the following high-severity security advisories:

            Users of the v3.x release line should upgrade to v3.1.7.

            Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.6...v3.1.7

            v3.1.6

            ⚠️ Security Warning

            This release addresses the following high-severity security advisories:

            Users of the v3.x release line should upgrade to v3.1.6.

            Full Changelog: https://github.com/fastify/fast-uri/compare/v3.1.5...v3.1.6

            Commits
            • 412e40a Bumped v3.1.7
            • 9f4c943 fix: backport port and IP-literal validation to v3.x (#216)
            • 1eb3ce4 fix: treat unterminated bracket hosts as reg-names again (#214)
            • 6f970b2 Bumped v3.1.6
            • d941579 fix: never run IDN canonicalization on bracketed IP literals
            • c0f0279 test: adapt decoded-scheme handler assertion to 3.x (no mailto scheme)
            • 37f3417 Merge commit from fork
            • 607bfbe Merge commit from fork
            • ae92a4c Merge commit from fork
            • 444ecda Merge commit from fork
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index f523ea3..a5c2f86 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1387,9 +1387,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", - "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz", + "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==", "funding": [ { "type": "github", From 40a14756cafd5a2aefa14e847a1ede855435b685 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 11:48:16 +0000 Subject: [PATCH 163/178] chore(deps): bump the all-actions group across 1 directory with 2 updates (#975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-actions group with 2 updates in the / directory: [actions/setup-java](https://github.com/actions/setup-java) and [github/codeql-action](https://github.com/github/codeql-action). Updates `actions/setup-java` from 5 to 6
            Release notes

            Sourced from actions/setup-java's releases.

            v6.0.0

            What's Changed

            ... (truncated)

            Commits

            Updates `github/codeql-action` from 4.37.8 to 4.37.9
            Release notes

            Sourced from github/codeql-action's releases.

            v4.37.9

            • Update default CodeQL bundle version to 2.26.4. #4106
            Changelog

            Sourced from github/codeql-action's changelog.

            4.37.9 - 26 Aug 2026

            • Update default CodeQL bundle version to 2.26.4. #4106
            Commits
            • cdf488f Merge pull request #4107 from github/update-v4.37.9-920ba7cd1
            • 7243f38 Update changelog for v4.37.9
            • 920ba7c Merge pull request #4106 from github/update-bundle/codeql-bundle-v2.26.4
            • ecfa6e1 Add changelog note
            • adcdf4a Update default bundle to codeql-bundle-v2.26.4
            • 486fec2 Merge pull request #4099 from github/update-supported-enterprise-server-versions
            • 134624c Merge pull request #4101 from github/dependabot/npm_and_yarn/npm-minor-457d82...
            • ff43db8 Merge pull request #4103 from github/mergeback/v4.37.8-to-main-db488dde
            • 4605e03 Rebuild
            • 099c869 Update changelog and version after v4.37.8
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/apidocs.yaml | 2 +- .github/workflows/build.yml | 6 +++--- .github/workflows/codeql.yml | 6 +++--- .github/workflows/conformance.yml | 8 ++++---- .github/workflows/gradle-publish.yml | 2 +- .github/workflows/samples.yml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/apidocs.yaml b/.github/workflows/apidocs.yaml index c3967d6..67770a7 100644 --- a/.github/workflows/apidocs.yaml +++ b/.github/workflows/apidocs.yaml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fb4f43e..ff99581 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} @@ -129,7 +129,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} @@ -171,7 +171,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 84f0523..a9ac7ff 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,13 +28,13 @@ jobs: uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.8 + uses: github/codeql-action/init@v4.37.9 with: languages: java-kotlin build-mode: manual @@ -52,6 +52,6 @@ jobs: --no-daemon --rerun-tasks --stacktrace - name: Analyze - uses: github/codeql-action/analyze@v4.37.8 + uses: github/codeql-action/analyze@v4.37.9 with: category: '/language:java-kotlin' diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 908107f..b3e3935 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -28,7 +28,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} @@ -79,7 +79,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} @@ -110,7 +110,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} @@ -149,7 +149,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} diff --git a/.github/workflows/gradle-publish.yml b/.github/workflows/gradle-publish.yml index 1cf24e4..f01f9c8 100644 --- a/.github/workflows/gradle-publish.yml +++ b/.github/workflows/gradle-publish.yml @@ -19,7 +19,7 @@ jobs: steps: - uses: actions/checkout@v7 - name: Set up JDK 21 - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: '21' distribution: 'temurin' diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml index 463c024..7463a9e 100644 --- a/.github/workflows/samples.yml +++ b/.github/workflows/samples.yml @@ -39,7 +39,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up JDK ${{ env.JAVA_VERSION }} - uses: actions/setup-java@v5 + uses: actions/setup-java@v6 with: java-version: ${{ env.JAVA_VERSION }} distribution: ${{ env.JAVA_DISTRIBUTION }} From 2f91865f3d100dced75f3570b17d40ff35c33880 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:57:00 +0200 Subject: [PATCH 164/178] chore(deps): bump com.anthropic:anthropic-java from 2.59.0 to 2.60.0 in /samples/kotlin-mcp-client in the other-dependencies group across 1 directory (#980) Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java). Updates `com.anthropic:anthropic-java` from 2.59.0 to 2.60.0
            Release notes

            Sourced from com.anthropic:anthropic-java's releases.

            v2.60.0

            2.60.0 (2026-09-01)

            Full Changelog: v2.59.0...v2.60.0

            Features

            • api: add external_user_onboarded_at to user profiles (2aa81c0)
            • api: add support for claude-fable-5-1 and claude-mythos-5-1 (f41a324)
            • api: add support for organization compliance settings in the Admin API (4b64a84)
            • api: support pagination on organization rate limit list endpoints (2aa81c0)
            • user_profiles: sort the user profile list by name with order_by=name (931543e)

            Bug Fixes

            • api: mark the beta header required on Admin API Tunnel operations (898dabf)
            • api: remove unsupported allowed_callers from the toolset entries (53bd597)
            • client: include non-JSON error response bodies in API errors (04045b5)

            Chores

            • api: remove unreleased thinking prefix_mismatched_behavior param (e01193a)
            • api: remove user profile relationship in favor of access_type (e01193a)
            • ci: keep the Maven artifact upload steps under stlc (7437d73)
            • docs: clarify disallowed characters in memory paths (20582c1)
            • internal: add browser-stubbed internal/node module and lint rule for Node built-in imports (2aa81c0)
            • internal: pin JAVA_HOME for detekt-rules tests and relax UnusedPrivateProperty for tests/examples (2aa81c0)
            • internal: read the request id shown in Terraform error diagnostics from the response header (2aa81c0)
            • internal: remove discriminator support from PropertyInfo (4b64a84)

            Documentation

            • api: backtick identifiers in managed-agents API descriptions (db40558)
            • api: describe external_key_id and compartment_id behavior on Claude Platform on AWS (5eefbe1)
            • changelog: detail the beta files/skills GA-shape change (#398) (0105936)
            Changelog

            Sourced from com.anthropic:anthropic-java's changelog.

            2.60.0 (2026-09-01)

            Full Changelog: v2.59.0...v2.60.0

            Features

            • api: add external_user_onboarded_at to user profiles (2aa81c0)
            • api: add support for claude-fable-5-1 and claude-mythos-5-1 (f41a324)
            • api: add support for organization compliance settings in the Admin API (4b64a84)
            • api: support pagination on organization rate limit list endpoints (2aa81c0)
            • user_profiles: sort the user profile list by name with order_by=name (931543e)

            Bug Fixes

            • api: mark the beta header required on Admin API Tunnel operations (898dabf)
            • api: remove unsupported allowed_callers from the toolset entries (53bd597)
            • client: include non-JSON error response bodies in API errors (04045b5)

            Chores

            • api: remove unreleased thinking prefix_mismatched_behavior param (e01193a)
            • api: remove user profile relationship in favor of access_type (e01193a)
            • ci: keep the Maven artifact upload steps under stlc (7437d73)
            • docs: clarify disallowed characters in memory paths (20582c1)
            • internal: add browser-stubbed internal/node module and lint rule for Node built-in imports (2aa81c0)
            • internal: pin JAVA_HOME for detekt-rules tests and relax UnusedPrivateProperty for tests/examples (2aa81c0)
            • internal: read the request id shown in Terraform error diagnostics from the response header (2aa81c0)
            • internal: remove discriminator support from PropertyInfo (4b64a84)

            Documentation

            • api: backtick identifiers in managed-agents API descriptions (db40558)
            • api: describe external_key_id and compartment_id behavior on Claude Platform on AWS (5eefbe1)
            • changelog: detail the beta files/skills GA-shape change (#398) (0105936)
            Commits
            • 1dfef96 Merge pull request #397 from anthropics/release-please--branches--main--chang...
            • 110af9e release: 2.60.0
            • f41a324 feat(api): add support for claude-fable-5-1 and claude-mythos-5-1
            • 04045b5 fix(client): include non-JSON error response bodies in API errors
            • 5eefbe1 docs(api): describe external_key_id and compartment_id behavior on Claude Pla...
            • 841463e Merge branch 'main' into next
            • 0105936 docs(changelog): detail the beta files/skills GA-shape change (#398)
            • 53bd597 fix(api): remove unsupported allowed_callers from the toolset entries
            • 20582c1 chore(docs): clarify disallowed characters in memory paths
            • db40558 docs(api): backtick identifiers in managed-agents API descriptions
            • Additional commits viewable in compare view

            [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.anthropic:anthropic-java&package-manager=gradle&previous-version=2.59.0&new-version=2.60.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
            Dependabot commands and options
            You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 03b7ad4..06a1c8f 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -anthropic = "2.59.0" +anthropic = "2.60.0" kotlin = "2.4.10" ktor = "3.5.2" mcp-kotlin = "0.15.0" From 45e3b8c1ec5513517e3a2016d32e8ddc759d18cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 15:55:00 +0200 Subject: [PATCH 165/178] chore(deps): bump org.jetbrains.kotlinx.binary-compatibility-validator from 0.18.1 to 0.18.2 in the gradle-plugins group across 1 directory (#982) Bumps the gradle-plugins group with 1 update in the / directory: [org.jetbrains.kotlinx.binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator). Updates `org.jetbrains.kotlinx.binary-compatibility-validator` from 0.18.1 to 0.18.2
            Release notes

            Sourced from org.jetbrains.kotlinx.binary-compatibility-validator's releases.

            0.18.2

            • Prevent configuration crash on hosts unrecognized by Kotlin/Native
            Commits
            • 534b4eb Release 0.18.2
            • 0332e22 Prevent configuration crash on hosts unrecognized by Kotlin/Native (#316)
            • 31dafe4 Updated warning about freezing development
            • 74e2c57 Updated warning about freezing development (#309)
            • See full diff in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c4d4f90..a40a5b3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] # plugins version atomicfu = "0.33.0" -binaryCompatibilityValidatorPlugin = "0.18.1" +binaryCompatibilityValidatorPlugin = "0.18.2" detekt = "2.0.0-alpha.6" dokka = "2.2.0" kotlin = "2.4.10" From b7047e77cf0625241bd177f17bbe35a1d4ae642c Mon Sep 17 00:00:00 2001 From: Recoordinate <296084221+latent-9@users.noreply.github.com> Date: Thu, 10 Sep 2026 05:00:31 +1200 Subject: [PATCH 166/178] fix(server): return INVALID_PARAMS for unknown prompt in prompts/get (#955) ## Problem `prompts/get` for a name that is not registered responds with JSON-RPC `-32603` (INTERNAL_ERROR). `handleGetPrompt` in `Server.kt` throws a bare `IllegalArgumentException` when the prompt is missing. `Protocol.respondWithError` maps any non-`McpException` cause to `INTERNAL_ERROR`, so the client receives `-32603` for what is a client-side bad parameter. The sibling handler `handleReadResource` in the same file already throws a typed `McpException(RESOURCE_NOT_FOUND)` for the equivalent not-found case, which reaches the client as `-32002`. The two not-found paths are inconsistent. In JSON-RPC, `-32603` means the server hit an internal fault. Requesting a prompt name that does not exist is a client error (an invalid `name` parameter), so a client cannot tell "the prompt does not exist" apart from "the server failed" and may retry a request that can never succeed. ## Change Throw a typed `McpException(INVALID_PARAMS)` from `handleGetPrompt`, consistent with `handleReadResource`. The message is unchanged. `AbstractPromptIntegrationTest.testNonExistentPrompt` asserted `-32603`; it now asserts `INVALID_PARAMS`. If you would prefer a dedicated error code for this case instead of `INVALID_PARAMS`, I am glad to adjust. --- .../sdk/integration/kotlin/AbstractPromptIntegrationTest.kt | 4 ++-- .../io/modelcontextprotocol/kotlin/sdk/server/Server.kt | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractPromptIntegrationTest.kt b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractPromptIntegrationTest.kt index eaa51ad..fb97782 100644 --- a/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractPromptIntegrationTest.kt +++ b/integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractPromptIntegrationTest.kt @@ -698,8 +698,8 @@ abstract class AbstractPromptIntegrationTest : KotlinTestBase() { val expectedMessage = "Prompt not found: non-existent-prompt" - withClue("Exception code should be INTERNAL_ERROR: -32603") { - exception.code shouldBe -32603 + withClue("Exception code should be INVALID_PARAMS: ${RPCError.ErrorCode.INVALID_PARAMS}") { + exception.code shouldBe RPCError.ErrorCode.INVALID_PARAMS } withClue("Unexpected error message for non-existent prompt") { exception.message shouldBe expectedMessage diff --git a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt index 51a2389..6f7711f 100644 --- a/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt +++ b/kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt @@ -682,7 +682,10 @@ public open class Server( val prompt = promptRegistry.get(requestParams.name) ?: run { logger.error { "Prompt not found: ${requestParams.name}" } - throw IllegalArgumentException("Prompt not found: ${requestParams.name}") + throw McpException( + code = RPCError.ErrorCode.INVALID_PARAMS, + message = "Prompt not found: ${requestParams.name}", + ) } return prompt.run { session.clientConnection.messageProvider(request) From ba5b1cce652eda3112cc3e9a9f02b62d50a49d35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:47:39 +0200 Subject: [PATCH 167/178] chore(deps): bump the all-dependencies group across 1 directory with 3 updates (#983) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 3 updates in the /integration-test/src/jvmTest/typescript directory: [zod](https://github.com/colinhacks/zod), [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [tsx](https://github.com/privatenumber/tsx). Updates `zod` from 4.5.2 to 4.5.4
            Release notes

            Sourced from zod's releases.

            v4.5.4

            Commits:

            • 84e416fbf4740527bbc8f319634f4e1b065bb42c fix(v4): stop the cycle walk from firing a default factory (#6500)
            • e8e206fa33ac5fe7ce20a2beb12d57b1cb3df653 4.5.4

            v4.5.3

            Commits:

            • e6b6ab347675cd2bd54b1bdbed16f98c59be82a9 docs(blog): widen the z.compile example to a 20-property schema
            • 87d6464418582bb96fc665a01f852ca6da324ad0 fix(docs): drop the OG description when the title wraps past two lines
            • 99fce394a026823e602b9c30d8d5d9f5f1932ce7 bench(v4): z.compile() against zod-compiler (#6499)
            • e3a695b6bf3f0d591ea682816e3cdaea04b0f967 docs(v4): record the email regex and container output-shape findings under Open
            • 7e24a24288183ce02554f1ded7775d0650a7b7e6 docs(blog): drop the reading time and put a GitHub link in the navbar
            • eab51ff3592b2d11d863f4ee4d5452f31a3de1b6 fix(v4): emit record numeric keys as strings in toJSONSchema (#6497)
            Commits
            • e8e206f 4.5.4
            • 84e416f fix(v4): stop the cycle walk from firing a default factory (#6500)
            • 1a16102 4.5.3
            • eab51ff fix(v4): emit record numeric keys as strings in toJSONSchema (#6497)
            • 7e24a24 docs(blog): drop the reading time and put a GitHub link in the navbar
            • e3a695b docs(v4): record the email regex and container output-shape findings under Open
            • 99fce39 bench(v4): z.compile() against zod-compiler (#6499)
            • 87d6464 fix(docs): drop the OG description when the title wraps past two lines
            • e6b6ab3 docs(blog): widen the z.compile example to a 20-property schema
            • See full diff in compare view

            Updates `@types/node` from 26.4.0 to 26.4.1
            Commits

            Updates `tsx` from 4.23.12 to 4.23.13
            Release notes

            Sourced from tsx's releases.

            v4.23.13

            4.23.13 (2026-08-30)

            Bug Fixes

            • cache: bound shared transform cache memory (#835) (28e1f12)

            This release is also available on:

            Commits

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 24 +++++++++---------- .../src/jvmTest/typescript/package.json | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index a5c2f86..5c6746d 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -10,14 +10,14 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", - "zod": "^4.5.2" + "zod": "^4.5.4" }, "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.4.0", + "@types/node": "^26.4.1", "cors": "^2.8.6", - "tsx": "^4.23.12", + "tsx": "^4.23.13", "typescript": "^7.0.2" } }, @@ -579,9 +579,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.4.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.0.tgz", - "integrity": "sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ==", + "version": "26.4.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.1.tgz", + "integrity": "sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==", "dev": true, "license": "MIT", "dependencies": { @@ -2035,9 +2035,9 @@ } }, "node_modules/tsx": { - "version": "4.23.12", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz", - "integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==", + "version": "4.23.13", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz", + "integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==", "dev": true, "license": "MIT", "dependencies": { @@ -2166,9 +2166,9 @@ "license": "ISC" }, "node_modules/zod": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.2.tgz", - "integrity": "sha512-XkYXCol10+ba/6F/cueWV+TezUeOqXW0hdeJt5CdXjTYeAgAQg5N03RQdJ80mhfFE72+pblvYMW4wy2Qp4Qbrg==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.4.tgz", + "integrity": "sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 312c4f8..287f0b8 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -11,14 +11,14 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", - "zod": "^4.5.2" + "zod": "^4.5.4" }, "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.4.0", + "@types/node": "^26.4.1", "cors": "^2.8.6", - "tsx": "^4.23.12", + "tsx": "^4.23.13", "typescript": "^7.0.2" } } From 318aabe74e3e7c9d1b57cc1ba216132ef06c82ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 16:10:41 +0200 Subject: [PATCH 168/178] chore(deps): bump hono from 4.13.1 to 4.13.7 in /integration-test/src/jvmTest/typescript (#987) Bumps [hono](https://github.com/honojs/hono) from 4.13.1 to 4.13.7.
            Release notes

            Sourced from hono's releases.

            v4.13.7

            Security fixes

            This release includes a fix for the following security issue:

            hono/jsx renders plain strings unescaped in boundary components, leading to XSS

            Affects: Suspense, ErrorBoundary, and Context.Provider in hono/jsx, and renderToString() / renderToReadableStream() in hono/jsx/dom/server. Fixes missing HTML escaping for a plain string placed directly as a child or fallback of these components, or as the root value of the server rendering functions, so untrusted strings could be emitted as markup. GHSA-hxh3-vqpv-xpqv


            Users who render untrusted strings inside Suspense, ErrorBoundary, or Context.Provider, or pass them directly to hono/jsx/dom/server, are strongly encouraged to upgrade to this version.

            v4.13.6

            What's Changed

            Full Changelog: https://github.com/honojs/hono/compare/v4.13.5...v4.13.6

            v4.13.5

            Security fixes

            This release includes fixes for the following security issues:

            Query parser reads parameters after the URL fragment, causing cache-key and proxy interpretation differentials

            Affects: Cache Middleware and applications behind a proxy, WAF, or logging layer that inspects query strings. Fixes query parsing that did not stop at the URL fragment, so a ? after a # was treated as the start of a query string and the application could read parameters that the other component never saw. GHSA-crvj-82cr-hjcx

            Incomplete fix for CVE-2026-39408: toSSG() still writes files outside the output directory

            Affects: toSSG() for Static Site Generation. Fixes a path normalization gap where consecutive parent-directory segments in ssgParams values were not fully collapsed, bypassing the containment check added in 4.12.12. GHSA-gqvv-2mrq-wpjv

            Unbounded dot-notation nesting in parseBody() can cause memory exhaustion

            Affects: parseBody() when dot-notation parsing is enabled. Fixes unbounded expansion of dot-separated field names, where a small request body could allocate a disproportionately large object graph and concurrent requests could exhaust the heap. GHSA-g6gw-c38x-mqfc


            Users who use Cache Middleware, deploy behind a proxy or WAF that inspects query strings, use Static Site Generation, or use parseBody({ dot: true }) are strongly encouraged to upgrade to this version.

            v4.13.4

            What's Changed

            • fix(request): handle params on unmatched requests in honojs/hono#5268
            • fix(jsx/dom): execute previous ref cleanup when ref prop changes on re-render in honojs/hono#5264
            • fix(reg-exp-router): associate wildcard middleware with matching routes in honojs/hono#5266
            • perf(router): share null object creation in honojs/hono#5267

            ... (truncated)

            Commits

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration-test/src/jvmTest/typescript/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index 5c6746d..d9312b7 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -1538,9 +1538,9 @@ } }, "node_modules/hono": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.1.tgz", - "integrity": "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==", + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.7.tgz", + "integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==", "license": "MIT", "engines": { "node": ">=16.9.0" From 5555b0d8ae964ca9dec24a3de4097fc85c66a930 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 23:50:17 +0200 Subject: [PATCH 169/178] chore(deps): bump org.jetbrains.kotlinx:kotlinx-collections-immutable from 0.5.1 to 0.5.2 in the kotlinx group across 1 directory (#981) Bumps the kotlinx group with 1 update in the / directory: [org.jetbrains.kotlinx:kotlinx-collections-immutable](https://github.com/Kotlin/kotlinx.collections.immutable). Updates `org.jetbrains.kotlinx:kotlinx-collections-immutable` from 0.5.1 to 0.5.2
            Release notes

            Sourced from org.jetbrains.kotlinx:kotlinx-collections-immutable's releases.

            v0.5.2

            • Fixed addingAll, removingAll, retainingAll, intersect, and containsAll on PersistentHashSet, puttingAll on PersistentHashMap, and their builder counterparts returning wrong results when a collision node meets a single element at the bottom trie level #294
            • Fixed puttingAll on PersistentHashMap, and putAll on its builder, keeping the receiver's value for a key that sits in a collision node on both sides #300
            • Fixed PersistentHashSet.equals being asymmetric after intersect, retainingAll, or the builder's retainAll #291
            • Fixed PersistentHashMapBuilder.put of an already stored value invalidating live iterators and making build() return a new map when the key is in a collision node #304
            • Fixed a live iterator of PersistentHashMapBuilder returning the old values after a putAll that only replaces values #308
            • Fixed PersistentOrderedMapBuilder iterators throwing ConcurrentModificationException after MutableMap.MutableEntry.setValue, or a put that only replaces a value, during iteration #307
            • Fixed MutableMap.MutableEntry.setValue on a PersistentOrderedMapBuilder entry re-adding the key after it was removed from the builder #310

            Full changelog: https://github.com/Kotlin/kotlinx.collections.immutable/compare/v0.5.1...v0.5.2

            Changelog

            Sourced from org.jetbrains.kotlinx:kotlinx-collections-immutable's changelog.

            0.5.2

            • Fixed addingAll, removingAll, retainingAll, intersect, and containsAll on PersistentHashSet, puttingAll on PersistentHashMap, and their builder counterparts returning wrong results when a collision node meets a single element at the bottom trie level #294
            • Fixed puttingAll on PersistentHashMap, and putAll on its builder, keeping the receiver's value for a key that sits in a collision node on both sides #300
            • Fixed PersistentHashSet.equals being asymmetric after intersect, retainingAll, or the builder's retainAll #291
            • Fixed PersistentHashMapBuilder.put of an already stored value invalidating live iterators and making build() return a new map when the key is in a collision node #304
            • Fixed a live iterator of PersistentHashMapBuilder returning the old values after a putAll that only replaces values #308
            • Fixed PersistentOrderedMapBuilder iterators throwing ConcurrentModificationException after MutableMap.MutableEntry.setValue, or a put that only replaces a value, during iteration #307
            • Fixed MutableMap.MutableEntry.setValue on a PersistentOrderedMapBuilder entry re-adding the key after it was removed from the builder #310
            Commits
            • 9f961e4 Release v0.5.2
            • 1d00eea Skip the setValue write when the entry's key is gone from the builder (#315)
            • 8a49b20 Count the value overwrites of putAll and keep the stored keys (#312)
            • 59bc873 Count only size changes for the ordered map builder's iterators (#311)
            • 2b9cc44 Return the collision node as is when the put value is already stored (#309)
            • c9a67cb Take the argument's value when two collision nodes share a key (#302)
            • 024f04c Dispatch bulk trie ops to collision helpers at the bottom level (#301)
            • 578f6ed Update kotlinx.benchmark to 0.4.17
            • e72f86e Lift the single remaining element to the root in set retainAll (#293)
            • 1fd89dd Restore commented-out invariant asserts (#290)
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a40a5b3..a00822b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ netty = "4.2.16.Final" # libraries version awaitility = "4.3.0" -collections-immutable = "0.5.1" +collections-immutable = "0.5.2" coroutines = "1.11.0" kotest = "6.2.4" kotlinx-io = "0.9.1" From be06a71053dde72af6197a68828d23adb1ad8be4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 15:44:06 +0200 Subject: [PATCH 170/178] chore(deps): bump org.jetbrains.kotlin.jvm from 2.4.10 to 2.4.20 in /samples/kotlin-mcp-client (#989) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [org.jetbrains.kotlin.jvm](https://github.com/JetBrains/kotlin) from 2.4.10 to 2.4.20.
            Release notes

            Sourced from org.jetbrains.kotlin.jvm's releases.

            Kotlin 2.4.20

            Changelog

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set

            ... (truncated)

            Changelog

            Sourced from org.jetbrains.kotlin.jvm's changelog.

            2.4.20

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set
            • KT-36740 MPP: False-positive incompatible types in .java when using expect-class returned by non-expect member from common when actual is actual typealias

            ... (truncated)

            Commits
            • 890ac1d Add Changelog for 2.4.20-RC3
            • 8860aed 🍒 [FIR] Fix suspend conversion when expected type is nullable (#7769)
            • ab5bcd9 Edit ChangeLog for 2.4.20-RC2
            • 9464edc Add ChangeLog for 2.4.20-RC2
            • 0261e43 Cherry-pick "Fix asBodyAndResultVar call in `visitInlinedLambdaInComposable...
            • 0763513 [box-tests] Workaround for klib compatibility tests (#7626)
            • 045aec6 [Wasm] Append scripts from webpack.config.d in the end of the file (#7615)
            • cd7173b 🍒 [2.4.20] [K/JS] Keep associated obj annotation only if getInstance survives...
            • d36a2ff CastsOptimizationPass: break aliases cycles (#7578)
            • 8664983 [CLI] Restore custom IC search scope creation
            • Additional commits viewable in compare view

            [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.jetbrains.kotlin.jvm&package-manager=gradle&previous-version=2.4.10&new-version=2.4.20)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
            Dependabot commands and options
            You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index 06a1c8f..c2edddb 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] anthropic = "2.60.0" -kotlin = "2.4.10" +kotlin = "2.4.20" ktor = "3.5.2" mcp-kotlin = "0.15.0" shadow = "9.6.1" From 12e4020d8d1bce6577e35d69a98afaf196055d52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 16:07:40 +0200 Subject: [PATCH 171/178] chore(deps): bump github/codeql-action from 4.37.9 to 4.38.0 in the all-actions group across 1 directory (#990) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-actions group with 1 update in the / directory: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.37.9 to 4.38.0
            Release notes

            Sourced from github/codeql-action's releases.

            v4.38.0

            • On GitHub-hosted runners, the CodeQL Action now deletes unused CodeQL bundles from the toolcache before downloading a different bundle, which frees up disk space for the analysis. We expect to roll this change out to everyone in September. #4124
            • The CodeQL Action now supports CodeQL releases that are compatible with Linux Arm64 and downloads the native linux-arm64 CodeQL bundle when available. #4072
            • Update default CodeQL bundle version to 2.27.0. #4129
            Changelog

            Sourced from github/codeql-action's changelog.

            4.38.0 - 09 Sept 2026

            • On GitHub-hosted runners, the CodeQL Action now deletes unused CodeQL bundles from the toolcache before downloading a different bundle, which frees up disk space for the analysis. We expect to roll this change out to everyone in September. #4124
            • The CodeQL Action now supports CodeQL releases that are compatible with Linux Arm64 and downloads the native linux-arm64 CodeQL bundle when available. #4072
            • Update default CodeQL bundle version to 2.27.0. #4129
            Commits
            • b96794f Merge pull request #4131 from github/update-v4.38.0-7e08580a9
            • 02d5093 Update changelog for v4.38.0
            • 7e08580 Merge pull request #4130 from github/henrymercer/workflow-runner-sizing
            • bfcc52b Run slow macOS checks on larger runners
            • 8c251e7 Merge pull request #4129 from github/update-bundle/codeql-bundle-v2.27.0
            • 0b7ca40 Add changelog note
            • 40484b3 Update default bundle to codeql-bundle-v2.27.0
            • 977e6ce Merge pull request #4124 from github/henrymercer/toolcache-bundle-cleanup
            • 40a6b38 Address toolcache cleanup review feedback
            • deece8f Apply suggestion from @​henrymercer
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a9ac7ff..2e7c58f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,7 +34,7 @@ jobs: java-version: ${{ env.JAVA_VERSION }} - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.9 + uses: github/codeql-action/init@v4.38.0 with: languages: java-kotlin build-mode: manual @@ -52,6 +52,6 @@ jobs: --no-daemon --rerun-tasks --stacktrace - name: Analyze - uses: github/codeql-action/analyze@v4.37.9 + uses: github/codeql-action/analyze@v4.38.0 with: category: '/language:java-kotlin' From f7877f2040f3b8dad5a0048a54ba5b9b3c8b974d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:03:30 +0200 Subject: [PATCH 172/178] chore(deps): bump the all-dependencies group across 1 directory with 2 updates (#991) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the all-dependencies group with 2 updates in the /integration-test/src/jvmTest/typescript directory: [zod](https://github.com/colinhacks/zod) and [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `zod` from 4.5.4 to 4.6.2
            Release notes

            Sourced from zod's releases.

            v4.6.2

            A patch on top of 4.6.1.

            v4.6.1

            A patch on top of 4.6.0.

            v4.6.0

            Zod 4.6 is now available.

            npm install zod@latest
            

            At a glance:

            • .validate() — checks input validity without building a result (up to 35x faster than .safeParse().success on a compiled schema)
            • z.instanceof().properties() — validates properties of an instance
            • fromJSONSchema() — enforces six validation keywords it used to ignore
            • z.iban() — electronic-format IBAN plus mod-97 checksum
            • z.withParser() — installs a parser generated elsewhere, for environments without new Function
            • Faster CommonJS — drops the getter on every export (~3x faster z.validate() under require)
            • Memory retention in recursive schemas — releases the parsed input, fixing a 4.5 out-of-memory regression
            • @zod/mini — Zod Mini as a standalone package, versioned in lockstep with zod since 4.5

            .validate()

            Standalone boolean validation, in Zod, Zod Mini, and Zod Core. It answers "is this input valid?" without constructing a ZodError, which makes rejection cheap. The return type is a guard on the schema's input type.

            z.validate(z.string(), "hi"); // true
            z.validate(z.string(), 42);   // false
            

            It is a method on Zod Classic schemas too. (#6547)

            const Player = z.object({
              username: z.string(),
              xp: z.number(),
            });
            

            </tr></table>

            ... (truncated)

            Commits
            • e359f73 4.6.2
            • 9446b5c fix: preserve undefined prefault outputs and object keys (#6587)
            • 0c483c5 docs: Zod 4.6 announcement post (#6546)
            • a00c3f3 docs: use Trigger.dev's brand-kit lockups for the platinum card
            • 62311eb 4.6.1
            • 2efa8b8 ci: give the npm wait a real budget and drop the back-publish path (#6583)
            • b12aa52 fix: preserve unique tags with defaulted discriminators (#6582)
            • dd9c36f fix(v4): defer recursive object index inference (#6580)
            • 574d480 fix(locales): clarify Tajik discriminator value message
            • c532d76 test(locales): cover Tajik error branches
            • Additional commits viewable in compare view

            Updates `@types/node` from 26.4.1 to 26.5.1
            Commits

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/jvmTest/typescript/package-lock.json | 24 +++++++++---------- .../src/jvmTest/typescript/package.json | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/integration-test/src/jvmTest/typescript/package-lock.json b/integration-test/src/jvmTest/typescript/package-lock.json index d9312b7..ffb53fc 100644 --- a/integration-test/src/jvmTest/typescript/package-lock.json +++ b/integration-test/src/jvmTest/typescript/package-lock.json @@ -10,12 +10,12 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", - "zod": "^4.5.4" + "zod": "^4.6.2" }, "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.4.1", + "@types/node": "^26.5.1", "cors": "^2.8.6", "tsx": "^4.23.13", "typescript": "^7.0.2" @@ -579,13 +579,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.4.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.1.tgz", - "integrity": "sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==", + "version": "26.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.5.1.tgz", + "integrity": "sha512-CzNm2FezW4VR/LjG6yUdiEgLE/rAQ9Slj5gCu/C2VrdcW7I0ahNZ8DRbHT7zOZ6r3ONgd/bsQIeSaoDGrd1C6g==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~8.3.0" + "undici-types": "~8.9.0" } }, "node_modules/@types/qs": { @@ -2120,9 +2120,9 @@ } }, "node_modules/undici-types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", - "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", "dev": true, "license": "MIT" }, @@ -2166,9 +2166,9 @@ "license": "ISC" }, "node_modules/zod": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.4.tgz", - "integrity": "sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.2.tgz", + "integrity": "sha512-lh5RCAGFa1Cm2hjtNwLQhSs/AsqdWnTQaBER9fEwN/88pSh7KOtJavtBx/0VlkN/uFd61SwYmljLMDAsHlvzBQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/integration-test/src/jvmTest/typescript/package.json b/integration-test/src/jvmTest/typescript/package.json index 287f0b8..b0147e4 100644 --- a/integration-test/src/jvmTest/typescript/package.json +++ b/integration-test/src/jvmTest/typescript/package.json @@ -11,12 +11,12 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.30.0", "express": "^5.2.1", - "zod": "^4.5.4" + "zod": "^4.6.2" }, "devDependencies": { "@types/cors": "^2.8.19", "@types/express": "^5.0.6", - "@types/node": "^26.4.1", + "@types/node": "^26.5.1", "cors": "^2.8.6", "tsx": "^4.23.13", "typescript": "^7.0.2" From d5ff46eda8d6897bbbfe2ccb1a452a45ae78ff27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:56:45 +0200 Subject: [PATCH 173/178] chore(deps): bump the kotest group across 1 directory with 3 updates (#992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the kotest group with 3 updates in the / directory: [io.kotest:kotest-assertions-core](https://github.com/kotest/kotest), [io.kotest:kotest-assertions-json](https://github.com/kotest/kotest) and [io.kotest:kotest-assertions-ktor](https://github.com/kotest/kotest). Updates `io.kotest:kotest-assertions-core` from 6.2.4 to 6.2.5
            Release notes

            Sourced from io.kotest:kotest-assertions-core's releases.

            v6.2.5

            What's Changed

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.4...v6.2.5

            Commits
            • 41df99d Fix Android StackWalker compatibility (#6222)
            • 8655ca7 add back jsoup assertions (#6226)
            • e2271eb Alex/make default extension registry thread safe (#6199)
            • fdca609 Bound the short/byte/uShort/uByte shrinkers by the generator range (#6224)
            • 56301a6 Make the shouldBeSingleton block overloads infix (#6223)
            • dfee83a Use withEdtSafeAnalysis to improve safe analysis for spec and style… (#6215)
            • c44d1c3 use a singleton strategy for getConfigurationFactory of Kotest legacy produce...
            • b74611b skill version update PR upon release (#6213)
            • 0d3c09a 6.2.4 claude marketplace manual update
            • See full diff in compare view

            Updates `io.kotest:kotest-assertions-json` from 6.2.4 to 6.2.5
            Release notes

            Sourced from io.kotest:kotest-assertions-json's releases.

            v6.2.5

            What's Changed

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.4...v6.2.5

            Commits
            • 41df99d Fix Android StackWalker compatibility (#6222)
            • 8655ca7 add back jsoup assertions (#6226)
            • e2271eb Alex/make default extension registry thread safe (#6199)
            • fdca609 Bound the short/byte/uShort/uByte shrinkers by the generator range (#6224)
            • 56301a6 Make the shouldBeSingleton block overloads infix (#6223)
            • dfee83a Use withEdtSafeAnalysis to improve safe analysis for spec and style… (#6215)
            • c44d1c3 use a singleton strategy for getConfigurationFactory of Kotest legacy produce...
            • b74611b skill version update PR upon release (#6213)
            • 0d3c09a 6.2.4 claude marketplace manual update
            • See full diff in compare view

            Updates `io.kotest:kotest-assertions-ktor` from 6.2.4 to 6.2.5
            Release notes

            Sourced from io.kotest:kotest-assertions-ktor's releases.

            v6.2.5

            What's Changed

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.4...v6.2.5

            Commits
            • 41df99d Fix Android StackWalker compatibility (#6222)
            • 8655ca7 add back jsoup assertions (#6226)
            • e2271eb Alex/make default extension registry thread safe (#6199)
            • fdca609 Bound the short/byte/uShort/uByte shrinkers by the generator range (#6224)
            • 56301a6 Make the shouldBeSingleton block overloads infix (#6223)
            • dfee83a Use withEdtSafeAnalysis to improve safe analysis for spec and style… (#6215)
            • c44d1c3 use a singleton strategy for getConfigurationFactory of Kotest legacy produce...
            • b74611b skill version update PR upon release (#6213)
            • 0d3c09a 6.2.4 claude marketplace manual update
            • See full diff in compare view

            Updates `io.kotest:kotest-assertions-json` from 6.2.4 to 6.2.5
            Release notes

            Sourced from io.kotest:kotest-assertions-json's releases.

            v6.2.5

            What's Changed

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.4...v6.2.5

            Commits
            • 41df99d Fix Android StackWalker compatibility (#6222)
            • 8655ca7 add back jsoup assertions (#6226)
            • e2271eb Alex/make default extension registry thread safe (#6199)
            • fdca609 Bound the short/byte/uShort/uByte shrinkers by the generator range (#6224)
            • 56301a6 Make the shouldBeSingleton block overloads infix (#6223)
            • dfee83a Use withEdtSafeAnalysis to improve safe analysis for spec and style… (#6215)
            • c44d1c3 use a singleton strategy for getConfigurationFactory of Kotest legacy produce...
            • b74611b skill version update PR upon release (#6213)
            • 0d3c09a 6.2.4 claude marketplace manual update
            • See full diff in compare view

            Updates `io.kotest:kotest-assertions-ktor` from 6.2.4 to 6.2.5
            Release notes

            Sourced from io.kotest:kotest-assertions-ktor's releases.

            v6.2.5

            What's Changed

            Full Changelog: https://github.com/kotest/kotest/compare/6.2.4...v6.2.5

            Commits
            • 41df99d Fix Android StackWalker compatibility (#6222)
            • 8655ca7 add back jsoup assertions (#6226)
            • e2271eb Alex/make default extension registry thread safe (#6199)
            • fdca609 Bound the short/byte/uShort/uByte shrinkers by the generator range (#6224)
            • 56301a6 Make the shouldBeSingleton block overloads infix (#6223)
            • dfee83a Use withEdtSafeAnalysis to improve safe analysis for spec and style… (#6215)
            • c44d1c3 use a singleton strategy for getConfigurationFactory of Kotest legacy produce...
            • b74611b skill version update PR upon release (#6213)
            • 0d3c09a 6.2.4 claude marketplace manual update
            • See full diff in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a00822b..9c2b948 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ netty = "4.2.16.Final" awaitility = "4.3.0" collections-immutable = "0.5.2" coroutines = "1.11.0" -kotest = "6.2.4" +kotest = "6.2.5" kotlinx-io = "0.9.1" ktor = "3.5.2" logging = "8.0.4" From e40ed0c7d738a56c83dd4c3187f5d93485a1868a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 16:15:30 +0200 Subject: [PATCH 174/178] chore(deps): bump the infrastructure group across 1 directory with 2 updates (#993) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the infrastructure group with 2 updates in the / directory: [io.netty:netty-bom](https://github.com/netty/netty) and org.slf4j:slf4j-simple. Updates `io.netty:netty-bom` from 4.2.16.Final to 4.2.18.Final
            Release notes

            Sourced from io.netty:netty-bom's releases.

            netty-4.2.18.Final

            Security fixes

            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-http (SPDY)
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-http (HTTP/1.1)
            • CVE-2026-XXXXX : denial of service vector in io.netty:netty-codec-http2
            • CVE-2026-XXXXX : improper certificate validation in io.netty:netty-handler-ssl-ocsp
            • CVE-2026-XXXXX : memory leak in io.netty:netty-codec-stomp
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-http
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http3
            • CVE-2026-XXXXX : denial of service vector in io.netty:netty-codec-stomp
            • CVE-2026-XXXXX : parser desync/response smuggling in io.netty:netty-codec-memcache
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-http3
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-http3
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-http3
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-smtp
            • CVE-2026-XXXXX : memory leak in io.netty:netty-codec-haproxy
            • CVE-2026-XXXXX : request smuggling in io.netty:netty-codec-http (RTSP)
            • CVE-2026-XXXXX : request smuggling in io.netty:netty-codec-http (HTTP/1)
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http2
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http (HTTP/1)
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http3
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http3 and in io.netty:netty-codec-http2
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http2
            • CVE-2026-XXXXX : improper hostname verification in io.netty:netty-codec-classes-quic
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-redis
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http (HTTP/1.1)
            • CVE-2026-XXXXX : request smuggling vector in io.netty:netty-codec-http (HTTP/1.1)
            • CVE-2026-XXXXX : unbounded resource usage in io.netty:netty-codec-mqtt
            • CVE-2026-XXXXX : improper CRLF neutralization in io.netty:netty-codec-smtp
            • CVE-2026-XXXXX : improper certificate validation in io.netty:netty-handler-ssl-ocsp
            • CVE-2026-XXXXX : improper header validation in io.netty:netty-codec-http2

            Compatibility Notes

            A number of security fixes have added additional validation and impose new resource usage limits, which may cause existing workloads to fail or be rejected. We recommend that you test your systems thoroughly as part of your Netty upgrade.

            Two specific changes are worth calling out:

            QUIC now explicitly requires X509ExtendedTrustManager when hostname verification is enabled. Previously, when configuring QUIC with an endpoint identification algorithm and an X509TrustManager, hostname verification would be silently skipped. This is now considered a misconfiguration and an exception will be thrown.

            HTTP/2 header value validation is now enabled by default. HTTP/2 header name validation has always been enabled by default, with an option to disable it, but HTTP/2 header value validation has been disabled by default until now. Configuration options still exist to disable this, but validation of HTTP header names and values are now both opt-in by default rather than opt-out.

            What's Changed

            ... (truncated)

            Commits
            • 2521f49 [maven-release-plugin] prepare release netty-4.2.18.Final
            • 6fd5327 HTTP/1 absolute-form Host mismatch is translated to HTTP/3 :authority, overri...
            • c44a052 SPDY: SpdySessionHandler must limit the concurrent streams
            • 374d965 HTTP: Limit the maximum number of concurrent pipelined requests
            • 7e8b325 HTTP/2: Limit HPACK encoding table size
            • e3ebf70 OCSP: Correctly handle that nextUpdate is optional
            • 5388535 STOMP: Correctly release partial content on handler removal
            • 3a80f5a WebSockets: Enforce a limit for the max pipelined requests in WebSocketServer...
            • 1b6ea48 HTTP3: Correctly handle ":authority" and "host" headers
            • 3630659 STOMP codec content-length long-to-int truncation causes infinite decode loop...
            • Additional commits viewable in compare view

            Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c2b948..a8d034f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kover = "0.9.9" ktlint = "14.2.0" knit = "0.5.1" mavenPublish = "0.37.0" -netty = "4.2.16.Final" +netty = "4.2.18.Final" # libraries version awaitility = "4.3.0" @@ -21,7 +21,7 @@ ktor = "3.5.2" logging = "8.0.4" mockk = "1.14.11" serialization = "1.11.0" -slf4j = "2.0.18" +slf4j = "2.0.19" logback = "1.6.3" junit = "5.14.4" From e9b976198be75b75d5903fd4f4f632ba463ebd09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 16:34:29 +0200 Subject: [PATCH 175/178] chore(deps): bump the other-dependencies group across 4 directories with 2 updates (#988) Bumps the other-dependencies group with 2 updates in the /samples/kotlin-mcp-client directory: [com.anthropic:anthropic-java](https://github.com/anthropics/anthropic-sdk-java) and org.slf4j:slf4j-simple. Bumps the other-dependencies group with 1 update in the /samples/kotlin-mcp-server directory: org.slf4j:slf4j-simple. Bumps the other-dependencies group with 1 update in the /samples/simple-streamable-server directory: org.slf4j:slf4j-simple. Bumps the other-dependencies group with 1 update in the /samples/weather-stdio-server directory: org.slf4j:slf4j-simple. Updates `com.anthropic:anthropic-java` from 2.60.0 to 2.62.0
            Release notes

            Sourced from com.anthropic:anthropic-java's releases.

            v2.62.0

            2.62.0 (2026-09-10)

            Full Changelog: v2.61.0...v2.62.0

            Features

            • api: add auto mode tool permissions for Managed Agents (e373fea)
            • api: add content_too_large web_fetch tool error code (96451de)
            • api: add the user-profiles-2026-09-04 beta value and external_user_details to user profiles (eb8c5b8)
            • api: support mounting public GitHub repositories without an authorization_token in Managed Agents sessions (2e1c9ed)

            Performance Improvements

            • streaming: append tool input JSON in place (d330f8b)
            • streaming: buffer text deltas instead of rebuilding blocks per delta (2bf8f70)

            Chores

            • docs: correct the environment scope field description (7888770)
            • internal: cap formatter JVM heap at 1 GiB (9b7b5a8)
            • internal: restore package version (28151f2)
            • internal: restore package version (6044d63)
            • internal: stop stamping the package version into generated files (ee275ad)
            • tests: restore empty test package marker files (3e2284c)

            v2.61.0

            2.61.0 (2026-09-04)

            Full Changelog: v2.60.0...v2.61.0

            Features

            • api: add Claude Tag category and user breakdowns to usage reports (7caaeb9)
            • api: add named types for organization compliance settings state (9576c86)
            • api: add workspace_id request option for multi-workspace credentials (cf7f13c)
            • api: raise Managed Agents vault refresh token limit to 8192 chars (d0c2286)

            Bug Fixes

            • api: remove response text block maxLength constraint (b6225ce)
            • client: read union common properties from raw JSON for unknown variants (3d2f38f)

            Chores

            • api: accept anthropic-version on Claude Enterprise admin endpoints (165fa6b)
            • api: declare specific error statuses instead of a generic 4XX response (e0dc35b)
            • api: update authentication parameters on spend limit create and delete (d054f6c)

            ... (truncated)

            Changelog

            Sourced from com.anthropic:anthropic-java's changelog.

            2.62.0 (2026-09-10)

            Full Changelog: v2.61.0...v2.62.0

            Features

            • api: add auto mode tool permissions for Managed Agents (e373fea)
            • api: add content_too_large web_fetch tool error code (96451de)
            • api: add the user-profiles-2026-09-04 beta value and external_user_details to user profiles (eb8c5b8)
            • api: support mounting public GitHub repositories without an authorization_token in Managed Agents sessions (2e1c9ed)

            Performance Improvements

            • streaming: append tool input JSON in place (d330f8b)
            • streaming: buffer text deltas instead of rebuilding blocks per delta (2bf8f70)

            Chores

            • docs: correct the environment scope field description (7888770)
            • internal: cap formatter JVM heap at 1 GiB (9b7b5a8)
            • internal: restore package version (28151f2)
            • internal: restore package version (6044d63)
            • internal: stop stamping the package version into generated files (ee275ad)
            • tests: restore empty test package marker files (3e2284c)

            2.61.0 (2026-09-04)

            Full Changelog: v2.60.0...v2.61.0

            Features

            • api: add Claude Tag category and user breakdowns to usage reports (7caaeb9)
            • api: add named types for organization compliance settings state (9576c86)
            • api: add workspace_id request option for multi-workspace credentials (cf7f13c)
            • api: raise Managed Agents vault refresh token limit to 8192 chars (d0c2286)
            • client: keep vault credential secrets out of Terraform state with write-only arguments (7556952)

            Bug Fixes

            • api: remove response text block maxLength constraint (b6225ce)
            • client: raise a clear error when an httpx object is passed instead of an httpx2 one (130d7af)
            • client: read union common properties from raw JSON for unknown variants (3d2f38f)

            Chores

            • api: accept anthropic-version on Claude Enterprise admin endpoints (165fa6b)

            ... (truncated)

            Commits
            • 88a1753 Merge pull request #400 from anthropics/release-please--branches--main--chang...
            • 6964f07 release: 2.62.0
            • e373fea feat(api): add auto mode tool permissions for Managed Agents
            • 2e1c9ed feat(api): support mounting public GitHub repositories without an authorizati...
            • eb8c5b8 feat(api): add the user-profiles-2026-09-04 beta value and external_user_deta...
            • 2bf8f70 perf(streaming): buffer text deltas instead of rebuilding blocks per delta
            • d330f8b perf(streaming): append tool input JSON in place
            • 7888770 chore(docs): correct the environment scope field description
            • 9b7b5a8 chore(internal): cap formatter JVM heap at 1 GiB
            • 96451de feat(api): add content_too_large web_fetch tool error code
            • Additional commits viewable in compare view

            Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Updates `org.slf4j:slf4j-simple` from 2.0.18 to 2.0.19 Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlin-mcp-client/gradle/libs.versions.toml | 4 ++-- samples/kotlin-mcp-server/gradle/libs.versions.toml | 2 +- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/kotlin-mcp-client/gradle/libs.versions.toml b/samples/kotlin-mcp-client/gradle/libs.versions.toml index c2edddb..b58eef2 100644 --- a/samples/kotlin-mcp-client/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-client/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] -anthropic = "2.60.0" +anthropic = "2.62.0" kotlin = "2.4.20" ktor = "3.5.2" mcp-kotlin = "0.15.0" shadow = "9.6.1" -slf4j = "2.0.18" +slf4j = "2.0.19" [libraries] anthropic-java = { group = "com.anthropic", name = "anthropic-java", version.ref = "anthropic" } diff --git a/samples/kotlin-mcp-server/gradle/libs.versions.toml b/samples/kotlin-mcp-server/gradle/libs.versions.toml index 5f8b83f..d46c2f1 100644 --- a/samples/kotlin-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlin-mcp-server/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.4.10" ktor = "3.5.2" mcp-kotlin = "0.15.0" -slf4j = "2.0.18" +slf4j = "2.0.19" shadow = "9.6.1" [libraries] diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index fd03619..0102599 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin = "2.4.10" ktor = "3.5.2" junit = "6.1.3" mcp-kotlin = "0.15.0" -slf4j = "2.0.18" +slf4j = "2.0.19" shadow = "9.6.1" [libraries] diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index b84a655..4301857 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -5,7 +5,7 @@ ktor = "3.5.2" logging = "8.0.4" mcp-kotlin = "0.15.0" shadow = "9.6.1" -slf4j = "2.0.18" +slf4j = "2.0.19" [libraries] kotlin-logging = { group = "io.github.oshai", name = "kotlin-logging-jvm", version.ref = "logging" } From 8b0badb88315ef55e1aaebb82314510e210a0866 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 17:26:51 +0200 Subject: [PATCH 176/178] chore(deps): bump kotlin from 2.4.10 to 2.4.20 in /samples/kotlinlang-mcp-server (#995) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `kotlin` from 2.4.10 to 2.4.20. Updates `org.jetbrains.kotlin.jvm` from 2.4.10 to 2.4.20
            Release notes

            Sourced from org.jetbrains.kotlin.jvm's releases.

            Kotlin 2.4.20

            Changelog

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set

            ... (truncated)

            Changelog

            Sourced from org.jetbrains.kotlin.jvm's changelog.

            2.4.20

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set
            • KT-36740 MPP: False-positive incompatible types in .java when using expect-class returned by non-expect member from common when actual is actual typealias

            ... (truncated)

            Commits
            • 890ac1d Add Changelog for 2.4.20-RC3
            • 8860aed 🍒 [FIR] Fix suspend conversion when expected type is nullable (#7769)
            • ab5bcd9 Edit ChangeLog for 2.4.20-RC2
            • 9464edc Add ChangeLog for 2.4.20-RC2
            • 0261e43 Cherry-pick "Fix asBodyAndResultVar call in `visitInlinedLambdaInComposable...
            • 0763513 [box-tests] Workaround for klib compatibility tests (#7626)
            • 045aec6 [Wasm] Append scripts from webpack.config.d in the end of the file (#7615)
            • cd7173b 🍒 [2.4.20] [K/JS] Keep associated obj annotation only if getInstance survives...
            • d36a2ff CastsOptimizationPass: break aliases cycles (#7578)
            • 8664983 [CLI] Restore custom IC search scope creation
            • Additional commits viewable in compare view

            Updates `org.jetbrains.kotlin.plugin.serialization` from 2.4.10 to 2.4.20
            Release notes

            Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

            Kotlin 2.4.20

            Changelog

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set

            ... (truncated)

            Changelog

            Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

            2.4.20

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set
            • KT-36740 MPP: False-positive incompatible types in .java when using expect-class returned by non-expect member from common when actual is actual typealias

            ... (truncated)

            Commits
            • 890ac1d Add Changelog for 2.4.20-RC3
            • 8860aed 🍒 [FIR] Fix suspend conversion when expected type is nullable (#7769)
            • ab5bcd9 Edit ChangeLog for 2.4.20-RC2
            • 9464edc Add ChangeLog for 2.4.20-RC2
            • 0261e43 Cherry-pick "Fix asBodyAndResultVar call in `visitInlinedLambdaInComposable...
            • 0763513 [box-tests] Workaround for klib compatibility tests (#7626)
            • 045aec6 [Wasm] Append scripts from webpack.config.d in the end of the file (#7615)
            • cd7173b 🍒 [2.4.20] [K/JS] Keep associated obj annotation only if getInstance survives...
            • d36a2ff CastsOptimizationPass: break aliases cycles (#7578)
            • 8664983 [CLI] Restore custom IC search scope creation
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/kotlinlang-mcp-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml index a113c64..0c11d3b 100644 --- a/samples/kotlinlang-mcp-server/gradle/libs.versions.toml +++ b/samples/kotlinlang-mcp-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.4.10" +kotlin = "2.4.20" ktor = "3.5.2" mcp-kotlin = "0.15.0" serialization = "1.11.0" From 1d04427cff47b31932409b90959869aa2934d680 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 17:58:02 +0200 Subject: [PATCH 177/178] chore(deps): bump kotlin from 2.4.10 to 2.4.20 in /samples/weather-stdio-server (#997) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `kotlin` from 2.4.10 to 2.4.20. Updates `org.jetbrains.kotlin.jvm` from 2.4.10 to 2.4.20
            Release notes

            Sourced from org.jetbrains.kotlin.jvm's releases.

            Kotlin 2.4.20

            Changelog

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set

            ... (truncated)

            Changelog

            Sourced from org.jetbrains.kotlin.jvm's changelog.

            2.4.20

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set
            • KT-36740 MPP: False-positive incompatible types in .java when using expect-class returned by non-expect member from common when actual is actual typealias

            ... (truncated)

            Commits
            • 890ac1d Add Changelog for 2.4.20-RC3
            • 8860aed 🍒 [FIR] Fix suspend conversion when expected type is nullable (#7769)
            • ab5bcd9 Edit ChangeLog for 2.4.20-RC2
            • 9464edc Add ChangeLog for 2.4.20-RC2
            • 0261e43 Cherry-pick "Fix asBodyAndResultVar call in `visitInlinedLambdaInComposable...
            • 0763513 [box-tests] Workaround for klib compatibility tests (#7626)
            • 045aec6 [Wasm] Append scripts from webpack.config.d in the end of the file (#7615)
            • cd7173b 🍒 [2.4.20] [K/JS] Keep associated obj annotation only if getInstance survives...
            • d36a2ff CastsOptimizationPass: break aliases cycles (#7578)
            • 8664983 [CLI] Restore custom IC search scope creation
            • Additional commits viewable in compare view

            Updates `org.jetbrains.kotlin.plugin.serialization` from 2.4.10 to 2.4.20
            Release notes

            Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

            Kotlin 2.4.20

            Changelog

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set

            ... (truncated)

            Changelog

            Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

            2.4.20

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set
            • KT-36740 MPP: False-positive incompatible types in .java when using expect-class returned by non-expect member from common when actual is actual typealias

            ... (truncated)

            Commits
            • 890ac1d Add Changelog for 2.4.20-RC3
            • 8860aed 🍒 [FIR] Fix suspend conversion when expected type is nullable (#7769)
            • ab5bcd9 Edit ChangeLog for 2.4.20-RC2
            • 9464edc Add ChangeLog for 2.4.20-RC2
            • 0261e43 Cherry-pick "Fix asBodyAndResultVar call in `visitInlinedLambdaInComposable...
            • 0763513 [box-tests] Workaround for klib compatibility tests (#7626)
            • 045aec6 [Wasm] Append scripts from webpack.config.d in the end of the file (#7615)
            • cd7173b 🍒 [2.4.20] [K/JS] Keep associated obj annotation only if getInstance survives...
            • d36a2ff CastsOptimizationPass: break aliases cycles (#7578)
            • 8664983 [CLI] Restore custom IC search scope creation
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/weather-stdio-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/weather-stdio-server/gradle/libs.versions.toml b/samples/weather-stdio-server/gradle/libs.versions.toml index 4301857..9d609a9 100644 --- a/samples/weather-stdio-server/gradle/libs.versions.toml +++ b/samples/weather-stdio-server/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] coroutines = "1.11.0" -kotlin = "2.4.10" +kotlin = "2.4.20" ktor = "3.5.2" logging = "8.0.4" mcp-kotlin = "0.15.0" From ae44babacce79c29509e78199880cb14bc62a71e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:04:06 +0200 Subject: [PATCH 178/178] chore(deps): bump kotlin from 2.4.10 to 2.4.20 in /samples/simple-streamable-server (#996) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `kotlin` from 2.4.10 to 2.4.20. Updates `org.jetbrains.kotlin.jvm` from 2.4.10 to 2.4.20
            Release notes

            Sourced from org.jetbrains.kotlin.jvm's releases.

            Kotlin 2.4.20

            Changelog

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set

            ... (truncated)

            Changelog

            Sourced from org.jetbrains.kotlin.jvm's changelog.

            2.4.20

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set
            • KT-36740 MPP: False-positive incompatible types in .java when using expect-class returned by non-expect member from common when actual is actual typealias

            ... (truncated)

            Commits
            • 890ac1d Add Changelog for 2.4.20-RC3
            • 8860aed 🍒 [FIR] Fix suspend conversion when expected type is nullable (#7769)
            • ab5bcd9 Edit ChangeLog for 2.4.20-RC2
            • 9464edc Add ChangeLog for 2.4.20-RC2
            • 0261e43 Cherry-pick "Fix asBodyAndResultVar call in `visitInlinedLambdaInComposable...
            • 0763513 [box-tests] Workaround for klib compatibility tests (#7626)
            • 045aec6 [Wasm] Append scripts from webpack.config.d in the end of the file (#7615)
            • cd7173b 🍒 [2.4.20] [K/JS] Keep associated obj annotation only if getInstance survives...
            • d36a2ff CastsOptimizationPass: break aliases cycles (#7578)
            • 8664983 [CLI] Restore custom IC search scope creation
            • Additional commits viewable in compare view

            Updates `org.jetbrains.kotlin.plugin.serialization` from 2.4.10 to 2.4.20
            Release notes

            Sourced from org.jetbrains.kotlin.plugin.serialization's releases.

            Kotlin 2.4.20

            Changelog

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set

            ... (truncated)

            Changelog

            Sourced from org.jetbrains.kotlin.plugin.serialization's changelog.

            2.4.20

            Analysis API

            • KT-86546 Check suspicious when over ConeKotlinType in ConeTypeCompatibilityChecker
            • KT-85418 Implement an API for accessing deserialized file annotations in Analysis API
            • KT-74448 K2. False positive MISSING_DEPENDENCY_SUPERCLASS in LinkedListTest.kt, kotlinx.coroutines
            • KT-85856 containingSymbol of constructor property differs for local and non-local classes
            • KT-65417 K2 IDE: KTOR false positive expect-actual matching error on enum class because of implicit clone() in non-JVM source sets

            Analysis API. Code Compilation

            • KT-76457 K2 IDE / KMP Debugger: KISEWA “Cannot compile a common source without a JVM counterpart” on evaluating inline fun from common module inside jvm

            Analysis API. FIR

            • KT-70552 No expects for actual
            • KT-69727 K2 IDE. Wrong error in the editor on calling clone function of actual enum instance in non-jvm platform
            • KT-69726 FP errors on declaring fun clone() in actual enum in not-jvm source-set
            • KT-86014 Types are broken after remove parameter through change signature
            • KT-86363 KotlinIllegalArgumentExceptionWithAttachments: No dangling modifier found on companion blocks
            • KT-86147 Drop kotlin.parallel.resolve.under.global.lock registry key
            • KT-85543 Avoid lazy resolve for the contracts phase if no constracts might be resolved

            Analysis API. Infrastructure

            • KT-84914 Do not publish analysis-api-test-framework
            • KT-86986 kotlin-compiler-common-for-ide bundles unrelated Analysis API modules
            • KT-86186 Analysis API: Codebase tests run twice in some analysis modules — pick a single JUnit runner and migrate
            • KT-85360 Drop kotlin-compiler-testdata-for-ide artifact
            • KT-85585 Simplify the dependencies graph for the Analysis API modules
            • KT-85381 Remove tests for the FE10 implementation

            Analysis API. Light Classes

            New Features

            • KT-84645 Support resolving to companion block members & extensions from Java (light classes)
            • KT-80775 Support PsiClass#getRecordComponents in light classes

            Fixes

            • KT-57537 SLC: propagate default parameter value from (@JvmOverloads) expect declarations to actual declarations
            • KT-85040 [Analysis API] Improve Java / Kotlin interop in KMP projects
            • KT-87301 SymbolLightAccessorMethod#isValid returns false for delegated properties
            • KT-87171 SLC: non-mapped Kotlin collection supertype is dropped from supertype list
            • KT-87250 JvmExposeBoxed: light classes shouldn't be autogenerated for private declarations
            • KT-70428 AA: good code is red when a Java class extends a Kotlin class implementing MutableList by delegation
            • KT-63568 Symbol Light Classes: KtAnnotationApplicationWithArgumentsInfo.normalizedArguments() may work incorrectly when psi is not set
            • KT-36740 MPP: False-positive incompatible types in .java when using expect-class returned by non-expect member from common when actual is actual typealias

            ... (truncated)

            Commits
            • 890ac1d Add Changelog for 2.4.20-RC3
            • 8860aed 🍒 [FIR] Fix suspend conversion when expected type is nullable (#7769)
            • ab5bcd9 Edit ChangeLog for 2.4.20-RC2
            • 9464edc Add ChangeLog for 2.4.20-RC2
            • 0261e43 Cherry-pick "Fix asBodyAndResultVar call in `visitInlinedLambdaInComposable...
            • 0763513 [box-tests] Workaround for klib compatibility tests (#7626)
            • 045aec6 [Wasm] Append scripts from webpack.config.d in the end of the file (#7615)
            • cd7173b 🍒 [2.4.20] [K/JS] Keep associated obj annotation only if getInstance survives...
            • d36a2ff CastsOptimizationPass: break aliases cycles (#7578)
            • 8664983 [CLI] Restore custom IC search scope creation
            • Additional commits viewable in compare view

            Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- samples/simple-streamable-server/gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/simple-streamable-server/gradle/libs.versions.toml b/samples/simple-streamable-server/gradle/libs.versions.toml index 0102599..5f35f74 100644 --- a/samples/simple-streamable-server/gradle/libs.versions.toml +++ b/samples/simple-streamable-server/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.4.10" +kotlin = "2.4.20" ktor = "3.5.2" junit = "6.1.3" mcp-kotlin = "0.15.0"