Skip to content

Commit 7434af9

Browse files
authored
Merge branch 'main' into feature/streamable-http-missing-tests
2 parents 849b21c + cceca4d commit 7434af9

43 files changed

Lines changed: 472 additions & 53 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/kdoc/SKILL.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
name: kdoc
3+
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."
4+
---
5+
6+
# KDoc Generator
7+
8+
Add KDoc comments to public Kotlin API declarations.
9+
10+
## What to document
11+
12+
All public declarations (no explicit `private`/`internal`/`protected`):
13+
- Classes, interfaces, objects, sealed classes/interfaces
14+
- Functions, extension functions
15+
- Properties
16+
- Enum classes and entries
17+
- Type aliases, annotation classes
18+
19+
Include `@Deprecated` elements.
20+
21+
## Context
22+
23+
Read the implementation, not just the signature, to write accurate descriptions. Understanding what the code actually does prevents superficial or misleading documentation.
24+
25+
## KDoc format
26+
27+
**Class/interface example:**
28+
29+
````kotlin
30+
/**
31+
* Manages active client sessions and their lifecycle.
32+
*
33+
* Sessions are created on first connection and cleaned up
34+
* when the transport closes.
35+
*
36+
* @property maxSessions upper limit on concurrent sessions
37+
* @property timeout idle timeout before a session is evicted
38+
*/
39+
````
40+
41+
**Function example:**
42+
43+
````kotlin
44+
/**
45+
* Registers a new tool with the given handler.
46+
*
47+
* Example:
48+
* ```kotlin
49+
* server.addTool(
50+
* name = "echo",
51+
* description = "Echoes input back",
52+
* ) { request ->
53+
* CallToolResult(content = listOf(TextContent("Echo: ${request.arguments}")))
54+
* }
55+
* ```
56+
*
57+
* @param name unique tool identifier
58+
* @param description human-readable tool description
59+
* @param handler suspend function invoked when the tool is called
60+
* @return the registered tool definition
61+
*/
62+
````
63+
64+
## Rules
65+
66+
- Summary: concise first sentence starting with a third-person verb ("Creates", "Returns", "Represents"). Expand to 2-3 sentences only when genuinely complex
67+
- **@property** in class-level KDoc for all public properties (never as individual KDoc on the property); **@param** for function parameters
68+
- **@return** for non-Unit return types
69+
- **Example block**: add for DSL builders, complex functions, extension functions with non-obvious usage. Skip for trivial one-liners and simple getters
70+
- **DSL builders**: always include an Example showing full usage with the receiver scope — this is critical for discoverability
71+
- KDoc links (`[ClassName]`, `[methodName]`): only where it adds clear navigational value
72+
- No **@throws** — don't document exceptions
73+
- No **suspend** notes — coroutine nature is visible from the signature
74+
- **Existing KDoc**: rewrite if incomplete (missing @param/@return/@property) or low quality

config/detekt/detekt.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,22 @@ empty-blocks:
2222
EmptyFunctionBlock:
2323
excludes: *testFolders
2424

25+
comments:
26+
UndocumentedPublicClass:
27+
active: true
28+
excludes: &testAndGeneratedFolders
29+
- '**/test/**'
30+
- '**/commonTest/**'
31+
- '**/jvmTest/**'
32+
- '**/jsTest/**'
33+
- '**/iosTest/**'
34+
- '**/generated-sources/**'
35+
ignoreDefaultCompanionObject: true
36+
UndocumentedPublicFunction:
37+
active: true
38+
excludes: *testAndGeneratedFolders
39+
UndocumentedPublicProperty:
40+
active: true
41+
excludes: *testAndGeneratedFolders
42+
searchProtectedProperty: false
43+
ignoreEnumEntries: true

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ kotlin.daemon.jvmargs=-Xmx4G
88
kotlin.native.ignoreDisabledTargets=true
99

1010
group=io.modelcontextprotocol
11-
version=0.10.0
11+
version=0.11.0

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ openapi-generator = "7.21.0"
1616
awaitility = "4.3.0"
1717
collections-immutable = "0.4.0"
1818
coroutines = "1.10.2"
19-
kotest = "6.1.9"
19+
kotest = "6.1.11"
2020
kotlinx-io = "0.9.0"
2121
ktor = "3.3.3"
2222
logging = "8.0.01"

integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionTest.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import io.kotest.matchers.string.shouldNotBeBlank
77
import io.modelcontextprotocol.kotlin.sdk.types.CallToolRequest
88
import io.modelcontextprotocol.kotlin.sdk.types.CallToolRequestParams
99
import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities
10+
import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotification
11+
import io.modelcontextprotocol.kotlin.sdk.types.ElicitationCompleteNotificationParams
1012
import io.modelcontextprotocol.kotlin.sdk.types.GetPromptRequest
1113
import io.modelcontextprotocol.kotlin.sdk.types.GetPromptRequestParams
1214
import io.modelcontextprotocol.kotlin.sdk.types.ListRootsRequest
@@ -77,6 +79,8 @@ class ClientConnectionTest : AbstractServerFeaturesTest() {
7779
val loggingMessage = onClientNotification<LoggingMessageNotification>(Method.Defined.NotificationsMessage)
7880
val resourceUpdated =
7981
onClientNotification<ResourceUpdatedNotification>(Method.Defined.NotificationsResourcesUpdated)
82+
val elicitationComplete =
83+
onClientNotification<ElicitationCompleteNotification>(Method.Defined.NotificationsElicitationComplete)
8084

8185
init {
8286
onClientRequest<ListRootsRequest, ListRootsResult>(Method.Defined.RootsList) {
@@ -109,6 +113,12 @@ class ClientConnectionTest : AbstractServerFeaturesTest() {
109113
withClue("sendResourceUpdated() delivered wrong URI") {
110114
resourceUri shouldBe "test://res"
111115
}
116+
withClue("sendElicitationComplete() did not deliver a notification to the client") {
117+
elicitationComplete.isCompleted shouldBe true
118+
}
119+
withClue("sendElicitationComplete() delivered wrong elicitationId") {
120+
elicitationComplete.await().params.elicitationId shouldBe "elicit-123"
121+
}
112122
capturedSessionId.shouldNotBeBlank()
113123
}
114124
}
@@ -128,6 +138,9 @@ class ClientConnectionTest : AbstractServerFeaturesTest() {
128138
),
129139
)
130140
sendResourceUpdated(ResourceUpdatedNotification(ResourceUpdatedNotificationParams("test://res")))
141+
sendElicitationComplete(
142+
ElicitationCompleteNotification(ElicitationCompleteNotificationParams(elicitationId = "elicit-123")),
143+
)
131144
cap.sessionId.complete(sessionId)
132145
}
133146

integration-test/src/jvmTest/typescript/package-lock.json

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

integration-test/src/jvmTest/typescript/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
"server:http": "tsx server/http-server.ts"
1010
},
1111
"dependencies": {
12-
"@modelcontextprotocol/sdk": "^1.28.0",
12+
"@modelcontextprotocol/sdk": "^1.29.0",
1313
"express": "^5.2.1",
1414
"zod": "^4.3.6"
1515
},
1616
"devDependencies": {
1717
"@types/cors": "^2.8.19",
1818
"@types/express": "^5.0.6",
19-
"@types/node": "^25.5.0",
19+
"@types/node": "^25.5.2",
2020
"cors": "^2.8.6",
2121
"tsx": "^4.21.0",
2222
"typescript": "^6.0.2"

kotlin-sdk-client/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ private const val MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version"
5151
private const val MCP_RESUMPTION_TOKEN_HEADER = "Last-Event-ID"
5252

5353
/**
54-
* Error class for Streamable HTTP transport errors.
54+
* Represents an error from the Streamable HTTP transport.
55+
*
56+
* @property code HTTP status code associated with the error, or `null` if unavailable
5557
*/
5658
public class StreamableHttpError(public val code: Int? = null, message: String? = null) :
5759
Exception("Streamable HTTP error: $message")
@@ -66,6 +68,9 @@ private sealed interface ConnectResult {
6668
* Client transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.
6769
* It will connect to a server using HTTP POST for sending messages and HTTP GET with Server-Sent Events
6870
* for receiving messages.
71+
*
72+
* @property sessionId session identifier assigned by the server after initialization, or `null` before connection
73+
* @property protocolVersion MCP protocol version negotiated with the server, or `null` before connection
6974
*/
7075
@Suppress("TooManyFunctions")
7176
public class StreamableHttpClientTransport(

kotlin-sdk-core/api/kotlin-sdk-core.api

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,65 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitResult$Compani
14171417
public final fun serializer ()Lkotlinx/serialization/KSerializer;
14181418
}
14191419

1420+
public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification : io/modelcontextprotocol/kotlin/sdk/types/ServerNotification {
1421+
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification$Companion;
1422+
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;)V
1423+
public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;
1424+
public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification;
1425+
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification;Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification;
1426+
public fun equals (Ljava/lang/Object;)Z
1427+
public fun getMethod ()Lio/modelcontextprotocol/kotlin/sdk/types/Method;
1428+
public fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;
1429+
public synthetic fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/NotificationParams;
1430+
public fun hashCode ()I
1431+
public fun toString ()Ljava/lang/String;
1432+
}
1433+
1434+
public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
1435+
public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification$$serializer;
1436+
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
1437+
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification;
1438+
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
1439+
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
1440+
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification;)V
1441+
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
1442+
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
1443+
}
1444+
1445+
public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotification$Companion {
1446+
public final fun serializer ()Lkotlinx/serialization/KSerializer;
1447+
}
1448+
1449+
public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams : io/modelcontextprotocol/kotlin/sdk/types/NotificationParams {
1450+
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams$Companion;
1451+
public fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;)V
1452+
public synthetic fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1453+
public final fun component1 ()Ljava/lang/String;
1454+
public final fun component2 ()Lkotlinx/serialization/json/JsonObject;
1455+
public final fun copy (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;
1456+
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;
1457+
public fun equals (Ljava/lang/Object;)Z
1458+
public final fun getElicitationId ()Ljava/lang/String;
1459+
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
1460+
public fun hashCode ()I
1461+
public fun toString ()Ljava/lang/String;
1462+
}
1463+
1464+
public final synthetic class io/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
1465+
public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams$$serializer;
1466+
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
1467+
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;
1468+
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
1469+
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
1470+
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams;)V
1471+
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
1472+
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
1473+
}
1474+
1475+
public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitationCompleteNotificationParams$Companion {
1476+
public final fun serializer ()Lkotlinx/serialization/KSerializer;
1477+
}
1478+
14201479
public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitationKt {
14211480
public static final fun ElicitRequestParams-EDEVuBg (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/ElicitRequestParams$RequestedSchema;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitRequestFormParams;
14221481
public static synthetic fun ElicitRequestParams-EDEVuBg$default (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/ElicitRequestParams$RequestedSchema;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ElicitRequestFormParams;
@@ -2939,6 +2998,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Method$Defined : jav
29392998
public static final field Initialize Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
29402999
public static final field LoggingSetLevel Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
29413000
public static final field NotificationsCancelled Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
3001+
public static final field NotificationsElicitationComplete Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
29423002
public static final field NotificationsInitialized Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
29433003
public static final field NotificationsMessage Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;
29443004
public static final field NotificationsProgress Lio/modelcontextprotocol/kotlin/sdk/types/Method$Defined;

kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/internal/utils.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ package io.modelcontextprotocol.kotlin.sdk.internal
22

33
import kotlinx.coroutines.CoroutineDispatcher
44

5+
/** Platform-specific [CoroutineDispatcher] for I/O-bound operations. */
56
public expect val IODispatcher: CoroutineDispatcher

0 commit comments

Comments
 (0)