Implement MCP task support (SEP-1686) (#1170)

Co-authored-by: Stephen Halter <halter73@gmail.com>
This commit is contained in:
Eirik Tsarpalis 2026-01-28 05:21:02 +02:00 • committed by GitHub
commit 10e4f5b20f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 11580 additions and 46 deletions

View file

@ -25,4 +25,14 @@ public sealed class CallToolRequestParams : RequestParams
/// </remarks>
[JsonPropertyName("arguments")]
public IDictionary<string, JsonElement>? Arguments { get; set; }
/// <summary>
/// Gets or sets optional task metadata to augment this request with task execution.
/// </summary>
/// <remarks>
/// When present, indicates that the requestor wants this operation executed as a task.
/// The receiver must support task augmentation for this specific request type.
/// </remarks>
[JsonPropertyName("task")]
public McpTaskMetadata? Task { get; set; }
}

View file

@ -56,4 +56,15 @@ public sealed class CallToolResult : Result
/// </remarks>
[JsonPropertyName("isError")]
public bool? IsError { get; set; }
/// <summary>
/// Gets or sets the task data for the newly created task.
/// </summary>
/// <remarks>
/// This property is populated only for task-augmented tool calls. When present, the other properties
/// (<see cref="Content"/>, <see cref="StructuredContent"/>, <see cref="IsError"/>) may not be populated.
/// The actual tool result can be retrieved later via <c>tasks/result</c>.
/// </remarks>
[JsonPropertyName("task")]
public McpTask? Task { get; set; }
}

View file

@ -0,0 +1,84 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the parameters for a tasks/cancel request to explicitly cancel a task.
/// </summary>
/// <remarks>
/// <para>
/// Receivers must reject cancellation requests for tasks already in a terminal status
/// (<see cref="McpTaskStatus.Completed"/>, <see cref="McpTaskStatus.Failed"/>, or
/// <see cref="McpTaskStatus.Cancelled"/>) with error code -32602 (Invalid params).
/// </para>
/// <para>
/// Upon receiving a valid cancellation request, receivers should attempt to stop the task
/// execution and must transition the task to <see cref="McpTaskStatus.Cancelled"/> status
/// before sending the response.
/// </para>
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class CancelMcpTaskRequestParams : RequestParams
{
/// <summary>
/// Gets or sets the unique identifier of the task to cancel.
/// </summary>
[JsonPropertyName("taskId")]
public required string TaskId { get; set; }
}
/// <summary>
/// Represents the result of a tasks/cancel request.
/// </summary>
/// <remarks>
/// The result contains the updated task state after cancellation. The task will be in
/// <see cref="McpTaskStatus.Cancelled"/> status if the cancellation was successful.
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class CancelMcpTaskResult : Result
{
/// <summary>
/// Gets or sets the task ID.
/// </summary>
[JsonPropertyName("taskId")]
public required string TaskId { get; set; }
/// <summary>
/// Gets or sets the current status of the task (should be <see cref="McpTaskStatus.Cancelled"/>).
/// </summary>
[JsonPropertyName("status")]
public required McpTaskStatus Status { get; set; }
/// <summary>
/// Gets or sets an optional message describing the cancellation.
/// </summary>
[JsonPropertyName("statusMessage")]
public string? StatusMessage { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task was created.
/// </summary>
[JsonPropertyName("createdAt")]
public required DateTimeOffset CreatedAt { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task status was last updated.
/// </summary>
[JsonPropertyName("lastUpdatedAt")]
public required DateTimeOffset LastUpdatedAt { get; set; }
/// <summary>
/// Gets or sets the time to live (retention duration) from creation before the task may be deleted.
/// </summary>
[JsonPropertyName("ttl")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? TimeToLive { get; set; }
/// <summary>
/// Gets or sets the suggested time between status checks.
/// </summary>
[JsonPropertyName("pollInterval")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? PollInterval { get; set; }
}

View file

@ -66,4 +66,20 @@ public sealed class ClientCapabilities
/// </summary>
[JsonPropertyName("elicitation")]
public ElicitationCapability? Elicitation { get; set; }
/// <summary>
/// Gets or sets the client's tasks capability for supporting task-augmented requests.
/// </summary>
/// <remarks>
/// <para>
/// The tasks capability enables servers to augment their requests with tasks for long-running
/// operations. When present, servers can request that certain operations (like sampling or
/// elicitation) execute asynchronously, with the ability to poll for status and retrieve results later.
/// </para>
/// <para>
/// See <see cref="McpTasksCapability"/> for details on configuring which operations support tasks.
/// </para>
/// </remarks>
[JsonPropertyName("tasks")]
public McpTasksCapability? Tasks { get; set; }
}

View file

@ -120,4 +120,14 @@ public sealed class CreateMessageRequestParams : RequestParams
/// </summary>
[JsonPropertyName("toolChoice")]
public ToolChoice? ToolChoice { get; set; }
/// <summary>
/// Gets or sets optional task metadata to augment this request with task execution.
/// </summary>
/// <remarks>
/// When present, indicates that the requestor wants this operation executed as a task.
/// The receiver must support task augmentation for this specific request type.
/// </remarks>
[JsonPropertyName("task")]
public McpTaskMetadata? Task { get; set; }
}

View file

@ -0,0 +1,28 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the response to a task-augmented request.
/// </summary>
/// <remarks>
/// <para>
/// When a client sends a request with a <c>task</c> parameter, the server immediately returns
/// a <see cref="CreateTaskResult"/> containing the created task information instead of the
/// normal result type. The actual result can be retrieved later via <c>tasks/result</c>.
/// </para>
/// <para>
/// This type is returned for any task-augmented request including <c>tools/call</c>,
/// <c>sampling/createMessage</c>, and <c>elicitation/create</c>.
/// </para>
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class CreateTaskResult : Result
{
/// <summary>
/// Gets or sets the task data for the newly created task.
/// </summary>
[JsonPropertyName("task")]
public McpTask Task { get; set; } = null!;
}

View file

@ -92,6 +92,16 @@ public sealed class ElicitRequestParams : RequestParams
[JsonPropertyName("requestedSchema")]
public RequestSchema? RequestedSchema { get; set; }
/// <summary>
/// Gets or sets optional task metadata to augment this request with task execution.
/// </summary>
/// <remarks>
/// When present, indicates that the requestor wants this operation executed as a task.
/// The receiver must support task augmentation for this specific request type.
/// </remarks>
[JsonPropertyName("task")]
public McpTaskMetadata? Task { get; set; }
/// <summary>Represents a request schema used in a form mode elicitation request.</summary>
public class RequestSchema
{

View file

@ -0,0 +1,27 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the parameters for a tasks/result request to retrieve the result of a completed task.
/// </summary>
/// <remarks>
/// <para>
/// This request blocks until the task reaches a terminal status (<see cref="McpTaskStatus.Completed"/>,
/// <see cref="McpTaskStatus.Failed"/>, or <see cref="McpTaskStatus.Cancelled"/>).
/// </para>
/// <para>
/// The result structure matches the original request type (e.g., <see cref="CallToolResult"/> for tools/call).
/// This is distinct from the initial <see cref="Result"/> response, which contains only task data.
/// </para>
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class GetTaskPayloadRequestParams : RequestParams
{
/// <summary>
/// Gets or sets the unique identifier of the task whose result to retrieve.
/// </summary>
[JsonPropertyName("taskId")]
public required string TaskId { get; set; }
}

View file

@ -0,0 +1,77 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the parameters for a tasks/get request to retrieve task status.
/// </summary>
/// <remarks>
/// Requestors poll for task completion by sending tasks/get requests. They should
/// respect the <see cref="McpTask.PollInterval"/> provided in responses when determining
/// polling frequency.
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class GetTaskRequestParams : RequestParams
{
/// <summary>
/// Gets or sets the unique identifier of the task to retrieve.
/// </summary>
[JsonPropertyName("taskId")]
public required string TaskId { get; set; }
}
/// <summary>
/// Represents the result of a tasks/get request.
/// </summary>
/// <remarks>
/// The result contains the current state of the task, including its status, timestamps,
/// and any status message.
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class GetTaskResult : Result
{
/// <summary>
/// Gets or sets the task ID.
/// </summary>
[JsonPropertyName("taskId")]
public required string TaskId { get; set; }
/// <summary>
/// Gets or sets the current status of the task.
/// </summary>
[JsonPropertyName("status")]
public required McpTaskStatus Status { get; set; }
/// <summary>
/// Gets or sets an optional human-readable message describing the current state.
/// </summary>
[JsonPropertyName("statusMessage")]
public string? StatusMessage { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task was created.
/// </summary>
[JsonPropertyName("createdAt")]
public required DateTimeOffset CreatedAt { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task status was last updated.
/// </summary>
[JsonPropertyName("lastUpdatedAt")]
public required DateTimeOffset LastUpdatedAt { get; set; }
/// <summary>
/// Gets or sets the time to live (retention duration) from creation before the task may be deleted.
/// </summary>
[JsonPropertyName("ttl")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? TimeToLive { get; set; }
/// <summary>
/// Gets or sets the suggested time between status checks.
/// </summary>
[JsonPropertyName("pollInterval")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? PollInterval { get; set; }
}

View file

@ -0,0 +1,34 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the parameters for a tasks/list request to retrieve a list of tasks.
/// </summary>
/// <remarks>
/// This operation supports cursor-based pagination. Receivers should use cursor-based
/// pagination to limit the number of tasks returned in a single response.
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class ListTasksRequestParams : PaginatedRequestParams
{
// Inherits Cursor property from PaginatedRequestParams
}
/// <summary>
/// Represents the result of a tasks/list request.
/// </summary>
/// <remarks>
/// The result contains an array of task objects and an optional cursor for pagination.
/// If <see cref="PaginatedResult.NextCursor"/> is present, more tasks are available.
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class ListTasksResult : PaginatedResult
{
/// <summary>
/// Gets or sets the list of tasks.
/// </summary>
[JsonPropertyName("tasks")]
public required McpTask[] Tasks { get; set; }
}

View file

@ -0,0 +1,104 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents an MCP task, which is a durable state machine carrying information
/// about the underlying execution state of a request.
/// </summary>
/// <remarks>
/// <para>
/// Tasks are useful for representing expensive computations and batch processing requests.
/// Each task is uniquely identifiable by a receiver-generated task ID.
/// </para>
/// <para>
/// Tasks follow a defined lifecycle through the <see cref="Status"/> property. They begin
/// in the <see cref="McpTaskStatus.Working"/> status and may transition through various states
/// before reaching a terminal status (<see cref="McpTaskStatus.Completed"/>, <see cref="McpTaskStatus.Failed"/>,
/// or <see cref="McpTaskStatus.Cancelled"/>).
/// </para>
/// <para>
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/basic/utilities/tasks.mdx">tasks specification</see> for details.
/// </para>
/// </remarks>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class McpTask
{
/// <summary>
/// Gets or sets the unique identifier for the task.
/// </summary>
/// <remarks>
/// Task IDs are generated by the receiver when creating a task and must be unique
/// among all tasks controlled by that receiver.
/// </remarks>
[JsonPropertyName("taskId")]
public required string TaskId { get; set; }
/// <summary>
/// Gets or sets the current state of the task execution.
/// </summary>
[JsonPropertyName("status")]
public required McpTaskStatus Status { get; set; }
/// <summary>
/// Gets or sets an optional human-readable message describing the current state.
/// </summary>
/// <remarks>
/// This message can be present for any status, including error details for failed tasks.
/// </remarks>
[JsonPropertyName("statusMessage")]
public string? StatusMessage { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task was created.
/// </summary>
/// <remarks>
/// Receivers must include this timestamp in all task responses to indicate when
/// the task was created.
/// </remarks>
[JsonPropertyName("createdAt")]
public required DateTimeOffset CreatedAt { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task status was last updated.
/// </summary>
/// <remarks>
/// Receivers must include this timestamp in all task responses to indicate when
/// the task was last updated.
/// </remarks>
[JsonPropertyName("lastUpdatedAt")]
public required DateTimeOffset LastUpdatedAt { get; set; }
/// <summary>
/// Gets or sets the time to live (retention duration) from creation before the task may be deleted.
/// </summary>
/// <remarks>
/// <para>
/// A null value indicates unlimited lifetime. After a task's TTL lifetime has elapsed,
/// receivers may delete the task and its results, regardless of the task status.
/// </para>
/// <para>
/// Receivers may override the requested TTL duration and must include the actual TTL
/// duration (or null for unlimited) in task responses.
/// </para>
/// </remarks>
[JsonPropertyName("ttl")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? TimeToLive { get; set; }
/// <summary>
/// Gets or sets the suggested time between status checks.
/// </summary>
/// <remarks>
/// Requestors should respect this value when provided to avoid excessive polling.
/// This value is optional and may not be present in all task responses.
/// </remarks>
[JsonPropertyName("pollInterval")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? PollInterval { get; set; }
private string DebuggerDisplay => $"Task {TaskId}: {Status}" + (StatusMessage != null ? $" - {StatusMessage}" : "");
}

View file

@ -0,0 +1,41 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents metadata for augmenting a request with task execution.
/// </summary>
/// <remarks>
/// <para>
/// When included in a request's params, this metadata signals that the requestor
/// wants the receiver to execute the request as a task rather than synchronously.
/// The receiver will return a <see cref="Result"/> containing task data
/// instead of the actual operation result.
/// </para>
/// <para>
/// Requestors can specify a desired TTL (time-to-live) duration for the task,
/// though receivers may override this value based on their resource management policies.
/// </para>
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class McpTaskMetadata
{
/// <summary>
/// Gets or sets the requested time to live (retention duration) to retain the task from creation.
/// </summary>
/// <remarks>
/// <para>
/// This is a hint to the receiver about how long the requestor expects to need access
/// to the task data. Receivers may override this value based on their resource constraints
/// and policies.
/// </para>
/// <para>
/// A null value indicates no specific retention requirement. The actual TTL used by the
/// receiver will be returned in the <see cref="McpTask.TimeToLive"/> property.
/// </para>
/// </remarks>
[JsonPropertyName("ttl")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? TimeToLive { get; set; }
}

View file

@ -0,0 +1,79 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the status of an MCP task.
/// </summary>
/// <remarks>
/// <para>
/// Tasks progress through a defined lifecycle:
/// <list type="bullet">
/// <item><description><see cref="Working"/>: The request is currently being processed.</description></item>
/// <item><description><see cref="InputRequired"/>: The receiver needs input from the requestor.
/// The requestor should call tasks/result to receive input requests.</description></item>
/// <item><description><see cref="Completed"/>: The request completed successfully and results are available.</description></item>
/// <item><description><see cref="Failed"/>: The request did not complete successfully.</description></item>
/// <item><description><see cref="Cancelled"/>: The request was cancelled before completion.</description></item>
/// </list>
/// </para>
/// <para>
/// Terminal states are <see cref="Completed"/>, <see cref="Failed"/>, and <see cref="Cancelled"/>.
/// Once a task reaches a terminal state, it cannot transition to any other status.
/// </para>
/// </remarks>
[JsonConverter(typeof(JsonStringEnumConverter<McpTaskStatus>))]
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public enum McpTaskStatus
{
/// <summary>
/// The request is currently being processed.
/// </summary>
/// <remarks>
/// Tasks begin in this status when created. From <see cref="Working"/>, tasks may transition
/// to <see cref="InputRequired"/>, <see cref="Completed"/>, <see cref="Failed"/>, or <see cref="Cancelled"/>.
/// </remarks>
[JsonStringEnumMemberName("working")]
Working,
/// <summary>
/// The receiver needs input from the requestor.
/// </summary>
/// <remarks>
/// The requestor should call tasks/result to receive input requests, even though the task
/// has not reached a terminal state. From <see cref="InputRequired"/>, tasks may transition
/// to <see cref="Working"/>, <see cref="Completed"/>, <see cref="Failed"/>, or <see cref="Cancelled"/>.
/// </remarks>
[JsonStringEnumMemberName("input_required")]
InputRequired,
/// <summary>
/// The request completed successfully and results are available.
/// </summary>
/// <remarks>
/// This is a terminal status. Tasks in this status cannot transition to any other status.
/// </remarks>
[JsonStringEnumMemberName("completed")]
Completed,
/// <summary>
/// The associated request did not complete successfully.
/// </summary>
/// <remarks>
/// This is a terminal status. For tool calls specifically, this includes cases where
/// the tool call result has isError set to true. Tasks in this status cannot transition
/// to any other status.
/// </remarks>
[JsonStringEnumMemberName("failed")]
Failed,
/// <summary>
/// The request was cancelled before completion.
/// </summary>
/// <remarks>
/// This is a terminal status. Tasks in this status cannot transition to any other status.
/// </remarks>
[JsonStringEnumMemberName("cancelled")]
Cancelled
}

View file

@ -0,0 +1,67 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the parameters for a notifications/tasks/status notification.
/// </summary>
/// <remarks>
/// <para>
/// When a task status changes, receivers may send this notification to inform the
/// requestor of the change. This notification includes the full task state.
/// </para>
/// <para>
/// Requestors must not rely on receiving this notification, as it is optional. Receivers
/// are not required to send status notifications and may choose to only send them for
/// certain status transitions. Requestors should continue to poll via tasks/get to ensure
/// they receive status updates.
/// </para>
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class McpTaskStatusNotificationParams : NotificationParams
{
/// <summary>
/// Gets or sets the task ID.
/// </summary>
[JsonPropertyName("taskId")]
public required string TaskId { get; set; }
/// <summary>
/// Gets or sets the current status of the task.
/// </summary>
[JsonPropertyName("status")]
public required McpTaskStatus Status { get; set; }
/// <summary>
/// Gets or sets an optional human-readable message describing the current state.
/// </summary>
[JsonPropertyName("statusMessage")]
public string? StatusMessage { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task was created.
/// </summary>
[JsonPropertyName("createdAt")]
public required DateTimeOffset CreatedAt { get; set; }
/// <summary>
/// Gets or sets the ISO 8601 timestamp when the task status was last updated.
/// </summary>
[JsonPropertyName("lastUpdatedAt")]
public required DateTimeOffset LastUpdatedAt { get; set; }
/// <summary>
/// Gets or sets the time to live (retention duration) from creation before the task may be deleted.
/// </summary>
[JsonPropertyName("ttl")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? TimeToLive { get; set; }
/// <summary>
/// Gets or sets the suggested time between status checks.
/// </summary>
[JsonPropertyName("pollInterval")]
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
public TimeSpan? PollInterval { get; set; }
}

View file

@ -0,0 +1,160 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Represents the tasks capability configuration for servers and clients.
/// </summary>
/// <remarks>
/// <para>
/// The tasks capability enables requestors (clients or servers) to augment their requests with
/// tasks for long-running operations. Tasks are durable state machines that carry information
/// about the underlying execution state of requests.
/// </para>
/// <para>
/// During initialization, both parties exchange their tasks capabilities to establish which
/// operations support task-based execution. Requestors should only augment requests with a
/// task if the corresponding capability has been declared by the receiver.
/// </para>
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class McpTasksCapability
{
/// <summary>
/// Gets or sets whether this party supports the tasks/list operation.
/// </summary>
/// <remarks>
/// When present, indicates support for listing all tasks.
/// </remarks>
[JsonPropertyName("list")]
public ListMcpTasksCapability? List { get; set; }
/// <summary>
/// Gets or sets whether this party supports the tasks/cancel operation.
/// </summary>
/// <remarks>
/// When present, indicates support for cancelling tasks.
/// </remarks>
[JsonPropertyName("cancel")]
public CancelMcpTasksCapability? Cancel { get; set; }
/// <summary>
/// Gets or sets which request types support task augmentation.
/// </summary>
/// <remarks>
/// <para>
/// The set of capabilities in this property is exhaustive. If a request type is not present,
/// it does not support task augmentation.
/// </para>
/// <para>
/// For servers, this typically includes tools/call. For clients, this typically includes
/// sampling/createMessage and elicitation/create.
/// </para>
/// </remarks>
[JsonPropertyName("requests")]
public RequestMcpTasksCapability? Requests { get; set; }
}
/// <summary>
/// Represents task support for tool-specific requests.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class RequestMcpTasksCapability
{
/// <summary>
/// Gets or sets task support for tool-related requests.
/// </summary>
[JsonPropertyName("tools")]
public ToolsMcpTasksCapability? Tools { get; set; }
/// <summary>
/// Gets or sets task support for sampling-related requests.
/// </summary>
[JsonPropertyName("sampling")]
public SamplingMcpTasksCapability? Sampling { get; set; }
/// <summary>
/// Gets or sets task support for elicitation-related requests.
/// </summary>
[JsonPropertyName("elicitation")]
public ElicitationMcpTasksCapability? Elicitation { get; set; }
}
/// <summary>
/// Represents task support for tool-related requests.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class ToolsMcpTasksCapability
{
/// <summary>
/// Gets or sets whether tools/call requests support task augmentation.
/// </summary>
/// <remarks>
/// When present, indicates that the server supports task-augmented tools/call requests.
/// </remarks>
[JsonPropertyName("call")]
public CallToolMcpTasksCapability? Call { get; set; }
}
/// <summary>
/// Represents task support for sampling-related requests.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class SamplingMcpTasksCapability
{
/// <summary>
/// Gets or sets whether sampling/createMessage requests support task augmentation.
/// </summary>
/// <remarks>
/// When present, indicates that the client supports task-augmented sampling/createMessage requests.
/// </remarks>
[JsonPropertyName("createMessage")]
public CreateMessageMcpTasksCapability? CreateMessage { get; set; }
}
/// <summary>
/// Represents task support for elicitation-related requests.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class ElicitationMcpTasksCapability
{
/// <summary>
/// Gets or sets whether elicitation/create requests support task augmentation.
/// </summary>
/// <remarks>
/// When present, indicates that the client supports task-augmented elicitation/create requests.
/// </remarks>
[JsonPropertyName("create")]
public CreateElicitationMcpTasksCapability? Create { get; set; }
}
/// <summary>
/// Represents the capability for listing tasks.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class ListMcpTasksCapability;
/// <summary>
/// Represents the capability for cancelling tasks.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class CancelMcpTasksCapability;
/// <summary>
/// Represents the capability for task-augmented tools/call requests.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class CallToolMcpTasksCapability;
/// <summary>
/// Represents the capability for task-augmented sampling/createMessage requests.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class CreateMessageMcpTasksCapability;
/// <summary>
/// Represents the capability for task-augmented elicitation/create requests.
/// </summary>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
public sealed class CreateElicitationMcpTasksCapability;

View file

@ -140,4 +140,41 @@ public static class NotificationMethods
/// </para>
/// </remarks>
public const string CancelledNotification = "notifications/cancelled";
/// <summary>
/// The name of the notification sent when a task status changes.
/// </summary>
/// <remarks>
/// <para>
/// When a task status changes, receivers may send this notification to inform the requestor
/// of the change. This notification includes the full task state.
/// </para>
/// <para>
/// Requestors must not rely on receiving this notification, as it is optional. Receivers
/// are not required to send status notifications and may choose to only send them for
/// certain status transitions. Requestors should continue to poll via tasks/get to ensure
/// they receive status updates.
/// </para>
/// </remarks>
public const string TaskStatusNotification = "notifications/tasks/status";
/// <summary>
/// The metadata key used to associate requests, responses, and notifications with a task.
/// </summary>
/// <remarks>
/// <para>
/// This constant defines the key <c>"io.modelcontextprotocol/related-task"</c> used in the
/// <c>_meta</c> field to associate messages with their originating task across the entire
/// request lifecycle.
/// </para>
/// <para>
/// For example, an elicitation that a task-augmented tool call depends on must share the
/// same related task ID with that tool call's task.
/// </para>
/// <para>
/// For <c>tasks/get</c>, <c>tasks/list</c>, and <c>tasks/cancel</c> operations, this
/// metadata should not be included as the taskId is already present in the message structure.
/// </para>
/// </remarks>
public const string RelatedTaskMetaKey = "io.modelcontextprotocol/related-task";
}

View file

@ -121,4 +121,32 @@ public static class RequestMethods
/// and information, establishing the protocol version and available features for the session.
/// </remarks>
public const string Initialize = "initialize";
/// <summary>
/// The name of the request method to retrieve task status.
/// </summary>
/// <remarks>
/// Requestors poll for task completion by sending tasks/get requests. They should respect
/// the pollInterval provided in responses when determining polling frequency.
/// </remarks>
public const string TasksGet = "tasks/get";
/// <summary>
/// The name of the request method to retrieve the result of a completed task.
/// </summary>
/// <remarks>
/// This request blocks until the task reaches a terminal status (completed, failed, or cancelled).
/// The result structure matches the original request type (e.g., CallToolResult for tools/call).
/// </remarks>
public const string TasksResult = "tasks/result";
/// <summary>
/// The name of the request method to retrieve a list of tasks with pagination support.
/// </summary>
public const string TasksList = "tasks/list";
/// <summary>
/// The name of the request method to explicitly cancel a task.
/// </summary>
public const string TasksCancel = "tasks/cancel";
}

View file

@ -65,4 +65,20 @@ public sealed class ServerCapabilities
/// </summary>
[JsonPropertyName("completions")]
public CompletionsCapability? Completions { get; set; }
/// <summary>
/// Gets or sets a server's tasks capability for supporting task-augmented requests.
/// </summary>
/// <remarks>
/// <para>
/// The tasks capability enables clients to augment their requests with tasks for long-running
/// operations. When present, clients can request that certain operations (like tool calls)
/// execute asynchronously, with the ability to poll for status and retrieve results later.
/// </para>
/// <para>
/// See <see cref="McpTasksCapability"/> for details on configuring which operations support tasks.
/// </para>
/// </remarks>
[JsonPropertyName("tasks")]
public McpTasksCapability? Tasks { get; set; }
}

View file

@ -0,0 +1,41 @@
using System.ComponentModel;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
/// <summary>
/// Provides a JSON converter for <see cref="TimeSpan"/> that serializes as integer milliseconds.
/// </summary>
/// <remarks>
/// This converter serializes TimeSpan values as the total number of milliseconds (as an integer),
/// and deserializes integer millisecond values back to TimeSpan. System.Text.Json automatically
/// handles nullable TimeSpan properties using this converter.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
public sealed class TimeSpanMillisecondsConverter : JsonConverter<TimeSpan>
{
/// <inheritdoc />
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType is JsonTokenType.Number)
{
if (reader.TryGetInt64(out long milliseconds))
{
return TimeSpan.FromMilliseconds(milliseconds);
}
// For non-integer values, convert from fractional milliseconds
double fractionalMilliseconds = reader.GetDouble();
return TimeSpan.FromTicks((long)(fractionalMilliseconds * TimeSpan.TicksPerMillisecond));
}
throw new JsonException($"Unable to convert {reader.TokenType} to TimeSpan.");
}
/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteNumberValue((long)value.TotalMilliseconds);
}
}

View file

@ -1,8 +1,9 @@
using ModelContextProtocol.Server;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using ModelContextProtocol.Server;
namespace ModelContextProtocol.Protocol;
@ -111,6 +112,17 @@ public sealed class Tool : IBaseMetadata
[JsonPropertyName("annotations")]
public ToolAnnotations? Annotations { get; set; }
/// <summary>
/// Gets or sets execution-related metadata for this tool.
/// </summary>
/// <remarks>
/// This property provides hints about how the tool should be executed, particularly
/// regarding task augmentation support. See <see cref="ToolExecution"/> for details.
/// </remarks>
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
[JsonPropertyName("execution")]
public ToolExecution? Execution { get; set; }
/// <summary>
/// Gets or sets an optional list of icons for this tool.
/// </summary>

Some files were not shown because too many files have changed in this diff Show more