Skip to content

Commit 3c38c82

Browse files
committed
Rewrite and restructure schema types
1 parent 33b2f62 commit 3c38c82

File tree

22 files changed

+3077
-0
lines changed

22 files changed

+3077
-0
lines changed

kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public const val IMPLEMENTATION_NAME: String = "mcp-ktor"
5151
public typealias ProgressCallback = (Progress) -> Unit
5252

5353
@OptIn(ExperimentalSerializationApi::class)
54+
@Deprecated("Use McpJson instead", ReplaceWith("McpJson"))
5455
public val McpJson: Json by lazy {
5556
Json {
5657
ignoreUnknownKeys = true

kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt

Lines changed: 590 additions & 0 deletions
Large diffs are not rendered by default.

kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.util.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@ internal object JSONRPCMessagePolymorphicSerializer :
265265
}
266266
}
267267

268+
@Deprecated(
269+
message = "Use `io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject` instead",
270+
replaceWith = ReplaceWith("EmptyJsonObject", "io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject"),
271+
level = DeprecationLevel.WARNING,
272+
)
268273
public val EmptyJsonObject: JsonObject = JsonObject(emptyMap())
269274

270275
public class RequestIdSerializer : KSerializer<RequestId> {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.modelcontextprotocol.kotlin.sdk.types
2+
3+
import kotlinx.serialization.json.JsonObject
4+
5+
/**
6+
* Represents an error specific to the MCP protocol.
7+
*
8+
* @property code The error code.
9+
* @property message The error message.
10+
* @property data Additional error data as a JSON object.
11+
*/
12+
public class McpException(public val code: Int, message: String, public val data: JsonObject? = null) : Exception() {
13+
override val message: String = "MCP error $code: $message"
14+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package io.modelcontextprotocol.kotlin.sdk.types
2+
3+
import kotlinx.serialization.Serializable
4+
import kotlinx.serialization.json.JsonObject
5+
6+
/**
7+
* Describes an MCP (Model Context Protocol) implementation.
8+
*
9+
* This metadata helps clients identify and display information about servers or clients,
10+
* including their name, version, and optional branding elements like icons and website links.
11+
*
12+
* @property name The programmatic identifier for this implementation.
13+
* Intended for logical use and API identification. If [title] is not provided,
14+
* this should be used as a fallback display name.
15+
* @property version The version string of this implementation (e.g., "1.0.0", "2.1.3-beta").
16+
* @property title Optional human-readable display name for this implementation.
17+
* Intended for UI and end-user contexts, optimized to be easily understood
18+
* even by those unfamiliar with domain-specific terminology.
19+
* If not provided, [name] should be used for display purposes.
20+
* @property websiteUrl Optional URL of the website for this implementation.
21+
* Can be used to provide documentation, support, or additional information.
22+
* @property icons Optional set of sized icons that clients can display in their user interface.
23+
* See [Icon] for supported formats and requirements.
24+
*/
25+
@Serializable
26+
public data class Implementation(
27+
val name: String,
28+
val version: String,
29+
val title: String? = null,
30+
val websiteUrl: String? = null,
31+
val icons: List<Icon>? = null,
32+
)
33+
34+
/**
35+
* Capabilities that a client may support.
36+
*
37+
* Known capabilities are defined here, but this is not a closed set: any client
38+
* can define its own additional capabilities through the [experimental] field.
39+
*
40+
* The presence of a capability object (non-null value) indicates that the client
41+
* supports that capability.
42+
*
43+
* @property sampling Present if the client supports sampling from an LLM.
44+
* @property roots Present if the client supports listing roots.
45+
* @property elicitation Present if the client supports elicitation from the server.
46+
* @property experimental Experimental, non-standard capabilities that the client supports.
47+
* Keys are capability names, values are capability-specific configuration objects.
48+
*/
49+
@Serializable
50+
public data class ClientCapabilities(
51+
public val sampling: JsonObject? = null,
52+
public val roots: Roots? = null,
53+
public val elicitation: JsonObject? = null,
54+
public val experimental: JsonObject? = null,
55+
) {
56+
57+
public companion object {
58+
public val sampling: JsonObject = EmptyJsonObject
59+
public val elicitation: JsonObject = EmptyJsonObject
60+
}
61+
62+
/**
63+
* Indicates that the client supports listing roots.
64+
*
65+
* Roots are the top-level directories or locations that the server can access.
66+
* When present (non-null), the server can query available roots and optionally
67+
* receive notifications when the roots list changes.
68+
*
69+
* @property listChanged Whether the client supports notifications for changes to the roots list.
70+
* If true, the client will send notifications when roots are added or removed.
71+
*/
72+
@Serializable
73+
public data class Roots(val listChanged: Boolean? = null)
74+
}
75+
76+
/**
77+
* Capabilities that a server may support.
78+
*
79+
* Known capabilities are defined here, but this is not a closed set: any server
80+
* can define its own additional capabilities through the [experimental] field.
81+
*
82+
* The presence of a capability object (non-null value) indicates that the server
83+
* supports that capability.
84+
*
85+
* @property tools Present if the server offers any tools to call.
86+
* @property resources Present if the server offers any resources to read.
87+
* @property prompts Present if the server offers any prompt templates.
88+
* @property logging Present if the server supports sending log messages to the client.
89+
* @property completions Present if the server supports argument autocompletion suggestions.
90+
* Keys are capability names, values are capability-specific configuration objects.
91+
* @property experimental Experimental, non-standard capabilities that the server supports.
92+
*/
93+
@Serializable
94+
public data class ServerCapabilities(
95+
val tools: Tools? = null,
96+
val resources: Resources? = null,
97+
val prompts: Prompts? = null,
98+
val logging: JsonObject? = null,
99+
val completions: JsonObject? = null,
100+
val experimental: JsonObject? = null,
101+
) {
102+
103+
public companion object {
104+
public val Logging: JsonObject = EmptyJsonObject
105+
public val Completions: JsonObject = EmptyJsonObject
106+
}
107+
108+
/**
109+
* Indicates that the server offers tools to call.
110+
*
111+
* When present (non-null), clients can list and invoke tools (functions, actions, etc.)
112+
* provided by the server.
113+
*
114+
* @property listChanged Whether this server supports notifications for changes to the tool list.
115+
* If true, the server will send notifications when tools are added, modified, or removed.
116+
*/
117+
@Serializable
118+
public data class Tools(val listChanged: Boolean? = null)
119+
120+
/**
121+
* Indicates that the server offers resources to read.
122+
*
123+
* When present (non-null), clients can list and read resources (files, data sources, etc.)
124+
* provided by the server.
125+
*
126+
* @property listChanged Whether this server supports notifications for changes to the resource list.
127+
* If true, the server will send notifications when resources are added or removed.
128+
* @property subscribe Whether this server supports subscribing to resource updates.
129+
* If true, clients can subscribe to receive notifications when specific
130+
* resources are modified.
131+
*/
132+
@Serializable
133+
public data class Resources(val listChanged: Boolean? = null, val subscribe: Boolean? = null)
134+
135+
/**
136+
* Indicates that the server offers prompt templates.
137+
*
138+
* When present (non-null), clients can list and invoke prompts provided by the server.
139+
*
140+
* @property listChanged Whether this server supports notifications for changes to the prompt list.
141+
* If true, the server will send notifications when prompts are added, modified, or removed.
142+
*/
143+
@Serializable
144+
public data class Prompts(val listChanged: Boolean? = null)
145+
}
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package io.modelcontextprotocol.kotlin.sdk.types
2+
3+
import kotlinx.serialization.ExperimentalSerializationApi
4+
import kotlinx.serialization.SerialName
5+
import kotlinx.serialization.Serializable
6+
import kotlinx.serialization.json.JsonClassDiscriminator
7+
import kotlinx.serialization.json.JsonObject
8+
import kotlin.jvm.JvmInline
9+
10+
// ============================================================================
11+
// Protocol Version Constants
12+
// ============================================================================
13+
14+
public const val LATEST_PROTOCOL_VERSION: String = "2025-03-26"
15+
16+
public val SUPPORTED_PROTOCOL_VERSIONS: Array<String> = arrayOf(
17+
LATEST_PROTOCOL_VERSION,
18+
"2024-11-05",
19+
)
20+
21+
// ============================================================================
22+
// Base Interfaces
23+
// ============================================================================
24+
25+
/**
26+
* Represents an entity that includes additional metadata in its responses.
27+
*/
28+
// TODO: реализовать meta
29+
// The _meta property/parameter is reserved by MCP to allow clients and servers to attach additional metadata to their interactions.
30+
// Certain key names are reserved by MCP for protocol-level metadata, as specified below; implementations MUST NOT make assumptions about values at these keys.
31+
// Additionally, definitions in the schema may reserve particular names for purpose-specific metadata, as declared in those definitions.
32+
// Key name format: valid _meta key names have two segments: an optional prefix, and a name.
33+
// Prefix:
34+
// If specified, MUST be a series of labels separated by dots (.), followed by a slash (/).
35+
// Labels MUST start with a letter and end with a letter or digit; interior characters can be letters, digits, or hyphens (-).
36+
// Any prefix beginning with zero or more valid labels, followed by modelcontextprotocol or mcp, followed by any valid label, is reserved for MCP use.
37+
// For example: modelcontextprotocol.io/, mcp.dev/, api.modelcontextprotocol.org/, and tools.mcp.com/ are all reserved.
38+
// Name:
39+
// Unless empty, MUST begin and end with an alphanumeric character ([a-z0-9A-Z]).
40+
// MAY contain hyphens (-), underscores (_), dots (.), and alphanumerics in between.
41+
@Serializable
42+
public sealed interface WithMeta {
43+
@SerialName("_meta")
44+
public val meta: JsonObject?
45+
}
46+
47+
// ============================================================================
48+
// Tokens
49+
// ============================================================================
50+
51+
/**
52+
* A progress token, used to associate progress notifications with the original request.
53+
*/
54+
@Serializable // TODO custom serializer
55+
public sealed interface ProgressToken {
56+
@JvmInline
57+
@Serializable
58+
public value class ProgressTokenString(public val value: String) : ProgressToken
59+
60+
@JvmInline
61+
@Serializable
62+
public value class ProgressTokenInt(public val value: Long) : ProgressToken
63+
}
64+
65+
// ============================================================================
66+
// Visual Elements
67+
// ============================================================================
68+
69+
/**
70+
* An optionally sized icon that can be displayed in a user interface.
71+
*
72+
* Icons help clients provide visual branding and identification for MCP implementations.
73+
*
74+
* **Security considerations:**
75+
* - Consumers SHOULD ensure URLs serving icons are from the same domain as the client/server
76+
* or a trusted domain to prevent malicious content.
77+
* - Consumers SHOULD take appropriate precautions when rendering SVGs as they can contain
78+
* executable JavaScript. Consider sanitizing SVG content or rendering in isolated contexts.
79+
*
80+
* @property src A standard URI pointing to an icon resource.
81+
* Maybe an HTTP/HTTPS URL or a data: URI with Base64-encoded image data.
82+
* Example: "https://example.com/icon.png" or "data:image/png;base64,iVBORw0KG..."
83+
* @property mimeType Optional MIME type override if the source MIME type is missing or generic.
84+
* For example, "image/png", "image/jpeg", or "image/svg+xml".
85+
* Useful when the URL doesn't include a file extension or uses a generic MIME type.
86+
* @property sizes Optional array of strings that specify sizes at which the icon can be used.
87+
* Each string should be in WxH format (e.g., "48x48", "96x96") or "any" for
88+
* scalable formats like SVG. If not provided, the client should assume that
89+
* the icon can be used at any size.
90+
* @property theme Optional specifier for the theme this icon is designed for.
91+
* [Theme.Light] indicates the icon is designed for a light background,
92+
* [Theme.Dark] indicates the icon is designed for a dark background.
93+
* If not provided, the client should assume the icon can be used with any theme.
94+
*/
95+
@Serializable
96+
public data class Icon(
97+
val src: String,
98+
val mimeType: String? = null,
99+
val sizes: List<String>? = null,
100+
val theme: Theme? = null,
101+
) {
102+
/**
103+
* The theme context for which an icon is designed.
104+
*
105+
* @property Light Icon designed for use with a light background (typically darker icon).
106+
* @property Dark Icon designed for use with a dark background (typically lighter icon).
107+
*/
108+
@Serializable
109+
public enum class Theme {
110+
/** Icon designed for use with a light background */
111+
@SerialName("light")
112+
Light,
113+
114+
/** Icon designed for use with a dark background */
115+
@SerialName("dark")
116+
Dark,
117+
}
118+
}
119+
120+
// ============================================================================
121+
// Roles and References
122+
// ============================================================================
123+
124+
/**
125+
* The sender or recipient of messages and data in a conversation.
126+
*/
127+
@Serializable
128+
public enum class Role {
129+
@SerialName("user")
130+
User,
131+
132+
@SerialName("assistant")
133+
Assistant,
134+
}
135+
136+
/**
137+
* Base interface for reference types in the protocol.
138+
*
139+
* References are used to point to other entities (prompts, resources, etc.)
140+
* without including their full definitions.
141+
*/
142+
@OptIn(ExperimentalSerializationApi::class)
143+
@Serializable
144+
@JsonClassDiscriminator("type")
145+
public sealed interface Reference
146+
147+
// ============================================================================
148+
// Annotations and Metadata
149+
// ============================================================================
150+
151+
/**
152+
* Optional annotations for the client.
153+
*
154+
* The client can use annotations to inform how objects are used or displayed.
155+
*
156+
* @property audience Describes who the intended customer of this object or data is.
157+
* Can include multiple entries to indicate content useful for multiple audiences
158+
* (e.g., [Role.user, Role.assistant]).
159+
* @property priority Describes how important this data is for operating the server.
160+
* A value of 1.0 means "most important" and indicates that the data is effectively required,
161+
* while 0.0 means "least important" and indicates that the data is entirely optional.
162+
* Should be a value between 0.0 and 1.0.
163+
* @property lastModified The moment the resource was last modified, as an ISO 8601 formatted string
164+
* (e.g., "2025-01-12T15:00:58Z").
165+
* Examples: last activity timestamp in an open file, timestamp when the resource was attached, etc.
166+
*/
167+
@Serializable
168+
public data class Annotations(
169+
val audience: List<Role>? = null,
170+
val priority: Double? = null,
171+
val lastModified: String? = null,
172+
) {
173+
init {
174+
require(priority == null || priority in 0.0..1.0) { "Priority must be between 0.0 and 1.0" }
175+
}
176+
}

0 commit comments

Comments
 (0)