todoist_subtasks_bulk_create
Create multiple subtasks under a parent task in Todoist using a single operation to save time and maintain organization.
Instructions
Create multiple subtasks under a parent task in a single operation
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| parent_task_id | No | ID of the parent task (provide this OR parent_task_name) | |
| parent_task_name | No | Name/content of the parent task (provide this OR parent_task_id) | |
| subtasks | Yes | Array of subtasks to create |
Implementation Reference
- src/handlers/subtask-handlers.ts:357-429 (handler)The core handler function that implements the todoist_subtasks_bulk_create tool. It validates input, finds the parent task, creates multiple subtasks sequentially using the Todoist API, handles failures individually, and returns results with created and failed subtasks.export async function handleBulkCreateSubtasks( todoistClient: TodoistApi, args: BulkCreateSubtasksArgs ): Promise<{ parent: TodoistTask; created: TodoistTask[]; failed: Array<{ task: (typeof args.subtasks)[number]; error: string }>; }> { try { // Validate subtasks array if (!args.subtasks || args.subtasks.length === 0) { throw new ValidationError("At least one subtask is required"); } // Find parent task const parent = await findTask(todoistClient, { task_id: args.parent_task_id, task_name: args.parent_task_name, }); const created: TodoistTask[] = []; const failed: Array<{ task: (typeof args.subtasks)[number]; error: string; }> = []; // Create subtasks sequentially for (const subtaskData of args.subtasks) { try { // Validate subtask data validateTaskContent(subtaskData.content); if (subtaskData.priority !== undefined) { validatePriority(subtaskData.priority); } if (subtaskData.deadline_date) { validateDateString(subtaskData.deadline_date, "deadline"); } // Create subtask const taskData: TaskCreationData = { content: subtaskData.content, parentId: parent.id, projectId: parent.projectId, }; if (subtaskData.description) taskData.description = subtaskData.description; if (subtaskData.due_string) taskData.dueString = subtaskData.due_string; const apiPriority = toApiPriority(subtaskData.priority); if (apiPriority !== undefined) taskData.priority = apiPriority; if (subtaskData.labels) taskData.labels = subtaskData.labels; if (subtaskData.deadline_date) { taskData.deadline = { date: subtaskData.deadline_date }; } const subtask = (await todoistClient.addTask(taskData)) as TodoistTask; created.push(subtask); } catch (error) { failed.push({ task: subtaskData, error: error instanceof Error ? error.message : "Unknown error", }); } } // Clear cache taskCache.clear(); return { parent, created, failed }; } catch (error) { throw ErrorHandler.handleAPIError("bulkCreateSubtasks", error); } }
- src/tools/subtask-tools.ts:52-108 (schema)The Tool object defining the input schema, name, and description for the todoist_subtasks_bulk_create tool, used for MCP tool listing and validation.export const BULK_CREATE_SUBTASKS_TOOL: Tool = { name: "todoist_subtasks_bulk_create", description: "Create multiple subtasks under a parent task in a single operation", inputSchema: { type: "object", properties: { parent_task_id: { type: "string", description: "ID of the parent task (provide this OR parent_task_name)", }, parent_task_name: { type: "string", description: "Name/content of the parent task (provide this OR parent_task_id)", }, subtasks: { type: "array", description: "Array of subtasks to create", items: { type: "object", properties: { content: { type: "string", description: "Content of the subtask", }, description: { type: "string", description: "Description of the subtask (optional)", }, due_string: { type: "string", description: "Human-readable due date string", }, priority: { type: "number", description: "Priority level 1 (highest) to 4 (lowest)", minimum: 1, maximum: 4, }, labels: { type: "array", items: { type: "string" }, description: "Array of label names", }, deadline_date: { type: "string", description: "Deadline date in YYYY-MM-DD format", }, }, required: ["content"], }, }, }, required: ["subtasks"], }, };
- src/index.ts:297-322 (registration)The switch case in the main MCP server request handler that routes calls to 'todoist_subtasks_bulk_create' to the specific handler function after validation.case "todoist_subtasks_bulk_create": if (!isBulkCreateSubtasksArgs(args)) { throw new Error("Invalid arguments for todoist_subtasks_bulk_create"); } const bulkSubtaskResult = await handleBulkCreateSubtasks( apiClient, args ); result = `Created ${bulkSubtaskResult.created.length} subtasks under parent "${bulkSubtaskResult.parent.content}" (ID: ${bulkSubtaskResult.parent.id})\n` + `Failed: ${bulkSubtaskResult.failed.length}`; if (bulkSubtaskResult.created.length > 0) { result += "\nCreated subtasks:\n" + bulkSubtaskResult.created .map((t) => `- ${t.content} (ID: ${t.id})`) .join("\n"); } if (bulkSubtaskResult.failed.length > 0) { result += "\nFailed subtasks:\n" + bulkSubtaskResult.failed .map((f) => `- ${f.task.content}: ${f.error}`) .join("\n"); } break;
- src/tools/index.ts:62-69 (registration)Aggregation of all tools including SUBTASK_TOOLS (which contains todoist_subtasks_bulk_create) into ALL_TOOLS array, used by the MCP server for listing available tools.export const ALL_TOOLS = [ ...TASK_TOOLS, ...PROJECT_TOOLS, ...COMMENT_TOOLS, ...LABEL_TOOLS, ...SUBTASK_TOOLS, ...TEST_TOOLS, ];