add-task
Add a new task to a Todo.txt file with optional priority, contexts, and projects. Specify a plain text description and format tags with @ for contexts and + for projects.
Instructions
Add a new task to the todo list. Description must be plain text. Priority must be a single uppercase letter (A-Z). Contexts must start with @, projects with +.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| description | Yes | ||
| priority | No | ||
| contexts | No | ||
| projects | No | ||
| extensions | No |
Implementation Reference
- src/tools.ts:30-56 (handler)The handler function for the 'add-task' tool. Validates inputs defensively, loads existing tasks, creates a new Item with the provided description and optional properties (priority, contexts, projects, extensions), appends it to the list, saves to file, and returns success message with new task ID.async ({ description, priority, contexts, projects, extensions }) => { // Handler-level validation (defensive) if (priority && typeof priority === "string" && !/^[A-Z]$/.test(priority)) { return { content: [{ type: "text", text: "Invalid priority: must be a single uppercase letter (A-Z)." }], isError: true }; } if (Array.isArray(contexts) && contexts.some((ctx: string) => !/^@\w+$/.test(ctx))) { return { content: [{ type: "text", text: "Invalid context: must start with @ and contain only word characters." }], isError: true }; } if (Array.isArray(projects) && projects.some((proj: string) => !/^\+\w+$/.test(proj))) { return { content: [{ type: "text", text: "Invalid project: must start with + and contain only word characters." }], isError: true }; } const tasks = await loadTasks(); const newTask = new Item(description as string); if (priority && typeof priority === "string") newTask.setPriority(priority); if (Array.isArray(contexts)) contexts.forEach((context: string) => newTask.addContext(context)); if (Array.isArray(projects)) projects.forEach((project: string) => newTask.addProject(project)); if (extensions) { Object.entries(extensions).forEach(([key, value]) => newTask.setExtension(key as string, value as string)); } tasks.push(newTask); await saveTasks(tasks); return { content: [ { type: "text", text: `Task added successfully. ID: ${tasks.length - 1}` }, ], }; }
- src/tools.ts:23-29 (schema)Input schema for 'add-task' tool using Zod: required description (non-empty, single-line <=200 chars), optional priority (single A-Z), contexts (array of @word), projects (+word), extensions (object).{ description: z.string().min(1, "Description cannot be empty").max(200, "Description too long").regex(/^[^\n\r]+$/, "Description must be a single line"), priority: z.string().regex(/^[A-Z]$/, "Priority must be a single uppercase letter (A-Z)").optional(), contexts: z.array(z.string().regex(/^@\w+$/, "Contexts must start with @ and contain only word characters")).optional(), projects: z.array(z.string().regex(/^\+\w+$/, "Projects must start with + and contain only word characters")).optional(), extensions: z.record(z.string(), z.string()).optional(), },
- src/tools.ts:20-22 (registration)Registration of the 'add-task' tool via server.tool() call, providing name, description, schema, and handler.server.tool( "add-task", "Add a new task to the todo list. Description must be plain text. Priority must be a single uppercase letter (A-Z). Contexts must start with @, projects with +.",
- src/tools.ts:8-11 (helper)Helper function saveTasks used by 'add-task' (and others) to persist the updated task list to the TODO_FILE_PATH.async function saveTasks(tasks: Item[]) { const content = tasks.map((task) => task.toString()).join("\n"); await fs.writeFile(TODO_FILE_PATH, content, "utf-8"); }