Skip to content

Commit fd3a858

Browse files
authored
feat: add tasks models (#566)
## Motivation and Context closes #421 #406 ## How Has This Been Tested? Unit tests ## Breaking Changes NaN ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed
1 parent 62e4e50 commit fd3a858

8 files changed

Lines changed: 1904 additions & 0 deletions

File tree

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

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

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,18 @@ public sealed interface Method {
3232
NotificationsToolsListChanged("notifications/tools/list_changed"),
3333
NotificationsRootsListChanged("notifications/roots/list_changed"),
3434
NotificationsPromptsListChanged("notifications/prompts/list_changed"),
35+
NotificationsTasksStatus("notifications/tasks/status"),
3536
ToolsList("tools/list"),
3637
ToolsCall("tools/call"),
3738
LoggingSetLevel("logging/setLevel"),
3839
SamplingCreateMessage("sampling/createMessage"),
3940
CompletionComplete("completion/complete"),
4041
RootsList("roots/list"),
4142
ElicitationCreate("elicitation/create"),
43+
TasksGet("tasks/get"),
44+
TasksResult("tasks/result"),
45+
TasksList("tasks/list"),
46+
TasksCancel("tasks/cancel"),
4247
}
4348

4449
/**

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,48 @@ public data class ToolListChangedNotification(override val params: BaseNotificat
348348
@EncodeDefault
349349
override val method: Method = Method.Defined.NotificationsToolsListChanged
350350
}
351+
352+
// ============================================================================
353+
// Task Status Notification
354+
// ============================================================================
355+
356+
/**
357+
* An optional notification from the receiver to the requestor, informing them that a task’s status has changed.
358+
* Receivers are not required to send these notifications.
359+
*
360+
* This notification can be sent by either side (both [ClientNotification] and [ServerNotification]).
361+
*
362+
* @property params The task status notification parameters containing the current task state.
363+
*/
364+
@Serializable
365+
public data class TaskStatusNotification(override val params: TaskStatusNotificationParams? = null) :
366+
ClientNotification,
367+
ServerNotification {
368+
@EncodeDefault
369+
override val method: Method = Method.Defined.NotificationsTasksStatus
370+
}
371+
372+
/**
373+
* Parameters for a notifications/tasks/status notification.
374+
*
375+
* @property taskId The task identifier.
376+
* @property status Current task state.
377+
* @property statusMessage Optional human-readable message describing the current task state.
378+
* @property createdAt ISO 8601 timestamp when the task was created.
379+
* @property lastUpdatedAt ISO 8601 timestamp when the task was last updated.
380+
* @property ttl Actual retention duration from creation in milliseconds, null for unlimited.
381+
* @property pollInterval Suggested polling interval in milliseconds.
382+
* @property meta Optional metadata for this notification.
383+
*/
384+
@Serializable
385+
public data class TaskStatusNotificationParams(
386+
override val taskId: String,
387+
override val status: TaskStatus,
388+
override val statusMessage: String? = null,
389+
override val createdAt: String,
390+
override val lastUpdatedAt: String,
391+
override val ttl: Long?,
392+
override val pollInterval: Long? = null,
393+
@SerialName("_meta") override val meta: JsonObject? = null,
394+
) : NotificationParams,
395+
TaskFields

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import kotlinx.serialization.Serializable
66
import kotlinx.serialization.json.JsonElement
77
import kotlinx.serialization.json.JsonObject
88
import kotlinx.serialization.json.JsonPrimitive
9+
import kotlinx.serialization.json.decodeFromJsonElement
910
import kotlinx.serialization.json.long
1011
import kotlinx.serialization.json.longOrNull
1112
import kotlin.jvm.JvmInline
@@ -22,6 +23,17 @@ public value class RequestMeta(public val json: JsonObject) {
2223
}
2324
}
2425

26+
/**
27+
* The related task metadata, if this request is associated with a task.
28+
*
29+
* @see RelatedTaskMetadata
30+
* @see RELATED_TASK_META_KEY
31+
*/
32+
public val relatedTask: RelatedTaskMetadata?
33+
get() = json[RELATED_TASK_META_KEY]?.let { element ->
34+
McpJson.decodeFromJsonElement(element)
35+
}
36+
2537
/**
2638
* Retrieves the value associated with the specified key from the JSON object.
2739
*

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ private val clientRequestDeserializers: Map<String, DeserializationStrategy<Clie
159159
Method.Defined.ResourcesTemplatesList.value to ListResourceTemplatesRequest.serializer(),
160160
Method.Defined.ToolsCall.value to CallToolRequest.serializer(),
161161
Method.Defined.ToolsList.value to ListToolsRequest.serializer(),
162+
Method.Defined.TasksGet.value to GetTaskRequest.serializer(),
163+
Method.Defined.TasksResult.value to GetTaskPayloadRequest.serializer(),
164+
Method.Defined.TasksList.value to ListTasksRequest.serializer(),
165+
Method.Defined.TasksCancel.value to CancelTaskRequest.serializer(),
162166
)
163167
}
164168

@@ -175,6 +179,10 @@ private val serverRequestDeserializers: Map<String, DeserializationStrategy<Serv
175179
Method.Defined.Ping.value to PingRequest.serializer(),
176180
Method.Defined.RootsList.value to ListRootsRequest.serializer(),
177181
Method.Defined.SamplingCreateMessage.value to CreateMessageRequest.serializer(),
182+
Method.Defined.TasksGet.value to GetTaskRequest.serializer(),
183+
Method.Defined.TasksResult.value to GetTaskPayloadRequest.serializer(),
184+
Method.Defined.TasksList.value to ListTasksRequest.serializer(),
185+
Method.Defined.TasksCancel.value to CancelTaskRequest.serializer(),
178186
)
179187
}
180188

@@ -212,6 +220,7 @@ private val clientNotificationDeserializers: Map<String, DeserializationStrategy
212220
Method.Defined.NotificationsProgress.value to ProgressNotification.serializer(),
213221
Method.Defined.NotificationsInitialized.value to InitializedNotification.serializer(),
214222
Method.Defined.NotificationsRootsListChanged.value to RootsListChangedNotification.serializer(),
223+
Method.Defined.NotificationsTasksStatus.value to TaskStatusNotification.serializer(),
215224
)
216225
}
217226

@@ -231,6 +240,7 @@ private val serverNotificationDeserializers: Map<String, DeserializationStrategy
231240
Method.Defined.NotificationsResourcesListChanged.value to ResourceListChangedNotification.serializer(),
232241
Method.Defined.NotificationsToolsListChanged.value to ToolListChangedNotification.serializer(),
233242
Method.Defined.NotificationsPromptsListChanged.value to PromptListChangedNotification.serializer(),
243+
Method.Defined.NotificationsTasksStatus.value to TaskStatusNotification.serializer(),
234244
)
235245
}
236246

@@ -301,6 +311,9 @@ private fun selectClientResultDeserializer(element: JsonElement): Deserializatio
301311
"model" in jsonObject && "role" in jsonObject -> CreateMessageResult.serializer()
302312
"roots" in jsonObject -> ListRootsResult.serializer()
303313
"action" in jsonObject -> ElicitResult.serializer()
314+
"task" in jsonObject -> CreateTaskResult.serializer()
315+
"tasks" in jsonObject -> ListTasksResult.serializer()
316+
"taskId" in jsonObject -> GetTaskResult.serializer()
304317
else -> null
305318
}
306319
}
@@ -309,6 +322,7 @@ private fun selectClientResultDeserializer(element: JsonElement): Deserializatio
309322
* Selects the appropriate deserializer for server results based on JSON content.
310323
* Returns null if the structure doesn't match any known server result type.
311324
*/
325+
@Suppress("CyclomaticComplexMethod")
312326
private fun selectServerResultDeserializer(element: JsonElement): DeserializationStrategy<ServerResult>? {
313327
val jsonObject = element.jsonObject
314328
return when {
@@ -321,6 +335,9 @@ private fun selectServerResultDeserializer(element: JsonElement): Deserializatio
321335
"messages" in jsonObject -> GetPromptResult.serializer()
322336
"contents" in jsonObject -> ReadResourceResult.serializer()
323337
"content" in jsonObject -> CallToolResult.serializer()
338+
"task" in jsonObject -> CreateTaskResult.serializer()
339+
"tasks" in jsonObject -> ListTasksResult.serializer()
340+
"taskId" in jsonObject -> GetTaskResult.serializer()
324341
else -> null
325342
}
326343
}

0 commit comments

Comments
 (0)