Skip to content

0.16.0

Latest

Choose a tag to compare

@devcrocod devcrocod released this 27 Oct 17:57
· 4 commits to main since this release
Immutable release. Only release title and notes can be modified.
4c55826

Description

This release closes memory-exhaustion holes in the WebSocket and Streamable HTTP servers, deprecates the SSE transport in favor of Streamable HTTP, moves APIs deprecated in 0.9.0–0.13.0 to ERROR, and adds experimental SEP-2575 discovery types.

Breaking Changes

Streamable HTTP sessions expire when idle and are capped by @devcrocod in #1032

mcpStreamableHttp kept every session until the client sent DELETE, so an initialize flood could exhaust server memory.

  • A session expires after sessionIdleTimeout without requests (default 30 minutes; an open GET stream does not count), and its id then answers 404 Not Found. Duration.INFINITE disables expiry.
  • At most maxSessions sessions are open at once (default 10,000); a new session beyond that gets 503 Service Unavailable.
  • GET without an Mcp-Session-Id header returns 400 Bad Request.
  • StreamableHttpClientTransport reports a 404 on its GET stream through onError. It does not start a new session by itself; the application has to.
  • The JVM signature of mcpStreamableHttp changed; recompile code built against earlier versions.
application.mcpStreamableHttp(
    path = "/mcp",
    sessionIdleTimeout = 10.minutes,
    maxSessions = 1_000,
) { server }

Deprecated APIs moved to ERROR by @devcrocod in #1128

APIs deprecated in 0.9.0–0.13.0 no longer compile; existing binaries keep working.

  • StreamableHttpServerTransport() and StreamableHttpServerTransport(enableJsonResponse, …) → StreamableHttpServerTransport(Configuration(...))
  • StreamableHttpClientTransport, HttpClient.mcpStreamableHttpTransport and HttpClient.mcpStreamableHttp with reconnectionTime → the overloads taking ReconnectionOptions(initialReconnectionDelay = ...)
  • ElicitRequest.requestedSchema → (params as ElicitRequestFormParams).requestedSchema
  • ElicitRequestParams(message, requestedSchema, meta) → ElicitRequestFormParams(...)
  • ClientCapabilities(sampling: JsonObject?, …) → the constructor with typed ClientCapabilities.Sampling and ClientCapabilities.Elicitation
  • StreamableHttpServerTransport.Configuration.enableDnsRebindingProtection, allowedHosts and allowedOrigins → install(DnsRebindingProtection) on the Ktor route

StdioServerTransport(inputStream, outputStream) is now hidden: rename the named arguments to input and output. Positional calls keep compiling.

The mcpStatelessStreamableHttp overload with eventStore, at ERROR since 0.15.0, is removed. Binaries built against 0.14.0 or earlier that call it fail with NoSuchMethodError until recompiled.

- StdioServerTransport(inputStream = source, outputStream = sink)
+ StdioServerTransport(input = source, output = sink)

server/discover types extend sealed hierarchies by @Yusufihsangorgel in #893

DiscoverRequest is a new ClientRequest, DiscoverResult a new ServerResult, and Method.Defined gains ServerDiscover. Exhaustive when expressions over these types need a new branch or an else.

Features

  • Experimental (@ExperimentalMcpApi) SEP-2575 types: the server/discover request and result (DiscoverRequest, DiscoverResult, CacheScope), request-scoped metadata accessors on RequestMeta (protocolVersion, clientInfo, clientCapabilities, logLevel), and UnsupportedProtocolVersionData for the new UNSUPPORTED_PROTOCOL_VERSION (-32022) error code. These are types and codecs only; the client and server do not use them yet, by @Yusufihsangorgel in #893
  • Custom transports can report errors through the new protected AbstractTransport.invokeOnErrorCallback, which swallows exceptions thrown by the onError callback and lets cancellation propagate, by @devcrocod in #998

Changed

  • The SDK is now compiled with Kotlin language and API version 2.2 (previously 2.1), by @devcrocod in #1026

Deprecated

  • The SSE transport is deprecated in favor of Streamable HTTP, following SEP-2596; behavior is unchanged, by @devcrocod in #1130
    • SseClientTransport → StreamableHttpClientTransport
    • HttpClient.mcpSseTransport → mcpStreamableHttpTransport; HttpClient.mcpSse → mcpStreamableHttp
    • SseServerTransport and Route.mcp → StreamableHttpServerTransport
    • Application.mcp → Application.mcpStreamableHttp

Security

  • Application.mcpWebSocket now caps inbound WebSocket messages at 16 MiB; before, a single large message could exhaust server memory. With Route.mcpWebSocket, set maxFrameSize when you install WebSockets. WebSocketMcpTransport now keeps reading after a message it cannot handle instead of stalling while frames pile up, and reports such messages and failed sessions through onError, by @devcrocod in #1129
  • mcpStreamableHttp expires idle sessions and caps their number, so an initialize flood can no longer exhaust server memory (see Breaking Changes), by @devcrocod in #1032
  • SseClientTransport refuses to start when the server's endpoint event points to a different origin, so a malicious server can no longer redirect requests, and their auth headers, to another host, by @ez-lbz in #958

Fixed

  • SseClientTransport resolves relative endpoint URLs per RFC 3986, so connecting to a server mounted under a sub-path such as mcp("/api/mcp/sse") no longer fails with 404, by @gibkim in #1100
  • Application.mcp and Application.mcpStreamableHttp no longer fail with DuplicatePluginException when the SSE plugin is already installed, so one application can host several Streamable HTTP endpoints, by @soulkeykim in #1092
  • ServerSession.onInitialized callbacks registered after the handshake now run immediately, and concurrent registrations are no longer lost; a duplicate notifications/initialized no longer runs the callbacks again, by @taekop in #1019
  • prompts/get for an unknown prompt returns INVALID_PARAMS (-32602) instead of INTERNAL_ERROR (-32603), by @latent-9 in #955
  • Tasks with unlimited retention are sent with "ttl": null, as the schema requires, instead of omitting the key, by @devcrocod in #1089
  • CancellationException no longer reaches onError callbacks or the log, by @devcrocod in #998

Maintenance

  • ABI checks use the Kotlin Gradle plugin's built-in validation (checkKotlinAbi / updateKotlinAbi) instead of binary-compatibility-validator, and every module gains a klib ABI dump, by @devcrocod in #1027
  • Trimmed the test suite to tests that guard real SDK behavior and fixed tests that could not fail; a local jvmTest run went from about 40 s to 5 s, by @devcrocod in #1054
  • Removed log-message assertion tests and the Logback test dependency from the server module, by @devcrocod in #1053
  • Fixed the flaky ChannelTransportTest, by @devcrocod in #1028

Dependencies

New Contributors

Full Changelog: 0.15.0...0.16.0