update_todo
Modify existing todo items by updating fields, searching for specific tasks, or managing tags to maintain organized task lists.
Instructions
Update fields on a todo item (supports search and tag ops)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/update_todo.ts:103-125 (handler)Core handler function executing the update_todo tool logic, resolving the todo selector, building updates, and persisting via storage.async function handleUpdateTodo( input: UpdateTodoInput ): Promise<CallToolResult> { const outcome = await updateTodoBySelector( toResolveInput({ id: input.id, query: input.query }), (todo) => buildUpdatePayload(todo, input) ); if (outcome.kind === 'error' || outcome.kind === 'ambiguous') { return outcome.response; } if (outcome.kind === 'no_updates') { return createErrorResponse('E_BAD_REQUEST', 'No fields provided to update'); } return createToolResponse({ ok: true, result: { item: outcome.todo, summary: `Updated todo "${outcome.todo.title}"`, nextActions: ['list_todos', 'complete_todo'], }, }); }
- src/schemas/inputs.ts:99-133 (schema)Zod input schema defining parameters for the update_todo tool including id/query selector, fields to update, clearFields, and tagOps.export const UpdateTodoSchema = z .object({ id: z .string() .min(1) .max(100) .optional() .describe('The ID of the todo to update'), query: z .string() .min(1) .max(200) .optional() .describe('Search text to find a single todo to update'), title: z.string().min(1).max(200).optional().describe('New title'), description: z.string().max(2000).optional().describe('New description'), completed: z.boolean().optional().describe('Completion status'), priority: z .enum(['low', 'normal', 'high']) .optional() .describe('New priority level'), dueDate: IsoDateSchema.optional().describe('New due date (ISO format)'), tags: z.array(TagSchema).max(50).optional().describe('New tags'), clearFields: z .array(z.enum(['description', 'dueDate', 'tags'])) .max(3) .optional() .describe('Fields to clear'), tagOps: TagOpsSchema.optional().describe('Tag modifications to apply'), }) .strict() .refine((value) => Boolean(value.id ?? value.query), { message: 'Provide id or query to identify the todo', });
- src/tools/update_todo.ts:127-148 (registration)Registers the 'update_todo' tool with the MCP server, specifying schema, description, and handler.export function registerUpdateTodo(server: McpServer): void { server.registerTool( 'update_todo', { title: 'Update Todo', description: 'Update fields on a todo item (supports search and tag ops)', inputSchema: UpdateTodoSchema, outputSchema: DefaultOutputSchema, annotations: { readOnlyHint: false, idempotentHint: true, }, }, async (input) => { try { return await handleUpdateTodo(input); } catch (err) { return createErrorResponse('E_UPDATE_TODO', getErrorMessage(err)); } } ); }
- src/lib/storage.ts:422-444 (helper)Key storage helper that resolves todo by selector, applies updates via callback, and persists changes to todos.json.export async function updateTodoBySelector( input: ResolveTodoInput, buildUpdates: (todo: Todo) => Partial<Omit<Todo, 'id' | 'createdAt'>> | null ): Promise<UpdateTodoOutcome> { return queueWrite(async () => { const todos = await readTodosFromDisk(); const outcome = unwrapResolution(resolveTodoTargetFromTodos(todos, input)); if (outcome.kind !== 'match') return outcome; const nextUpdates = buildUpdates(outcome.todo); if (!nextUpdates || Object.keys(nextUpdates).length === 0) { return { kind: 'no_updates' }; } const updatedTodo = updateTodoInList(todos, outcome.todo.id, nextUpdates); if (!updatedTodo) { return createNotFoundOutcome(outcome.todo.id); } await persistTodos(todos); return { kind: 'match', todo: updatedTodo }; }); }
- src/tools/index.ts:10-17 (registration)Central registration function that calls registerUpdateTodo among others.export function registerAllTools(server: McpServer): void { registerAddTodo(server); registerAddTodos(server); registerListTodos(server); registerUpdateTodo(server); registerCompleteTodo(server); registerDeleteTodo(server); }