Implement MCP task support (SEP-1686) (#1170)
Co-authored-by: Stephen Halter <halter73@gmail.com>
This commit is contained in:
parent
81664c3fce
commit
10e4f5b20f
1 changed files with 11580 additions and 46 deletions
|
|
@ -46,6 +46,14 @@ public class TestServerTransport : ITransport
|
|||
await SamplingAsync(request, cancellationToken);
|
||||
else if (request.Method == RequestMethods.ElicitationCreate)
|
||||
await ElicitAsync(request, cancellationToken);
|
||||
else if (request.Method == RequestMethods.TasksGet)
|
||||
await TasksGetAsync(request, cancellationToken);
|
||||
else if (request.Method == RequestMethods.TasksResult)
|
||||
await TasksResultAsync(request, cancellationToken);
|
||||
else if (request.Method == RequestMethods.TasksList)
|
||||
await TasksListAsync(request, cancellationToken);
|
||||
else if (request.Method == RequestMethods.TasksCancel)
|
||||
await TasksCancelAsync(request, cancellationToken);
|
||||
else
|
||||
await WriteMessageAsync(request, cancellationToken);
|
||||
}
|
||||
|
|
@ -71,19 +79,161 @@ public class TestServerTransport : ITransport
|
|||
|
||||
private async Task SamplingAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
// Check if the request is task-augmented (has Task metadata)
|
||||
var requestParams = JsonSerializer.Deserialize<CreateMessageRequestParams>(request.Params, McpJsonUtilities.DefaultOptions);
|
||||
if (requestParams?.Task is not null && MockTask is not null)
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new CreateMessageResult { Content = [new TextContentBlock { Text = "" }], Model = "model"}, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
// Return a task-augmented response
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new CreateTaskResult { Task = MockTask }, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return a normal sampling response
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new CreateMessageResult { Content = [new TextContentBlock { Text = "" }], Model = "model" }, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ElicitAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// Check if the request is task-augmented (has Task metadata)
|
||||
var requestParams = JsonSerializer.Deserialize<ElicitRequestParams>(request.Params, McpJsonUtilities.DefaultOptions);
|
||||
if (requestParams?.Task is not null && MockTask is not null)
|
||||
{
|
||||
// Return a task-augmented response
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new CreateTaskResult { Task = MockTask }, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return a normal elicitation response
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new ElicitResult { Action = "decline" }, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the task to return from tasks/get requests.
|
||||
/// </summary>
|
||||
public McpTask? MockTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the result to return from tasks/result requests.
|
||||
/// </summary>
|
||||
public object? MockTaskResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of tasks to return from tasks/list requests.
|
||||
/// </summary>
|
||||
public McpTask[]? MockTaskList { get; set; }
|
||||
|
||||
private async Task TasksGetAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var task = MockTask ?? new McpTask
|
||||
{
|
||||
TaskId = "test-task-id",
|
||||
Status = McpTaskStatus.Completed,
|
||||
CreatedAt = DateTimeOffset.UtcNow.AddMinutes(-5),
|
||||
LastUpdatedAt = DateTimeOffset.UtcNow,
|
||||
};
|
||||
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new ElicitResult { Action = "decline" }, McpJsonUtilities.DefaultOptions),
|
||||
Result = JsonSerializer.SerializeToNode(new GetTaskResult
|
||||
{
|
||||
TaskId = task.TaskId,
|
||||
Status = task.Status,
|
||||
StatusMessage = task.StatusMessage,
|
||||
CreatedAt = task.CreatedAt,
|
||||
LastUpdatedAt = task.LastUpdatedAt,
|
||||
TimeToLive = task.TimeToLive,
|
||||
PollInterval = task.PollInterval
|
||||
}, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task TasksResultAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = MockTaskResult ?? new CreateMessageResult
|
||||
{
|
||||
Content = [new TextContentBlock { Text = "Task result" }],
|
||||
Model = "test-model"
|
||||
};
|
||||
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(result, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task TasksListAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tasks = MockTaskList ?? [
|
||||
new McpTask
|
||||
{
|
||||
TaskId = "task-1",
|
||||
Status = McpTaskStatus.Completed,
|
||||
CreatedAt = DateTimeOffset.UtcNow.AddMinutes(-5),
|
||||
LastUpdatedAt = DateTimeOffset.UtcNow,
|
||||
},
|
||||
new McpTask
|
||||
{
|
||||
TaskId = "task-2",
|
||||
Status = McpTaskStatus.Working,
|
||||
CreatedAt = DateTimeOffset.UtcNow.AddMinutes(-3),
|
||||
LastUpdatedAt = DateTimeOffset.UtcNow,
|
||||
}
|
||||
];
|
||||
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new ListTasksResult
|
||||
{
|
||||
Tasks = tasks,
|
||||
}, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task TasksCancelAsync(JsonRpcRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var task = MockTask ?? new McpTask
|
||||
{
|
||||
TaskId = "test-task-id",
|
||||
Status = McpTaskStatus.Cancelled,
|
||||
StatusMessage = "Task cancelled by request",
|
||||
CreatedAt = DateTimeOffset.UtcNow.AddMinutes(-5),
|
||||
LastUpdatedAt = DateTimeOffset.UtcNow,
|
||||
};
|
||||
|
||||
await WriteMessageAsync(new JsonRpcResponse
|
||||
{
|
||||
Id = request.Id,
|
||||
Result = JsonSerializer.SerializeToNode(new CancelMcpTaskResult
|
||||
{
|
||||
TaskId = task.TaskId,
|
||||
Status = McpTaskStatus.Cancelled,
|
||||
StatusMessage = task.StatusMessage ?? "Task cancelled",
|
||||
CreatedAt = task.CreatedAt,
|
||||
LastUpdatedAt = DateTimeOffset.UtcNow,
|
||||
TimeToLive = task.TimeToLive,
|
||||
PollInterval = task.PollInterval
|
||||
}, McpJsonUtilities.DefaultOptions),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue