tasks_update
Update multiple tasks to a new status in bulk by ID. Returns a complete summary and prevents accidental modifications during mass updates.
Instructions
Update tasks in bulk by ID to a different status. Returns complete summary no need to call tasks_summary afterwards. Prevents AI accidentally rename or deleting tasks during mass updates, not even possible
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| source_id | No | Source ID from task_setup() response - Defaults to most recent in the workspace if not provided - Try to always provide it! - If you don't have it, ask the user for a file path and call task_setup() | |
| ids | Yes | The IDs of existing tasks | |
| status | Yes | You might need to infer it from the context: - "To Do" for tasks coming up next (e.g. "Do X next") - "In Progress" for what you'll do now (e.g. "First do X") - "Reminders" instructions for you (the AI) to be constantly reminded of - "Notes" to collect non-actionable notes - "Deleted" when they want these removed - Updating tasks to In Progress moves others to To Do, finishing a In Progress task moves the first Done to In Progress | |
| index | No | 0-based index to place the tasks. e.g.: - 0 for "Do this next" - Omit to place at the end ("Do this later") |
Implementation Reference
- src/tools.ts:130-150 (handler)Handler for the tasks_update tool (defined as 'update'). Resolves task IDs to texts, handles errors, and delegates to the add tool handler with an update context flag for special behavior.handler: (args, context = {}) => { const meta = metadata.load(args.source_id) const texts = args.ids.map((id) => { const task = meta.tasksByIdOrText[id] if (task) { return task.text } if (util.isId(id)) { throw new Error(`Task ID ${id} not found`) } // Assume the AI passed a text for a new task by mistake return id }) // Use add internally also for DELETED return tools.add.handler({ source_id: args.source_id, status: args.status, index: args.index, texts, }, { ...context, update: true }) },
- src/tools.ts:118-127 (schema)Zod input schema for the tasks_update tool, defining source_id, ids, status (including deleted), and optional index.schema: z.object({ source_id: schemas.sourceId, ids: schemas.ids, status: z.union([schemas.status, z.literal(env.STATUS_DELETED)]).describe(util.trimLines(` ${schemas.status.description} - "${env.STATUS_DELETED}" when they want these removed ${env.AUTO_WIP ? `- Updating tasks to ${env.STATUS_WIP} moves others to ${env.STATUS_TODO}, finishing a ${env.STATUS_WIP} task moves the first ${env.STATUS_DONE} to ${env.STATUS_WIP}` : ''} `)), index: schemas.index, }),
- src/tools.ts:117-151 (registration)Registration of the 'update' tool in the central tools object. The name is prefixed to 'tasks_update' by defineTool if PREFIX_TOOLS is enabled.update: defineTool('update', { schema: z.object({ source_id: schemas.sourceId, ids: schemas.ids, status: z.union([schemas.status, z.literal(env.STATUS_DELETED)]).describe(util.trimLines(` ${schemas.status.description} - "${env.STATUS_DELETED}" when they want these removed ${env.AUTO_WIP ? `- Updating tasks to ${env.STATUS_WIP} moves others to ${env.STATUS_TODO}, finishing a ${env.STATUS_WIP} task moves the first ${env.STATUS_DONE} to ${env.STATUS_WIP}` : ''} `)), index: schemas.index, }), fromArgs: ([taskIds, status]) => ({ ids: split(taskIds) || [], status }), description: 'Update tasks in bulk by ID to a different status. Returns complete summary no need to call tasks_summary afterwards. Prevents AI accidentally rename or deleting tasks during mass updates, not even possible', handler: (args, context = {}) => { const meta = metadata.load(args.source_id) const texts = args.ids.map((id) => { const task = meta.tasksByIdOrText[id] if (task) { return task.text } if (util.isId(id)) { throw new Error(`Task ID ${id} not found`) } // Assume the AI passed a text for a new task by mistake return id }) // Use add internally also for DELETED return tools.add.handler({ source_id: args.source_id, status: args.status, index: args.index, texts, }, { ...context, update: true }) }, }),
- src/server.ts:15-42 (registration)MCP server registration loop that adds all enabled tools from tools.ts (including tasks_update) to the FastMCP server instance.// Register all tools & resources for (const tool of Object.values(tools)) { if (!tool.isEnabled) { continue } if (tool.isResource) { // Register as resource server.addResource({ uri: `resource://${tool.name}`, name: tool.description, mimeType: 'text/plain', load: () => cli.runTool(tool, []).then(text => ({ text })), }) } else { // Register as tool with enhanced logging server.addTool({ annotations: { openWorldHint: false, // This tool doesn't interact with external systems readOnlyHint: tool.isReadOnly, title: tool.name, }, name: tool.name, description: tool.description, parameters: tool.schema, execute: (args) => cli.runTool(tool, args), }) } }
- src/tools.ts:197-214 (helper)Utility function to define tools, which prefixes the name with 'tasks_' (creating 'tasks_update' from 'update') if PREFIX_TOOLS environment variable is set.function defineTool<S extends ZodSchema>(name: string, tool: { schema: S description: string isResource?: boolean isReadOnly?: boolean isEnabled?: boolean handler: (args: z.infer<S>, context?: any) => any fromArgs: (args: string[]) => z.infer<S> }) { const toolName = env.PREFIX_TOOLS ? `tasks_${name}` : name return { ...tool, name: toolName, isResource: tool.isResource ?? false, isReadOnly: tool.isReadOnly ?? false, isEnabled: tool.isEnabled ?? true, } }