Implement MCP task support (SEP-1686) (#1170)
Co-authored-by: Stephen Halter <halter73@gmail.com>
This commit is contained in:
parent
81664c3fce
commit
10e4f5b20f
21 changed files with 11580 additions and 46 deletions
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
28
src/ModelContextProtocol.Core/Protocol/CreateTaskResult.cs
Normal file
28
src/ModelContextProtocol.Core/Protocol/CreateTaskResult.cs
Normal 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!;
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
104
src/ModelContextProtocol.Core/Protocol/McpTask.cs
Normal file
104
src/ModelContextProtocol.Core/Protocol/McpTask.cs
Normal 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}" : "");
|
||||
}
|
||||
41
src/ModelContextProtocol.Core/Protocol/McpTaskMetadata.cs
Normal file
41
src/ModelContextProtocol.Core/Protocol/McpTaskMetadata.cs
Normal 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; }
|
||||
}
|
||||
79
src/ModelContextProtocol.Core/Protocol/McpTaskStatus.cs
Normal file
79
src/ModelContextProtocol.Core/Protocol/McpTaskStatus.cs
Normal 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
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
160
src/ModelContextProtocol.Core/Protocol/McpTasksCapability.cs
Normal file
160
src/ModelContextProtocol.Core/Protocol/McpTasksCapability.cs
Normal 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;
|
||||
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
Loading…
Reference in a new issue