Compare commits
320 changed files with 8397 additions and 27484 deletions
|
|
@ -1,81 +0,0 @@
|
|||
---
|
||||
name: kdoc
|
||||
description: "Add KDoc documentation to Kotlin public API. Use whenever the user asks to document Kotlin code, add KDoc, generate API docs, mentions undocumented public declarations, or wants to improve existing documentation. Also trigger when the user says 'add docs', 'document this class/file/module', 'write KDoc', or asks about missing documentation in Kotlin code."
|
||||
---
|
||||
|
||||
# KDoc Generator
|
||||
|
||||
Add KDoc to all public Kotlin declarations (classes, interfaces, objects, functions, properties, enums, type aliases, annotations — including `@Deprecated`). Read the implementation, not just the signature, to write accurate descriptions.
|
||||
|
||||
## Tag placement
|
||||
|
||||
| Where the declaration lives | Tag |
|
||||
|---|---|
|
||||
| Primary-ctor `val` / `var` (public, internal, or protected) | `@property` in class KDoc |
|
||||
| Primary-ctor `name: Type` (no `val`/`var`) | `@param` in class KDoc |
|
||||
| Primary-ctor `private val` / `private var` | `@param` in class KDoc |
|
||||
| Body of class/object/interface/sealed interface | inline `/** */` above the declaration |
|
||||
| Function parameter | `@param` |
|
||||
| Non-Unit return type | `@return` |
|
||||
|
||||
## Style
|
||||
|
||||
- Summary: one concise sentence, third-person verb ("Creates", "Returns", "Represents"). Expand to 2-3 sentences only when genuinely complex.
|
||||
- **Example block**: mandatory for DSL builders (show full receiver-scope usage); add for complex functions or non-obvious extension functions; skip for one-liners and simple getters.
|
||||
- KDoc links (`[ClassName]`, `[methodName]`) only where they add navigational value.
|
||||
- Don't write `@throws` or "suspend" notes.
|
||||
- Rewrite existing KDoc if incomplete or low quality.
|
||||
|
||||
## Examples
|
||||
|
||||
**Class with mixed primary-constructor parameters:**
|
||||
|
||||
````kotlin
|
||||
/**
|
||||
* Manages active client sessions and their lifecycle.
|
||||
*
|
||||
* @property maxSessions upper limit on concurrent sessions
|
||||
* @param scope coroutine scope for session lifecycle tasks
|
||||
* @param secret used internally for session token signing
|
||||
*/
|
||||
public class SessionManager(
|
||||
public val maxSessions: Int, // public val → @property
|
||||
scope: CoroutineScope, // no val/var → @param
|
||||
private val secret: ByteArray, // private val → @param
|
||||
)
|
||||
````
|
||||
|
||||
**Body and interface properties (inline `/** */`):**
|
||||
|
||||
````kotlin
|
||||
/** Represents an entity that includes additional metadata. */
|
||||
public interface WithMeta {
|
||||
/** Optional metadata attached to this entity. */
|
||||
public val meta: JsonObject?
|
||||
}
|
||||
|
||||
public class Connection(public val id: String) {
|
||||
/** Capabilities negotiated during the handshake, or `null` before initialize completes. */
|
||||
public val capabilities: ServerCapabilities? get() = ...
|
||||
}
|
||||
````
|
||||
|
||||
**Function with Example block:**
|
||||
|
||||
````kotlin
|
||||
/**
|
||||
* Registers a new tool with the given handler.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* server.addTool(name = "echo", description = "Echoes input back") { request ->
|
||||
* CallToolResult(content = listOf(TextContent("Echo: ${request.arguments}")))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param name unique tool identifier
|
||||
* @param description human-readable tool description
|
||||
* @param handler suspend function invoked when the tool is called
|
||||
* @return the registered tool definition
|
||||
*/
|
||||
````
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
---
|
||||
name: mcp-docs
|
||||
description: >
|
||||
Fetch live MCP specification and docs from modelcontextprotocol.io. Training data may be
|
||||
outdated — default to using this skill when the query touches MCP protocol in any way.
|
||||
Trigger for: implementing or debugging MCP features (sampling, elicitation, completion, tools,
|
||||
resources, prompts, transports); SEPs or spec requirements; MCP transport behavior (SSE,
|
||||
Streamable HTTP, reconnection, retry); authorization/OAuth; conformance test failures;
|
||||
capability negotiation; message schemas. Skip only for pure Kotlin, build system, or
|
||||
refactoring tasks with zero MCP protocol dependency. When in doubt, trigger.
|
||||
user_invocable: true
|
||||
---
|
||||
|
||||
# MCP Documentation Skill
|
||||
|
||||
Provides access to the official MCP specification and docs from modelcontextprotocol.io. The spec evolves faster than training data — always consult live documentation for protocol specifics like message schemas, required fields, capability negotiation, error handling, and transport requirements.
|
||||
|
||||
## When to use
|
||||
|
||||
**Proactively** (without being asked):
|
||||
- Implementing a feature defined in the MCP spec
|
||||
- Reviewing code that implements MCP protocol behavior
|
||||
- Fixing conformance test failures
|
||||
|
||||
**On demand** (user asks or invokes `/mcp-docs`):
|
||||
- Questions about how a specific MCP feature works
|
||||
- Clarifying spec ambiguities
|
||||
- Looking up SEPs (Specification Enhancement Proposals)
|
||||
|
||||
## How to fetch documentation
|
||||
|
||||
### Strategy: MCP tool first, llms.txt fallback
|
||||
|
||||
**Step 1 — Try the MCP search tool.** If `search_model_context_protocol` is available, use it:
|
||||
|
||||
```
|
||||
search_model_context_protocol(query: "<your search query>")
|
||||
```
|
||||
|
||||
One call, semantically ranked results. Fastest path.
|
||||
|
||||
**Step 2 — Fallback to llms.txt + WebFetch.** If the MCP tool is not available:
|
||||
|
||||
1. Fetch the documentation index:
|
||||
```
|
||||
WebFetch("https://modelcontextprotocol.io/llms.txt", "Return the full content as-is")
|
||||
```
|
||||
|
||||
2. Identify the relevant page URL(s) from the index. Key sections:
|
||||
- **Specification**: `specification/...` — protocol details, message formats, transports, lifecycle
|
||||
- **SEPs**: `seps/...` — specification enhancement proposals
|
||||
- **Learning**: `docs/learn/...` — architecture, concepts
|
||||
- **Development**: `docs/develop/...` — building clients/servers
|
||||
|
||||
3. Fetch the specific page:
|
||||
```
|
||||
WebFetch("<page-url>", "Return the full content of this documentation page")
|
||||
```
|
||||
|
||||
### Version handling
|
||||
|
||||
Always use the latest spec version by default. Only use a specific version or draft when the user explicitly requests it (e.g., "check the 2025-03-26 spec" or "what does the draft say").
|
||||
|
||||
### Search guidance
|
||||
|
||||
- Protocol message formats, required fields, capability negotiation → **Specification** section
|
||||
- Feature motivation, design rationale → relevant **SEP**
|
||||
- High-level concepts and architecture → **Learning** resources
|
||||
- Use your judgment on query count. A field-level question may need one page; implementing a feature may need 2-3.
|
||||
|
||||
## Presenting information
|
||||
|
||||
- **Always cite sources.** Include links to spec pages used: `(source: <url>)`
|
||||
- **Spec over training data** for specific protocol details (schemas, fields, error codes, capabilities). Training data is fine for general MCP concepts.
|
||||
- **Preserve RFC 2119 language.** The spec uses MUST/SHOULD/MAY — keep this distinction when explaining requirements.
|
||||
- **Be concise.** Focus on the details relevant to the user's task. Avoid dumping entire spec pages — extract what matters for the specific question or implementation at hand.
|
||||
93
.github/dependabot.yml
vendored
93
.github/dependabot.yml
vendored
|
|
@ -1,109 +1,20 @@
|
|||
# yaml-language-server: $schema=https://json.schemastore.org/dependabot-2.0.json
|
||||
# Configuration: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
# Configuration options:
|
||||
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#about-the-dependabotyml-file
|
||||
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
# Root Gradle project (includes buildSrc)
|
||||
- package-ecosystem: "gradle"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
commit-message:
|
||||
prefix: "chore(deps):"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "kotlin"
|
||||
open-pull-requests-limit: 10
|
||||
groups:
|
||||
ktor:
|
||||
patterns:
|
||||
- "io.ktor:*"
|
||||
kotlinx:
|
||||
patterns:
|
||||
- "org.jetbrains.kotlinx:*"
|
||||
kotlin:
|
||||
patterns:
|
||||
- "org.jetbrains.kotlin:*"
|
||||
kotest:
|
||||
patterns:
|
||||
- "io.kotest:*"
|
||||
testing:
|
||||
patterns:
|
||||
- "io.mockk:*"
|
||||
- "dev.mokksy:*"
|
||||
- "org.awaitility:*"
|
||||
- "org.junit.jupiter:*"
|
||||
infrastructure:
|
||||
patterns:
|
||||
- "io.netty:*"
|
||||
- "io.github.oshai:*"
|
||||
- "org.slf4j:*"
|
||||
gradle-plugins:
|
||||
patterns:
|
||||
- "dev.detekt"
|
||||
- "org.jetbrains.kotlinx.kover"
|
||||
- "org.jlleitschuh.gradle.ktlint"
|
||||
- "org.jetbrains.kotlinx.knit"
|
||||
- "org.jetbrains.kotlinx.binary-compatibility-validator"
|
||||
- "org.openapi.generator"
|
||||
- "org.jetbrains.dokka:*"
|
||||
- "com.vanniktech:*"
|
||||
|
||||
# Samples (independent Gradle builds)
|
||||
- package-ecosystem: "gradle"
|
||||
directories:
|
||||
- "/samples/*"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
commit-message:
|
||||
prefix: "chore(deps):"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "kotlin"
|
||||
- "samples"
|
||||
open-pull-requests-limit: 10
|
||||
groups:
|
||||
other-dependencies:
|
||||
patterns:
|
||||
- "*"
|
||||
exclude-patterns:
|
||||
- "io.ktor*"
|
||||
- "org.jetbrains.kotlin*"
|
||||
- "io.modelcontextprotocol*"
|
||||
|
||||
# npm (integration tests)
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/integration-test/src/jvmTest/typescript"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
commit-message:
|
||||
prefix: "chore(deps):"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "javascript"
|
||||
open-pull-requests-limit: 10
|
||||
groups:
|
||||
all-dependencies:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
# GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
commit-message:
|
||||
prefix: "chore(deps):"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "github-actions"
|
||||
open-pull-requests-limit: 10
|
||||
groups:
|
||||
all-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
|
|
|||
15
.github/workflows/apidocs.yaml
vendored
15
.github/workflows/apidocs.yaml
vendored
|
|
@ -24,27 +24,30 @@ jobs:
|
|||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true # Fetch Hugo themes (true OR recursive)
|
||||
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
|
||||
|
||||
- name: Set up JDK ${{ env.JAVA_VERSION }}
|
||||
uses: actions/setup-java@v6
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
cache: gradle
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Generate Dokka Site
|
||||
run: |-
|
||||
./gradlew knit docs:classes docs:knitCheck dokkaGenerate
|
||||
./gradlew clean knit docs:classes docs:knitCheck dokkaGenerate
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v5
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: build/dokka/html
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v5
|
||||
uses: actions/deploy-pages@v4
|
||||
|
|
|
|||
4
.github/workflows/automations.yml
vendored
4
.github/workflows/automations.yml
vendored
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
name: Mark/unmark stale PRs and issues
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v11
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
debug-only: ${{ env.DRY_RUN }}
|
||||
exempt-draft-pr: true
|
||||
|
|
@ -66,7 +66,7 @@ jobs:
|
|||
name: Close stale PRs and issues
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v11
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
debug-only: ${{ env.DRY_RUN }}
|
||||
only-labels: 'stale'
|
||||
|
|
|
|||
81
.github/workflows/build.yml
vendored
81
.github/workflows/build.yml
vendored
|
|
@ -13,12 +13,14 @@ concurrency:
|
|||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
checks: write
|
||||
pull-requests: write # only required if `comment: true` was enabled
|
||||
|
||||
env:
|
||||
JAVA_VERSION: 21
|
||||
JAVA_DISTRIBUTION: temurin
|
||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
||||
JAVA_OPTS: "-Dfile.encoding=UTF-8 -Djava.awt.headless=true"
|
||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dkotlin.compiler.execution.strategy=in-process"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -34,26 +36,31 @@ jobs:
|
|||
include:
|
||||
- os: ubuntu-latest
|
||||
job-name: "Linux Tests"
|
||||
gradle-tasks: "build"
|
||||
gradle-tasks: "build ktlintCheck koverLog koverHtmlReport koverXmlReport publishToMavenLocal -Pversion=1-SNAPSHOT"
|
||||
max-workers: 3
|
||||
|
||||
- os: windows-latest
|
||||
job-name: "Windows Tests"
|
||||
gradle-tasks: "jvmTest -x :integration-test:jvmTest"
|
||||
max-workers: 3
|
||||
|
||||
- os: macos-latest
|
||||
job-name: "iOS Simulator tests"
|
||||
gradle-tasks: "iosSimulatorArm64Test"
|
||||
gradle-tasks: "linkIosSimulatorArm64 iosSimulatorArm64Test"
|
||||
max-workers: 2
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK ${{ env.JAVA_VERSION }}
|
||||
uses: actions/setup-java@v6
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
|
||||
- name: Set up Node.js
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
uses: actions/setup-node@v7
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22' # increase only after https://github.com/nodejs/node/issues/56645 will be fixed
|
||||
|
||||
|
|
@ -63,30 +70,24 @@ jobs:
|
|||
run: npm ci
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
with:
|
||||
validate-wrappers: true
|
||||
add-job-summary: 'always'
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-home-cache-includes: |
|
||||
caches
|
||||
notifications
|
||||
sdks
|
||||
../.konan/**
|
||||
|
||||
- name: ${{ matrix.job-name }}
|
||||
run: |-
|
||||
./gradlew ${{ matrix.gradle-tasks }} --max-workers ${{ matrix.max-workers }} --continue --rerun-tasks
|
||||
|
||||
- name: Coverage Report
|
||||
if: ${{ success() && matrix.os == 'ubuntu-latest' }}
|
||||
run: ./gradlew koverLog koverHtmlReport koverXmlReport
|
||||
|
||||
- name: Publish to Maven Local
|
||||
if: ${{ success() && matrix.os == 'ubuntu-latest' }}
|
||||
run: ./gradlew publishToMavenLocal -Pversion=1-SNAPSHOT
|
||||
./gradlew ${{ matrix.gradle-tasks }} -x :conformance-test:test --max-workers ${{ matrix.max-workers }} --continue --rerun-tasks --configure-on-demand --parallel
|
||||
|
||||
- name: Upload Reports
|
||||
if: failure()
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: reports-build-${{ matrix.os }}
|
||||
|
|
@ -99,16 +100,34 @@ jobs:
|
|||
with:
|
||||
annotate_only: true
|
||||
detailed_summary: true
|
||||
flaky_summary: true
|
||||
group_suite: true
|
||||
include_empty_in_summary: false
|
||||
include_time_in_summary: true
|
||||
report_paths: '**/test-results/**/TEST-*.xml'
|
||||
truncate_stack_traces: false
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
if: ${{ !cancelled() && matrix.os == 'ubuntu-latest' }}
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
report_type: coverage
|
||||
directory: ./build/reports/kover
|
||||
files: report.xml
|
||||
|
||||
- name: Upload test results to Codecov
|
||||
if: ${{ !cancelled() && matrix.os == 'ubuntu-latest' }}
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
report_type: test_results
|
||||
|
||||
|
||||
- name: Archive Maven Local Repository
|
||||
if: ${{ success() && matrix.os == 'ubuntu-latest' }}
|
||||
run: |
|
||||
cd ~/.m2/repository/io/modelcontextprotocol && zip -r $GITHUB_WORKSPACE/local-maven-repository.zip .
|
||||
cd ~/.m2/repository && zip -r $GITHUB_WORKSPACE/local-maven-repository.zip .
|
||||
|
||||
- name: Upload Maven Local Repository
|
||||
if: ${{ success() && matrix.os == 'ubuntu-latest' }}
|
||||
|
|
@ -126,20 +145,21 @@ jobs:
|
|||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK ${{ env.JAVA_VERSION }}
|
||||
uses: actions/setup-java@v6
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
with:
|
||||
validate-wrappers: true
|
||||
add-job-summary: 'always'
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
gradle-home-cache-includes: |
|
||||
caches
|
||||
notifications
|
||||
|
|
@ -148,36 +168,35 @@ jobs:
|
|||
|
||||
- name: Run Knit
|
||||
run: |-
|
||||
./gradlew knit docs:classes docs:knitCheck --max-workers 3 --continue --rerun-tasks
|
||||
./gradlew knit docs:classes docs:knitCheck -x :conformance-test:test --max-workers 3 --continue --rerun-tasks --configure-on-demand --parallel
|
||||
|
||||
|
||||
samples:
|
||||
needs: [ build ]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sample:
|
||||
- kotlin-mcp-client
|
||||
- kotlin-mcp-server
|
||||
- simple-streamable-server
|
||||
- weather-stdio-server
|
||||
|
||||
name: "Build Sample: ${{ matrix.sample }}"
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
JAVA_OPTS: "-Xmx8g -Dfile.encoding=UTF-8 -Djava.awt.headless=true -Dkotlin.daemon.jvm.options=-Xmx6g"
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK ${{ env.JAVA_VERSION }}
|
||||
uses: actions/setup-java@v6
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
with:
|
||||
add-job-summary: 'always'
|
||||
cache-read-only: true
|
||||
|
|
@ -195,8 +214,8 @@ jobs:
|
|||
|
||||
- name: Extract Maven Local Repository
|
||||
run: |
|
||||
mkdir -p ~/.m2/repository/io/modelcontextprotocol
|
||||
unzip -o local-maven-repository.zip -d ~/.m2/repository/io/modelcontextprotocol
|
||||
mkdir -p ~/.m2/repository
|
||||
unzip -o local-maven-repository.zip -d ~/.m2/repository
|
||||
|
||||
- name: "Build Sample: ${{ matrix.sample }}"
|
||||
working-directory: ./samples/${{ matrix.sample }}
|
||||
|
|
|
|||
48
.github/workflows/codeql.yml
vendored
48
.github/workflows/codeql.yml
vendored
|
|
@ -1,14 +1,16 @@
|
|||
name: "CodeQL Advanced"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
schedule:
|
||||
- cron: '0 7 * * 1' # Monday 8:00 CET (7:00 UTC)
|
||||
- cron: '0 4 * * 0'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
env:
|
||||
JAVA_VERSION: 21
|
||||
|
|
@ -16,42 +18,64 @@ env:
|
|||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
name: Analyze (${{ matrix.language }})
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ java-kotlin ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v7
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK ${{ env.JAVA_VERSION }}
|
||||
uses: actions/setup-java@v6
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4.38.0
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: java-kotlin
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: manual
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
with:
|
||||
validate-wrappers: true
|
||||
cache-read-only: true
|
||||
|
||||
- name: Build Kotlin sources
|
||||
run: |
|
||||
./gradlew compileKotlinJvm :conformance-test:compileKotlin \
|
||||
./gradlew \
|
||||
:kotlin-sdk-core:compileKotlinJvm \
|
||||
:kotlin-sdk-client:compileKotlinJvm \
|
||||
:kotlin-sdk-server:compileKotlinJvm \
|
||||
:kotlin-sdk:compileKotlinJvm \
|
||||
:integration-test:compileKotlinJvm \
|
||||
:conformance-test:testClasses \
|
||||
detekt \
|
||||
-Pkotlin.incremental=false \
|
||||
--no-daemon --rerun-tasks --stacktrace
|
||||
--no-daemon --stacktrace --rerun-tasks
|
||||
|
||||
- name: Analyze
|
||||
uses: github/codeql-action/analyze@v4.38.0
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: '/language:java-kotlin'
|
||||
category: '/language:${{ matrix.language }}'
|
||||
|
|
|
|||
183
.github/workflows/conformance.yml
vendored
183
.github/workflows/conformance.yml
vendored
|
|
@ -7,166 +7,67 @@ on:
|
|||
push:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
JAVA_VERSION: '21'
|
||||
JAVA_DISTRIBUTION: temurin
|
||||
NODE_VERSION: '22'
|
||||
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
# Cancel only when the run is NOT on `main` branch
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
jobs:
|
||||
server:
|
||||
runs-on: ubuntu-latest
|
||||
name: Conformance Server Tests
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew :conformance-test:installDist
|
||||
|
||||
- name: Start server
|
||||
run: |
|
||||
MCP_PORT=3001 conformance-test/build/install/conformance-test/bin/conformance-test &
|
||||
for i in $(seq 1 30); do
|
||||
if curl -s -o /dev/null http://localhost:3001/mcp; then
|
||||
echo "Server is ready"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
- name: Run conformance tests
|
||||
uses: modelcontextprotocol/conformance@v0.1.16
|
||||
with:
|
||||
mode: server
|
||||
url: http://localhost:3001/mcp
|
||||
suite: active
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
expected-failures: ./conformance-test/conformance-baseline.yml
|
||||
|
||||
client:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Conformance Client Tests: ${{ matrix.scenario }}"
|
||||
run-conformance:
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Run Conformance Tests on ${{ matrix.os }}
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
JAVA_OPTS: "-Xmx8g -Dfile.encoding=UTF-8 -Djava.awt.headless=true -Dkotlin.daemon.jvm.options=-Xmx6g"
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
scenario:
|
||||
- initialize
|
||||
- tools_call
|
||||
- elicitation-sep1034-client-defaults
|
||||
- sse-retry
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
max-workers: 3
|
||||
- os: windows-latest
|
||||
max-workers: 3
|
||||
- os: macos-latest
|
||||
max-workers: 2
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v6
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22' # increase only after https://github.com/nodejs/node/issues/56645 will be fixed
|
||||
|
||||
- name: Setup Conformance Tests
|
||||
working-directory: conformance-test
|
||||
run: |-
|
||||
npm install -g @modelcontextprotocol/conformance@0.1.8
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
with:
|
||||
add-job-summary: 'always'
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
gradle-home-cache-includes: |
|
||||
caches
|
||||
notifications
|
||||
sdks
|
||||
../.konan/**
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew :conformance-test:installDist
|
||||
- name: Run Conformance Tests
|
||||
run: |-
|
||||
./gradlew :conformance-test:test --no-daemon --max-workers ${{ matrix.max-workers }}
|
||||
|
||||
- name: Run conformance tests
|
||||
uses: modelcontextprotocol/conformance@v0.1.16
|
||||
- name: Upload Conformance Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
mode: client
|
||||
command: conformance-test/build/install/conformance-test/bin/conformance-client
|
||||
scenario: ${{ matrix.scenario }}
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
expected-failures: ./conformance-test/conformance-baseline.yml
|
||||
|
||||
auth:
|
||||
runs-on: ubuntu-latest
|
||||
name: Conformance Auth Tests
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew :conformance-test:installDist
|
||||
|
||||
- name: Run conformance tests
|
||||
uses: modelcontextprotocol/conformance@v0.1.16
|
||||
with:
|
||||
mode: client
|
||||
command: conformance-test/build/install/conformance-test/bin/conformance-client
|
||||
suite: auth
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
expected-failures: ./conformance-test/conformance-baseline.yml
|
||||
|
||||
auth-scenarios:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Conformance Auth Scenario: ${{ matrix.scenario }}"
|
||||
timeout-minutes: 20
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
scenario:
|
||||
- auth/client-credentials-jwt
|
||||
- auth/client-credentials-basic
|
||||
- auth/cross-app-access-complete-flow
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
with:
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew :conformance-test:installDist
|
||||
|
||||
- name: Run conformance tests
|
||||
uses: modelcontextprotocol/conformance@v0.1.16
|
||||
with:
|
||||
mode: client
|
||||
command: conformance-test/build/install/conformance-test/bin/conformance-client
|
||||
scenario: ${{ matrix.scenario }}
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
expected-failures: ./conformance-test/conformance-baseline.yml
|
||||
name: conformance-results-${{ matrix.os }}
|
||||
path: conformance-test/results/
|
||||
|
|
|
|||
23
.github/workflows/dependabot-auto-merge.yml
vendored
23
.github/workflows/dependabot-auto-merge.yml
vendored
|
|
@ -1,23 +0,0 @@
|
|||
name: Auto-merge Dependabot
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
auto-merge:
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dependabot/fetch-metadata@v3
|
||||
id: metadata
|
||||
|
||||
- if: >-
|
||||
steps.metadata.outputs.package-ecosystem == 'github_actions' ||
|
||||
steps.metadata.outputs.package-ecosystem == 'npm_and_yarn'
|
||||
run: gh pr merge --auto --squash "$PR_URL"
|
||||
env:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
38
.github/workflows/gradle-publish.yml
vendored
38
.github/workflows/gradle-publish.yml
vendored
|
|
@ -1,3 +1,10 @@
|
|||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
|
||||
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
|
||||
|
||||
name: Release
|
||||
|
||||
on:
|
||||
|
|
@ -10,30 +17,39 @@ jobs:
|
|||
runs-on: macos-latest
|
||||
environment: release
|
||||
env:
|
||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
||||
JAVA_OPTS: "-Xmx4g -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=768m -Djava.awt.headless=true"
|
||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dkotlin.compiler.execution.strategy=in-process"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v6
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: '22' # increase only after https://github.com/nodejs/node/issues/56645 will be fixed
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Check
|
||||
run: ./gradlew check --no-configuration-cache
|
||||
- name: Clean Build with Gradle
|
||||
run: ./gradlew clean build -x :conformance-test:test --rerun-tasks --max-workers 2 --continue --configure-on-demand --parallel
|
||||
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@v6
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
annotate_only: true
|
||||
detailed_summary: true
|
||||
flaky_summary: true
|
||||
group_suite: true
|
||||
include_empty_in_summary: false
|
||||
include_time_in_summary: true
|
||||
report_paths: '**/test-results/**/TEST-*.xml'
|
||||
truncate_stack_traces: false
|
||||
|
||||
- name: Publish to Maven Central Portal
|
||||
id: publish
|
||||
|
|
|
|||
14
.github/workflows/samples.yml
vendored
14
.github/workflows/samples.yml
vendored
|
|
@ -19,7 +19,6 @@ concurrency:
|
|||
env:
|
||||
JAVA_VERSION: 21
|
||||
JAVA_DISTRIBUTION: temurin
|
||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -30,22 +29,23 @@ jobs:
|
|||
sample:
|
||||
- kotlin-mcp-client
|
||||
- kotlin-mcp-server
|
||||
- simple-streamable-server
|
||||
- weather-stdio-server
|
||||
|
||||
name: Build Sample (${{ matrix.sample }})
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
JAVA_OPTS: "-Xmx8g -Dfile.encoding=UTF-8 -Djava.awt.headless=true -Dkotlin.daemon.jvm.options=-Xmx6g"
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK ${{ env.JAVA_VERSION }}
|
||||
uses: actions/setup-java@v6
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: ${{ env.JAVA_VERSION }}
|
||||
distribution: ${{ env.JAVA_DISTRIBUTION }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6.3.0
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
with:
|
||||
validate-wrappers: true
|
||||
add-job-summary: 'always'
|
||||
|
|
@ -53,10 +53,10 @@ jobs:
|
|||
|
||||
- name: "Build Sample: ${{ matrix.sample }}"
|
||||
working-directory: ./samples/${{ matrix.sample }}
|
||||
run: ./gradlew build
|
||||
run: ./gradlew --no-daemon build
|
||||
|
||||
- name: Upload Reports
|
||||
if: failure()
|
||||
if: ${{ !cancelled() }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: reports-samples-${{ matrix.sample }}
|
||||
|
|
|
|||
9
.idea/detekt.xml
generated
Normal file
9
.idea/detekt.xml
generated
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DetektPluginSettings">
|
||||
<option name="enableDetekt" value="true" />
|
||||
<option name="enableForProjectResult" value="Accepted" />
|
||||
<option name="redirectChannels" value="true" />
|
||||
<option name="treatAsErrors" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/externalDependencies.xml
generated
Normal file
7
.idea/externalDependencies.xml
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalDependencies">
|
||||
<plugin id="detekt" />
|
||||
<plugin id="com.nbadal.ktlint" />
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/ktlint-plugin.xml
generated
Normal file
7
.idea/ktlint-plugin.xml
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="com.nbadal.ktlint.KtlintProjectSettings">
|
||||
<ktlintMode>DISTRACT_FREE</ktlintMode>
|
||||
<ktlintRulesetVersion>DEFAULT</ktlintRulesetVersion>
|
||||
</component>
|
||||
</project>
|
||||
372
AGENTS.md
372
AGENTS.md
|
|
@ -1,82 +1,334 @@
|
|||
# AGENTS: Development Guidelines for AI Contributors
|
||||
|
||||
This file provides guidance to AI coding agents working with code in this repository.
|
||||
This document is for autonomous agents and AI copilots contributing code to this repository.
|
||||
Follow these rules to keep changes safe, comprehensible, and easy to maintain.
|
||||
|
||||
## Project
|
||||
## Repository Layout
|
||||
|
||||
Kotlin Multiplatform SDK for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io). Targets JVM, Native (macOS/Linux/Windows), JS, and Wasm. Implements both MCP clients and servers with pluggable transports.
|
||||
- `kotlin-sdk-core`: Core protocol types, transport abstractions, serialization utilities
|
||||
- `kotlin-sdk-client`: Client transports (STDIO, SSE, StreamableHttp, WebSocket)
|
||||
- `kotlin-sdk-server`: Server transports + Ktor integration (STDIO, SSE, WebSocket)
|
||||
- `kotlin-sdk`: Umbrella module that aggregates all three above
|
||||
- `test-utils`: Shared test utilities
|
||||
- `integration-test`: Integration tests with TypeScript/other implementations
|
||||
- `conformance-test`: Protocol conformance tests
|
||||
- `samples/`: Sample projects (composite builds)
|
||||
- Package structure: `io.modelcontextprotocol.kotlin.sdk.*`
|
||||
- JVM 11+, Kotlin 2.2+
|
||||
|
||||
## Build Commands
|
||||
## Prime Directives
|
||||
|
||||
1. **Tests first, always.**
|
||||
- Before changing code, identify or add tests that express the desired behavior.
|
||||
- Prefer readable, minimal tests over clever ones. Tests are documentation.
|
||||
2. **Keep tests simple and explicit.**
|
||||
- Arrange/Act/Assert structure; avoid hidden magic and overuse of helpers.
|
||||
- Prefer concrete inputs/outputs; avoid randomness and time dependence.
|
||||
3. **Uphold SOLID principles** in production code:
|
||||
- Single Responsibility: each class/function should do one thing well.
|
||||
- Open/Closed: extend via new code, avoid risky edits to stable code paths.
|
||||
- Liskov Substitution: honor contracts; keep types substitutable.
|
||||
- Interface Segregation: keep abstractions small and focused.
|
||||
- Dependency Inversion: depend on abstractions, not concretions.
|
||||
4. **Make the minimal change** that satisfies the tests and the issue.
|
||||
Stay focused on a single concern and avoid "drive-by" changes.
|
||||
5. **Never commit changes!** It's human who should verify and commit to git.
|
||||
6. **Keep the build green.** Do not merge changes that break existing tests.
|
||||
7. **Prefer clarity** over micro-optimizations and cleverness.
|
||||
8. **Ask when uncertain.** If requirements are ambiguous, request clarification with a concise question.
|
||||
9. **Write code with the quality of a Kotlin Champion.**
|
||||
10. **Use MCP servers** like `jetbrains` and `intellij-index` to explore the codebase, for code navigation, analysis,
|
||||
refactoring, and running tests.
|
||||
11. **Use the Bash tool for terminal commands** instead of MCP terminal execution features.
|
||||
12. **Suggest updates** to AGENTS.md/CLAUDE.md with best practices and guidelines.
|
||||
|
||||
## Code Style
|
||||
|
||||
### Kotlin
|
||||
|
||||
- Avoid changing public API signatures. Run `./gradlew apiCheck` before every commit.
|
||||
- **Explicit API mode** is strict: all public APIs must have explicit visibility modifiers and return types.
|
||||
- Anything under an `internal` directory is not part of the public API and may change freely.
|
||||
- Package structure follows: `io.modelcontextprotocol.kotlin.sdk.*`
|
||||
- Follow Kotlin coding conventions
|
||||
- Use the provided `.editorconfig` for consistent formatting
|
||||
- Use Kotlin typesafe DSL builders where possible; prioritize fluent builder style over standard builder methods
|
||||
- Prefer DSL builder style (method with lambda blocks) over constructors, if possible
|
||||
- Use `val` for immutable properties and `var` for mutable; consider `lateinit var` instead of nullable types when
|
||||
appropriate
|
||||
- Use multi-dollar interpolation prefix for strings where applicable
|
||||
- Use fully qualified imports instead of star imports
|
||||
- Ensure backward compatibility when making changes
|
||||
|
||||
## Testing Guidance
|
||||
|
||||
### Test Organization
|
||||
|
||||
- **Location**: `src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/`
|
||||
- **Platform-specific**: `src/jvmTest/`, `src/jsTest/`, etc.
|
||||
- **Naming**: Use function `Names with backticks`, e.g., `fun \`should return 200 OK\`()`
|
||||
- **Structure**: Arrange/Act/Assert pattern
|
||||
- **Documentation**: Keep tests self-documenting; don't add KDocs to tests.
|
||||
|
||||
### Test Principles
|
||||
|
||||
- Write comprehensive tests for new features. Always add tests for new features or bug fixes, even if not explicitly
|
||||
requested.
|
||||
- **Prioritize test readability**
|
||||
- Avoid creating too many test methods; use parametrized tests when testing multiple similar scenarios
|
||||
- When running tests on Kotlin Multiplatform projects, run JVM tests only unless asked for other platforms
|
||||
|
||||
### Test Framework Stack
|
||||
|
||||
- **kotlin-test**: Core test framework
|
||||
- **Kotest assertions**: Use infix style (`shouldBe`, `shouldContain`) instead of `assertEquals`.
|
||||
- Use `shouldMatchJson` from kotest-assertions-json for JSON validation.
|
||||
- For nullable objects with nested properties, prefer `shouldNotBeNull { ... }` blocks:
|
||||
```kotlin
|
||||
content.annotations shouldNotBeNull {
|
||||
priority shouldBe 1.0
|
||||
}
|
||||
```
|
||||
- **mockk**: Mocking library
|
||||
- **Ktor MockEngine**: For HTTP client mocking (`io.ktor:ktor-client-mock`)
|
||||
- **Java tests**: Use JUnit5, Mockito, AssertJ core
|
||||
- **Serialization test utilities** (`io.modelcontextprotocol.kotlin.test.utils`):
|
||||
- `verifySerialization(value, json, expectedJson)` — serializes, asserts match, round-trips back; use for most serialization tests
|
||||
- `verifyDeserialization(json, payload)` — deserializes from JSON, re-serializes, asserts match; returns the object for further assertions
|
||||
- Always test both empty/null/omitted and non-null cases for nullable fields; `McpJson` has `explicitNulls = false` so null properties must be absent from JSON, not `null`
|
||||
|
||||
### Kotest Patterns
|
||||
|
||||
- Basic assertions: Use infix style (`shouldBe`, `shouldContain`) instead of `assertEquals`.
|
||||
```kotlin
|
||||
result shouldBe expected
|
||||
list shouldContain item
|
||||
```
|
||||
- Nullable Assertions
|
||||
```kotlin
|
||||
// Preferred: lambda-style for multiple assertions
|
||||
content.annotations shouldNotBeNull {
|
||||
priority shouldBe 1.0
|
||||
}
|
||||
```
|
||||
|
||||
- JSON Assertions (kotest-assertions-json):
|
||||
```kotlin
|
||||
// language=json
|
||||
val expected = """
|
||||
{
|
||||
"id": 123
|
||||
}
|
||||
""".trimIndent()
|
||||
actual shouldEqualJson expected
|
||||
```
|
||||
|
||||
- Soft Assertions
|
||||
```kotlin
|
||||
// Use for multiple assertions on SAME subject
|
||||
assertSoftly(subject) {
|
||||
name shouldBe "test"
|
||||
value shouldBe 42
|
||||
}
|
||||
// DON'T use for different subjects or single assertions
|
||||
```
|
||||
- Clues (Use Sparingly)
|
||||
```kotlin
|
||||
// Only when assertion is NOT obvious
|
||||
withClue("Failed to parse response") {
|
||||
result shouldNotBe null
|
||||
}
|
||||
```
|
||||
|
||||
#### Avoiding `this.` in Lambda Blocks
|
||||
|
||||
```kotlin
|
||||
// Avoid explicit `this.` unless necessary for disambiguation
|
||||
prop.shouldNotBeNull {
|
||||
enum shouldHaveSize 2 // Preferred
|
||||
this.enum shouldHaveSize 2 // Avoid
|
||||
}
|
||||
```
|
||||
|
||||
### Multiplatform Patterns
|
||||
|
||||
- Use `expect`/`actual` pattern for platform-specific implementations in `utils.*` files.
|
||||
- Test changes on JVM first, then verify platform-specific behavior if needed.
|
||||
- Supported targets: JVM (11+), JS/Wasm, iOS, watchOS, tvOS.
|
||||
|
||||
## Coding Guidance
|
||||
|
||||
### Module Boundaries
|
||||
|
||||
- Respect separation of concerns between modules
|
||||
- Keep abstractions framework-agnostic
|
||||
- Avoid leaking implementation details across module boundaries
|
||||
|
||||
### Serialization
|
||||
|
||||
- Use Kotlinx Serialization with explicit `@Serializable` annotations
|
||||
- JSON config is defined in `jsonUtils.kt` as `McpJson` — use it consistently
|
||||
- Register custom serializers in companion objects
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Use sealed classes for result states
|
||||
- Map errors to JSON-RPC error codes in protocol handlers
|
||||
- Log errors using `io.github.oshai.kotlinlogging.KotlinLogging`
|
||||
- Never log sensitive data (credentials, tokens)
|
||||
|
||||
### Code Quality
|
||||
|
||||
- Handle nullability and references as established patterns
|
||||
- Keep changes small and reversible; prefer adding functions over editing many call sites
|
||||
- Add focused comments **only** where intent is non-obvious
|
||||
- Use `git mv` command when moving version-controlled files
|
||||
- Never commit or push changes. This is a Human responsibility.
|
||||
|
||||
## Workflow for AI Agents
|
||||
|
||||
1. **Understand the issue**
|
||||
- Summarize requirement in 1-2 sentences
|
||||
- Identify affected files and tests; ask if unclear
|
||||
|
||||
2. **Plan minimal changes**
|
||||
- Use TaskCreate/TaskUpdate to track work, or EnterPlanMode for complex changes
|
||||
- Document affected files and approach
|
||||
|
||||
3. **Work with code**
|
||||
- View, edit, and run tests through MCP tools
|
||||
|
||||
4. **Start with tests**
|
||||
- Update existing or add new tests in relevant modules
|
||||
|
||||
5. **Implement the change**
|
||||
- Prefer composition and small functions
|
||||
- Avoid breaking public APIs without tests and discussion
|
||||
|
||||
6. **Run tests locally**
|
||||
```bash
|
||||
./gradlew test
|
||||
./gradlew :kotlin-sdk-core:test # Specific module
|
||||
./gradlew :integration-test:test # Integration tests
|
||||
```
|
||||
|
||||
7. **Verify results**
|
||||
- Use Kotest JSON matchers for schema validation
|
||||
- Double-check the readability of code and tests
|
||||
|
||||
8. **Document key decisions**
|
||||
- Brief notes in markdown document, if requested
|
||||
|
||||
## Build and Run Commands
|
||||
|
||||
```bash
|
||||
./gradlew ktlintCheck # Lint check
|
||||
./gradlew detekt # Static analysis
|
||||
./gradlew ktlintFormat # Auto-fix lint issues
|
||||
./gradlew apiCheck # Check public API compatibility (run before committing)
|
||||
./gradlew apiDump # Update API dump after intentional API changes
|
||||
./gradlew koverLog # Print coverage summary
|
||||
./gradlew koverXmlReport # Generate XML coverage report
|
||||
# Build all modules
|
||||
./gradlew build
|
||||
|
||||
# Run all tests
|
||||
./gradlew test
|
||||
|
||||
# Run specific module tests
|
||||
./gradlew :kotlin-sdk-core:test
|
||||
./gradlew :kotlin-sdk-client:test
|
||||
./gradlew :kotlin-sdk-server:test
|
||||
|
||||
# Check API compatibility (required before commit)
|
||||
./gradlew apiCheck
|
||||
|
||||
# Update API dump (after intentional API changes)
|
||||
./gradlew apiDump
|
||||
|
||||
# Platform-specific tests
|
||||
./gradlew jsTest
|
||||
./gradlew wasmJsTest
|
||||
```
|
||||
|
||||
Run a single test class:
|
||||
```bash
|
||||
./gradlew :kotlin-sdk-server:jvmTest --tests "io.modelcontextprotocol.kotlin.sdk.server.StdioServerTransportTest"
|
||||
```
|
||||
## Definition of done
|
||||
|
||||
Run a single test method:
|
||||
```bash
|
||||
./gradlew :kotlin-sdk-core:jvmTest --tests "*.ProtocolTest.should preserve existing meta when adding progress token"
|
||||
```
|
||||
- Tests for affected functionality exist
|
||||
- All tests pass across all targets
|
||||
- Changes are focused on a single concern.
|
||||
- Code respects module boundaries
|
||||
- `./gradlew apiCheck` passes
|
||||
- Documentation updated for user-facing changes
|
||||
|
||||
Conformance tests (requires Node.js + npx):
|
||||
```bash
|
||||
./conformance-test/run-conformance.sh all # All suites sequentially
|
||||
./conformance-test/run-conformance.sh server # Server suite only
|
||||
./conformance-test/run-conformance.sh client # Client core suite (initialize, tools_call, elicitation, sse-retry)
|
||||
./conformance-test/run-conformance.sh client-auth # Client auth suite (20 OAuth scenarios)
|
||||
```
|
||||
## Documentation
|
||||
|
||||
## Module Structure
|
||||
### General Guidelines
|
||||
|
||||
```
|
||||
kotlin-sdk-core Core: protocol types, JSON-RPC, Transport abstraction, Protocol base class
|
||||
kotlin-sdk-client Client: MCP client implementation (tools, prompts, resources, sampling)
|
||||
kotlin-sdk-server Server: MCP server implementation (feature registries, sessions)
|
||||
kotlin-sdk-testing ChannelTransport for in-memory client-server testing
|
||||
kotlin-sdk Umbrella module aggregating client + server
|
||||
test-utils Shared test helpers (mockk, kotest, awaitility)
|
||||
conformance-test MCP specification compliance tests (external runner)
|
||||
integration-test End-to-end tests
|
||||
samples/ Runnable examples (servers and clients)
|
||||
```
|
||||
- **Never make up documentation/facts**
|
||||
- Update README files when adding new features
|
||||
- Document API changes in the appropriate module
|
||||
- **Keep documentation concise and straight to the point**
|
||||
- Always verify documentation matches code; fix discrepancies
|
||||
- Write tutorials in Markdown format in README.md
|
||||
|
||||
## Architecture
|
||||
### KDoc Guidelines
|
||||
|
||||
Layered design:
|
||||
- Properly document interfaces and abstract classes in production code
|
||||
- Avoid KDocs on override functions to reduce verbosity
|
||||
- Update KDocs when API changes
|
||||
- Use references: `[SendMessageRequest]` instead of `SendMessageRequest`
|
||||
- Add brief code examples to KDocs
|
||||
- Add links to specifications with verified URLs; never add broken links
|
||||
|
||||
```
|
||||
Application (tools, prompts, resources)
|
||||
→ Client / Server (typed MCP operations, capability enforcement)
|
||||
→ Protocol (JSON-RPC framing, request correlation, timeouts)
|
||||
→ Transport (pluggable I/O: stdio, SSE, Streamable HTTP, WebSocket)
|
||||
```
|
||||
### Module.md Files for Dokka
|
||||
|
||||
## Code Conventions
|
||||
Each module must have a `Module.md` file at the module root for Dokka-generated API documentation.
|
||||
|
||||
- **Explicit API mode (Strict)**: all public declarations must have explicit visibility modifiers and return types
|
||||
- **DSL builders**: prefer DSL builder style (lambda blocks) over direct constructors
|
||||
- **Multi-dollar interpolation**: use `$$"""..."""` for strings containing literal `$` (e.g., JSON with `$ref`, `$defs`)
|
||||
- **`McpJson` has `explicitNulls = false`**: null properties must be absent from JSON, not `"field": null`
|
||||
- **Logging**: use `io.github.oshai.kotlinlogging.KotlinLogging`
|
||||
- **Structured concurrency**: every coroutine must have a bounded scope and lifetime; always re-throw `CancellationException`; never hold `Mutex` across suspension points
|
||||
**Format Requirements** (per [Dokka specification](https://kotlinlang.org/docs/dokka-module-and-package-docs.html)):
|
||||
|
||||
## Testing
|
||||
- Must start with `# Module module-name` (level 1 header)
|
||||
- Package documentation uses `# Package package.name` (level 1 header)
|
||||
- All other content uses level 2+ headers (`##`, `###`, etc.)
|
||||
|
||||
- **JVM first**: run `jvmTest` instead of `test` — full multiplatform test runs are slow and rarely needed during development
|
||||
- **Test naming**: use backtick syntax — `fun \`should return 200 OK\`()`
|
||||
- **Frameworks**: JUnit 5 (runner) + Kotest (assertions) + MockK (mocking) + Awaitility (async waits)
|
||||
- **In-memory testing**: `ChannelTransport.createLinkedPair()` connects client and server without network
|
||||
**Content Guidelines**:
|
||||
|
||||
## Skills
|
||||
- **Purpose**: Provide module-level overview in generated API docs
|
||||
- **Detail level**: API documentation style (concise, focused on classes/interfaces)
|
||||
- **Module section**:
|
||||
- Brief module description (1-2 sentences)
|
||||
- Platform support (format: "Multiplatform • Kotlin 2.2+" or "JVM only • Kotlin 2.2+")
|
||||
- Key classes/components (use Dokka references like `[ClassName]`)
|
||||
- Example (minimal, demonstrating primary usage)
|
||||
- **Package sections**: Use `# Package package.name` headers with brief description
|
||||
- **Optional sections**: Features, Limitations, Related Specifications
|
||||
- **Style**:
|
||||
- Use bullet points over prose
|
||||
- Keep examples short (5-15 lines)
|
||||
- Reference related modules using Dokka links
|
||||
- Avoid duplicating README content
|
||||
|
||||
- `/mcp-docs` — fetches live MCP specification and docs; use when implementing or debugging MCP protocol features
|
||||
**Example structure (markdown)**:
|
||||
|
||||
# Module module-name
|
||||
|
||||
Brief description.
|
||||
|
||||
**Platform Support:** Multiplatform • Kotlin 2.2+
|
||||
|
||||
## Key Classes
|
||||
|
||||
- [MainClass] - what it does
|
||||
- [HelperClass] - what it does
|
||||
|
||||
## Example
|
||||
|
||||
```kotlin
|
||||
val example = MainClass()
|
||||
```
|
||||
|
||||
# Package package.name
|
||||
|
||||
Package description.
|
||||
|
||||
# Package another.package
|
||||
|
||||
Another package description.
|
||||
|
||||
## When to Ask for Help
|
||||
|
||||
- Requirements conflict with existing tests or documentation
|
||||
- The smallest change still requires altering core abstractions
|
||||
- Unclear expected schema shape for a new feature—ask for a concrete, readable test case to anchor implementation
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
AGENTS.md
|
||||
1
CLAUDE.md
Normal file
1
CLAUDE.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
@AGENTS.md
|
||||
64
README.md
64
README.md
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
[](https://central.sonatype.com/artifact/io.modelcontextprotocol/kotlin-sdk)
|
||||
[](https://github.com/modelcontextprotocol/kotlin-sdk/actions/workflows/build.yml)
|
||||
[](https://github.com/modelcontextprotocol/kotlin-sdk/actions/workflows/conformance.yml)
|
||||
[](https://codecov.io/github/modelcontextprotocol/kotlin-sdk)
|
||||
|
||||
[](http://kotlinlang.org)
|
||||
[](https://kotlinlang.org/docs/multiplatform.html)
|
||||
[](http://java.com)
|
||||
[](LICENSE)
|
||||
|
||||
[](https://deepwiki.com/modelcontextprotocol/kotlin-sdk)
|
||||
|
||||
Kotlin Multiplatform SDK for the [Model Context Protocol](https://modelcontextprotocol.io).
|
||||
It enables Kotlin applications targeting JVM, Native, JS, and Wasm to implement MCP clients and servers using a
|
||||
|
|
@ -181,18 +183,15 @@ fun main(args: Array<String>) = runBlocking {
|
|||
|
||||
### 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](samples/simple-streamable-server) sample.
|
||||
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
|
||||
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.server.mcp
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.Implementation
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities
|
||||
|
|
@ -201,6 +200,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema
|
|||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val port = args.firstOrNull()?.toIntOrNull() ?: 3000
|
||||
val mcpServer = Server(
|
||||
|
|
@ -226,9 +226,9 @@ fun main(args: Array<String>) {
|
|||
) { request ->
|
||||
CallToolResult(content = listOf(TextContent("Hello, world!")))
|
||||
}
|
||||
|
||||
|
||||
embeddedServer(CIO, host = "127.0.0.1", port = port) {
|
||||
mcpStreamableHttp {
|
||||
mcp {
|
||||
mcpServer
|
||||
}
|
||||
}.start(wait = true)
|
||||
|
|
@ -243,7 +243,7 @@ You can run the server and then connect to it using the client or test with the
|
|||
npx -y @modelcontextprotocol/inspector
|
||||
```
|
||||
|
||||
In the inspector UI, connect to `http://localhost:3000/mcp`.
|
||||
In the inspector UI, connect to `http://localhost:3000`.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
|
|
@ -729,7 +729,7 @@ val client = Client(
|
|||
)
|
||||
|
||||
client.setRequestHandler<CreateMessageRequest>(Method.Defined.SamplingCreateMessage) { request, _ ->
|
||||
val content = request.messages.lastOrNull()?.content?.firstOrNull()
|
||||
val content = request.messages.lastOrNull()?.content
|
||||
val prompt = if (content is TextContent) content.text else "your topic"
|
||||
CreateMessageResult(
|
||||
model = "gpt-4o-mini",
|
||||
|
|
@ -766,10 +766,8 @@ CLI tooling that spawns a helper process. No networking setup is required.
|
|||
|
||||
`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.
|
||||
|
||||
These helpers automatically install `ContentNegotiation` with `McpJson` — do not install it yourself, or a warning will
|
||||
be logged. Both accept a `path` parameter (default: `"/mcp"`) to mount the endpoint at any URL:
|
||||
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
|
||||
|
|
@ -789,7 +787,6 @@ private class MyServer :
|
|||
|
||||
fun main() {
|
||||
-->
|
||||
|
||||
```kotlin
|
||||
embeddedServer(CIO, port = 3000) {
|
||||
mcpStreamableHttp(path = "/api/mcp") {
|
||||
|
|
@ -797,36 +794,16 @@ embeddedServer(CIO, port = 3000) {
|
|||
}
|
||||
}.start(wait = true)
|
||||
```
|
||||
|
||||
<!--- SUFFIX
|
||||
}
|
||||
-->
|
||||
<!--- KNIT example-server-routes-01.kt -->
|
||||
|
||||
**CORS for browser-based clients (e.g. MCP Inspector):** if you connect from a browser-based
|
||||
client you need to install the Ktor CORS plugin so that MCP-specific headers are allowed and exposed:
|
||||
|
||||
```kotlin
|
||||
install(CORS) {
|
||||
anyHost() // restrict to specific origins in production
|
||||
allowMethod(HttpMethod.Options)
|
||||
allowMethod(HttpMethod.Get)
|
||||
allowMethod(HttpMethod.Post)
|
||||
allowMethod(HttpMethod.Delete)
|
||||
allowNonSimpleContentTypes = true
|
||||
allowHeader("Mcp-Session-Id")
|
||||
allowHeader("Mcp-Protocol-Version")
|
||||
exposeHeader("Mcp-Session-Id")
|
||||
exposeHeader("Mcp-Protocol-Version")
|
||||
}
|
||||
```
|
||||
|
||||
### SSE Transport
|
||||
|
||||
Server-Sent Events remain available for backwards compatibility with older MCP clients. Two Ktor helpers are provided:
|
||||
|
||||
- **`Application.mcp { }`** — installs SSE and `ContentNegotiation` with `McpJson` automatically, then registers MCP
|
||||
endpoints at `/`. Do not install `ContentNegotiation` yourself — the SDK handles it.
|
||||
- **`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:
|
||||
|
||||
|
|
@ -854,7 +831,6 @@ private class MyServer :
|
|||
|
||||
fun main() {
|
||||
-->
|
||||
|
||||
```kotlin
|
||||
embeddedServer(CIO, port = 3000) {
|
||||
install(SSE)
|
||||
|
|
@ -865,7 +841,6 @@ embeddedServer(CIO, port = 3000) {
|
|||
}
|
||||
}.start(wait = true)
|
||||
```
|
||||
|
||||
<!--- SUFFIX
|
||||
}
|
||||
-->
|
||||
|
|
@ -905,12 +880,14 @@ allowing for easy testing of MCP functionality without the need for network setu
|
|||
|
||||
## 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.
|
||||
| Scenario | Description | Example |
|
||||
|--------------------------|-----------------------------------------------------------------|--------------------------------------------------------------------------|
|
||||
| Streamable HTTP server | Full MCP server with prompts, resources, tools, completions | [samples/kotlin-mcp-server](./samples/kotlin-mcp-server) |
|
||||
| STDIO weather server | Minimal STDIO transport server exposing weather info and alerts | [samples/weather-stdio-server](./samples/weather-stdio-server) |
|
||||
| Interactive STDIO client | MCP client that connects over STDIO and pipes requests to LLMs | [samples/kotlin-mcp-client](./samples/kotlin-mcp-client) |
|
||||
| Streamable HTTP client | MCP client demo in a runnable notebook | [samples/notebooks/McpClient.ipynb](./samples/notebooks/McpClient.ipynb) |
|
||||
|
||||
## Documentation
|
||||
[](https://deepwiki.com/modelcontextprotocol/kotlin-sdk)
|
||||
|
||||
- [API Reference](https://kotlin.sdk.modelcontextprotocol.io/)
|
||||
- [Model Context Protocol documentation](https://modelcontextprotocol.io)
|
||||
|
|
@ -922,5 +899,4 @@ Please see the [contribution guide](CONTRIBUTING.md) and the [Code of conduct](C
|
|||
|
||||
## License
|
||||
|
||||
This project is licensed under Apache 2.0 for new contributions, with existing code under MIT—see the [LICENSE](LICENSE)
|
||||
file for details.
|
||||
This project is licensed under Apache 2.0 for new contributions, with existing code under MIT—see the [LICENSE](LICENSE) file for details.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import dev.detekt.gradle.extensions.FailOnSeverity
|
||||
|
||||
plugins {
|
||||
id("mcp.dokka")
|
||||
alias(libs.plugins.detekt)
|
||||
alias(libs.plugins.ktlint)
|
||||
alias(libs.plugins.kover)
|
||||
}
|
||||
|
|
@ -20,6 +23,13 @@ dependencies {
|
|||
subprojects {
|
||||
apply(plugin = "org.jlleitschuh.gradle.ktlint")
|
||||
apply(plugin = "org.jetbrains.kotlinx.kover")
|
||||
apply(plugin = "dev.detekt")
|
||||
|
||||
detekt {
|
||||
config = files("$rootDir/config/detekt/detekt.yml")
|
||||
buildUponDefaultConfig = true
|
||||
failOnSeverity.set(FailOnSeverity.Error)
|
||||
}
|
||||
}
|
||||
|
||||
dokka {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.detekt.gradle)
|
||||
implementation(libs.kotlin.gradle)
|
||||
implementation(libs.kotlin.serialization)
|
||||
implementation(libs.kotlinx.atomicfu.gradle)
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
import dev.detekt.gradle.Detekt
|
||||
import dev.detekt.gradle.extensions.FailOnSeverity
|
||||
|
||||
plugins {
|
||||
id("dev.detekt")
|
||||
}
|
||||
|
||||
detekt {
|
||||
config = files("$rootDir/config/detekt/detekt.yml")
|
||||
buildUponDefaultConfig = false
|
||||
parallel = true
|
||||
failOnSeverity = FailOnSeverity.Error
|
||||
}
|
||||
|
||||
tasks.withType<Detekt>().configureEach {
|
||||
exclude("**/generated/**", "**/generated-sources/**", "**/build/**")
|
||||
}
|
||||
|
||||
pluginManager.withPlugin("org.jetbrains.kotlin.multiplatform") {
|
||||
tasks.named("detekt").configure {
|
||||
dependsOn("detektMainJvm")
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue