fix!: Migrate Ktor extension functions from Routing to Route (#237) (#531)

# Migrate Ktor extension functions from `Routing` to `Route` (#237)

- Replaced `Routing` with `Route` in MCP-related functions for better
composability in nested contexts.
- Updated tests to verify compatibility with nested routes and subpaths.
- Deprecated legacy signatures and removed redundant overloads.

## How Has This Been Tested?
Unit test

## Breaking Changes
`Routing.mcp(...) `extension was replaced with `Route.mcp(...)`

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

## Additional context
Based on #314 by @IainHull but that PR is too outdated.
This commit is contained in:
Konstantin Pavlov 2026-02-18 16:43:37 +02:00 • committed by GitHub
commit bb79e200c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -183,6 +183,7 @@ fun main(args: Array<String>) = runBlocking {
Create an MCP server that exposes a simple tool and runs on an embedded Ktor server with SSE transport:
<!--- CLEAR -->
```kotlin
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
@ -761,14 +762,89 @@ CLI tooling that spawns a helper process. No networking setup is required.
### Streamable HTTP Transport
`StreamableHttpClientTransport` and the Ktor `streamableHttpApp()` helpers expose MCP over a single HTTP endpoint with
optional JSON-only or SSE streaming responses. This is the recommended choice for remote deployments and integrates
nicely with proxies or service meshes.
`StreamableHttpClientTransport` and the Ktor `mcpStreamableHttp()` / `mcpStatelessStreamableHttp()` helpers expose MCP
over a single HTTP endpoint with optional JSON-only or SSE streaming responses. This is the recommended choice for
remote deployments and integrates nicely with proxies or service meshes. Both accept a `path` parameter (default:
`"/mcp"`) to mount the endpoint at any URL:
<!--- CLEAR -->
<!--- INCLUDE
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.modelcontextprotocol.kotlin.sdk.server.Server
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
import io.modelcontextprotocol.kotlin.sdk.server.mcpStreamableHttp
import io.modelcontextprotocol.kotlin.sdk.types.Implementation
import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities
private class MyServer :
Server(
serverInfo = Implementation(name = "ExampleServer", version = "1.0"),
options = ServerOptions(capabilities = ServerCapabilities()),
)
fun main() {
-->
```kotlin
embeddedServer(CIO, port = 3000) {
mcpStreamableHttp(path = "/api/mcp") {
MyServer()
}
}.start(wait = true)
```
<!--- SUFFIX
}
-->
<!--- KNIT example-server-routes-01.kt -->
### SSE Transport
Server-Sent Events remain available for backwards compatibility with older MCP clients. Use `SseServerTransport` or the
SSE Ktor plugin when you need drop-in compatibility, but prefer Streamable HTTP for new projects.
Server-Sent Events remain available for backwards compatibility with older MCP clients. Two Ktor helpers are provided:
- **`Application.mcp { }`** — installs the SSE plugin automatically and registers MCP endpoints at `/`.
- **`Route.mcp { }`** — registers MCP endpoints at the current route path; requires `install(SSE)` in the application
first. Use this to host MCP alongside other routes or under a path prefix:
<!--- CLEAR -->
<!--- INCLUDE
import io.ktor.server.application.install
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.ktor.server.response.respondText
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import io.ktor.server.sse.SSE
import io.modelcontextprotocol.kotlin.sdk.server.Server
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
import io.modelcontextprotocol.kotlin.sdk.server.mcp
import io.modelcontextprotocol.kotlin.sdk.types.Implementation
import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities
private class MyServer :
Server(
serverInfo = Implementation(name = "ExampleServer", version = "1.0"),
options = ServerOptions(capabilities = ServerCapabilities()),
)
fun main() {
-->
```kotlin
embeddedServer(CIO, port = 3000) {
install(SSE)
routing {
route("/api/mcp") {
mcp { MyServer() }
}
}
}.start(wait = true)
```
<!--- SUFFIX
}
-->
<!--- KNIT example-server-routes-02.kt -->
Prefer Streamable HTTP for new projects.
### WebSocket Transport