Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions kotlin-sdk-core/api/kotlin-sdk-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -606,17 +606,19 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CancelledNotificatio
public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Companion;
public fun <init> ()V
public fun <init> (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)V
public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)V
public synthetic fun <init> (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Lkotlinx/serialization/json/JsonObject;
public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;
public final fun component3 ()Lkotlinx/serialization/json/JsonObject;
public final fun component4 ()Lkotlinx/serialization/json/JsonObject;
public final fun copy (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;
public final fun component5 ()Ljava/util/Map;
public final fun copy (Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities;
public fun equals (Ljava/lang/Object;)Z
public final fun getElicitation ()Lkotlinx/serialization/json/JsonObject;
public final fun getExperimental ()Lkotlinx/serialization/json/JsonObject;
public final fun getExtensions ()Ljava/util/Map;
public final fun getRoots ()Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilities$Roots;
public final fun getSampling ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
Expand Down Expand Up @@ -676,6 +678,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ClientCapabilitiesBu
public final fun elicitation (Lkotlinx/serialization/json/JsonObject;)V
public final fun experimental (Lkotlin/jvm/functions/Function1;)V
public final fun experimental (Lkotlinx/serialization/json/JsonObject;)V
public final fun extensions (Ljava/util/Map;)V
public final fun roots (Ljava/lang/Boolean;)V
public static synthetic fun roots$default (Lio/modelcontextprotocol/kotlin/sdk/types/ClientCapabilitiesBuilder;Ljava/lang/Boolean;ILjava/lang/Object;)V
public final fun sampling (Lkotlin/jvm/functions/Function1;)V
Expand Down Expand Up @@ -4245,19 +4248,21 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Sampling_dslKt {
public final class io/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Companion;
public fun <init> ()V
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)V
public synthetic fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)V
public synthetic fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;
public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;
public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;
public final fun component4 ()Lkotlinx/serialization/json/JsonObject;
public final fun component5 ()Lkotlinx/serialization/json/JsonObject;
public final fun component6 ()Lkotlinx/serialization/json/JsonObject;
public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;
public final fun component7 ()Ljava/util/Map;
public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Tools;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Ljava/util/Map;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities;
public fun equals (Ljava/lang/Object;)Z
public final fun getCompletions ()Lkotlinx/serialization/json/JsonObject;
public final fun getExperimental ()Lkotlinx/serialization/json/JsonObject;
public final fun getExtensions ()Ljava/util/Map;
public final fun getLogging ()Lkotlinx/serialization/json/JsonObject;
public final fun getPrompts ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Prompts;
public final fun getResources ()Lio/modelcontextprotocol/kotlin/sdk/types/ServerCapabilities$Resources;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class ClientCapabilitiesBuilder @PublishedApi internal constructor() {
private var sampling: JsonObject? = null
private var roots: ClientCapabilities.Roots? = null
private var elicitation: JsonObject? = null
private var extensions: Map<String, JsonObject>? = null
private var experimental: JsonObject? = null

/**
Expand Down Expand Up @@ -132,6 +133,30 @@ public class ClientCapabilitiesBuilder @PublishedApi internal constructor() {
*/
public fun elicitation(block: JsonObjectBuilder.() -> Unit): Unit = elicitation(buildJsonObject(block))

/**
* Defines extensions that the client supports.
*
* Extension identifiers use the format `{vendor-prefix}/{extension-name}`,
* e.g., `"io.modelcontextprotocol/ui"`. Each value is an extension-specific
* settings object; an empty [JsonObject] indicates no settings.
*
* Example:
* ```kotlin
* capabilities {
* extensions(mapOf(
* "io.modelcontextprotocol/ui" to buildJsonObject {
* put("mimeTypes", JsonArray(listOf(JsonPrimitive("text/html"))))
* }
* ))
* }
* ```
*
* @param value The map of extension identifiers to their settings
*/
public fun extensions(value: Map<String, JsonObject>) {
this.extensions = value
}

/**
* Defines experimental, non-standard capabilities that the client supports.
*
Expand Down Expand Up @@ -177,6 +202,7 @@ public class ClientCapabilitiesBuilder @PublishedApi internal constructor() {
sampling = sampling,
roots = roots,
elicitation = elicitation,
extensions = extensions,
experimental = experimental,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,17 @@ public data class Implementation(
* @property elicitation Present if the client supports elicitation from the server.
* @property experimental Experimental, non-standard capabilities that the client supports.
* Keys are capability names, values are capability-specific configuration objects.
* @property extensions Optional extensions that the client supports.
* Keys are extension identifiers (e.g., `"io.modelcontextprotocol/ui"`),
* values are extension-specific settings objects.
*/
@Serializable
public data class ClientCapabilities(
public val sampling: JsonObject? = null,
public val roots: Roots? = null,
public val elicitation: JsonObject? = null,
public val experimental: JsonObject? = null,
public val extensions: Map<String, JsonObject>? = null,
) {
Comment on lines 55 to 59
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the new extensions parameter to ClientCapabilities changes the primary constructor/signature and Kotlin default-args synthetic constructor, which is ABI-breaking for already-compiled Kotlin/Java consumers (potential NoSuchMethodError). This should be called out as a breaking change in the PR/release notes, or mitigated by preserving the old constructor signature (e.g., a deprecated secondary constructor delegating to the new one with extensions = null).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

@eritscher eritscher Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kpavlov not sure if this is a false positive. It doesn't look anything has been done to preserve constructor signatures in the past. I can mention this in the PR description.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true


/**
Expand Down Expand Up @@ -93,6 +97,9 @@ public data class ClientCapabilities(
* @property completions Present if the server supports argument autocompletion suggestions.
* Keys are capability names, values are capability-specific configuration objects.
* @property experimental Experimental, non-standard capabilities that the server supports.
* @property extensions Optional extensions that the server supports.
* Keys are extension identifiers (e.g., `"io.modelcontextprotocol/ui"`),
* values are extension-specific settings objects.
*/
@Serializable
public data class ServerCapabilities(
Expand All @@ -102,6 +109,7 @@ public data class ServerCapabilities(
val logging: JsonObject? = null,
val completions: JsonObject? = null,
val experimental: JsonObject? = null,
val extensions: Map<String, JsonObject>? = null,
) {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,53 @@ class CapabilitiesTest {
)
}

@Test
fun `should serialize ClientCapabilities with extensions`() {
val extensions = mapOf(
"io.modelcontextprotocol/ui" to buildJsonObject {
put("mimeTypes", buildJsonObject { put("text/html", true) })
},
)
val capabilities = ClientCapabilities(
extensions = extensions,
)
verifySerialization(
capabilities,
McpJson,
"""
{
"extensions": {
"io.modelcontextprotocol/ui": {
"mimeTypes": {
"text/html": true
}
}
}
}
""".trimIndent(),
)
}

@Test
fun `should serialize ClientCapabilities with empty extensions settings`() {
val capabilities = ClientCapabilities(
extensions = mapOf(
"io.modelcontextprotocol/ui" to EmptyJsonObject,
),
)
verifySerialization(
capabilities,
McpJson,
"""
{
"extensions": {
"io.modelcontextprotocol/ui": {}
}
}
""".trimIndent(),
)
}

@Test
fun `should serialize ClientCapabilities with experimental`() {
val experimental = buildJsonObject {
Expand Down Expand Up @@ -215,11 +262,15 @@ class CapabilitiesTest {
val experimental = buildJsonObject {
put("feature1", buildJsonObject { put("enabled", true) })
}
val extensions = mapOf(
"io.modelcontextprotocol/ui" to EmptyJsonObject,
)
val capabilities = ClientCapabilities(
sampling = ClientCapabilities.sampling,
roots = ClientCapabilities.Roots(listChanged = true),
elicitation = ClientCapabilities.elicitation,
experimental = experimental,
extensions = extensions,
)
verifySerialization(
capabilities,
Expand All @@ -235,6 +286,9 @@ class CapabilitiesTest {
"feature1": {
"enabled": true
}
},
"extensions": {
"io.modelcontextprotocol/ui": {}
}
}
""".trimIndent(),
Expand Down Expand Up @@ -270,6 +324,7 @@ class CapabilitiesTest {
assertNull(capabilities.roots)
assertNull(capabilities.elicitation)
assertNull(capabilities.experimental)
assertNull(capabilities.extensions)
}

@Test
Expand All @@ -278,6 +333,11 @@ class CapabilitiesTest {
sampling = ClientCapabilities.sampling,
roots = ClientCapabilities.Roots(listChanged = false),
elicitation = ClientCapabilities.elicitation,
extensions = mapOf(
"io.modelcontextprotocol/ui" to buildJsonObject {
put("mimeTypes", buildJsonObject { put("text/html", true) })
},
),
)

verifySerializationRoundTrip(original, McpJson)
Expand Down Expand Up @@ -466,6 +526,32 @@ class CapabilitiesTest {
)
}

@Test
fun `should serialize ServerCapabilities with extensions`() {
val capabilities = ServerCapabilities(
extensions = mapOf(
"io.modelcontextprotocol/ui" to EmptyJsonObject,
"com.example/custom" to buildJsonObject {
put("setting", "value")
},
),
)
verifySerialization(
capabilities,
McpJson,
"""
{
"extensions": {
"io.modelcontextprotocol/ui": {},
"com.example/custom": {
"setting": "value"
}
}
}
""".trimIndent(),
)
}

@Test
fun `should serialize ServerCapabilities with experimental`() {
val experimental = buildJsonObject {
Expand Down Expand Up @@ -499,6 +585,9 @@ class CapabilitiesTest {
val experimental = buildJsonObject {
put("feature1", buildJsonObject { put("enabled", true) })
}
val extensions = mapOf(
"io.modelcontextprotocol/ui" to EmptyJsonObject,
)
val capabilities = ServerCapabilities(
tools = ServerCapabilities.Tools(listChanged = true),
resources = ServerCapabilities.Resources(
Expand All @@ -509,6 +598,7 @@ class CapabilitiesTest {
logging = ServerCapabilities.Logging,
completions = ServerCapabilities.Completions,
experimental = experimental,
extensions = extensions,
)
verifySerialization(
capabilities,
Expand All @@ -531,6 +621,9 @@ class CapabilitiesTest {
"feature1": {
"enabled": true
}
},
"extensions": {
"io.modelcontextprotocol/ui": {}
}
}
""".trimIndent(),
Expand Down Expand Up @@ -578,6 +671,7 @@ class CapabilitiesTest {
assertNull(capabilities.logging)
assertNull(capabilities.completions)
assertNull(capabilities.experimental)
assertNull(capabilities.extensions)
}

@Test
Expand All @@ -590,6 +684,9 @@ class CapabilitiesTest {
),
prompts = ServerCapabilities.Prompts(listChanged = true),
logging = ServerCapabilities.Logging,
extensions = mapOf(
"io.modelcontextprotocol/ui" to EmptyJsonObject,
),
)

verifySerializationRoundTrip(original, McpJson)
Expand Down
Loading
Loading