feat: SEP-1686 Tasks (#844)

finished SEP-1686
closes #421 

## Breaking Changes
none

## 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
This commit is contained in:
Pavel Gorgulov 2026-06-30 22:04:15 +02:00 • committed by GitHub
commit 57e546d378
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 105 additions and 10 deletions

View file

@ -390,6 +390,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequest : io
public final fun getName ()Ljava/lang/String;
public fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;
public synthetic fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestParams;
public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -421,17 +422,19 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequestBuild
public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams : io/modelcontextprotocol/kotlin/sdk/types/RequestParams {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams$Companion;
public synthetic fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Lkotlinx/serialization/json/JsonObject;
public final fun component3-VI-3G7E ()Lkotlinx/serialization/json/JsonObject;
public final fun copy-EDEVuBg (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;
public static synthetic fun copy-EDEVuBg$default (Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;
public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;
public final fun component4-VI-3G7E ()Lkotlinx/serialization/json/JsonObject;
public final fun copy-6R815Ik (Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;
public static synthetic fun copy-6R815Ik$default (Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CallToolRequestParams;
public fun equals (Ljava/lang/Object;)Z
public final fun getArguments ()Lkotlinx/serialization/json/JsonObject;
public fun getMeta-VI-3G7E ()Lkotlinx/serialization/json/JsonObject;
public final fun getName ()Ljava/lang/String;
public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1161,6 +1164,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest
public synthetic fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestParams;
public final fun getStopSequences ()Ljava/util/List;
public final fun getSystemPrompt ()Ljava/lang/String;
public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;
public final fun getTemperature ()Ljava/lang/Double;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
@ -1205,11 +1209,12 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest
public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams : io/modelcontextprotocol/kotlin/sdk/types/RequestParams {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams$Companion;
public synthetic fun <init> (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()I
public final fun component10 ()Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;
public final fun component11-VI-3G7E ()Lkotlinx/serialization/json/JsonObject;
public final fun component11 ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;
public final fun component12-VI-3G7E ()Lkotlinx/serialization/json/JsonObject;
public final fun component2 ()Ljava/util/List;
public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;
public final fun component4 ()Ljava/lang/String;
@ -1218,8 +1223,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest
public final fun component7 ()Ljava/util/List;
public final fun component8 ()Lkotlinx/serialization/json/JsonObject;
public final fun component9 ()Ljava/util/List;
public final fun copy-APmi5RE (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;
public static synthetic fun copy-APmi5RE$default (Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;
public final fun copy-7OuPiQU (ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;
public static synthetic fun copy-7OuPiQU$default (Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;ILjava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;Ljava/lang/Double;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;Ljava/util/List;Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequestParams;
public fun equals (Ljava/lang/Object;)Z
public final fun getIncludeContext ()Lio/modelcontextprotocol/kotlin/sdk/types/IncludeContext;
public final fun getMaxTokens ()I
@ -1229,6 +1234,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageRequest
public final fun getModelPreferences ()Lio/modelcontextprotocol/kotlin/sdk/types/ModelPreferences;
public final fun getStopSequences ()Ljava/util/List;
public final fun getSystemPrompt ()Ljava/lang/String;
public final fun getTask ()Lio/modelcontextprotocol/kotlin/sdk/types/TaskMetadata;
public final fun getTemperature ()Ljava/lang/Double;
public final fun getToolChoice ()Lio/modelcontextprotocol/kotlin/sdk/types/ToolChoice;
public final fun getTools ()Ljava/util/List;

View file

@ -182,6 +182,12 @@ public data class CreateMessageRequest(override val params: CreateMessageRequest
public val metadata: JsonObject?
get() = params.metadata
/**
* Task metadata, if the caller is requesting task-augmented execution.
*/
public val task: TaskMetadata?
get() = params.task
/**
* Metadata for this request. May include a progressToken for out-of-band progress notifications.
*/
@ -216,6 +222,8 @@ public data class CreateMessageRequest(override val params: CreateMessageRequest
* @property toolChoice Optional policy controlling how the model uses the provided [tools].
* The client MUST return an error if this field is present but the client did not advertise
* [ClientCapabilities.Sampling.tools].
* @property task If set, requests task-augmented execution. A receiver that supports it returns
* a [CreateTaskResult] (result via `tasks/result`); otherwise it returns a [CreateMessageResult] directly.
* @property meta Optional metadata for this request. May include a progressToken for
* out-of-band progress notifications.
*/
@ -231,6 +239,7 @@ public data class CreateMessageRequestParams(
val metadata: JsonObject? = null,
val tools: List<Tool>? = null,
val toolChoice: ToolChoice? = null,
val task: TaskMetadata? = null,
@SerialName("_meta")
override val meta: RequestMeta? = null,
) : RequestParams

View file

@ -203,6 +203,12 @@ public data class CallToolRequest(override val params: CallToolRequestParams) :
public val arguments: JsonObject?
get() = params.arguments
/**
* Task metadata, if the caller is requesting task-augmented execution.
*/
public val task: TaskMetadata?
get() = params.task
/**
* Metadata for this request. May include a progressToken for out-of-band progress notifications.
*/
@ -216,6 +222,8 @@ public data class CallToolRequest(override val params: CallToolRequestParams) :
* @property name The name of the tool to invoke.
* @property arguments Arguments to pass to the tool. Keys are argument names, values are the argument values.
* The structure must match the tool's input schema.
* @property task If set, requests task-augmented execution. A receiver that supports it returns
* a [CreateTaskResult] (result via `tasks/result`); otherwise it returns a [CallToolResult] directly.
* @property meta Optional metadata for this request. May include a progressToken for
* out-of-band progress notifications.
*/
@ -223,6 +231,7 @@ public data class CallToolRequest(override val params: CallToolRequestParams) :
public data class CallToolRequestParams(
val name: String,
val arguments: JsonObject? = null,
val task: TaskMetadata? = null,
@SerialName("_meta")
override val meta: RequestMeta? = null,
) : RequestParams

View file

@ -367,6 +367,26 @@ class SamplingTest {
decoded.toolChoice shouldBe ToolChoice(mode = ToolChoice.Mode.Required)
}
@Test
fun `CreateMessageRequestParams task defaults to null and is omitted when encoding`() {
val params = CreateMessageRequestParams(maxTokens = 100, messages = emptyList())
params.task shouldBe null
val encoded = McpJson.encodeToString(CreateMessageRequestParams.serializer(), params)
assertEquals(false, "\"task\"" in encoded)
}
@Test
fun `CreateMessageRequestParams round-trips task`() {
val original = CreateMessageRequestParams(
maxTokens = 100,
messages = emptyList(),
task = TaskMetadata(ttl = 60_000L),
)
val encoded = McpJson.encodeToString(CreateMessageRequestParams.serializer(), original)
val decoded = McpJson.decodeFromString(CreateMessageRequestParams.serializer(), encoded)
decoded.task shouldBe TaskMetadata(ttl = 60_000L)
}
@Test
fun `StopReason ToolUse serialises as toolUse`() {
StopReason.ToolUse.value shouldBe "toolUse"

View file

@ -319,6 +319,57 @@ class ToolsTest {
assertEquals(ProgressToken(77), params.meta?.progressToken)
}
@Test
fun `should serialize CallToolRequest with task augmentation`() {
val request = CallToolRequest(
CallToolRequestParams(
name = "long-running",
arguments = buildJsonObject { put("query", "MCP protocol") },
task = TaskMetadata(ttl = 60_000L),
),
)
verifySerialization(
request,
McpJson,
"""
{
"method": "tools/call",
"params": {
"name": "long-running",
"arguments": {
"query": "MCP protocol"
},
"task": {
"ttl": 60000
}
}
}
""".trimIndent(),
)
assertEquals(TaskMetadata(ttl = 60_000L), request.task)
}
@Test
fun `should omit task from CallToolRequest when null`() {
val request = CallToolRequest(CallToolRequestParams(name = "plain"))
assertEquals(null, request.task)
verifySerialization(
request,
McpJson,
"""
{
"method": "tools/call",
"params": {
"name": "plain"
}
}
""".trimIndent(),
)
}
@Test
fun `should serialize CallToolResult with structured content`() {
val result = CallToolResult(