task_update
Modify task details in Saga MCP's project tracker by updating specific fields like status, priority, or due date, with automatic activity logging for status changes.
Instructions
Update a task. Pass only fields to change. Status transitions are automatically logged in the activity log.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Task ID | |
| title | No | ||
| description | No | ||
| status | No | ||
| priority | No | ||
| assigned_to | No | ||
| estimated_hours | No | ||
| actual_hours | No | ||
| due_date | No | ||
| source_ref | No | Link to source code location | |
| depends_on | No | Task IDs this task depends on (replaces existing) | |
| sort_order | No | ||
| tags | No |
Implementation Reference
- src/tools/tasks.ts:335-400 (handler)The function 'handleTaskUpdate' implements the logic for the 'task_update' tool. It updates database records, handles dependencies, and logs activity.
function handleTaskUpdate(args: Record<string, unknown>) { const db = getDb(); const id = args.id as number; const oldRow = db.prepare('SELECT * FROM tasks WHERE id = ?').get(id) as Record<string, unknown> | undefined; if (!oldRow) throw new Error(`Task ${id} not found`); const update = buildUpdate('tasks', id, args, [ 'title', 'description', 'status', 'priority', 'assigned_to', 'estimated_hours', 'actual_hours', 'due_date', 'source_ref', 'sort_order', 'tags', ]); let newRow: Record<string, unknown>; if (update) { newRow = db.prepare(update.sql).get(...update.params) as Record<string, unknown>; logEntityUpdate(db, 'task', id, newRow.title as string, oldRow, newRow, [ 'status', 'priority', 'assigned_to', 'title', ]); } else if (args.depends_on !== undefined) { // Only depends_on changed, no column updates newRow = oldRow; } else { throw new Error('No fields to update'); } // Handle dependency updates if (args.depends_on !== undefined) { const dependsOn = args.depends_on as number[]; setDependencies(db, id, dependsOn); logActivity(db, 'task', id, 'updated', 'depends_on', null, dependsOn.length > 0 ? dependsOn.join(',') : '(none)', `Task '${newRow.title}' dependencies updated: [${dependsOn.join(', ')}]`); evaluateAndUpdateDependencies(db, id); // Re-fetch in case status changed newRow = db.prepare('SELECT * FROM tasks WHERE id = ?').get(id) as Record<string, unknown>; } // Auto time tracking: when status changes to done and actual_hours wasn't manually set const statusChanged = args.status && oldRow.status !== args.status; if (statusChanged && args.status === 'done' && !args.actual_hours && !newRow.actual_hours) { const startEntry = db.prepare( `SELECT created_at FROM activity_log WHERE entity_type = 'task' AND entity_id = ? AND action = 'status_changed' AND field_name = 'status' AND new_value = 'in_progress' ORDER BY created_at DESC LIMIT 1` ).get(id) as { created_at: string } | undefined; if (startEntry) { const startMs = new Date(startEntry.created_at + 'Z').getTime(); const nowMs = Date.now(); const hours = Math.round(((nowMs - startMs) / 3_600_000) * 10) / 10; // 1 decimal if (hours > 0) { db.prepare('UPDATE tasks SET actual_hours = ? WHERE id = ?').run(hours, id); (newRow as Record<string, unknown>).actual_hours = hours; logActivity(db, 'task', id, 'updated', 'actual_hours', null, String(hours), `Task '${newRow.title}' auto-tracked: ${hours}h`); } } } // Re-evaluate downstream tasks when this task is marked done if (statusChanged && args.status === 'done') { reevaluateDownstream(db, id); } - src/tools/tasks.ts:86-115 (schema)The schema definition for the 'task_update' tool, specifying its input properties.
name: 'task_update', description: 'Update a task. Pass only fields to change. Status transitions are automatically logged in the activity log.', annotations: { title: 'Update Task', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }, inputSchema: { type: 'object', properties: { id: { type: 'integer', description: 'Task ID' }, title: { type: 'string' }, description: { type: 'string' }, status: { type: 'string', enum: ['todo', 'in_progress', 'review', 'done', 'blocked'] }, priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] }, assigned_to: { type: 'string' }, estimated_hours: { type: 'number' }, actual_hours: { type: 'number' }, due_date: { type: 'string' }, source_ref: { type: 'object', description: 'Link to source code location', properties: { file: { type: 'string', description: 'File path' }, line_start: { type: 'integer', description: 'Start line number' }, line_end: { type: 'integer', description: 'End line number' }, repo: { type: 'string', description: 'Repository URL or name' }, commit: { type: 'string', description: 'Commit hash' }, }, required: ['file'], }, depends_on: { type: 'array', items: { type: 'integer' }, description: 'Task IDs this task depends on (replaces existing)' }, sort_order: { type: 'integer' }, - src/tools/tasks.ts:408-408 (registration)Registration of 'task_update' handler in the tools list.
task_update: handleTaskUpdate,