Skip to main content
Glama
windalfin

ClickUp MCP Server

by windalfin

create_task

Create a single task in a ClickUp list to organize individual work items. Provide task name, description, and list details to add tasks to your project management system.

Instructions

Create a single task in a ClickUp list. Use this tool for individual task creation only. For multiple tasks, use create_bulk_tasks instead. Before calling this tool, check if you already have the necessary list ID from previous responses in the conversation history, as this avoids redundant lookups. When creating a task, you must provide either a listId or listName.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesName of the task. Put a relevant emoji followed by a blank space before the name.
descriptionNoPlain text description for the task
markdown_descriptionNoMarkdown formatted description for the task. If provided, this takes precedence over description
listIdNoID of the list to create the task in (optional if using listName instead). If you have this ID from a previous response, use it directly rather than looking up by name.
listNameNoName of the list to create the task in - will automatically find the list by name (optional if using listId instead). Only use this if you don't already have the list ID from previous responses.
statusNoOPTIONAL: Override the default ClickUp status. In most cases, you should omit this to use ClickUp defaults
priorityNoPriority of the task (1-4), where 1 is urgent/highest priority and 4 is lowest priority. Only set this when the user explicitly requests a priority level.
dueDateNoDue date of the task (Unix timestamp in milliseconds). Convert dates to this format before submitting.

Implementation Reference

  • The primary handler function for the 'create_task' tool, dispatched by the MCP server. It validates inputs, resolves list ID if using listName, constructs CreateTaskData, calls the ClickUp task service to create the task, and returns a formatted MCP content response.
    export async function handleCreateTask(parameters: any) {
      const { name, description, markdown_description, listId, listName, status, priority, dueDate } = parameters;
      
      // Validate required fields
      if (!name) {
        throw new Error("Task name is required");
      }
      
      let targetListId = listId;
      
      // If no listId but listName is provided, look up the list ID
      if (!targetListId && listName) {
        // Use workspace service to find the list by name in the hierarchy
        const hierarchy = await workspaceService.getWorkspaceHierarchy();
        const listInfo = workspaceService.findIDByNameInHierarchy(hierarchy, listName, 'list');
        
        if (!listInfo) {
          throw new Error(`List "${listName}" not found`);
        }
        targetListId = listInfo.id;
      }
      
      if (!targetListId) {
        throw new Error("Either listId or listName must be provided");
      }
    
      // Prepare task data
      const taskData: CreateTaskData = {
        name,
        description,
        markdown_description,
        status,
        priority: priority as TaskPriority,
        due_date: dueDate ? parseDueDate(dueDate) : undefined
      };
    
      // Add due_date_time flag if due date is set
      if (dueDate && taskData.due_date) {
        taskData.due_date_time = true;
      }
    
      // Create the task
      const task = await taskService.createTask(targetListId, taskData);
    
      // Format response
      return {
        content: [{
          type: "text",
          text: JSON.stringify({
            id: task.id,
            name: task.name,
            url: task.url,
            status: task.status?.status || "New",
            due_date: task.due_date ? formatDueDate(Number(task.due_date)) : undefined,
            list: task.list.name,
            space: task.space.name,
            folder: task.folder?.name
          }, null, 2)
        }]
      };
    }
  • The input JSON Schema for the create_task tool, defining parameters like name (required), description, listId/listName, status, priority, dueDate.
    inputSchema: {
      type: "object",
      properties: {
        name: {
          type: "string",
          description: "Name of the task. Put a relevant emoji followed by a blank space before the name."
        },
        description: {
          type: "string",
          description: "Plain text description for the task"
        },
        markdown_description: {
          type: "string",
          description: "Markdown formatted description for the task. If provided, this takes precedence over description"
        },
        listId: {
          type: "string",
          description: "ID of the list to create the task in (optional if using listName instead). If you have this ID from a previous response, use it directly rather than looking up by name."
        },
        listName: {
          type: "string",
          description: "Name of the list to create the task in - will automatically find the list by name (optional if using listId instead). Only use this if you don't already have the list ID from previous responses."
        },
        status: {
          type: "string",
          description: "OPTIONAL: Override the default ClickUp status. In most cases, you should omit this to use ClickUp defaults"
        },
        priority: {
          type: "number",
          description: "Priority of the task (1-4), where 1 is urgent/highest priority and 4 is lowest priority. Only set this when the user explicitly requests a priority level."
        },
        dueDate: {
          type: "string",
          description: "Due date of the task (Unix timestamp in milliseconds). Convert dates to this format before submitting."
        }
      },
      required: ["name"]
    },
  • src/server.ts:102-103 (registration)
    Dispatch registration in the MCP server's CallToolRequestSchema handler: routes 'create_task' calls to handleCreateTask.
    case "create_task":
      return handleCreateTask(params);
  • src/server.ts:67-93 (registration)
    Tool registration in ListToolsRequestSchema handler: includes createTaskTool in the list of available tools.
    server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: [
          workspaceHierarchyTool,
          createTaskTool,
          getTaskTool,
          getTasksTool,
          updateTaskTool,
          moveTaskTool,
          duplicateTaskTool,
          deleteTaskTool,
          createBulkTasksTool,
          updateBulkTasksTool,
          moveBulkTasksTool,
          deleteBulkTasksTool,
          createListTool,
          createListInFolderTool,
          getListTool,
          updateListTool,
          deleteListTool,
          createFolderTool,
          getFolderTool,
          updateFolderTool,
          deleteFolderTool
        ]
      };
    });
  • The underlying ClickUp service method taskService.createTask called by the handler to perform the actual task creation API call.
    async createTask(listId: string, taskData: CreateTaskData): Promise<ClickUpTask> {
      this.logOperation('createTask', { listId, ...taskData });
      
      try {
        return await this.makeRequest(async () => {
          const response = await this.client.post<ClickUpTask>(
            `/list/${listId}/task`,
            taskData
          );
          return response.data;
        });
      } catch (error) {
        throw this.handleError(error, `Failed to create task in list ${listId}`);
      }
    }
    
    /**
     * Get all tasks in a list with optional filtering
     * @param listId The ID of the list to get tasks from
     * @param filters Optional filters to apply
     * @returns List of tasks matching the filters
     */
    async getTasks(listId: string, filters: TaskFilters = {}): Promise<ClickUpTask[]> {
      this.logOperation('getTasks', { listId, filters });
      
      try {
        return await this.makeRequest(async () => {
          const params = new URLSearchParams();
          
          // Add all filters to the query parameters
          if (filters.include_closed) params.append('include_closed', String(filters.include_closed));
          if (filters.subtasks) params.append('subtasks', String(filters.subtasks));
          if (filters.page) params.append('page', String(filters.page));
          if (filters.order_by) params.append('order_by', filters.order_by);
          if (filters.reverse) params.append('reverse', String(filters.reverse));
          if (filters.statuses && filters.statuses.length > 0) {
            filters.statuses.forEach(status => params.append('statuses[]', status));
          }
          if (filters.assignees && filters.assignees.length > 0) {
            filters.assignees.forEach(assignee => params.append('assignees[]', assignee));
          }
          if (filters.due_date_gt) params.append('due_date_gt', String(filters.due_date_gt));
          if (filters.due_date_lt) params.append('due_date_lt', String(filters.due_date_lt));
          if (filters.date_created_gt) params.append('date_created_gt', String(filters.date_created_gt));
          if (filters.date_created_lt) params.append('date_created_lt', String(filters.date_created_lt));
          if (filters.date_updated_gt) params.append('date_updated_gt', String(filters.date_updated_gt));
          if (filters.date_updated_lt) params.append('date_updated_lt', String(filters.date_updated_lt));
          
          // Handle custom fields if present
          if (filters.custom_fields) {
            Object.entries(filters.custom_fields).forEach(([key, value]) => {
              params.append(`custom_fields[${key}]`, String(value));
            });
  • TypeScript interface CreateTaskData used to type the task data payload sent to ClickUp API.
    export interface CreateTaskData {
      name: string;
      description?: string;
      markdown_description?: string;
      assignees?: (number | string)[];
      tags?: string[];
      status?: string;
      priority?: TaskPriority;
      due_date?: number;
      due_date_time?: boolean;
      time_estimate?: number;
      start_date?: number;
      start_date_time?: boolean;
      notify_all?: boolean;
      parent?: string | null;
      links_to?: string | null;
      check_required_custom_fields?: boolean;
      custom_fields?: Array<{
        id: string;
        value: any;
      }>;
    }
    
    /**
     * Data for creating a list
     */
    export interface CreateListData {
      name: string;
      content?: string;
      due_date?: number;
      due_date_time?: boolean;
      priority?: TaskPriority;
      assignee?: number;
      status?: string;
    }
    
    /**
     * Data for creating a folder
     */
    export interface CreateFolderData {
      name: string;
      override_statuses?: boolean;
    }
    
    /**
     * Update task data (partial)
     */
    export interface UpdateTaskData extends Partial<CreateTaskData> {}
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively communicates that this is a write operation ('Create'), mentions the requirement to provide either listId or listName, and gives practical guidance about checking conversation history. However, it doesn't mention authentication requirements, rate limits, or what happens on failure, which would be valuable for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured with four focused sentences that each serve a distinct purpose: stating the tool's function, differentiating from siblings, providing operational guidance, and specifying parameter requirements. There is no wasted language, and the most critical information appears first.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no annotations and no output schema, the description does well by covering purpose, sibling differentiation, usage guidelines, and parameter relationships. However, it doesn't describe what the tool returns or potential error conditions, which would be helpful given the absence of output schema. The 100% schema coverage helps compensate for some of these gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the baseline is 3. The description adds meaningful context beyond the schema by explaining the relationship between listId and listName parameters ('you must provide either a listId or listName'), and reinforces the guidance about using existing list IDs from conversation history. This provides valuable semantic context that complements the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Create a single task'), target resource ('in a ClickUp list'), and scope ('individual task creation only'). It explicitly distinguishes this tool from its sibling 'create_bulk_tasks' by specifying the single-task use case, providing clear differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool ('for individual task creation only') and when not to ('For multiple tasks, use create_bulk_tasks instead'). It also offers practical advice about checking conversation history for list IDs to avoid redundant lookups, giving clear operational context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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