todoist_task_update
Update existing Todoist tasks by ID or name to modify content, due dates, priority, labels, projects, or sections for better task management.
Instructions
Update an existing task found by ID or partial name search. Supports updating content, description, due date, priority, labels, deadline, project, and section
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| task_id | No | Task ID to update (optional, takes precedence over task_name) | |
| task_name | No | Partial task name to search for (case-insensitive, used if task_id not provided) | |
| content | No | New content/title for the task (optional) | |
| description | No | New description for the task (optional) | |
| due_string | No | New due date in natural language like 'tomorrow', 'next Monday' (optional) | |
| priority | No | New priority from 1 (normal) to 4 (urgent) (optional) | |
| labels | No | Array of label names to assign to the task (optional) | |
| deadline_date | No | New deadline in YYYY-MM-DD format (optional) | |
| project_id | No | Move task to this project ID (optional) | |
| section_id | No | Move task to this section ID (optional) |
Implementation Reference
- src/handlers/task-handlers.ts:374-459 (handler)The core handler function that implements the logic for updating a Todoist task by ID or partial name, handling content, description, due date, priority, labels, project, and section updates.export async function handleUpdateTask( todoistClient: TodoistApi, args: any ): Promise<string> { // Handle both snake_case and camelCase const { taskId, taskName } = extractTaskIdentifiers(args); // Validate that at least one identifier is provided validateTaskIdentifier(taskId, taskName); validateLabels(args.labels); // Clear cache since we're updating taskCache.clear(); const matchingTask = await findTaskByIdOrName(todoistClient, args); const requestedProjectId = typeof args.project_id === "string" ? args.project_id : undefined; const requestedSectionId = typeof args.section_id === "string" ? args.section_id : undefined; const updateData: Partial<TodoistTaskData> = {}; if (args.content) updateData.content = args.content; if (args.description !== undefined) updateData.description = args.description; if (args.due_string) updateData.dueString = args.due_string; const apiPriorityUpdate = toApiPriority(args.priority); if (apiPriorityUpdate !== undefined) updateData.priority = apiPriorityUpdate; const labelsProvided = Object.prototype.hasOwnProperty.call(args, "labels"); if (labelsProvided) { updateData.labels = Array.isArray(args.labels) ? args.labels : []; } let latestTask = matchingTask; if (Object.keys(updateData).length > 0) { latestTask = await todoistClient.updateTask(matchingTask.id, updateData); } if (requestedProjectId && requestedProjectId !== latestTask.projectId) { const movedTasks = await todoistClient.moveTasks([matchingTask.id], { projectId: requestedProjectId, }); if (movedTasks.length > 0) { latestTask = movedTasks[0]; } } if (requestedSectionId && requestedSectionId !== latestTask.sectionId) { const movedTasks = await todoistClient.moveTasks([matchingTask.id], { sectionId: requestedSectionId, }); if (movedTasks.length > 0) { latestTask = movedTasks[0]; } } // Check if this was a dry-run operation const isDryRun = (latestTask as any).__dryRun === true; const prefix = isDryRun ? "[DRY-RUN] " : ""; const displayUpdatedPriority = fromApiPriority(latestTask.priority); const updatedDueDetails = formatDueDetails(latestTask.due); const projectLine = requestedProjectId && latestTask.projectId ? `\nNew Project ID: ${latestTask.projectId}` : ""; const sectionLine = requestedSectionId ? `\nNew Section ID: ${latestTask.sectionId ?? "None"}` : ""; const labelsLine = labelsProvided ? `\nNew Labels: ${ latestTask.labels && latestTask.labels.length > 0 ? latestTask.labels.join(", ") : "None" }` : ""; return `${prefix}Task "${matchingTask.content}" updated:\nNew Title: ${ latestTask.content }${ latestTask.description ? `\nNew Description: ${latestTask.description}` : "" }${updatedDueDetails ? `\nNew Due Date: ${updatedDueDetails}` : ""}${ displayUpdatedPriority ? `\nNew Priority: ${displayUpdatedPriority}` : "" }${projectLine}${sectionLine}${labelsLine}`; }
- src/tools/task-tools.ts:115-172 (schema)The Tool schema definition including inputSchema for validating arguments to the todoist_task_update tool.export const UPDATE_TASK_TOOL: Tool = { name: "todoist_task_update", description: "Update an existing task found by ID or partial name search. Supports updating content, description, due date, priority, labels, deadline, project, and section", inputSchema: { type: "object", properties: { task_id: { type: "string", description: "Task ID to update (optional, takes precedence over task_name)", }, task_name: { type: "string", description: "Partial task name to search for (case-insensitive, used if task_id not provided)", }, content: { type: "string", description: "New content/title for the task (optional)", }, description: { type: "string", description: "New description for the task (optional)", }, due_string: { type: "string", description: "New due date in natural language like 'tomorrow', 'next Monday' (optional)", }, priority: { type: "number", description: "New priority from 1 (normal) to 4 (urgent) (optional)", enum: [1, 2, 3, 4], }, labels: { type: "array", items: { type: "string", }, description: "Array of label names to assign to the task (optional)", }, deadline_date: { type: "string", description: "New deadline in YYYY-MM-DD format (optional)", }, project_id: { type: "string", description: "Move task to this project ID (optional)", }, section_id: { type: "string", description: "Move task to this section ID (optional)", }, }, required: [], }, };
- src/index.ts:163-168 (registration)The switch case in the main CallToolRequestSchema handler that dispatches calls to todoist_task_update to the appropriate handler function.case "todoist_task_update": if (!isUpdateTaskArgs(args)) { throw new Error("Invalid arguments for todoist_task_update"); } result = await handleUpdateTask(apiClient, args); break;