delete_bulk_tasks
Permanently delete multiple ClickUp tasks at once using task IDs or task names with list names. This action cannot be undone.
Instructions
⚠️ PERMANENTLY DELETE multiple tasks. This action cannot be undone. For each task, you MUST provide either:
taskId alone (preferred and safest)
taskName + listName (use with caution)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tasks | Yes | Array of tasks to delete |
Implementation Reference
- src/tools/task.ts:1567-1671 (handler)MCP tool handler for delete_bulk_tasks: resolves task names to IDs using list lookups if needed, collects task IDs, calls taskService.deleteBulkTasks, processes and returns results with success/failure details.if (!tasks || !Array.isArray(tasks) || tasks.length === 0) { throw new Error('You must provide a non-empty array of tasks to delete'); } const results = { total: tasks.length, successful: 0, failed: 0, failures: [] as any[], deleted: [] as any[] }; // Collect all task IDs for deletion const taskIdsToDelete: string[] = []; const taskMap = new Map<string, any>(); // First, resolve all task IDs for (const task of tasks) { try { let taskId = task.taskId; if (!taskId && task.taskName) { if (!task.listName) { throw new Error(`List name is required when using task name for task "${task.taskName}"`); } const listInfo = await findListIDByName(workspaceService, task.listName); if (!listInfo) { throw new Error(`List "${task.listName}" not found`); } const taskList = await taskService.getTasks(listInfo.id); const foundTask = taskList.find(t => t.name.toLowerCase() === task.taskName.toLowerCase()); if (!foundTask) { throw new Error(`Task "${task.taskName}" not found in list "${task.listName}"`); } taskId = foundTask.id; // Store original task info for the response taskMap.set(taskId, { id: taskId, name: foundTask.name, originalTask: task }); } else if (taskId) { // Store task ID with basic info for the response taskMap.set(taskId, { id: taskId, name: task.taskName || "Unknown", originalTask: task }); } else { throw new Error("Either taskId or taskName must be provided for each task"); } taskIdsToDelete.push(taskId); } catch (error: any) { results.failed++; results.failures.push({ task: task.taskId || task.taskName, error: error.message }); } } // Perform the bulk delete operation if we have tasks to delete if (taskIdsToDelete.length > 0) { try { const bulkResult = await taskService.deleteBulkTasks(taskIdsToDelete); // Process successful deletions for (const deletedId of bulkResult.successfulItems) { results.successful++; const taskInfo = taskMap.get(deletedId); results.deleted.push({ id: deletedId, name: taskInfo?.name || "Unknown", deleted: true }); } // Process failed deletions for (const failure of bulkResult.failedItems) { results.failed++; const taskInfo = taskMap.get(failure.item); results.failures.push({ task: taskInfo?.name || failure.item, error: failure.error.message }); } } catch (error: any) { // If the bulk delete fails entirely, mark all remaining tasks as failed for (const taskId of taskIdsToDelete) { const taskInfo = taskMap.get(taskId); if (taskInfo && !results.deleted.some(t => t.id === taskId) && !results.failures.some(f => f.task === taskId || f.task === taskInfo.name)) { results.failed++; results.failures.push({ task: taskInfo.name || taskId, error: error.message }); } } } } return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] }; }
- src/tools/task.ts:714-744 (schema)Input schema definition for the delete_bulk_tasks tool, specifying an array of tasks each with optional taskId (preferred) or taskName + required listName.export const deleteBulkTasksTool = { name: "delete_bulk_tasks", description: "\u26a0\ufe0f PERMANENTLY DELETE multiple tasks. This action cannot be undone. For each task, you MUST provide either:\n1. taskId alone (preferred and safest)\n2. taskName + listName (use with caution)", inputSchema: { type: "object", properties: { tasks: { type: "array", description: "Array of tasks to delete", items: { type: "object", properties: { taskId: { type: "string", description: "Task ID (preferred). Use instead of taskName if available." }, taskName: { type: "string", description: "Task name. Requires listName when used." }, listName: { type: "string", description: "REQUIRED with taskName: List containing the task." } } } } }, required: ["tasks"] } };
- src/services/clickup/task.ts:592-622 (helper)Core service method deleteBulkTasks: uses BulkProcessor to batch delete tasks by calling deleteTask on each taskId, handles errors and returns BulkOperationResult.async deleteBulkTasks( taskIds: string[], options?: BulkOperationOptions ): Promise<BulkOperationResult<string>> { this.logOperation('deleteBulkTasks', { taskCount: taskIds.length, batchSize: options?.batchSize, concurrency: options?.concurrency }); try { return await this.bulkProcessor.processBulk( taskIds, async (taskId) => { await this.deleteTask(taskId); return taskId; }, options ); } catch (error: any) { if (error instanceof ClickUpServiceError) { throw error; } throw new ClickUpServiceError( `Failed to delete tasks in bulk: ${error.message}`, ErrorCode.UNKNOWN, error ); } }
- src/server.ts:122-123 (registration)Server switch case routes 'delete_bulk_tasks' tool calls to handleDeleteBulkTasks handler.case "delete_bulk_tasks": return handleDeleteBulkTasks(params as { tasks: any[] });
- src/server.ts:81-81 (registration)deleteBulkTasksTool included in the list of tools returned by ListToolsRequestHandler.deleteBulkTasksTool,