Every tool description now leads with what the tool does AND when to reach for it, since MCP clients rank tools by that text. Per-parameter prose moved onto the parameters as [Description], exhaustive result-shape enumerations and design/history rationale dropped, and the repeated boilerplate clauses (lean-task-ref, batch cap, refused-while-Running) pulled into McpToolDocs, which also documents the style for future tools. Tool-level description text: 20494 -> 13605 chars (-34%); combined with the new parameter descriptions 18517 (-10%). Closes gaps that caused wrong calls rather than just verbose ones: - list_task_attachments returns metadata only, no file content - run_task_now shares continue_task's single override slot and throws when busy - list_runs is ordered oldest-first and feeds get_run - workingDir on create_list/update_list is an existing local git repo path, unvalidated until the first task run - get_task_worktree's behind=0 also means the main ref was unreachable Removes get_task_status_values: a whole tool entry for static reference text. GetTask's description is now the canonical place for status meanings.
47 lines
2.0 KiB
C#
47 lines
2.0 KiB
C#
using System.ComponentModel;
|
|
using ClaudeDo.Data.Repositories;
|
|
using ClaudeDo.Worker.Hub;
|
|
using ModelContextProtocol.Server;
|
|
|
|
namespace ClaudeDo.Worker.External;
|
|
|
|
public sealed record HandoffListHandlerResult(bool Requested, string TaskId, int SurvivingCount);
|
|
|
|
[McpServerToolType]
|
|
public sealed class HandoffMcpTools
|
|
{
|
|
private readonly TaskRepository _tasks;
|
|
private readonly HubBroadcaster _broadcaster;
|
|
|
|
public HandoffMcpTools(TaskRepository tasks, HubBroadcaster broadcaster)
|
|
{
|
|
_tasks = tasks;
|
|
_broadcaster = broadcaster;
|
|
}
|
|
|
|
[McpServerTool, Description(
|
|
"Call at the end of Phase 2 of the list handler (\"Let Claude handle it\") to hand this run off " +
|
|
"to a fresh ConPTY session that carries out Phases 3-5, without dragging along this session's " +
|
|
"dedupe/rewrite context. Reuses the SAME handler task -- no new task is created, and " +
|
|
"HandlerBaseCommit is untouched. The current tile stays open; you must end your own turn " +
|
|
"immediately after calling this.")]
|
|
public async Task<HandoffListHandlerResult> HandoffListHandler(
|
|
[Description("This session's own handler task id.")] string taskId,
|
|
[Description("The tasks that made it past dedupe, in the order to run them.")] IReadOnlyList<string> survivingTaskIds,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
if (survivingTaskIds.Count == 0)
|
|
throw new InvalidOperationException("survivingTaskIds must contain at least one task id.");
|
|
|
|
_ = await _tasks.GetByIdAsync(taskId, cancellationToken)
|
|
?? throw new InvalidOperationException($"Task {taskId} not found.");
|
|
|
|
foreach (var id in survivingTaskIds)
|
|
_ = await _tasks.GetByIdAsync(id, cancellationToken)
|
|
?? throw new InvalidOperationException($"Task {id} not found.");
|
|
|
|
await _broadcaster.HandoffRequested(taskId, survivingTaskIds);
|
|
return new HandoffListHandlerResult(true, taskId, survivingTaskIds.Count);
|
|
}
|
|
}
|