Skip to main content
Glama
windalfin

ClickUp MCP Server

by windalfin

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:

  1. taskId alone (preferred and safest)

  2. taskName + listName (use with caution)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tasksYesArray of tasks to delete

Implementation Reference

  • 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)
        }]
      };
    }
  • 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"]
      }
    };
  • 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,

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/windalfin/clickup-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server