Allow setting ParentTaskId when updating a task via the API (with validation that the parent exists) and when creating a task via the MCP create_task tool. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
118 lines
5.1 KiB
C#
118 lines
5.1 KiB
C#
using System.ComponentModel;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using ModelContextProtocol.Server;
|
|
|
|
namespace TaskTracker.MCP.Tools;
|
|
|
|
[McpServerToolType]
|
|
public sealed class TaskTools
|
|
{
|
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
{
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
WriteIndented = true
|
|
};
|
|
|
|
[McpServerTool, Description("Get the currently active work task with its latest notes and recent context events")]
|
|
public static async Task<string> GetActiveTask(HttpClient client)
|
|
{
|
|
var response = await client.GetAsync("/api/tasks/active");
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("List work tasks, optionally filtered by status (Pending, Active, Paused, Completed, Abandoned)")]
|
|
public static async Task<string> ListTasks(
|
|
HttpClient client,
|
|
[Description("Filter by status: Pending, Active, Paused, Completed, Abandoned")] string? status = null)
|
|
{
|
|
var url = "/api/tasks";
|
|
if (!string.IsNullOrEmpty(status))
|
|
url += $"?status={status}";
|
|
|
|
var response = await client.GetAsync(url);
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Create a new work task")]
|
|
public static async Task<string> CreateTask(
|
|
HttpClient client,
|
|
[Description("Title of the task")] string title,
|
|
[Description("Optional description")] string? description = null,
|
|
[Description("Optional category (e.g. Engineering, Email, LaserCutting)")] string? category = null,
|
|
[Description("Optional parent task ID to create this as a subtask")] int? parentTaskId = null)
|
|
{
|
|
var payload = new { title, description, category, parentTaskId };
|
|
var response = await client.PostAsJsonAsync("/api/tasks", payload, JsonOptions);
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Start/activate a task by ID. Automatically pauses any currently active task.")]
|
|
public static async Task<string> StartTask(
|
|
HttpClient client,
|
|
[Description("The task ID to start")] int taskId)
|
|
{
|
|
var response = await client.PutAsync($"/api/tasks/{taskId}/start", null);
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Pause a task with an optional note about why it was paused")]
|
|
public static async Task<string> PauseTask(
|
|
HttpClient client,
|
|
[Description("The task ID to pause")] int taskId,
|
|
[Description("Optional note about why the task is being paused")] string? note = null)
|
|
{
|
|
var payload = new { note };
|
|
var response = await client.PutAsJsonAsync($"/api/tasks/{taskId}/pause", payload, JsonOptions);
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Resume a paused task with an optional note about context for resuming")]
|
|
public static async Task<string> ResumeTask(
|
|
HttpClient client,
|
|
[Description("The task ID to resume")] int taskId,
|
|
[Description("Optional note about context for resuming")] string? note = null)
|
|
{
|
|
var payload = new { note };
|
|
var response = await client.PutAsJsonAsync($"/api/tasks/{taskId}/resume", payload, JsonOptions);
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Mark a task as complete")]
|
|
public static async Task<string> CompleteTask(
|
|
HttpClient client,
|
|
[Description("The task ID to complete")] int taskId)
|
|
{
|
|
var response = await client.PutAsync($"/api/tasks/{taskId}/complete", null);
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Add a note to a task")]
|
|
public static async Task<string> AddNote(
|
|
HttpClient client,
|
|
[Description("The task ID")] int taskId,
|
|
[Description("The note content")] string content,
|
|
[Description("Note type: General, PauseNote, or ResumeNote")] string type = "General")
|
|
{
|
|
var payload = new { content, type };
|
|
var response = await client.PostAsJsonAsync($"/api/tasks/{taskId}/notes", payload, JsonOptions);
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Get a summary of recent window/browser activity grouped by application, useful for understanding what the user has been working on")]
|
|
public static async Task<string> GetContextSummary(HttpClient client)
|
|
{
|
|
var response = await client.GetAsync("/api/context/summary");
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
[McpServerTool, Description("Get raw context events (window switches, browser navigations) from the last N minutes")]
|
|
public static async Task<string> GetRecentContext(
|
|
HttpClient client,
|
|
[Description("Number of minutes to look back (default 30)")] int minutes = 30)
|
|
{
|
|
var response = await client.GetAsync($"/api/context/recent?minutes={minutes}");
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
}
|