-
Notifications
You must be signed in to change notification settings - Fork 175
Update notification schema #199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ import kotlinx.serialization.Serializable | |||||
| import kotlinx.serialization.json.JsonElement | ||||||
| import kotlinx.serialization.json.JsonObject | ||||||
| import kotlinx.serialization.json.JsonPrimitive | ||||||
| import kotlinx.serialization.json.buildJsonObject | ||||||
| import kotlinx.serialization.json.decodeFromJsonElement | ||||||
| import kotlinx.serialization.json.encodeToJsonElement | ||||||
| import kotlinx.serialization.json.jsonObject | ||||||
|
|
@@ -125,10 +126,11 @@ public sealed interface Request { | |||||
| * @return The JSON-RPC request representation. | ||||||
| */ | ||||||
| internal fun Request.toJSON(): JSONRPCRequest { | ||||||
| val encoded = JsonObject(McpJson.encodeToJsonElement(this).jsonObject.minus("method")) | ||||||
| val fullJson = McpJson.encodeToJsonElement(this).jsonObject | ||||||
| val params = JsonObject(fullJson.filterKeys { it != "method" }) | ||||||
| return JSONRPCRequest( | ||||||
| method = method.value, | ||||||
| params = encoded, | ||||||
| params = params, | ||||||
| jsonrpc = JSONRPC_VERSION, | ||||||
| ) | ||||||
| } | ||||||
|
|
@@ -139,8 +141,7 @@ internal fun Request.toJSON(): JSONRPCRequest { | |||||
| * @return The decoded [Request] or null | ||||||
| */ | ||||||
| internal fun JSONRPCRequest.fromJSON(): Request { | ||||||
| val requestData = JsonObject(params.jsonObject.plus("method" to JsonPrimitive(method))) | ||||||
|
|
||||||
| val requestData = JsonObject(params.jsonObject + ("method" to JsonPrimitive(method))) | ||||||
| val deserializer = selectRequestDeserializer(method) | ||||||
| return McpJson.decodeFromJsonElement(deserializer, requestData) | ||||||
| } | ||||||
|
|
@@ -159,6 +160,7 @@ public open class CustomRequest(override val method: Method) : Request | |||||
| @Serializable(with = NotificationPolymorphicSerializer::class) | ||||||
| public sealed interface Notification { | ||||||
| public val method: Method | ||||||
| public val params: NotificationParams? | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
|
|
@@ -167,10 +169,9 @@ public sealed interface Notification { | |||||
| * @return The JSON-RPC notification representation. | ||||||
| */ | ||||||
| internal fun Notification.toJSON(): JSONRPCNotification { | ||||||
| val encoded = JsonObject(McpJson.encodeToJsonElement<Notification>(this).jsonObject.minus("method")) | ||||||
| return JSONRPCNotification( | ||||||
| method.value, | ||||||
| params = encoded | ||||||
| method = method.value, | ||||||
| params = McpJson.encodeToJsonElement(params), | ||||||
| ) | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -180,7 +181,10 @@ internal fun Notification.toJSON(): JSONRPCNotification { | |||||
| * @return The decoded [Notification]. | ||||||
| */ | ||||||
| internal fun JSONRPCNotification.fromJSON(): Notification { | ||||||
| val data = JsonObject(params.jsonObject.plus("method" to JsonPrimitive(method))) | ||||||
| val data = buildJsonObject { | ||||||
| put("method", JsonPrimitive(method)) | ||||||
| put("params", params) | ||||||
| } | ||||||
| return McpJson.decodeFromJsonElement<Notification>(data) | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -295,6 +299,12 @@ public data class JSONRPCError( | |||||
| val data: JsonObject = EmptyJsonObject, | ||||||
| ) : JSONRPCMessage | ||||||
|
|
||||||
| /** | ||||||
| * Base interface for notification parameters with optional metadata. | ||||||
| */ | ||||||
| @Serializable | ||||||
| public sealed interface NotificationParams : WithMeta | ||||||
|
|
||||||
| /* Cancellation */ | ||||||
| /** | ||||||
| * This notification can be sent by either side to indicate that it is cancelling a previously issued request. | ||||||
|
|
@@ -307,19 +317,24 @@ public data class JSONRPCError( | |||||
| */ | ||||||
| @Serializable | ||||||
| public data class CancelledNotification( | ||||||
| /** | ||||||
| * The ID of the request to cancel. | ||||||
| * | ||||||
| * It MUST correspond to the ID of a request previously issued in the same direction. | ||||||
| */ | ||||||
| val requestId: RequestId, | ||||||
| /** | ||||||
| * An optional string describing the reason for the cancellation. This MAY be logged or presented to the user. | ||||||
| */ | ||||||
| val reason: String?, | ||||||
| override val _meta: JsonObject = EmptyJsonObject, | ||||||
| ) : ClientNotification, ServerNotification, WithMeta { | ||||||
| override val params: Params, | ||||||
| ) : ClientNotification, ServerNotification { | ||||||
| override val method: Method = Method.Defined.NotificationsCancelled | ||||||
|
|
||||||
| @Serializable | ||||||
| public data class Params( | ||||||
| /** | ||||||
| * The ID of the request to cancel. | ||||||
| * | ||||||
| * It MUST correspond to the ID of a request previously issued in the same direction. | ||||||
| */ | ||||||
| val requestId: RequestId, | ||||||
| /** | ||||||
| * An optional string describing the reason for the cancellation. This MAY be logged or presented to the user. | ||||||
| */ | ||||||
| val reason: String? = null, | ||||||
| override val _meta: JsonObject = EmptyJsonObject, | ||||||
| ) : NotificationParams | ||||||
| } | ||||||
|
|
||||||
| /* Initialization */ | ||||||
|
|
@@ -408,7 +423,7 @@ public sealed interface ServerResult : RequestResult | |||||
| */ | ||||||
| @Serializable | ||||||
| public data class UnknownMethodRequestOrNotification( | ||||||
| override val method: Method, | ||||||
| override val method: Method, override val params: NotificationParams? = null, | ||||||
|
||||||
| override val method: Method, override val params: NotificationParams? = null, | |
| override val method: Method, override val params: NotificationParams = DefaultNotificationParams, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The serialization logic for notifications doesn't handle null params correctly. When params is null, encoding it will create a JSON null value, but the protocol may expect the params field to be omitted entirely.