Track MCP LogoTrack MCP
Track MCP LogoTrack MCP

The world's largest repository of Model Context Protocol servers. Discover, explore, and submit MCP tools.

Product

  • Categories
  • Top MCP
  • New & Updated
  • Submit MCP

Company

  • About

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy

© 2026 TrackMCP. All rights reserved.

Built with ❤️ by Krishna Goyal

    Kotlin Sdk

    The official Kotlin SDK for Model Context Protocol servers and clients. Maintained in collaboration with JetBrains Trusted by 1100+ developers.

    1,130 stars
    Kotlin
    Updated Nov 4, 2025
    kotlin-multiplatform
    mcp

    Table of Contents

    • Table of Contents
    • Overview
    • Installation
    • Artifacts
    • Gradle setup (JVM)
    • Multiplatform
    • Ktor dependencies
    • Quickstart
    • Creating a Client
    • Creating a Server
    • Core Concepts
    • MCP Primitives
    • Capabilities
    • Server Capabilities
    • Client Capabilities
    • Server Features
    • Prompts
    • Resources
    • Tools
    • Completion
    • Logging
    • Pagination
    • Client Features
    • Roots
    • Sampling
    • Transports
    • STDIO Transport
    • Streamable HTTP Transport
    • SSE Transport
    • WebSocket Transport
    • ChannelTransport (testing)
    • Connecting your server
    • Examples
    • Documentation
    • Contributing
    • License

    Table of Contents

    • Table of Contents
    • Overview
    • Installation
    • Artifacts
    • Gradle setup (JVM)
    • Multiplatform
    • Ktor dependencies
    • Quickstart
    • Creating a Client
    • Creating a Server
    • Core Concepts
    • MCP Primitives
    • Capabilities
    • Server Capabilities
    • Client Capabilities
    • Server Features
    • Prompts
    • Resources
    • Tools
    • Completion
    • Logging
    • Pagination
    • Client Features
    • Roots
    • Sampling
    • Transports
    • STDIO Transport
    • Streamable HTTP Transport
    • SSE Transport
    • WebSocket Transport
    • ChannelTransport (testing)
    • Connecting your server
    • Examples
    • Documentation
    • Contributing
    • License

    Documentation

    MCP Kotlin SDK

    Maven Central

    Build

    Conformance Tests

    codecov

    Kotlin

    Kotlin Multiplatform

    JVM

    License

    Ask DeepWiki

    Kotlin Multiplatform SDK for the Model Context Protocol.

    It enables Kotlin applications targeting JVM, Native, JS, and Wasm to implement MCP clients and servers using a

    standardized protocol interface.

    Table of Contents

    • Overview
    • Installation
    • Artifacts
    • Gradle setup (JVM)
    • Multiplatform
    • Ktor dependencies
    • Quickstart
    • Creating a Client
    • Creating a Server
    • Core Concepts
    • MCP Primitives
    • Capabilities
    • Server Capabilities
    • Client Capabilities
    • Server Features
    • Prompts
    • Resources
    • Tools
    • Completion
    • Logging
    • Pagination
    • Client Features
    • Roots
    • Sampling
    • Transports
    • STDIO Transport
    • Streamable HTTP Transport
    • SSE Transport
    • WebSocket Transport
    • ChannelTransport (testing)
    • Connecting your server
    • Examples
    • Documentation
    • Contributing
    • License

    Overview

    The Model Context Protocol allows applications to provide context for LLMs in a standardized way,

    separating the concerns of providing context from the actual LLM interaction.

    This Kotlin SDK implements the MCP specification, making it easy to:

    • Build MCP clients that can connect to any MCP server
    • Create MCP servers that expose resources, prompts, and tools
    • Target JVM, Native, JS, and Wasm from a single codebase
    • Use standard transports like stdio, SSE, Streamable HTTP, and WebSocket
    • Handle MCP protocol messages and lifecycle events with coroutine-friendly APIs

    Installation

    Artifacts

    • io.modelcontextprotocol:kotlin-sdk – umbrella SDK (client + server APIs)
    • io.modelcontextprotocol:kotlin-sdk-client – client-only APIs
    • io.modelcontextprotocol:kotlin-sdk-server – server-only APIs

    Gradle setup (JVM)

    Add the Maven Central repository and the SDK dependency:

    kotlin
    repositories {
        mavenCentral()
    }
    
    dependencies {
        // See the badge above for the latest version
        implementation("io.modelcontextprotocol:kotlin-sdk:$mcpVersion")
    }

    Use _kotlin-sdk-client_ or _kotlin-sdk-server_ if you only need one side of the API:

    kotlin
    dependencies {
        implementation("io.modelcontextprotocol:kotlin-sdk-client:$mcpVersion")
        implementation("io.modelcontextprotocol:kotlin-sdk-server:$mcpVersion")
    }

    Multiplatform

    In a Kotlin Multiplatform project you can add the SDK to commonMain:

    kotlin
    commonMain {
        dependencies {
            // Works as a common dependency as well as the platform one
            implementation("io.modelcontextprotocol:kotlin-sdk:$mcpVersion")
        }
    }

    Ktor dependencies

    The Kotlin MCP SDK uses Ktor, but it does not add Ktor engine dependencies transitively.

    You need to declare

    Ktor client/server

    dependencies yourself (or reuse the ones already used in your project),

    for example:

    kotlin
    dependencies {
        // MCP client with Ktor
        implementation("io.ktor:ktor-client-cio:$ktorVersion")
        implementation("io.modelcontextprotocol:kotlin-sdk-client:$mcpVersion")
    
        // MCP server with Ktor
        implementation("io.ktor:ktor-server-netty:$ktorVersion")
        implementation("io.modelcontextprotocol:kotlin-sdk-server:$mcpVersion")
    }

    Quickstart

    Let's create a simple MCP client and server to demonstrate the basic usage of the Kotlin SDK.

    Creating a Client

    Create an MCP client that connects to a server via Streamable HTTP transport and lists available tools:

    kotlin
    import io.ktor.client.HttpClient
    import io.ktor.client.plugins.sse.SSE
    import io.modelcontextprotocol.kotlin.sdk.client.Client
    import io.modelcontextprotocol.kotlin.sdk.client.StreamableHttpClientTransport
    import io.modelcontextprotocol.kotlin.sdk.types.Implementation
    import kotlinx.coroutines.runBlocking
    
    fun main(args: Array) = runBlocking {
        val url = args.firstOrNull() ?: "http://localhost:3000/mcp"
    
        val httpClient = HttpClient { install(SSE) }
    
        val client = Client(
            clientInfo = Implementation(
                name = "example-client",
                version = "1.0.0"
            )
        )
    
        val transport = StreamableHttpClientTransport(
            client = httpClient,
            url = url
        )
    
        // Connect to server
        client.connect(transport)
    
        // List available tools
        val tools = client.listTools().tools
    
        println(tools)
    }

    Creating a Server

    Create an MCP server that exposes a simple tool and runs on an embedded Ktor server with Streamable HTTP transport.

    For a full working project with all required dependencies, see

    the simple-streamable-server sample.

    kotlin
    import io.ktor.serialization.kotlinx.json.json
    import io.ktor.server.application.install
    import io.ktor.server.cio.CIO
    import io.ktor.server.engine.embeddedServer
    import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
    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.CallToolResult
    import io.modelcontextprotocol.kotlin.sdk.types.Implementation
    import io.modelcontextprotocol.kotlin.sdk.types.McpJson
    import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities
    import io.modelcontextprotocol.kotlin.sdk.types.TextContent
    import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema
    import kotlinx.serialization.json.buildJsonObject
    import kotlinx.serialization.json.put
    
    fun main(args: Array) {
        val port = args.firstOrNull()?.toIntOrNull() ?: 3000
        val mcpServer = Server(
            serverInfo = Implementation(
                name = "example-server",
                version = "1.0.0"
            ),
            options = ServerOptions(
                capabilities = ServerCapabilities(
                    tools = ServerCapabilities.Tools(listChanged = true),
                ),
            )
        )
    
        mcpServer.addTool(
            name = "example-tool",
            description = "An example tool",
            inputSchema = ToolSchema(
                properties = buildJsonObject {
                    put("input", buildJsonObject { put("type", "string") })
                }
            )
        ) { request ->
            CallToolResult(content = listOf(TextContent("Hello, world!")))
        }
    
        embeddedServer(CIO, host = "127.0.0.1", port = port) {
            install(ContentNegotiation) {
                json(McpJson)
            }
            mcpStreamableHttp {
                mcpServer
            }
        }.start(wait = true)
    }

    You can run the server and then connect to it using the client or test with the MCP Inspector:

    bash
    npx -y @modelcontextprotocol/inspector

    In the inspector UI, connect to http://localhost:3000/mcp.

    Core Concepts

    MCP Primitives

    The MCP protocol defines core primitives that enable communication between servers and clients:

    PrimitiveServer RoleClient RoleDescription
    PromptsProvides prompt templates with optional argumentsRequests and uses promptsInteractive templates for LLM interactions
    ResourcesExposes data sources (files, API responses, etc.)Reads and subscribes to resourcesContextual data for augmenting LLM context
    ToolsDefines executable functionsCalls tools to perform actionsFunctions the LLM can invoke to take actions
    SamplingRequests LLM completions from clientExecutes LLM calls and returns resultsServer-initiated LLM requests (reverse direction)

    Capabilities

    Capabilities define what features a server or client supports. They are declared during initialization and determine

    what operations are available.

    Server Capabilities

    Servers declare their capabilities to inform clients what features they provide:

    CapabilityFeature FlagsDescription
    promptslistChangedPrompt template management and notifications
    resourcessubscribelistChangedResource exposure, subscriptions, and update notifications
    toolslistChangedTool discovery, execution, and list change notifications
    logging-Server logging to client console
    completions-Argument autocompletion suggestions
    experimentalCustom propertiesNon-standard experimental features

    Client Capabilities

    Clients declare their capabilities to inform servers what features they support:

    CapabilityFeature FlagsDescription
    sampling-Client can sample from an LLM (execute model requests)
    rootslistChangedClient exposes root directories and can notify of changes
    elicitation-Client can display schema/form dialogs for structured input
    experimentalCustom propertiesNon-standard experimental features

    Server Features

    The Server API lets you wire prompts, resources, and tools with only a few lines of Kotlin. Each feature is registered

    up front and then resolved lazily when a client asks for it, so your handlers stay small and suspendable.

    Prompts

    Prompts are user-controlled templates that clients discover via prompts/list and fetch with prompts/get when a user

    chooses one (think slash commands or saved flows). They’re best for repeatable, structured starters rather than ad-hoc

    model calls.

    kotlin
    val server = Server(
        serverInfo = Implementation(
            name = "example-server",
            version = "1.0.0"
        ),
        options = ServerOptions(
            capabilities = ServerCapabilities(
                prompts = ServerCapabilities.Prompts(listChanged = true),
            ),
        )
    )
    
    server.addPrompt(
        name = "code-review",
        description = "Ask the model to review a diff",
        arguments = listOf(
            PromptArgument(name = "diff", description = "Unified diff", required = true),
        ),
    ) { request ->
        GetPromptResult(
            description = "Quick code review helper",
            messages = listOf(
                PromptMessage(
                    role = Role.User,
                    content = TextContent(text = "Review this change:\n${request.arguments?.get("diff")}"),
                ),
            ),
        )
    }

    Use prompts for anything that deserves a template: bug triage questions, onboarding checklists, or saved searches. Set

    listChanged = true only if your prompt catalog can change at runtime and your server will emit

    notifications/prompts/list_changed when it does.

    Resources

    Resources are application-driven context that clients discover via resources/list or resources/templates/list, then

    fetch with resources/read. Register each one with a stable URI and return a ReadResourceResult when asked—contents

    can be text or binary blobs.

    kotlin
    val server = Server(
        serverInfo = Implementation(
            name = "example-server",
            version = "1.0.0"
        ),
        options = ServerOptions(
            capabilities = ServerCapabilities(
                resources = ServerCapabilities.Resources(subscribe = true, listChanged = true),
            ),
        )
    )
    
    server.addResource(
        uri = "note://release/latest",
        name = "Release notes",
        description = "Last deployment summary",
        mimeType = "text/markdown",
    ) { request ->
        ReadResourceResult(
            contents = listOf(
                TextResourceContents(
                    text = "Ship 42 reached production successfully.",
                    uri = request.uri,
                    mimeType = "text/markdown",
                ),
            ),
        )
    }

    Resources can be static text, generated JSON, or blobs—anything the client can surface to the user or inject into the

    model context. Set subscribe = true if you emit notifications/resources/updated for changes to specific URIs, and

    listChanged = true if you’ll send notifications/resources/list_changed when the catalog itself changes.

    Tools

    Tools are model-controlled capabilities the client exposes to the model. Clients discover them via tools/list, invoke

    them with tools/call, and your handlers receive JSON arguments, can emit streaming logs or progress, and return a

    CallToolResult. Keep a human in the loop for sensitive operations.

    kotlin
    val server = Server(
        serverInfo = Implementation(
            name = "example-server",
            version = "1.0.0"
        ),
        options = ServerOptions(
            capabilities = ServerCapabilities(
                tools = ServerCapabilities.Tools(listChanged = true),
            ),
        )
    )
    
    server.addTool(
        name = "echo",
        description = "Return whatever the user sent back to them",
    ) { request ->
        val text = request.arguments?.get("text")?.jsonPrimitive?.content ?: "(empty)"
        CallToolResult(content = listOf(TextContent(text = "Echo: $text")))
    }

    Register as many tools as you need—long-running jobs can report progress via the request context, and tools can also

    trigger sampling (see below) when they need the client’s LLM. Set listChanged = true only if your tool catalog can

    change at runtime and your server will emit notifications/tools/list_changed when it does.

    Completion

    Completion provides argument suggestions for prompts or resource templates. Declare the completions capability and

    handle completion/complete requests to return up to 100 ranked values (include total/hasMore if you paginate).

    kotlin
    val server = Server(
        serverInfo = Implementation(
            name = "example-server",
            version = "1.0.0"
        ),
        options = ServerOptions(
            capabilities = ServerCapabilities(
                completions = ServerCapabilities.Completions,
            ),
        )
    )
    
    val session = server.createSession(
        StdioServerTransport(
            inputStream = System.`in`.asSource().buffered(),
            outputStream = System.out.asSink().buffered()
        )
    )
    
    session.setRequestHandler(Method.Defined.CompletionComplete) { request, _ ->
        val options = listOf("kotlin", "compose", "coroutine")
        val matches = options.filter { it.startsWith(request.argument.value.lowercase()) }
    
        CompleteResult(
            completion = CompleteResult.Completion(
                values = matches.take(3),
                total = matches.size,
                hasMore = matches.size > 3,
            ),
        )
    }

    Use context.arguments to refine suggestions for dependent fields (e.g., framework list filtered by chosen language).

    Logging

    Logging lets the server stream structured log notifications to the client using RFC 5424 levels (debug → emergency).

    Declare the logging capability; clients can raise the minimum level with logging/setLevel, and the server emits

    notifications/message with severity, optional logger name, and JSON data.

    kotlin
    val server = Server(
        serverInfo = Implementation("example-server", "1.0.0"),
        options = ServerOptions(
            capabilities = ServerCapabilities(
                logging = ServerCapabilities.Logging,
            ),
        )
    )
    
    val session = server.createSession(
        StdioServerTransport(
            inputStream = System.`in`.asSource().buffered(),
            outputStream = System.out.asSink().buffered()
        )
    )
    
    session.sendLoggingMessage(
        LoggingMessageNotification(
            LoggingMessageNotificationParams(
                level = LoggingLevel.Info,
                logger = "startup",
                data = buildJsonObject { put("message", "Server started") },
            ),
        ),
    )

    Keep logs free of sensitive data, and expect clients to surface them in their own UI.

    Pagination

    List operations return paginated results with an opaque nextCursor, clients echo that cursor to fetch the next page.

    Supported list calls: resources/list, resources/templates/list, prompts/list, and tools/list.

    Treat cursors as opaque—don’t parse or persist them across sessions.

    kotlin
    val server = Server(
        serverInfo = Implementation("example-server", "1.0.0"),
        options = ServerOptions(
            capabilities = ServerCapabilities(
                resources = ServerCapabilities.Resources(),
            ),
        )
    )
    
    val session = server.createSession(
        StdioServerTransport(
            inputStream = System.`in`.asSource().buffered(),
            outputStream = System.out.asSink().buffered()
        )
    )
    
    val resources = listOf(
        Resource(uri = "note://1", name = "Note 1", description = "First"),
        Resource(uri = "note://2", name = "Note 2", description = "Second"),
        Resource(uri = "note://3", name = "Note 3", description = "Third"),
    )
    val pageSize = 2
    
    session.setRequestHandler(Method.Defined.ResourcesList) { request, _ ->
        val start = request.params?.cursor?.toIntOrNull() ?: 0
        val page = resources.drop(start).take(pageSize)
        val next = if (start + page.size 
    
    Include `nextCursor` only when more items remain an absent cursor ends pagination.
    
    ### Client Features
    
    Clients advertise their capabilities (roots, sampling, elicitation, etc.) during initialization. After that they can
    serve requests from the server while still initiating calls such as `listTools` or `callTool`.
    
    #### Roots
    
    Roots let the client declare where the server is allowed to operate. Declare the `roots` capability, respond to
    `roots/list`, and emit `notifications/roots/list_changed` if you set `listChanged = true`. URIs **must** be `file://`
    paths.

    val client = Client(

    clientInfo = Implementation("demo-client", "1.0.0"),

    options = ClientOptions(

    capabilities = ClientCapabilities(roots = ClientCapabilities.Roots(listChanged = true)),

    ),

    )

    client.addRoot(

    uri = "file:///Users/demo/projects",

    name = "Projects",

    )

    client.sendRootsListChanged()

    code
    Call `addRoot`/`removeRoot` whenever your file system view changes, and use `sendRootsListChanged()` to notify the
    server. Keep root lists user-controlled and revoke entries that are no longer authorized.
    
    #### Sampling
    
    Sampling lets the server ask the client to call its preferred LLM. Declare the `sampling` capability (and
    `sampling.tools` if you allow tool-enabled sampling), and handle `sampling/createMessage`. Keep a human in the loop for
    approvals.

    val client = Client(

    clientInfo = Implementation("demo-client", "1.0.0"),

    options = ClientOptions(

    capabilities = ClientCapabilities(

    sampling = buildJsonObject { putJsonObject("tools") { } }, // drop tools if you don't support tool use

    ),

    ),

    )

    client.setRequestHandler(Method.Defined.SamplingCreateMessage) { request, _ ->

    val content = request.messages.lastOrNull()?.content

    val prompt = if (content is TextContent) content.text else "your topic"

    CreateMessageResult(

    model = "gpt-4o-mini",

    role = Role.Assistant,

    content = TextContent(text = "Here is a short note about $prompt"),

    )

    }

    code
    Inside the handler you can pick any model/provider, require approvals, or reject the request. If you don’t support tool
    use, omit `sampling.tools` from capabilities.
    
    
    
    
    
    ## Transports
    
    All transports share the same API surface, so you can change deployment style without touching business logic. Pick the
    transport that best matches where the server runs.
    
    ### STDIO Transport
    
    `StdioClientTransport` and `StdioServerTransport` tunnel MCP messages over stdin/stdout—perfect for editor plugins or
    CLI tooling that spawns a helper process. No networking setup is required.
    
    ### Streamable HTTP Transport
    
    `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:

    embeddedServer(CIO, port = 3000) {

    mcpStreamableHttp(path = "/api/mcp") {

    MyServer()

    }

    }.start(wait = true)

    code
    ### SSE Transport
    
    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:

    embeddedServer(CIO, port = 3000) {

    install(SSE)

    routing {

    route("/api/mcp") {

    mcp { MyServer() }

    }

    }

    }.start(wait = true)

    code
    Prefer Streamable HTTP for new projects.
    
    ### WebSocket Transport
    
    `WebSocketClientTransport` plus the matching server utilities provide full-duplex, low-latency connections—useful when
    you expect lots of notifications or long-running sessions behind a reverse proxy that already terminates WebSockets.
    
    ### ChannelTransport (testing)
    
    `ChannelTransport` provides a simple, non-networked transport for testing and local development.
    It uses Kotlin coroutines channels to provide a full-duplex connection between a client and server,
    allowing for easy testing of MCP functionality without the need for network setup.
    
    ## Connecting your server
    
    1. Start a sample HTTP server on port 3000:

    ./gradlew :samples:kotlin-mcp-server:run

    code
    2. Connect with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) or Claude Desktop/Code:

    npx -y @modelcontextprotocol/inspector --connect http://localhost:3000

    # or

    claude mcp add --transport http kotlin-mcp http://localhost:3000

    code
    3. In the Inspector, confirm prompts, tools, resources, completions, and logs show up. Iterate locally until you’re
       ready to host the server wherever you prefer.
    
    ## Examples
    
    The [samples](./samples) directory contains runnable projects demonstrating
    MCP server and client implementations with various transports.
    See the [samples overview](./samples/README.md) for a comparison table and detailed descriptions.
    
    ## Documentation
    
    - [API Reference](https://kotlin.sdk.modelcontextprotocol.io/)
    - [Model Context Protocol documentation](https://modelcontextprotocol.io)
    - [MCP specification](https://modelcontextprotocol.io/specification/latest)
    
    ## Contributing
    
    Please see the [contribution guide](CONTRIBUTING.md) and the [Code of conduct](CODE_OF_CONDUCT.md) before contributing.
    
    ## License
    
    This project is licensed under Apache 2.0 for new contributions, with existing code under MIT—see the [LICENSE](LICENSE)
    file for details.

    Similar MCP

    Based on tags & features

    • MC

      Mcpjungle

      Go·
      617
    • AN

      Anyquery

      Go·
      1.4k
    • MC

      Mcp Server Kubernetes

      TypeScript·
      1.1k
    • WE

      Web Eval Agent

      Python·
      1.2k

    Trending MCP

    Most active this week

    • PL

      Playwright Mcp

      TypeScript·
      22.1k
    • SE

      Serena

      Python·
      14.5k
    • MC

      Mcp Playwright

      TypeScript·
      4.9k
    • MC

      Mcp Server Cloudflare

      TypeScript·
      3.0k
    View All MCP Servers

    Similar MCP

    Based on tags & features

    • MC

      Mcpjungle

      Go·
      617
    • AN

      Anyquery

      Go·
      1.4k
    • MC

      Mcp Server Kubernetes

      TypeScript·
      1.1k
    • WE

      Web Eval Agent

      Python·
      1.2k

    Trending MCP

    Most active this week

    • PL

      Playwright Mcp

      TypeScript·
      22.1k
    • SE

      Serena

      Python·
      14.5k
    • MC

      Mcp Playwright

      TypeScript·
      4.9k
    • MC

      Mcp Server Cloudflare

      TypeScript·
      3.0k