Implement SEP-2663 Tasks Extension (#1579)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
ed07fdb6f4
commit
dbb7a20176
30 changed files with 8190 additions and 11405 deletions
|
|
@ -26,24 +26,4 @@ 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>
|
||||
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
|
||||
[JsonIgnore]
|
||||
public McpTaskMetadata? Task
|
||||
{
|
||||
get => TaskCore;
|
||||
set => TaskCore = value;
|
||||
}
|
||||
|
||||
// See ExperimentalInternalPropertyTests.cs before modifying this property.
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("task")]
|
||||
internal McpTaskMetadata? TaskCore { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,25 +64,4 @@ 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>
|
||||
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
|
||||
[JsonIgnore]
|
||||
public McpTask? Task
|
||||
{
|
||||
get => TaskCore;
|
||||
set => TaskCore = value;
|
||||
}
|
||||
|
||||
// See ExperimentalInternalPropertyTests.cs before modifying this property.
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("task")]
|
||||
internal McpTask? TaskCore { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
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; }
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the parameters for a <c>tasks/cancel</c> request to signal intent to cancel an in-progress task.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Cancellation is cooperative: the request signals intent, and the server decides whether and when to honor it.
|
||||
/// A server is not obligated to actually stop the work; it is only obligated to acknowledge the request.
|
||||
/// Eventual transition to <see cref="McpTaskStatus.Cancelled"/> is not guaranteed.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The <c>notifications/cancelled</c> notification must not be used for task cancellation.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class CancelTaskRequestParams : RequestParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the task to cancel.
|
||||
/// </summary>
|
||||
[JsonPropertyName("taskId")]
|
||||
public required string TaskId { get; set; }
|
||||
}
|
||||
22
src/ModelContextProtocol.Core/Protocol/CancelTaskResult.cs
Normal file
22
src/ModelContextProtocol.Core/Protocol/CancelTaskResult.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the result of a <c>tasks/cancel</c> request. This is an empty acknowledgement.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The server acknowledges the request with an empty result. Cancellation processing is
|
||||
/// eventually consistent — the task's observable status may remain <see cref="McpTaskStatus.Working"/>
|
||||
/// after the ack, and may ultimately reach a terminal status other than <see cref="McpTaskStatus.Cancelled"/>
|
||||
/// if the work finished before cancellation could take effect.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class CancelTaskResult : Result
|
||||
{
|
||||
}
|
||||
|
|
@ -68,32 +68,6 @@ public sealed class ClientCapabilities
|
|||
[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>
|
||||
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
|
||||
[JsonIgnore]
|
||||
public McpTasksCapability? Tasks
|
||||
{
|
||||
get => TasksCore;
|
||||
set => TasksCore = value;
|
||||
}
|
||||
|
||||
// See ExperimentalInternalPropertyTests.cs before modifying this property.
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("tasks")]
|
||||
internal McpTasksCapability? TasksCore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets optional MCP extensions that the client supports.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -153,24 +153,4 @@ public sealed class CreateMessageRequestParams : RequestParams
|
|||
/// </remarks>
|
||||
[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>
|
||||
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
|
||||
[JsonIgnore]
|
||||
public McpTaskMetadata? Task
|
||||
{
|
||||
get => TaskCore;
|
||||
set => TaskCore = value;
|
||||
}
|
||||
|
||||
// See ExperimentalInternalPropertyTests.cs before modifying this property.
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("task")]
|
||||
internal McpTaskMetadata? TaskCore { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,68 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the response to a task-augmented request.
|
||||
/// Represents the result returned by a server when it creates a task in lieu of a standard result.
|
||||
/// </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>.
|
||||
/// A server returns <see cref="CreateTaskResult"/> instead of the standard result shape (e.g., <see cref="CallToolResult"/>)
|
||||
/// to indicate that the request will be processed asynchronously. The client then uses
|
||||
/// <see cref="TaskId"/> for subsequent <c>tasks/get</c>, <c>tasks/update</c>, and <c>tasks/cancel</c> calls.
|
||||
/// </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>.
|
||||
/// A server must not return <see cref="CreateTaskResult"/> to a client that did not include the
|
||||
/// <c>io.modelcontextprotocol/tasks</c> extension capability on its request.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </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.
|
||||
/// Gets or sets the stable identifier for this task.
|
||||
/// </summary>
|
||||
[JsonPropertyName("task")]
|
||||
public McpTask Task { get; set; } = null!;
|
||||
[JsonPropertyName("taskId")]
|
||||
public required string TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current task status.
|
||||
/// </summary>
|
||||
[JsonPropertyName("status")]
|
||||
public required McpTaskStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional message describing the current task 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 was last updated.
|
||||
/// </summary>
|
||||
[JsonPropertyName("lastUpdatedAt")]
|
||||
public required DateTimeOffset LastUpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time-to-live duration from creation in milliseconds, or <see langword="null"/> for unlimited.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ttlMs")]
|
||||
public long? TtlMs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the suggested polling interval in milliseconds.
|
||||
/// </summary>
|
||||
[JsonPropertyName("pollIntervalMs")]
|
||||
public long? PollIntervalMs { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,26 +92,6 @@ 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>
|
||||
[Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)]
|
||||
[JsonIgnore]
|
||||
public McpTaskMetadata? Task
|
||||
{
|
||||
get => TaskCore;
|
||||
set => TaskCore = value;
|
||||
}
|
||||
|
||||
// See ExperimentalInternalPropertyTests.cs before modifying this property.
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("task")]
|
||||
internal McpTaskMetadata? TaskCore { get; set; }
|
||||
|
||||
/// <summary>Represents a request schema used in a form mode elicitation request.</summary>
|
||||
public sealed class RequestSchema
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
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; }
|
||||
}
|
||||
|
|
@ -1,77 +1,26 @@
|
|||
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.
|
||||
/// Represents the parameters for a <c>tasks/get</c> request to poll for task completion.
|
||||
/// </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.
|
||||
/// <para>
|
||||
/// Clients poll for task completion by sending <c>tasks/get</c> requests.
|
||||
/// Clients should respect the <see cref="GetTaskResult.PollIntervalMs"/> provided in responses
|
||||
/// when determining polling frequency.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </para>
|
||||
/// </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.
|
||||
/// Gets or sets the identifier of the task to query.
|
||||
/// </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; }
|
||||
}
|
||||
|
|
|
|||
450
src/ModelContextProtocol.Core/Protocol/GetTaskResult.cs
Normal file
450
src/ModelContextProtocol.Core/Protocol/GetTaskResult.cs
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the result of a <c>tasks/get</c> request, containing the full task state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is the abstract base for status-specific task results. The concrete type returned depends on the
|
||||
/// task's current <see cref="Status"/>:
|
||||
/// <list type="bullet">
|
||||
/// <item><see cref="WorkingTaskResult"/> — <see cref="McpTaskStatus.Working"/></item>
|
||||
/// <item><see cref="CompletedTaskResult"/> — <see cref="McpTaskStatus.Completed"/></item>
|
||||
/// <item><see cref="FailedTaskResult"/> — <see cref="McpTaskStatus.Failed"/></item>
|
||||
/// <item><see cref="CancelledTaskResult"/> — <see cref="McpTaskStatus.Cancelled"/></item>
|
||||
/// <item><see cref="InputRequiredTaskResult"/> — <see cref="McpTaskStatus.InputRequired"/></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[JsonConverter(typeof(Converter))]
|
||||
public abstract class GetTaskResult : Result
|
||||
{
|
||||
/// <summary>Prevent external derivations.</summary>
|
||||
private protected GetTaskResult()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the stable identifier for this task.
|
||||
/// </summary>
|
||||
[JsonPropertyName("taskId")]
|
||||
public required string TaskId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current task status.
|
||||
/// </summary>
|
||||
[JsonPropertyName("status")]
|
||||
public abstract McpTaskStatus Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional message describing the current task 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 was last updated.
|
||||
/// </summary>
|
||||
[JsonPropertyName("lastUpdatedAt")]
|
||||
public required DateTimeOffset LastUpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time-to-live duration from creation in milliseconds, or <see langword="null"/> for unlimited.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ttlMs")]
|
||||
public long? TtlMs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the suggested polling interval in milliseconds.
|
||||
/// </summary>
|
||||
[JsonPropertyName("pollIntervalMs")]
|
||||
public long? PollIntervalMs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// JSON converter that deserializes <see cref="GetTaskResult"/> to the appropriate concrete subtype
|
||||
/// based on the <c>status</c> discriminator field.
|
||||
/// </summary>
|
||||
internal sealed class Converter : JsonConverter<GetTaskResult>
|
||||
{
|
||||
public override GetTaskResult? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.StartObject)
|
||||
{
|
||||
throw new JsonException("Expected StartObject token for GetTaskResult.");
|
||||
}
|
||||
|
||||
string? taskId = null;
|
||||
string? statusString = null;
|
||||
string? statusMessage = null;
|
||||
DateTimeOffset? createdAt = null;
|
||||
DateTimeOffset? lastUpdatedAt = null;
|
||||
long? ttlMs = null;
|
||||
long? pollIntervalMs = null;
|
||||
string? resultType = null;
|
||||
JsonObject? meta = null;
|
||||
JsonElement? result = null;
|
||||
JsonElement? error = null;
|
||||
Dictionary<string, InputRequest>? inputRequests = null;
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.EndObject)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||
{
|
||||
throw new JsonException("Expected property name.");
|
||||
}
|
||||
|
||||
string propertyName = reader.GetString()!;
|
||||
reader.Read();
|
||||
|
||||
switch (propertyName)
|
||||
{
|
||||
case "taskId":
|
||||
taskId = reader.GetString();
|
||||
break;
|
||||
case "status":
|
||||
statusString = reader.GetString();
|
||||
break;
|
||||
case "statusMessage":
|
||||
statusMessage = reader.GetString();
|
||||
break;
|
||||
case "createdAt":
|
||||
createdAt = reader.GetDateTimeOffset();
|
||||
break;
|
||||
case "lastUpdatedAt":
|
||||
lastUpdatedAt = reader.GetDateTimeOffset();
|
||||
break;
|
||||
case "ttlMs":
|
||||
ttlMs = reader.GetInt64();
|
||||
break;
|
||||
case "pollIntervalMs":
|
||||
pollIntervalMs = reader.GetInt64();
|
||||
break;
|
||||
case "resultType":
|
||||
resultType = reader.GetString();
|
||||
break;
|
||||
case "_meta":
|
||||
meta = JsonSerializer.Deserialize(ref reader, options.GetTypeInfo<JsonObject>());
|
||||
break;
|
||||
case "result":
|
||||
result = JsonElement.ParseValue(ref reader);
|
||||
break;
|
||||
case "error":
|
||||
error = JsonElement.ParseValue(ref reader);
|
||||
break;
|
||||
case "inputRequests":
|
||||
if (reader.TokenType != JsonTokenType.StartObject)
|
||||
{
|
||||
throw new JsonException("'inputRequests' must be a JSON object.");
|
||||
}
|
||||
inputRequests = new Dictionary<string, InputRequest>(StringComparer.Ordinal);
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.EndObject)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||
{
|
||||
throw new JsonException("Expected property name in 'inputRequests'.");
|
||||
}
|
||||
string requestKey = reader.GetString()!;
|
||||
reader.Read();
|
||||
var inputRequest = JsonSerializer.Deserialize(ref reader, McpJsonUtilities.JsonContext.Default.InputRequest)
|
||||
?? throw new JsonException($"Failed to deserialize InputRequest for key '{requestKey}'.");
|
||||
inputRequests[requestKey] = inputRequest;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (taskId is null)
|
||||
{
|
||||
throw new JsonException("Missing required 'taskId' property on GetTaskResult.");
|
||||
}
|
||||
|
||||
if (statusString is null)
|
||||
{
|
||||
throw new JsonException("Missing required 'status' property on GetTaskResult.");
|
||||
}
|
||||
|
||||
if (createdAt is null)
|
||||
{
|
||||
throw new JsonException("Missing required 'createdAt' property on GetTaskResult.");
|
||||
}
|
||||
|
||||
if (lastUpdatedAt is null)
|
||||
{
|
||||
throw new JsonException("Missing required 'lastUpdatedAt' property on GetTaskResult.");
|
||||
}
|
||||
|
||||
GetTaskResult taskResult = statusString switch
|
||||
{
|
||||
"working" => new WorkingTaskResult
|
||||
{
|
||||
TaskId = taskId,
|
||||
CreatedAt = createdAt.Value,
|
||||
LastUpdatedAt = lastUpdatedAt.Value,
|
||||
},
|
||||
"completed" => result is not null
|
||||
? new CompletedTaskResult
|
||||
{
|
||||
TaskId = taskId,
|
||||
CreatedAt = createdAt.Value,
|
||||
LastUpdatedAt = lastUpdatedAt.Value,
|
||||
Result = result.Value,
|
||||
}
|
||||
: throw new JsonException("Completed task is missing required 'result' property."),
|
||||
"failed" => error is not null
|
||||
? new FailedTaskResult
|
||||
{
|
||||
TaskId = taskId,
|
||||
CreatedAt = createdAt.Value,
|
||||
LastUpdatedAt = lastUpdatedAt.Value,
|
||||
Error = error.Value,
|
||||
}
|
||||
: throw new JsonException("Failed task is missing required 'error' property."),
|
||||
"cancelled" => new CancelledTaskResult
|
||||
{
|
||||
TaskId = taskId,
|
||||
CreatedAt = createdAt.Value,
|
||||
LastUpdatedAt = lastUpdatedAt.Value,
|
||||
},
|
||||
"input_required" => inputRequests is not null
|
||||
? new InputRequiredTaskResult
|
||||
{
|
||||
TaskId = taskId,
|
||||
CreatedAt = createdAt.Value,
|
||||
LastUpdatedAt = lastUpdatedAt.Value,
|
||||
InputRequests = inputRequests,
|
||||
}
|
||||
: throw new JsonException("Input-required task is missing required 'inputRequests' property."),
|
||||
_ => throw new JsonException($"Unknown task status: '{statusString}'.")
|
||||
};
|
||||
|
||||
taskResult.StatusMessage = statusMessage;
|
||||
taskResult.TtlMs = ttlMs;
|
||||
taskResult.PollIntervalMs = pollIntervalMs;
|
||||
taskResult.ResultType = resultType;
|
||||
taskResult.Meta = meta;
|
||||
|
||||
return taskResult;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, GetTaskResult value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
|
||||
if (value.ResultType is not null)
|
||||
{
|
||||
writer.WriteString("resultType", value.ResultType);
|
||||
}
|
||||
|
||||
if (value.Meta is not null)
|
||||
{
|
||||
writer.WritePropertyName("_meta");
|
||||
JsonSerializer.Serialize(writer, value.Meta, options.GetTypeInfo<JsonObject>());
|
||||
}
|
||||
|
||||
writer.WriteString("taskId", value.TaskId);
|
||||
writer.WriteString("status", value.Status switch
|
||||
{
|
||||
McpTaskStatus.Working => "working",
|
||||
McpTaskStatus.Completed => "completed",
|
||||
McpTaskStatus.Failed => "failed",
|
||||
McpTaskStatus.Cancelled => "cancelled",
|
||||
McpTaskStatus.InputRequired => "input_required",
|
||||
_ => throw new JsonException($"Unknown McpTaskStatus: {value.Status}")
|
||||
});
|
||||
|
||||
if (value.StatusMessage is not null)
|
||||
{
|
||||
writer.WriteString("statusMessage", value.StatusMessage);
|
||||
}
|
||||
|
||||
writer.WriteString("createdAt", value.CreatedAt);
|
||||
writer.WriteString("lastUpdatedAt", value.LastUpdatedAt);
|
||||
|
||||
if (value.TtlMs is not null)
|
||||
{
|
||||
writer.WriteNumber("ttlMs", value.TtlMs.Value);
|
||||
}
|
||||
|
||||
if (value.PollIntervalMs is not null)
|
||||
{
|
||||
writer.WriteNumber("pollIntervalMs", value.PollIntervalMs.Value);
|
||||
}
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case CompletedTaskResult completed:
|
||||
writer.WritePropertyName("result");
|
||||
completed.Result.WriteTo(writer);
|
||||
break;
|
||||
case FailedTaskResult failed:
|
||||
writer.WritePropertyName("error");
|
||||
failed.Error.WriteTo(writer);
|
||||
break;
|
||||
case InputRequiredTaskResult inputRequired:
|
||||
writer.WritePropertyName("inputRequests");
|
||||
writer.WriteStartObject();
|
||||
if (inputRequired.InputRequests is { } reqs)
|
||||
{
|
||||
foreach (var kvp in reqs)
|
||||
{
|
||||
writer.WritePropertyName(kvp.Key);
|
||||
JsonSerializer.Serialize(writer, kvp.Value, McpJsonUtilities.JsonContext.Default.InputRequest);
|
||||
}
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
break;
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a task that is currently being processed by the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </remarks>
|
||||
public sealed class WorkingTaskResult : GetTaskResult
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[JsonPropertyName("status")]
|
||||
public override McpTaskStatus Status => McpTaskStatus.Working;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a task that has completed successfully, carrying the final result.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The <see cref="Result"/> field contains the result structure matching the original request type.
|
||||
/// For example, a <c>tools/call</c> task would contain the <see cref="CallToolResult"/> structure.
|
||||
/// This includes tool calls that returned results with <c>isError: true</c>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class CompletedTaskResult : GetTaskResult
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[JsonPropertyName("status")]
|
||||
public override McpTaskStatus Status => McpTaskStatus.Completed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the final result of the task as raw JSON.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The structure matches the result type of the original request.
|
||||
/// </remarks>
|
||||
[JsonPropertyName("result")]
|
||||
public required JsonElement Result { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a task that failed due to a JSON-RPC error during execution.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The <see cref="Error"/> field contains the JSON-RPC error object that caused the failure.
|
||||
/// This status must not be used for non-JSON-RPC errors.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class FailedTaskResult : GetTaskResult
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[JsonPropertyName("status")]
|
||||
public override McpTaskStatus Status => McpTaskStatus.Failed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the JSON-RPC error that caused the task to fail.
|
||||
/// </summary>
|
||||
[JsonPropertyName("error")]
|
||||
public required JsonElement Error { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a task that was cancelled before completion.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </remarks>
|
||||
public sealed class CancelledTaskResult : GetTaskResult
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[JsonPropertyName("status")]
|
||||
public override McpTaskStatus Status => McpTaskStatus.Cancelled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a task that requires input from the client before it can proceed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The <see cref="InputRequests"/> field contains outstanding server-to-client requests
|
||||
/// that the client must fulfil. Each entry is keyed by an arbitrary identifier for matching
|
||||
/// requests to responses, and each value is an <see cref="InputRequest"/> wrapping the
|
||||
/// server-to-client request payload.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Clients must treat each entry as they would the equivalent standalone server-to-client request.
|
||||
/// Clients should deduplicate keys across consecutive polls to avoid presenting the same request
|
||||
/// to the user or model more than once.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class InputRequiredTaskResult : GetTaskResult
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[JsonPropertyName("status")]
|
||||
public override McpTaskStatus Status => McpTaskStatus.InputRequired;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the server-to-client requests that need to be fulfilled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Keys are arbitrary identifiers for matching requests to responses.
|
||||
/// Each value is an <see cref="InputRequest"/> wrapping the server-to-client request
|
||||
/// (e.g., a sampling, elicitation, or roots-list request).
|
||||
/// </remarks>
|
||||
[JsonPropertyName("inputRequests")]
|
||||
public IDictionary<string, InputRequest>? InputRequests { get; set; }
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
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 IList<McpTask> Tasks { get; set; }
|
||||
}
|
||||
18
src/ModelContextProtocol.Core/Protocol/McpExtensions.cs
Normal file
18
src/ModelContextProtocol.Core/Protocol/McpExtensions.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
namespace ModelContextProtocol.Protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Provides constants for well-known MCP extension identifiers.
|
||||
/// </summary>
|
||||
public static class McpExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// The extension identifier for the MCP Tasks extension.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When included in client per-request capabilities, indicates the client can handle
|
||||
/// <see cref="CreateTaskResult"/> in lieu of a standard result.
|
||||
/// See the <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </remarks>
|
||||
public const string Tasks = "io.modelcontextprotocol/tasks";
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
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}" : "");
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
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; }
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ModelContextProtocol.Protocol;
|
||||
|
|
@ -7,73 +6,44 @@ namespace ModelContextProtocol.Protocol;
|
|||
/// 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>
|
||||
/// Tasks are durable state machines that carry information about the underlying execution state
|
||||
/// of the request they augment. See the
|
||||
/// <see href="https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md">SEP-2663</see>
|
||||
/// specification for details.
|
||||
/// </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.
|
||||
/// The server needs input from the client before the task can proceed.
|
||||
/// The <c>tasks/get</c> response will include outstanding requests in the <c>inputRequests</c> field.
|
||||
/// </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.
|
||||
/// This includes tool calls that returned results with <c>isError: true</c>.
|
||||
/// </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
|
||||
Cancelled,
|
||||
|
||||
/// <summary>
|
||||
/// The request failed due to a JSON-RPC error during execution.
|
||||
/// This status must not be used for non-JSON-RPC errors.
|
||||
/// </summary>
|
||||
[JsonStringEnumMemberName("failed")]
|
||||
Failed,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
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; }
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
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;
|
||||
|
|
@ -143,39 +143,12 @@ public static class NotificationMethods
|
|||
public const string CancelledNotification = "notifications/cancelled";
|
||||
|
||||
/// <summary>
|
||||
/// The name of the notification sent when a task status changes.
|
||||
/// The name of the notification sent by the server to push task status updates to subscribed clients.
|
||||
/// </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>
|
||||
/// Part of the <c>io.modelcontextprotocol/tasks</c> extension.
|
||||
/// Each notification carries a complete task state for the current status, identical to what
|
||||
/// <c>tasks/get</c> would have returned at that moment.
|
||||
/// </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";
|
||||
public const string TaskStatusNotification = "notifications/tasks";
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue