Mirror of https://github.com/modelcontextprotocol/kotlin-sdk — The official Kotlin SDK for Model Context Protocol servers and clients. Maintained in collaboration with JetBrains
  • Kotlin 98%
  • TypeScript 1.7%
  • Shell 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Pavel Gorgulov 74c93745cd
Proposal: DSL Builders for request types (#399)
This PR introduces type-safe DSL builders for all MCP request types,
making it easier to construct requests
  
  ### Current Solution
  
  All request types now have DSL builders:
  ```kotlin
  // Initialize request
  val request = initializeRequest {
      protocolVersion = "2024-11-05"
      capabilities {
          sampling(ClientCapabilities.sampling)
          roots(listChanged = true)
      }
      info("MyClient", "1.0.0")
  }

  // Create message request with conversation
  val messageRequest = createMessageRequest {
      maxTokens = 1000
      systemPrompt = "You are a helpful assistant"
      messages {
          user { "What is the capital of France?" }
          assistant { "The capital of France is Paris." }
          user { "What about Germany?" }
      }
  }

  // Call tool request
  val toolRequest = callToolRequest {
      name = "searchDatabase"
      arguments {
          put("query", "users")
          put("limit", 10)
      }
  }

  // Elicit request with schema
  val elicitRequest = elicitationRequest {
      message = "Please provide your contact information"
      requestedSchema {
          properties {
              put("email", JsonObject(mapOf(
                  "type" to JsonPrimitive("string"),
                  "description" to JsonPrimitive("Your email address")
              )))
          }
          required = listOf("email")
      }
  }
```

Each DSL builder includes:
  - Clear separation of required (but runtime) vs optional fields
  - Multiple usage examples
  - Concise error messages with examples when required fields are missing
  - Cross-references to related types

### Design Considerations

1. Function Naming Convention

The current naming convention (e.g., initializeRequest, callToolRequest) might be confusing since these functions don't send requests, they just build request objects.

Alternative approach: Add a build prefix to clarify intent:
  - `initializeRequest` → `buildInitializeRequest`
  - `callToolRequest` → `buildCallToolRequest`
  - `createMessageRequest` → `buildCreateMessageRequest`

This would make it clearer that these are builder functions.

2. Runtime vs Compile-Time Validation

Currently, required fields are validated at runtime in the `build()` method:

```kotlin
val request = initializeRequest {
      protocolVersion = "2024-11-05"
      // Missing required fields: capabilities, info
      // Error thrown at runtime ❌
}
```

Alternative approach: Use Compose UI style where required parameters are in the function signature:

```kotlin
fun initializeRequest(
      protocolVersion: String,
      capabilities: ClientCapabilities,
      info: Implementation,
      block: InitializeRequestBuilder.() -> Unit = {}
  ): InitializeRequest
```

```kotlin
// Usage
val request = initializeRequest(
  protocolVersion = "2024-11-05",
capabilities = ClientCapabilities(sampling =
ClientCapabilities.sampling),
  info = Implementation("MyClient", "1.0.0")
 ) {
      // Optional fields only
      meta { put("key", "value") }
}
```

Pros:
- Compile-time safety for required fields ✅
- Clear which fields are required ✅
- Better IDE autocomplete ✅

Cons:
- Multiple trailing lambdas can be confusing:

```kotlin
// When required fields include lambdas
val request = elicitationRequest(
      message = "Enter info",
      requestedSchema = { /* lambda 1 */ }
) { /* lambda 2 for optional fields */ }
```

- Less consistent DSL feel
- More verbose for simple cases
2025-11-20 19:46:07 +01:00
.github Add Ktor BOM for dependency management across all modules, run Kotlin-MCP-Server Sample (#367) 2025-11-04 11:44:39 +02:00
buildSrc Update JVM target to 11 in Gradle build configuration (#394) 2025-11-12 13:40:44 +02:00
docs Add module documentation and enhance Dokka configuration (#261) 2025-09-15 17:44:43 +02:00
gradle Bump com.vanniktech:gradle-maven-publish-plugin from 0.34.0 to 0.35.0 (#403) 2025-11-18 17:14:44 +02:00
kotlin-sdk Kotlin-MCP can't be used without ktor-bom starting from 0.7.5 (#390) (#392) 2025-11-12 15:32:54 +02:00
kotlin-sdk-client Handle additional error types in client initialization handling (#404) 2025-11-20 19:09:23 +01:00
kotlin-sdk-core Proposal: DSL Builders for request types (#399) 2025-11-20 19:46:07 +01:00
kotlin-sdk-server Add test with new schema types (#389) 2025-11-14 11:39:43 +02:00
kotlin-sdk-test Handle additional error types in client initialization handling (#404) 2025-11-20 19:09:23 +01:00
samples Add example Kotlin Notebook demonstrating MCP client (#397) 2025-11-14 16:43:55 +02:00
.editorconfig Add ktlint (#213) 2025-08-05 13:10:44 +00:00
.gitignore Update .gitignore to exclude kotlin-js-store directory (#343) 2025-10-30 13:19:06 +01:00
AGENTS.md Add AGENTS.md (#349) 2025-10-27 15:01:14 +01:00
build.gradle.kts New MCP Schema types (#386) 2025-11-11 12:25:23 +01:00
CODE_OF_CONDUCT.md Update license 2024-12-16 21:20:35 +01:00
CONTRIBUTING.md Update package name across the project (#2) 2024-12-17 07:28:51 +01:00
gradle.properties Bump version to 0.8.0-SNAPSHOT and update mcp-kotlin dependency in samples (#385) 2025-11-11 10:56:45 +02:00
gradlew Update Gradle to version 9.2.0 across all projects (#377) 2025-11-07 17:07:20 +02:00
gradlew.bat Update Gradle to version 9.2.0 across all projects (#377) 2025-11-07 17:07:20 +02:00
LICENSE Update license 2024-12-16 21:20:35 +01:00
README.md Update JVM target to 11 in Gradle build configuration (#394) 2025-11-12 13:40:44 +02:00
settings.gradle.kts Exclude samples from composite gradle build (#337) 2025-10-23 18:41:57 +02:00

MCP Kotlin SDK

Maven Central Build Kotlin Kotlin Multiplatform JVM License

Kotlin Multiplatform implementation of the Model Context Protocol (MCP), providing both client and server capabilities for integrating with LLM surfaces across various platforms.

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 SDK implements the MCP specification for Kotlin, enabling you to build applications that can communicate using MCP on the JVM, WebAssembly and iOS.

  • Build MCP clients that can connect to any MCP server
  • Create MCP servers that expose resources, prompts and tools
  • Use standard transports like stdio, SSE, and WebSocket
  • Handle all MCP protocol messages and lifecycle events

Samples

  • kotlin-mcp-server: demonstrates a multiplatform (JVM, Wasm) MCP server setup with various features and transports.
  • weather-stdio-server: shows how to build a Kotlin MCP server providing weather forecast and alerts using STDIO transport.
  • kotlin-mcp-client: demonstrates building an interactive Kotlin MCP client that connects to an MCP server via STDIO and integrates with Anthropic’s API.

Installation

Add the new repository to your build file:

repositories {
    mavenCentral()
}

Add the dependency:

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

MCP SDK uses Ktor, but does not come with a specific engine dependency. You should add Ktor client and/or Ktor server dependency to your project yourself, e.g.:

dependencies {
    // for client:
    implementation("io.ktor:ktor-client-cio:$ktorVersion")
    // for server:
    implementation("io.ktor:ktor-server-netty:$ktorVersion")
    
}

Quick Start

Creating a Client

import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.client.StdioClientTransport
import io.modelcontextprotocol.kotlin.sdk.Implementation

val client = Client(
    clientInfo = Implementation(
        name = "example-client",
        version = "1.0.0"
    )
)

val transport = StdioClientTransport(
    inputStream = processInputStream,
    outputStream = processOutputStream
)

// Connect to server
client.connect(transport)

// List available resources
val resources = client.listResources()

// Read a specific resource
val resourceContent = client.readResource(
    ReadResourceRequest(uri = "file:///example.txt")
)

Creating a Server

import io.modelcontextprotocol.kotlin.sdk.server.Server
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
import io.modelcontextprotocol.kotlin.sdk.server.StdioServerTransport
import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities

val server = Server(
    serverInfo = Implementation(
        name = "example-server",
        version = "1.0.0"
    ),
    options = ServerOptions(
        capabilities = ServerCapabilities(
            resources = ServerCapabilities.Resources(
                subscribe = true,
                listChanged = true
            )
        )
    )
){ 
    "This server provides example resources and demonstrates MCP capabilities." 
}

// Add a resource
server.addResource(
    uri = "file:///example.txt",
    name = "Example Resource",
    description = "An example text file",
    mimeType = "text/plain"
) { request ->
    ReadResourceResult(
        contents = listOf(
            TextResourceContents(
                text = "This is the content of the example resource.",
                uri = request.uri,
                mimeType = "text/plain"
            )
        )
    )
}

// Start server with stdio transport
val transport = StdioServerTransport()
server.connect(transport)

Using SSE Transport

Directly in Ktor's Application:

import io.ktor.server.application.*
import io.modelcontextprotocol.kotlin.sdk.server.mcp

fun Application.module() {
    mcp {
        Server(
            serverInfo = Implementation(
                name = "example-sse-server",
                version = "1.0.0"
            ),
            options = ServerOptions(
                capabilities = ServerCapabilities(
                    prompts = ServerCapabilities.Prompts(listChanged = null),
                    resources = ServerCapabilities.Resources(subscribe = null, listChanged = null)
                )
            ),
        ) { 
            "This SSE server provides prompts and resources via Server-Sent Events."
        }
    }
}

Inside a custom Ktor's Route:

import io.ktor.server.application.*
import io.ktor.server.sse.SSE
import io.modelcontextprotocol.kotlin.sdk.server.mcp

fun Application.module() {
    install(SSE)

    routing {
        route("myRoute") {
            mcp {
                Server(
                    serverInfo = Implementation(
                        name = "example-sse-server",
                        version = "1.0.0"
                    ),
                    options = ServerOptions(
                        capabilities = ServerCapabilities(
                            prompts = ServerCapabilities.Prompts(listChanged = null),
                            resources = ServerCapabilities.Resources(subscribe = null, listChanged = null)
                        )
                    ),
                ) {
                    "Connect via SSE to interact with this MCP server."
                }
            }
        }
    }
}

Contributing

Please see the contribution guide and the Code of conduct before contributing.

License

This project is licensed under the MIT License—see the LICENSE file for details.