Module kotlin-sdk-server
February 18, 2026 · View on GitHub
kotlin-sdk-server contains the server-side building blocks for Model Context Protocol (MCP) applications written in
Kotlin Multiplatform. It pairs the protocol types from kotlin-sdk-core with transport implementations and utilities
that make it straightforward to expose tools, prompts, and resources to MCP clients.
What the module provides
- Server runtime: The
Serverclass coordinates sessions, initialization flow, and capability enforcement. It tracks active sessions and cleans them up when transports close. - Feature registries: Helpers to register and remove tools, prompts, resources, and resource templates. Registry listeners emit list-changed notifications when the capability is enabled.
- Transports: Ready-to-use transports for STDIO (CLI-style hosting), Ktor Server-Sent Events (SSE) with POST
back-channel, and Ktor WebSocket. All share the common
Transportabstraction from the SDK. - Ktor integration: Extension functions (
Route.mcp,Route.mcpWebSocket, andApplicationvariants) that plug MCP into an existing Ktor server with minimal boilerplate. - Notifications: Built-in support for resource subscription, resource-updated events, and feature list change notifications when capabilities are set accordingly.
Typical server setup
- Declare capabilities your server supports using
ServerOptions. Capabilities drive which handlers are installed and whether list-change notifications are emitted. - Register features: tools, prompts, resources, and resource templates. Handlers run in suspending context and can be removed or replaced at runtime.
- Attach a transport and open a session via
createSession(transport). Multiple sessions can be active simultaneously. - Close the server to tear down transports and unsubscribe sessions.
Minimal STDIO server
val server = Server(
serverInfo = Implementation(name = "demo-server", version = "1.0.0"),
options = ServerOptions(
capabilities = ServerCapabilities(
tools = ServerCapabilities.Tools(listChanged = true)
)
)
) {
addTool(
name = "hello",
description = "Greets the caller by name"
) { request ->
val name = request.params.arguments?.get("name")?.jsonPrimitive?.content ?: "there"
CallToolResult(
content = listOf(TextContent("Hello, $name!")),
isError = false,
)
}
}
val transport = StdioServerTransport(
System.`in`.asSource().buffered(),
System.out.asSink().buffered()
)
server.createSession(transport)
Hosting with Ktor (SSE)
fun Application.module() {
mcp {
Server(
serverInfo = Implementation("ktor-sse", "1.0.0"),
options = ServerOptions(
ServerCapabilities(
prompts = ServerCapabilities.Prompts(listChanged = true),
resources = ServerCapabilities.Resources(listChanged = true, subscribe = true),
)
)
) {
addPrompt(
name = "welcome",
description = "Explain how to use the server"
) {
GetPromptResult(
description = "Welcome to the MCP server",
messages = listOf(CreateMessageResult.Message(TextContent("Try listing tools first")))
)
}
}
}
}
The SSE route exposes a streaming GET endpoint and a POST endpoint for client messages. Session affinity is maintained
by a sessionId query parameter managed by the SDK.
Hosting with Ktor (WebSocket)
fun Application.module() {
mcpWebSocket {
Server(
serverInfo = Implementation("ktor-ws", "1.0.0"),
options = ServerOptions(ServerCapabilities(tools = ServerCapabilities.Tools()))
)
}
}
mcpWebSocket installs Ktor WebSockets and wires message handling over a single bidirectional connection.
Feature registration details
- Tools:
addToolaccepts aTooldescriptor or inline parameters plus a suspend handler.removeToolandaddTools/removeToolssupport dynamic updates. - Prompts:
addPromptwires a provider that returnsGetPromptResultand optional arguments metadata. - Resources:
addResourceexposes static or generated content viaReadResourceResult;addResourcesbatch-registers. Templates and roots are also supported for structured discovery. - Instructions: Provide static text or a function via
instructionsProviderto send per-session usage guidance during initialization.
Lifecycle and diagnostics
- Sessions emit callbacks via
onConnectandonClose. DeprecatedonInitializedexists for backward compatibility; prefer session-level hooks. - The server enforces declared capabilities; attempting to register an unsupported feature throws with a descriptive message.
- Logging uses
KotlinLogging; avoid logging secrets. To inspect traffic, run the server with DEBUG level enabled.
Use this module whenever you need to expose MCP features from a Kotlin service—whether embedding in a CLI via STDIO, serving from Ktor over SSE/WebSocket, or composing transports for custom environments. Public APIs are explicit to keep server-facing contracts stable for consumers.