К основному содержанию
правило официальный · GitHub

kotlin-mcp-server — правило для GitHub Copilot

Набор практик и паттернов для создания MCP-серверов на Kotlin через официальный SDK io.modelcontextprotocol:kotlin-sdk. Правило помогает Copilot генерировать корректный код серверов.

Установить в GitHub Copilot · Вручную: положить файлы Все способы и платформы ↓
.github/instructions/kotlin-mcp-server.instructions.md
Открыть на GitHub

Что делает kotlin-mcp-server

Правило задаёт Copilot контекст для разработки MCP-серверов на Kotlin. Внутри — паттерны работы с официальным SDK io.modelcontextprotocol:kotlin-sdk: создание сервера через класс Server, регистрация инструментов через server.addTool(), ресурсов через server.addResource() и промптов через server.addPrompt(). Все операции в SDK — suspending-функции, поэтому правило показывает, как строить код на корутинах.

Отдельный блок посвящён транспорту: stdio через StdioServerTransport для локальных серверов и SSE поверх Ktor для HTTP. Для SSE правило даёт пример с embeddedServer(Netty, port = 8080) и плагином mcp. Обработка ошибок — через try/catch с IllegalArgumentException и require() для валидации входных данных.

Правило применяется к файлам **/*.kt, **/*.kts, **/build.gradle.kts и **/settings.gradle.kts. Для работы нужно, чтобы в проекте была подключена зависимость io.modelcontextprotocol:kotlin-sdk, а для SSE-транспорта — Ktor.

Какие задачи решает

  • создать MCP-сервер на Kotlin с типизированной обработкой запросов
  • зарегистрировать инструменты через server.addTool() с JSON-схемой входных данных
  • настроить транспорт stdio или SSE поверх Ktor
  • обрабатывать ошибки валидации и возвращать isError в CallToolResult
  • организовать параллельные вызовы внутри инструмента на корутинах

Примеры запросов агенту

  • Сгенерируй каркас MCP-сервера на Kotlin с инструментом поиска по запросу и лимиту
  • Покажи, как подключить SSE-транспорт через Ktor для моего сервера
  • Добавь ресурс с чтением файла и обработкой отсутствующего пути

Как установить kotlin-mcp-server

Вручную: положить файлы

.github/instructions/kotlin-mcp-server.instructions.md

Поле applyTo задаёт, к каким файлам применять

По шагам, с командами для каждой платформы: AGENTS.md и CLAUDE.md: что это, кто читает и какой выбрать

Вопросы о kotlin-mcp-server

Как установить kotlin-mcp-server в GitHub Copilot?

Скопируй правило в файл .github/instructions/kotlin-mcp-server.instructions.md в репозитории. Copilot подхватит его автоматически для файлов **/*.kt, **/*.kts, **/build.gradle.kts и **/settings.gradle.kts.

Что делает kotlin-mcp-server?

Правило задаёт Copilot паттерны разработки MCP-серверов на Kotlin с официальным SDK. Оно покрывает создание сервера, регистрацию инструментов, ресурсов и промптов, настройку транспорта и обработку ошибок.

Что нужно для работы правила?

В проекте должна быть подключена зависимость io.modelcontextprotocol:kotlin-sdk. Для SSE-транспорта дополнительно нужен Ktor с модулями server-core, server-netty и поддержкой плагина mcp.

Исходный текст

kotlin-mcp-server.instructions.md · MIT
---
description: 'Best practices and patterns for building Model Context Protocol (MCP) servers in Kotlin using the official io.modelcontextprotocol:kotlin-sdk library.'
applyTo: "**/*.kt, **/*.kts, **/build.gradle.kts, **/settings.gradle.kts"
---

# Kotlin MCP Server Development Guidelines

When building MCP servers in Kotlin, follow these best practices and patterns using the official Kotlin SDK.

## Server Setup

Create an MCP server using the `Server` class:

```kotlin
import io.modelcontextprotocol.kotlin.sdk.server.Server
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
import io.modelcontextprotocol.kotlin.sdk.Implementation
import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities

val server = Server(
    serverInfo = Implementation(
        name = "my-server",
        version = "1.0.0"
    ),
    options = ServerOptions(
        capabilities = ServerCapabilities(
            tools = ServerCapabilities.Tools(),
            resources = ServerCapabilities.Resources(
                subscribe = true,
                listChanged = true
            ),
            prompts = ServerCapabilities.Prompts(listChanged = true)
        )
    )
) {
    "Server description goes here"
}
```

## Adding Tools

Use `server.addTool()` to register tools with typed request/response handling:

```kotlin
import io.modelcontextprotocol.kotlin.sdk.CallToolRequest
import io.modelcontextprotocol.kotlin.sdk.CallToolResult
import io.modelcontextprotocol.kotlin.sdk.TextContent

server.addTool(
    name = "search",
    description = "Search for information",
    inputSchema = buildJsonObject {
        put("type", "object")
        putJsonObject("properties") {
            putJsonObject("query") {
                put("type", "string")
                put("description", "The search query")
            }
            putJsonObject("limit") {
                put("type", "integer")
                put("description", "Maximum results to return")
            }
        }
        putJsonArray("required") {
            add("query")
        }
    }
) { request: CallToolRequest ->
    val query = request.params.arguments["query"] as? String
        ?: throw IllegalArgumentException("query is required")
    val limit = (request.params.arguments["limit"] as? Number)?.toInt() ?: 10
    
    // Perform search
    val results = performSearch(query, limit)
    
    CallToolResult(
        content = listOf(
            TextContent(
                text = results.joinToString("\n")
            )
        )
    )
}
```

## Adding Resources

Use `server.addResource()` to provide accessible data:

```kotlin
import io.modelcontextprotocol.kotlin.sdk.ReadResourceRequest
import io.modelcontextprotocol.kotlin.sdk.ReadResourceResult
import io.modelcontextprotocol.kotlin.sdk.TextResourceContents

server.addResource(
    uri = "file:///data/example.txt",
    name = "Example Data",
    description = "Example resource data",
    mimeType = "text/plain"
) { request: ReadResourceRequest ->
    val content = loadResourceContent(request.uri)
    
    ReadResourceResult(
        contents = listOf(
            TextResourceContents(
                text = content,
                uri = request.uri,
                mimeType = "text/plain"
            )
        )
    )
}
```

## Adding Prompts

Use `server.addPrompt()` for reusable prompt templates:

```kotlin
import io.modelcontextprotocol.kotlin.sdk.GetPromptRequest
import io.modelcontextprotocol.kotlin.sdk.GetPromptResult
import io.modelcontextprotocol.kotlin.sdk.PromptMessage
import io.modelcontextprotocol.kotlin.sdk.Role

server.addPrompt(
    name = "analyze",
    description = "Analyze a topic",
    arguments = listOf(
        PromptArgument(
            name = "topic",
            description = "The topic to analyze",
            required = true
        )
    )
) { request: GetPromptRequest ->
    val topic = request.params.arguments?.get("topic") as? String
        ?: throw IllegalArgumentException("topic is required")
    
    GetPromptResult(
        description = "Analyze the given topic",
        messages = listOf(
            PromptMessage(
                role = Role.User,
                content = TextContent(
                    text = "Analyze this topic: $topic"
                )
            )
        )
    )
}
```

## Transport Configuration

### Stdio Transport

For communication over stdin/stdout:

```kotlin
import io.modelcontextprotocol.kotlin.sdk.server.StdioServerTransport

suspend fun main() {
    val transport = StdioServerTransport()
    server.connect(transport)
}
```

### SSE Transport with Ktor

For HTTP-based communication using Server-Sent Events:

```kotlin
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.modelcontextprotocol.kotlin.sdk.server.mcp

fun main() {
    embeddedServer(Netty, port = 8080) {
        mcp {
            Server(
                serverInfo = Implementation(
                    name = "sse-server",
                    version = "1.0.0"
                ),
                options = ServerOptions(
                    capabilities = ServerCapabilities(
                        tools = ServerCapabilities.Tools()
                    )
                )
            ) {
                "SSE-based MCP server"
            }
        }
    }.start(wait = true)
}
```

## Coroutine Usage

All MCP operations are suspending functions. Use Kotlin coroutines properly:

```kotlin
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.async

server.addTool(
    name = "parallel-search",
    description = "Search multiple sources in parallel"
) { request ->
    coroutineScope {
        val source1 = async { searchSource1(query) }
        val source2 = async { searchSource2(query) }
        
        val results = source1.await() + source2.await()
        
        CallToolResult(
            content = listOf(TextContent(text = results.joinToString("\n")))
        )
    }
}
```

## Error Handling

Use Kotlin's exception handling and provide meaningful error messages:

```kotlin
server.addTool(
    name = "validate-input",
    description = "Process validated input"
) { request ->
    try {
        val input = request.params.arguments["input"] as? String
            ?: throw IllegalArgumentException("input is required")
        
        require(input.isNotBlank()) { "input cannot be blank" }
        
        val result = processInput(input)
        
        CallToolResult(
            content = listOf(TextContent(text = result))
        )
    } catch (e: IllegalArgumentException) {
        CallToolResult(
            isError = true,
            content = listOf(TextContent(text = "Validation error: ${e.message}"))
        )
    }
}
```

## JSON Schema with kotlinx.serialization

Use kotlinx.serialization for type-safe JSON schemas:

```kotlin
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.*

@Serializable
data class SearchInput(
    val query: String,
    val limit: Int = 10,
    val filters: List<String> = emptyList()
)

fun createToolSchema(): JsonObject = buildJsonObject {
    put("type", "object")
    putJsonObject("properties") {
        putJsonObject("query") {
            put("type", "string")
            put("description", "Search query")
        }
        putJsonObject("limit") {
            put("type", "integer")
            put("default", 10)
        }
        putJsonObject("filters") {
            put("type", "array")
            putJsonObject("items") {
                put("type", "string")
            }
        }
    }
    putJsonArray("required") {
        add("query")
    }
}
```

## Gradle Configuration

Set up your `build.gradle.kts` properly:

```kotlin
plugins {
    kotlin("jvm") version "2.1.0"
    kotlin("plugin.serialization") version "2.1.0"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.modelcontextprotocol:kotlin-sdk:0.7.2")
    
    // For client transport
    implementation("io.ktor:ktor-client-cio:3.0.0")
    
    // For server transport
    implementation("io.ktor:ktor-server-netty:3.0.0")
    
    // For JSON serialization
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
    
    // For coroutines
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
}
```

## Multiplatform Support

The Kotlin SDK supports Kotlin Multiplatform (JVM, Wasm, iOS):

```kotlin
kotlin {
    jvm()
    js(IR) {
        browser()
        nodejs()
    }
    wasmJs()
    
    sourceSets {
        commonMain.dependencies {
            implementation("io.modelcontextprotocol:kotlin-sdk:0.7.2")
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
        }
    }
}
```

## Resource Lifecycle

Handle resource updates and subscriptions:

```kotlin
server.addResource(
    uri = "file:///dynamic/data",
    name = "Dynamic Data",
    description = "Frequently updated data",
    mimeType = "application/json"
) { request ->
    // Provide current state
    ReadResourceResult(
        contents = listOf(
            TextResourceContents(
                text = getCurrentData(),
                uri = request.uri,
                mimeType = "application/json"
            )
        )
    )
}

// Notify clients when resource changes
server.notifyResourceListChanged()
```

## Testing

Test your MCP tools using Kotlin coroutines test utilities:

```kotlin
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals

class ServerTest {
    @Test
    fun testSearchTool() = runTest {
        val server = createTestServer()
        
        val request = CallToolRequest(
            params = CallToolParams(
                name = "search",
                arguments = mapOf("query" to "test", "limit" to 5)
            )
        )
        
        val result = server.callTool(request)
        
        assertEquals(false, result.isError)
        assert(result.content.isNotEmpty())
    }
}
```

## Common Patterns

### Logging

Use structured logging with a Kotlin logging library:

```kotlin
import io.github.oshai.kotlinlogging.KotlinLogging

private val logger = KotlinLogging.logger {}

server.addTool(
    name = "logged-operation",
    description = "Operation with logging"
) { request ->
    logger.info { "Tool called with args: ${request.params.arguments}" }
    
    try {
        val result = performOperation(request)
        logger.info { "Operation succeeded" }
        result
    } catch (e: Exception) {
        logger.error(e) { "Operation failed" }
        throw e
    }
}
```

### Configuration

Use data classes for configuration:

```kotlin
import kotlinx.serialization.Serializable

@Serializable
data class ServerConfig(
    val name: String = "my-server",
    val version: String = "1.0.0",
    val port: Int = 8080,
    val enableTools: Boolean = true
)

fun loadConfig(): ServerConfig {
    // Load from environment or config file
    return ServerConfig(
        name = System.getenv("SERVER_NAME") ?: "my-server",
        version = System.getenv("VERSION") ?: "1.0.0"
    )
}
```

### Dependency Injection

Use constructor injection for testability:

```kotlin
class MyServer(
    private val dataService: DataService,
    private val config: ServerConfig
) {
    fun createServer() = Server(
        serverInfo = Implementation(
            name = config.name,
            version = config.version
        )
    ) {
        "MCP Server with DI"
    }.apply {
        addTool(
            name = "fetch-data",
            description = "Fetch data using injected service"
        ) { request ->
            val data = dataService.fetchData()
            CallToolResult(
                content = listOf(TextContent(text = data))
            )
        }
    }
}
```

© github · MIT · github/awesome-copilot

Похожие правила IDE

Все правила IDE по теме «Настройка агента: память, контекст, субагенты» →

Из того же набора928

Весь набор →
localization Правило задаёт порядок локализации Markdown-документов: от выбора формата локали до проверки результата и добавления дисклеймера. ★ 40 418звёзд репо langchain-python Правило для GitHub Copilot, которое подсказывает агенту паттерны LangChain: Runnable, LCEL, чат-модели, ретриверы и векторные хранилища. Пригодится, если вы пишете на Python с LangChain. ★ 40 418звёзд репо kubernetes-manifests Задаёт стандарты оформления манифестов Kubernetes для GitHub Copilot. Помогает генерировать безопасные конфигурации с готовыми лимитами ресурсов, пробами и метками. ★ 40 418звёзд репо kubernetes-deployment-best-practices Правило помогает Copilot готовить манифесты Kubernetes с настройками проб, ресурсов, конфигурации и сетевого доступа. Пригодится при создании и проверке деплоя. ★ 40 418звёзд репо joyride-workspace-automation Настраивает GitHub Copilot для интерактивной автоматизации VS Code на ClojureScript через Joyride. Помогает писать проектные скрипты через REPL прямо внутри редактора. ★ 40 418звёзд репо joyride-user-project Правило помогает разрабатывать проекты Joyride на ClojureScript через REPL и автоматизировать VS Code. Оно пригодится, когда нужно проверить код в среде VS Code до правок файлов. ★ 40 418звёзд репо java-upgrade Правило подсказывает Copilot подключить скилл java-upgrade, когда вы меняете версию Java в Maven или Gradle. Пригодится при переходе между LTS. ★ 40 418звёзд репо java-mcp-server Набор инструкций для разработки MCP-серверов на Java с официальным MCP Java SDK 2.x. Помогает настроить сборку, транспорт и регистрацию инструментов. ★ 40 418звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой