Compare commits

..
37 changed files with 123 additions and 909 deletions

View file

@ -27,14 +27,14 @@ jobs:
- uses: actions/checkout@v7
- 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@v6
- name: Generate Dokka Site
run: |-

View file

@ -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'

View file

@ -46,7 +46,7 @@ jobs:
- uses: actions/checkout@v7
- 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 }}
@ -63,7 +63,7 @@ jobs:
run: npm ci
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6.3.0
uses: gradle/actions/setup-gradle@v6
with:
validate-wrappers: true
add-job-summary: 'always'
@ -129,13 +129,13 @@ jobs:
- uses: actions/checkout@v7
- 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@v6
with:
validate-wrappers: true
add-job-summary: 'always'
@ -171,13 +171,13 @@ jobs:
- uses: actions/checkout@v7
- 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@v6
with:
add-job-summary: 'always'
cache-read-only: true

View file

@ -28,19 +28,19 @@ jobs:
uses: actions/checkout@v7
- 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 }}
- name: Initialize CodeQL
uses: github/codeql-action/init@v4.38.0
uses: github/codeql-action/init@v4
with:
languages: java-kotlin
build-mode: manual
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6.3.0
uses: gradle/actions/setup-gradle@v6
with:
validate-wrappers: true
cache-read-only: true
@ -52,6 +52,6 @@ jobs:
--no-daemon --rerun-tasks --stacktrace
- name: Analyze
uses: github/codeql-action/analyze@v4.38.0
uses: github/codeql-action/analyze@v4
with:
category: '/language:java-kotlin'

View file

@ -28,13 +28,13 @@ jobs:
- uses: actions/checkout@v7
- name: Set up JDK
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@v6
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
@ -79,13 +79,13 @@ jobs:
- uses: actions/checkout@v7
- name: Set up JDK
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@v6
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
@ -110,13 +110,13 @@ jobs:
- uses: actions/checkout@v7
- name: Set up JDK
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@v6
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
@ -149,13 +149,13 @@ jobs:
- uses: actions/checkout@v7
- name: Set up JDK
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@v6
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}

View file

@ -19,7 +19,7 @@ jobs:
steps:
- uses: actions/checkout@v7
- name: Set up JDK 21
uses: actions/setup-java@v6
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
@ -30,7 +30,7 @@ jobs:
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@v6
- name: Check
run: ./gradlew check --no-configuration-cache

View file

@ -39,13 +39,13 @@ jobs:
- uses: actions/checkout@v7
- 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@v6
with:
validate-wrappers: true
add-job-summary: 'always'

View file

@ -1,28 +1,28 @@
[versions]
# plugins version
atomicfu = "0.33.0"
binaryCompatibilityValidatorPlugin = "0.18.2"
detekt = "2.0.0-alpha.6"
binaryCompatibilityValidatorPlugin = "0.18.1"
detekt = "2.0.0-alpha.5"
dokka = "2.2.0"
kotlin = "2.4.10"
kotlin = "2.4.0"
kover = "0.9.9"
ktlint = "14.2.0"
knit = "0.5.1"
mavenPublish = "0.37.0"
netty = "4.2.18.Final"
netty = "4.2.16.Final"
# libraries version
awaitility = "4.3.0"
collections-immutable = "0.5.2"
collections-immutable = "0.5.1"
coroutines = "1.11.0"
kotest = "6.2.5"
kotest = "6.2.3"
kotlinx-io = "0.9.1"
ktor = "3.5.2"
ktor = "3.5.1"
logging = "8.0.4"
mockk = "1.14.11"
serialization = "1.11.0"
slf4j = "2.0.19"
logback = "1.6.3"
slf4j = "2.0.18"
logback = "1.5.38"
junit = "5.14.4"
[libraries]

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500

View file

@ -698,8 +698,8 @@ abstract class AbstractPromptIntegrationTest : KotlinTestBase() {
val expectedMessage = "Prompt not found: non-existent-prompt"
withClue("Exception code should be INVALID_PARAMS: ${RPCError.ErrorCode.INVALID_PARAMS}") {
exception.code shouldBe RPCError.ErrorCode.INVALID_PARAMS
withClue("Exception code should be INTERNAL_ERROR: -32603") {
exception.code shouldBe -32603
}
withClue("Unexpected error message for non-existent prompt") {
exception.message shouldBe expectedMessage

View file

@ -8,16 +8,16 @@
"name": "mcp-typescript-test-sdk",
"version": "1.0.0",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.30.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"express": "^5.2.1",
"zod": "^4.6.2"
"zod": "^4.4.3"
},
"devDependencies": {
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/node": "^26.5.1",
"@types/node": "^26.1.1",
"cors": "^2.8.6",
"tsx": "^4.23.13",
"tsx": "^4.23.1",
"typescript": "^7.0.2"
}
},
@ -464,24 +464,24 @@
}
},
"node_modules/@hono/node-server": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.0.tgz",
"integrity": "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==",
"version": "1.19.13",
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.13.tgz",
"integrity": "sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ==",
"license": "MIT",
"engines": {
"node": ">=20"
"node": ">=18.14.1"
},
"peerDependencies": {
"hono": "^4"
}
},
"node_modules/@modelcontextprotocol/sdk": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz",
"integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==",
"version": "1.29.0",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
"integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==",
"license": "MIT",
"dependencies": {
"@hono/node-server": "^1.19.9 || ^2.0.5",
"@hono/node-server": "^1.19.9",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"content-type": "^1.0.5",
@ -579,13 +579,13 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "26.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.5.1.tgz",
"integrity": "sha512-CzNm2FezW4VR/LjG6yUdiEgLE/rAQ9Slj5gCu/C2VrdcW7I0ahNZ8DRbHT7zOZ6r3ONgd/bsQIeSaoDGrd1C6g==",
"version": "26.1.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz",
"integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~8.9.0"
"undici-types": "~8.3.0"
}
},
"node_modules/@types/qs": {
@ -1229,9 +1229,9 @@
}
},
"node_modules/es-object-atoms": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
"integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@ -1387,9 +1387,9 @@
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz",
"integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
"integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
"funding": [
{
"type": "github",
@ -1526,9 +1526,9 @@
}
},
"node_modules/hasown": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@ -1538,9 +1538,9 @@
}
},
"node_modules/hono": {
"version": "4.13.7",
"resolved": "https://registry.npmjs.org/hono/-/hono-4.13.7.tgz",
"integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==",
"version": "4.12.27",
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.27.tgz",
"integrity": "sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==",
"license": "MIT",
"engines": {
"node": ">=16.9.0"
@ -1589,9 +1589,9 @@
"license": "ISC"
},
"node_modules/ip-address": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
"integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
"license": "MIT",
"engines": {
"node": ">= 12"
@ -1802,13 +1802,12 @@
}
},
"node_modules/qs": {
"version": "6.16.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz",
"integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==",
"version": "6.15.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"license": "BSD-3-Clause",
"dependencies": {
"es-define-property": "^1.0.1",
"side-channel": "^1.1.1"
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
@ -1945,14 +1944,14 @@
}
},
"node_modules/side-channel": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
"integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.4",
"side-channel-list": "^1.0.1",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
@ -1964,13 +1963,13 @@
}
},
"node_modules/side-channel-list": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
"integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.4"
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
@ -2035,9 +2034,9 @@
}
},
"node_modules/tsx": {
"version": "4.23.13",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz",
"integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==",
"version": "4.23.1",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz",
"integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2120,9 +2119,9 @@
}
},
"node_modules/undici-types": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
"integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
"integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
"dev": true,
"license": "MIT"
},
@ -2166,9 +2165,9 @@
"license": "ISC"
},
"node_modules/zod": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.6.2.tgz",
"integrity": "sha512-lh5RCAGFa1Cm2hjtNwLQhSs/AsqdWnTQaBER9fEwN/88pSh7KOtJavtBx/0VlkN/uFd61SwYmljLMDAsHlvzBQ==",
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
"integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"

View file

@ -9,16 +9,16 @@
"server:http": "tsx server/http-server.ts"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.30.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"express": "^5.2.1",
"zod": "^4.6.2"
"zod": "^4.4.3"
},
"devDependencies": {
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/node": "^26.5.1",
"@types/node": "^26.1.1",
"cors": "^2.8.6",
"tsx": "^4.23.13",
"tsx": "^4.23.1",
"typescript": "^7.0.2"
}
}

View file

@ -390,19 +390,6 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/BooleanSchema$Compan
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/CacheScope : java/lang/Enum {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope$Companion;
public static final field Private Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope;
public static final field Public Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope;
public static fun values ()[Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/CacheScope$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequest$Companion;
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;)V
@ -1408,104 +1395,6 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CustomRequest$Compan
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$Companion;
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;)V
public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;
public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest;
public fun equals (Ljava/lang/Object;)Z
public final fun getMeta--Khlwt8 ()Lkotlinx/serialization/json/JsonObject;
public fun getMethod ()Lio/modelcontextprotocol/kotlin/sdk/types/Method;
public fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;
public synthetic fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestParams;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$$serializer;
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequest$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams : io/modelcontextprotocol/kotlin/sdk/types/RequestParams {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$Companion;
public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1--Khlwt8 ()Lkotlinx/serialization/json/JsonObject;
public final fun copy-hVVZdjo (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;
public static synthetic fun copy-hVVZdjo$default (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;
public fun equals (Ljava/lang/Object;)Z
public fun getMeta--Khlwt8 ()Lkotlinx/serialization/json/JsonObject;
public synthetic fun getMeta-VI-3G7E ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$$serializer;
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverRequestParams$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverResult : io/modelcontextprotocol/kotlin/sdk/types/ServerResult {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$Companion;
public fun <init> (Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;)V
public synthetic fun <init> (Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/util/List;
public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/String;
public final fun component5 ()J
public final fun component6 ()Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope;
public final fun component7 ()Lkotlinx/serialization/json/JsonObject;
public final fun copy (Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Ljava/lang/String;Ljava/lang/String;JLio/modelcontextprotocol/kotlin/sdk/types/CacheScope;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getCacheScope ()Lio/modelcontextprotocol/kotlin/sdk/types/CacheScope;
public final fun getCapabilities ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;
public final fun getInstructions ()Ljava/lang/String;
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getResultType ()Ljava/lang/String;
public final fun getSupportedVersions ()Ljava/util/List;
public final fun getTtlMs ()J
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$$serializer;
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/DiscoverResult;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/DiscoverResult$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/DoubleSchema : io/modelcontextprotocol/kotlin/sdk/types/NumberSchemaDefinition {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/DoubleSchema$Companion;
public fun <init> ()V
@ -3356,7 +3245,6 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Method$Defined : jav
public static final field ResourcesUnsubscribe Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
public static final field RootsList Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
public static final field SamplingCreateMessage Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
public static final field ServerDiscover Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
public static final field TasksCancel Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
public static final field TasksGet Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
public static final field TasksList Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
@ -3879,7 +3767,6 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/RPCError$ErrorCode {
public static final field PARSE_ERROR I
public static final field REQUEST_TIMEOUT I
public static final field RESOURCE_NOT_FOUND I
public static final field UNSUPPORTED_PROTOCOL_VERSION I
public static final field URL_ELICITATION_REQUIRED I
}
@ -4125,12 +4012,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/RequestMeta {
public static fun equals-impl (Lkotlinx/serialization/json/JsonObject;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)Z
public static final fun get-impl (Lkotlinx/serialization/json/JsonObject;Ljava/lang/String;)Lkotlinx/serialization/json/JsonElement;
public static final fun getClientCapabilities-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;
public static final fun getClientInfo-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/Implementation;
public final fun getJson ()Lkotlinx/serialization/json/JsonObject;
public static final fun getLogLevel-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/LoggingLevel;
public static final fun getProgressToken-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/RequestId;
public static final fun getProtocolVersion-impl (Lkotlinx/serialization/json/JsonObject;)Ljava/lang/String;
public static final fun getRelatedTask-impl (Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/RelatedTaskMetadata;
public fun hashCode ()I
public static fun hashCode-impl (Lkotlinx/serialization/json/JsonObject;)I
@ -5853,35 +5736,6 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/UnsubscribeRequestPa
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$Companion;
public fun <init> (Ljava/util/List;Ljava/lang/String;)V
public final fun component1 ()Ljava/util/List;
public final fun component2 ()Ljava/lang/String;
public final fun copy (Ljava/util/List;Ljava/lang/String;)Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData;
public fun equals (Ljava/lang/Object;)Z
public final fun getRequested ()Ljava/lang/String;
public final fun getSupported ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$$serializer;
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData;)V
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/UnsupportedProtocolVersionData$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/UntitledMultiSelectEnumSchema : io/modelcontextprotocol/kotlin/sdk/types/MultiSelectEnumSchema {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/UntitledMultiSelectEnumSchema$Companion;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Lio/modelcontextprotocol/kotlin/sdk/types/UntitledMultiSelectEnumSchema$Items;Ljava/util/List;)V

View file

@ -1,107 +0,0 @@
package io.modelcontextprotocol.kotlin.sdk.types
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Required
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.JsonObject
/**
* Parameters for a `server/discover` request.
*
* Discovery belongs to the request-scoped lifecycle and therefore requires a protocol version and
* client capabilities in [meta]. Client information is recommended by the protocol but optional.
* Unknown metadata entries are preserved by [RequestMeta].
*
* @property meta request-scoped protocol and client metadata
* @throws IllegalArgumentException if required request-scoped metadata is absent
* @throws SerializationException if required metadata is malformed
*/
@Serializable
@ExperimentalMcpApi
public data class DiscoverRequestParams(
@SerialName("_meta")
override val meta: RequestMeta,
) : RequestParams {
init {
requireNotNull(meta.protocolVersion) { "${RequestMetaKeys.PROTOCOL_VERSION} is required" }
requireNotNull(meta.clientCapabilities) { "${RequestMetaKeys.CLIENT_CAPABILITIES} is required" }
}
}
/**
* Requests the protocol versions, capabilities, and metadata advertised by a server.
*
* @property params request metadata required by the request-scoped lifecycle
*/
@Serializable
@ExperimentalMcpApi
public data class DiscoverRequest(override val params: DiscoverRequestParams) : ClientRequest {
@OptIn(ExperimentalSerializationApi::class)
@EncodeDefault
override val method: Method = Method.Defined.ServerDiscover
/** Metadata for this request. */
public val meta: RequestMeta
get() = params.meta
}
/** Defines where a cached discovery result may be reused. */
@Serializable
@ExperimentalMcpApi
public enum class CacheScope {
/** The result may only be reused within the same authorization context. */
@SerialName("private")
Private,
/** The result may be shared across authorization contexts. */
@SerialName("public")
Public,
}
/**
* Result returned by `server/discover`.
*
* @property supportedVersions protocol versions supported by the server
* @property capabilities capabilities advertised by the server
* @property instructions optional guidance for clients using the server
* @property resultType discriminator for the result representation
* @property ttlMs number of milliseconds clients may treat this result as fresh
* @property cacheScope authorization boundary within which the result may be reused
* @property meta optional response metadata, including optional server information
* @throws IllegalArgumentException if [ttlMs] is negative
*/
@Serializable
@ExperimentalMcpApi
public data class DiscoverResult(
val supportedVersions: List<String>,
val capabilities: ServerCapabilities,
val instructions: String? = null,
@EncodeDefault
val resultType: String = COMPLETE_RESULT_TYPE,
@Required
val ttlMs: Long = 0,
@Required
val cacheScope: CacheScope = CacheScope.Private,
@SerialName("_meta")
override val meta: JsonObject? = null,
) : ServerResult {
init {
require(ttlMs >= 0) { "ttlMs must be non-negative, but was $ttlMs" }
}
}
/**
* Data returned when a request selects an unsupported protocol version.
*
* @property supported protocol versions supported by the receiver
* @property requested protocol version selected by the request
*/
@Serializable
@ExperimentalMcpApi
public data class UnsupportedProtocolVersionData(val supported: List<String>, val requested: String)
internal const val COMPLETE_RESULT_TYPE: String = "complete"

View file

@ -269,9 +269,6 @@ public data class RPCError(val code: Int, val message: String, val data: JsonEle
/** Resource not found */
public const val RESOURCE_NOT_FOUND: Int = -32002
/** The request selected a protocol version that the receiver does not support. */
public const val UNSUPPORTED_PROTOCOL_VERSION: Int = -32022
/**
* A URL-mode elicitation must be completed before the request can be processed.
* The error [data][RPCError.data] carries the required URL-mode elicitations

View file

@ -16,7 +16,6 @@ public sealed interface Method {
@Serializable
public enum class Defined(override val value: String) : Method {
Initialize("initialize"),
ServerDiscover("server/discover"),
Ping("ping"),
ResourcesList("resources/list"),
ResourcesTemplatesList("resources/templates/list"),

View file

@ -1,10 +1,8 @@
package io.modelcontextprotocol.kotlin.sdk.types
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
@ -13,13 +11,6 @@ import kotlinx.serialization.json.long
import kotlinx.serialization.json.longOrNull
import kotlin.jvm.JvmInline
internal object RequestMetaKeys {
const val PROTOCOL_VERSION: String = "io.modelcontextprotocol/protocolVersion"
const val CLIENT_INFO: String = "io.modelcontextprotocol/clientInfo"
const val CLIENT_CAPABILITIES: String = "io.modelcontextprotocol/clientCapabilities"
const val LOG_LEVEL: String = "io.modelcontextprotocol/logLevel"
}
/**
* Metadata attached to a request's `_meta` field.
*
@ -49,88 +40,6 @@ public value class RequestMeta(public val json: JsonObject) {
McpJson.decodeFromJsonElement(element)
}
/**
* The MCP protocol version selected for this request, or `null` when absent.
*
* This field is required by the request-scoped lifecycle introduced in protocol version
* `2026-07-28`, but remains optional here so older requests retain their wire shape.
*
* @throws SerializationException if the field is present but is not a string
*/
@ExperimentalMcpApi
public val protocolVersion: String?
get() = json[RequestMetaKeys.PROTOCOL_VERSION]?.let { element ->
if (element !is JsonPrimitive || !element.isString) {
throw SerializationException("${RequestMetaKeys.PROTOCOL_VERSION} must be a JSON string")
}
element.content
}
/**
* Information about the client making this request, or `null` when absent.
*
* Request-scoped clients should include this field unless specifically configured not to do
* so. The self-reported value is intended for display, logging, and debugging; servers should
* not use it to change behavior or rely on it for security decisions.
*
* @throws SerializationException if the field is present but is not a valid [Implementation]
*/
@ExperimentalMcpApi
public val clientInfo: Implementation?
get() = json[RequestMetaKeys.CLIENT_INFO]?.let { element ->
try {
McpJson.decodeFromJsonElement<Implementation>(element)
} catch (cause: SerializationException) {
throw SerializationException(
"${RequestMetaKeys.CLIENT_INFO} must be a valid client implementation",
cause,
)
}
}
/**
* Capabilities declared by the client for this request, or `null` when absent.
*
* Servers using the request-scoped lifecycle must not infer capabilities from an earlier
* request. An empty object means the client supports no optional capabilities.
*
* @throws SerializationException if the field is present but is not valid [ClientCapabilities]
*/
@ExperimentalMcpApi
public val clientCapabilities: ClientCapabilities?
get() = json[RequestMetaKeys.CLIENT_CAPABILITIES]?.let { element ->
try {
McpJson.decodeFromJsonElement<ClientCapabilities>(element)
} catch (cause: SerializationException) {
throw SerializationException(
"${RequestMetaKeys.CLIENT_CAPABILITIES} must be a valid client capabilities object",
cause,
)
}
}
/**
* Minimum severity of request-associated log notifications, or `null` when absent.
*
* In the request-scoped lifecycle, absence means that the server must not emit log
* notifications for this request.
*
* @throws SerializationException if the field is present but is not a valid [LoggingLevel]
*/
@Deprecated("Per-request log levels are deprecated as of MCP protocol version 2026-07-28 (SEP-2577).")
@ExperimentalMcpApi
public val logLevel: LoggingLevel?
get() = json[RequestMetaKeys.LOG_LEVEL]?.let { element ->
try {
McpJson.decodeFromJsonElement<LoggingLevel>(element)
} catch (cause: SerializationException) {
throw SerializationException(
"${RequestMetaKeys.LOG_LEVEL} must be a valid logging level",
cause,
)
}
}
/**
* Retrieves the value associated with the specified key from the JSON object.
*

View file

@ -1,7 +1,6 @@
package io.modelcontextprotocol.kotlin.sdk.types
import io.github.oshai.kotlinlogging.KotlinLogging
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
@ -239,11 +238,9 @@ internal object ResourceContentsPolymorphicSerializer :
// Request Serializers
// ============================================================================
@OptIn(ExperimentalMcpApi::class)
private val clientRequestDeserializers: Map<String, DeserializationStrategy<ClientRequest>> by lazy {
mapOf(
Method.Defined.CompletionComplete.value to CompleteRequest.serializer(),
Method.Defined.ServerDiscover.value to DiscoverRequest.serializer(),
Method.Defined.Initialize.value to InitializeRequest.serializer(),
Method.Defined.Ping.value to PingRequest.serializer(),
Method.Defined.LoggingSetLevel.value to SetLevelRequest.serializer(),
@ -420,16 +417,9 @@ private fun selectClientResultDeserializer(element: JsonElement): Deserializatio
* Selects the appropriate deserializer for server results based on JSON content.
* Returns null if the structure doesn't match any known server result type.
*/
@OptIn(ExperimentalMcpApi::class)
private fun selectServerResultDeserializer(element: JsonElement): DeserializationStrategy<ServerResult>? {
val jsonObject = element.jsonObject
val isDiscoverResult =
"supportedVersions" in jsonObject &&
"capabilities" in jsonObject &&
"ttlMs" in jsonObject &&
"cacheScope" in jsonObject
return when {
isDiscoverResult -> DiscoverResult.serializer()
"protocolVersion" in jsonObject && "capabilities" in jsonObject -> InitializeResult.serializer()
"completion" in jsonObject -> CompleteResult.serializer()
"tools" in jsonObject -> ListToolsResult.serializer()

View file

@ -1,324 +0,0 @@
package io.modelcontextprotocol.kotlin.sdk.types
import io.kotest.assertions.json.shouldEqualJson
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
import kotlin.test.assertFailsWith
import kotlin.test.assertIs
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
@OptIn(ExperimentalMcpApi::class)
class DiscoveryTest {
@Test
fun `should decode server discover request from its wire shape`() {
val request = McpJson.decodeFromString<Request>(
"""
{
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "test-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
""".trimIndent(),
)
val discover = assertIs<DiscoverRequest>(request)
assertEquals(Method.Defined.ServerDiscover, discover.method)
assertEquals("2026-07-28", discover.meta.protocolVersion)
assertEquals("test-client", discover.meta.clientInfo?.name)
assertEquals(ClientCapabilities(), discover.meta.clientCapabilities)
}
@Test
fun `should decode discovery request without optional client info`() {
val request = McpJson.decodeFromString<Request>(
"""
{
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"com.example/traceId": "trace-123"
}
}
}
""".trimIndent(),
)
val discover = assertIs<DiscoverRequest>(request)
assertEquals("2026-07-28", discover.meta.protocolVersion)
assertEquals(ClientCapabilities(), discover.meta.clientCapabilities)
assertNull(discover.meta.clientInfo)
assertNotNull(discover.meta["com.example/traceId"])
McpJson.encodeToString<Request>(discover) shouldEqualJson """
{
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"com.example/traceId": "trace-123"
}
}
}
""".trimIndent()
}
@Test
fun `should reject discovery requests without required request metadata`() {
val invalidParams = listOf(
"{}" to "_meta",
"""{"_meta": {}}""" to RequestMetaKeys.PROTOCOL_VERSION,
"""
{
"_meta": {
"${RequestMetaKeys.PROTOCOL_VERSION}": "2026-07-28",
"${RequestMetaKeys.CLIENT_INFO}": {
"name": "test-client",
"version": "1.0.0"
}
}
}
""".trimIndent() to RequestMetaKeys.CLIENT_CAPABILITIES,
)
invalidParams.forEach { (params, missingField) ->
val failure = assertFails {
McpJson.decodeFromString<Request>(
"""{"method": "server/discover", "params": $params}""",
)
}
assertTrue(
failure.message.orEmpty().contains(missingField),
"Expected failure to identify missing field $missingField, but was: $failure",
)
}
}
@Test
fun `should serialize every required discovery result field`() {
val result = DiscoverResult(
supportedVersions = listOf("2026-07-28"),
capabilities = ServerCapabilities(
tools = ServerCapabilities.Tools(listChanged = true),
),
instructions = "Use tools intentionally.",
)
McpJson.encodeToString<ServerResult>(result) shouldEqualJson """
{
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {"listChanged": true}
},
"instructions": "Use tools intentionally.",
"resultType": "complete",
"ttlMs": 0,
"cacheScope": "private"
}
""".trimIndent()
}
@Test
fun `should encode optional server info in result metadata`() {
val result = DiscoverResult(
supportedVersions = listOf("2026-07-28"),
capabilities = ServerCapabilities(),
meta = Json.parseToJsonElement(
"""
{
"io.modelcontextprotocol/serverInfo": {
"name": "test-server",
"version": "2.0.0"
},
"com.example/source": "edge"
}
""".trimIndent(),
).jsonObject,
)
McpJson.encodeToString<ServerResult>(result) shouldEqualJson """
{
"supportedVersions": ["2026-07-28"],
"capabilities": {},
"resultType": "complete",
"ttlMs": 0,
"cacheScope": "private",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "test-server",
"version": "2.0.0"
},
"com.example/source": "edge"
}
}
""".trimIndent()
assertEquals(
Json.parseToJsonElement("""{"name":"test-server","version":"2.0.0"}"""),
result.meta?.get("io.modelcontextprotocol/serverInfo"),
)
}
@Test
fun `should encode required defaults independently of McpJson`() {
val result = DiscoverResult(
supportedVersions = listOf("2026-07-28"),
capabilities = ServerCapabilities(),
)
Json.encodeToString(result) shouldEqualJson """
{
"supportedVersions": ["2026-07-28"],
"capabilities": {},
"resultType": "complete",
"ttlMs": 0,
"cacheScope": "private"
}
""".trimIndent()
}
@Test
fun `should reject discovery results without required cache fields`() {
val invalidResults = listOf(
"""
{
"supportedVersions": ["2026-07-28"],
"capabilities": {},
"cacheScope": "private"
}
""".trimIndent(),
"""
{
"supportedVersions": ["2026-07-28"],
"capabilities": {},
"ttlMs": 0
}
""".trimIndent(),
)
invalidResults.forEach { wire ->
assertFails { McpJson.decodeFromString<DiscoverResult>(wire) }
assertFails { McpJson.decodeFromString<ServerResult>(wire) }
}
}
@Test
fun `should use complete when a discovery result omits resultType`() {
val result = McpJson.decodeFromString<ServerResult>(
"""
{
"supportedVersions": ["2026-07-28"],
"capabilities": {},
"ttlMs": 0,
"cacheScope": "private"
}
""".trimIndent(),
)
assertEquals(COMPLETE_RESULT_TYPE, assertIs<DiscoverResult>(result).resultType)
}
@Test
fun `should deserialize discovery results polymorphically`() {
val wire =
"""
{
"supportedVersions": ["2026-07-28"],
"capabilities": {},
"resultType": "complete",
"ttlMs": 250,
"cacheScope": "public",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "server",
"version": "1"
},
"com.example/source": "edge"
}
}
""".trimIndent()
val result = McpJson.decodeFromString<ServerResult>(wire)
val discover = assertIs<DiscoverResult>(result)
assertEquals(250, discover.ttlMs)
assertEquals(CacheScope.Public, discover.cacheScope)
assertEquals(
Json.parseToJsonElement("""{"name":"server","version":"1"}"""),
discover.meta?.get("io.modelcontextprotocol/serverInfo"),
)
assertNotNull(discover.meta?.get("com.example/source"))
McpJson.encodeToString<ServerResult>(discover) shouldEqualJson wire
}
@Test
fun `should not treat supportedVersions alone as a discovery discriminator`() {
val result = McpJson.decodeFromString<ServerResult>(
"""
{
"tools": [],
"supportedVersions": ["extension-value"]
}
""".trimIndent(),
)
assertIs<ListToolsResult>(result)
}
@Test
fun `should not treat an initialize extension as a discovery result`() {
val result = McpJson.decodeFromString<ServerResult>(
"""
{
"protocolVersion": "2025-06-18",
"capabilities": {},
"serverInfo": {
"name": "test-server",
"version": "1.0.0"
},
"supportedVersions": ["extension-value"]
}
""".trimIndent(),
)
assertIs<InitializeResult>(result)
}
@Test
fun `should reject a negative discovery ttl`() {
assertFailsWith<IllegalArgumentException> {
DiscoverResult(
supportedVersions = listOf("2026-07-28"),
capabilities = ServerCapabilities(),
ttlMs = -1,
)
}
}
@Test
fun `unsupported version data should round trip without losing versions`() {
val data = UnsupportedProtocolVersionData(
supported = listOf("2026-07-28", "2025-11-25"),
requested = "2099-01-01",
)
val encoded = McpJson.encodeToString(data)
assertEquals(data, McpJson.decodeFromString(encoded))
assertEquals(-32022, RPCError.ErrorCode.UNSUPPORTED_PROTOCOL_VERSION)
}
}

Some files were not shown because too many files have changed in this diff Show more