Skip to main content
Glama

ClickUp MCP Server

ClickUp MCP Server

MCP server for ClickUp API. Manage projects, tasks, time tracking, goals, and team collaboration with a flexible hierarchical project management system.

Features

  • Hierarchical Organization: Workspace → Space → Folder → List → Task

  • Task Management: Create, update, and track tasks with custom fields

  • Time Tracking: Log time entries and estimates

  • Goals: Set and track goals with progress metrics

  • Custom Fields: Flexible metadata for tasks

  • Collaboration: Comments, assignments, and notifications

  • Search: Find tasks across your workspace

  • Statuses: Customizable per-list status workflows

Setup

Prerequisites

  • ClickUp account (free or paid)

  • API token

Environment Variables

  • CLICKUP_API_TOKEN (required): Your ClickUp API token

How to get credentials:

  1. Go to app.clickup.com

  2. Log in to your account

  3. Click your avatar → Settings

  4. Go to "Apps" in the sidebar

  5. Click "Generate" under "API Token"

  6. Copy the token (starts with pk_)

  7. Store as CLICKUP_API_TOKEN

Direct link: https://app.clickup.com/settings/apps

Important: Keep your API token secure. It has full access to your ClickUp account.

Rate Limits

  • Standard: 100 requests per minute per token

  • Rate limit headers included in responses

  • HTTP 429 response when limit exceeded

  • Consider caching for frequently accessed data

Hierarchy Overview

ClickUp uses a hierarchical structure:

Workspace (Team) └─ Space ├─ Folder (optional) │ └─ List │ └─ Task │ └─ Subtask └─ List (folderless) └─ Task

Available Tools

Workspace & Space Management

list_workspaces

List all accessible workspaces (teams).

Example:

workspaces = await list_workspaces() # Returns: # { # "teams": [ # { # "id": "123", # "name": "My Workspace", # "color": "#FF0000", # "avatar": "https://...", # "members": [...] # } # ] # }

list_spaces

List spaces in a workspace.

Parameters:

  • workspace_id (string, required): Workspace ID

  • archived (bool, optional): Include archived (default: false)

Example:

spaces = await list_spaces(workspace_id="123") # Returns: # { # "spaces": [ # { # "id": "456", # "name": "Marketing", # "private": false, # "statuses": [...], # "multiple_assignees": true, # "features": { # "due_dates": {"enabled": true}, # "time_tracking": {"enabled": true} # } # } # ] # }

get_space

Get space details.

Parameters:

  • space_id (string, required): Space ID

Example:

space = await get_space(space_id="456")

Folder & List Management

list_folders

List folders in a space.

Parameters:

  • space_id (string, required): Space ID

  • archived (bool, optional): Include archived (default: false)

Example:

folders = await list_folders(space_id="456") # Returns: # { # "folders": [ # { # "id": "789", # "name": "Q4 Campaigns", # "orderindex": 0, # "task_count": 15, # "lists": [...] # } # ] # }

list_lists

List lists in a folder or space.

Parameters:

  • folder_id (string, optional): Folder ID

  • space_id (string, optional): Space ID (for folderless lists)

  • archived (bool, optional): Include archived (default: false)

Example:

# Lists in a folder lists = await list_lists(folder_id="789") # Folderless lists in a space lists = await list_lists(space_id="456") # Returns: # { # "lists": [ # { # "id": "abc123", # "name": "Sprint Backlog", # "orderindex": 0, # "status": { # "status": "active", # "color": "#87909e" # }, # "task_count": 42 # } # ] # }

Task Management

list_tasks

List tasks with filters.

Parameters:

  • list_id (string, required): List ID

  • archived (bool, optional): Include archived (default: false)

  • page (int, optional): Page number (default: 0)

  • order_by (string, optional): Order by (created, updated, due_date)

  • reverse (bool, optional): Reverse order (default: true)

  • subtasks (bool, optional): Include subtasks (default: true)

  • statuses (list, optional): Filter by status names

  • include_closed (bool, optional): Include closed tasks (default: false)

  • assignees (list, optional): Filter by assignee user IDs

  • tags (list, optional): Filter by tag names

  • due_date_gt (int, optional): Due date greater than (Unix ms)

  • due_date_lt (int, optional): Due date less than (Unix ms)

Example:

# All tasks in a list tasks = await list_tasks(list_id="abc123") # Open tasks assigned to specific user tasks = await list_tasks( list_id="abc123", assignees=["12345"], include_closed=False ) # Tasks due this week import time now = int(time.time() * 1000) week_later = now + (7 * 24 * 60 * 60 * 1000) tasks = await list_tasks( list_id="abc123", due_date_gt=now, due_date_lt=week_later ) # Tasks with specific status tasks = await list_tasks( list_id="abc123", statuses=["in progress", "review"] )

get_task

Get task details with custom fields.

Parameters:

  • task_id (string, required): Task ID

Example:

task = await get_task(task_id="xyz789") # Returns: # { # "id": "xyz789", # "name": "Implement user authentication", # "description": "Add OAuth 2.0 support", # "status": { # "status": "in progress", # "color": "#d3d3d3" # }, # "orderindex": "1.00", # "date_created": "1633024800000", # "date_updated": "1633111200000", # "date_closed": null, # "creator": {"id": 123, "username": "user"}, # "assignees": [{"id": 456, "username": "dev"}], # "tags": [{"name": "backend", "tag_fg": "#000", "tag_bg": "#FFF"}], # "parent": null, # "priority": 2, # "due_date": "1633197600000", # "start_date": "1633024800000", # "time_estimate": 7200000, # "time_spent": 3600000, # "custom_fields": [...], # "list": {"id": "abc123", "name": "Sprint"}, # "folder": {"id": "789", "name": "Engineering"}, # "space": {"id": "456"}, # "url": "https://app.clickup.com/t/xyz789" # }

create_task

Create a new task.

Parameters:

  • list_id (string, required): List ID

  • name (string, required): Task name

  • description (string, optional): Task description

  • assignees (list, optional): Assignee user IDs

  • tags (list, optional): Tag names

  • status (string, optional): Status name

  • priority (int, optional): Priority (1=urgent, 2=high, 3=normal, 4=low)

  • due_date (int, optional): Due date (Unix timestamp ms)

  • due_date_time (bool, optional): Include time (default: false)

  • time_estimate (int, optional): Time estimate in milliseconds

  • start_date (int, optional): Start date (Unix timestamp ms)

  • start_date_time (bool, optional): Include time (default: false)

  • notify_all (bool, optional): Notify assignees (default: true)

  • parent (string, optional): Parent task ID (for subtasks)

  • custom_fields (list, optional): Custom field objects

Priority Levels:

  • 1: Urgent (red flag)

  • 2: High (yellow flag)

  • 3: Normal (blue flag, default)

  • 4: Low (gray flag)

Example:

# Simple task task = await create_task( list_id="abc123", name="Write API documentation" ) # Full task with all options import time tomorrow = int((time.time() + 86400) * 1000) task = await create_task( list_id="abc123", name="Deploy to production", description="Deploy version 2.0.0 with new features", assignees=[12345, 67890], tags=["deployment", "urgent"], status="todo", priority=1, due_date=tomorrow, due_date_time=True, time_estimate=3600000, # 1 hour in ms notify_all=True ) # Subtask subtask = await create_task( list_id="abc123", name="Run database migrations", parent="xyz789", # Parent task ID assignees=[12345], priority=2 ) # Task with custom fields task = await create_task( list_id="abc123", name="Bug fix: Login issue", custom_fields=[ {"id": "field_123", "value": "Bug"}, {"id": "field_456", "value": "High"} ] )

update_task

Update task details.

Parameters:

  • task_id (string, required): Task ID

  • name (string, optional): Updated name

  • description (string, optional): Updated description

  • status (string, optional): Updated status

  • priority (int, optional): Updated priority (1-4)

  • due_date (int, optional): Updated due date (Unix ms)

  • time_estimate (int, optional): Updated time estimate (ms)

  • assignees (dict, optional): Assignees {"add": [ids], "rem": [ids]}

Example:

# Update task status task = await update_task( task_id="xyz789", status="in progress" ) # Add assignees task = await update_task( task_id="xyz789", assignees={"add": [12345, 67890]} ) # Remove assignees task = await update_task( task_id="xyz789", assignees={"rem": [12345]} ) # Update priority and due date import time next_week = int((time.time() + 7 * 86400) * 1000) task = await update_task( task_id="xyz789", priority=1, due_date=next_week )

delete_task

Delete a task.

Parameters:

  • task_id (string, required): Task ID

Example:

result = await delete_task(task_id="xyz789")

Comments

add_task_comment

Add comment to a task.

Parameters:

  • task_id (string, required): Task ID

  • comment_text (string, required): Comment text

  • assignee (int, optional): Assign comment to user ID

  • notify_all (bool, optional): Notify all assignees (default: true)

Example:

# Simple comment comment = await add_task_comment( task_id="xyz789", comment_text="Great progress on this task!" ) # Comment with assignment comment = await add_task_comment( task_id="xyz789", comment_text="Can you review this?", assignee=12345, notify_all=True )

list_task_comments

Get task comments.

Parameters:

  • task_id (string, required): Task ID

Example:

comments = await list_task_comments(task_id="xyz789") # Returns: # { # "comments": [ # { # "id": "123", # "comment_text": "Great work!", # "user": {"id": 456, "username": "user"}, # "date": "1633024800000" # } # ] # }

Time Tracking

create_time_entry

Track time on a task.

Parameters:

  • task_id (string, required): Task ID

  • duration (int, required): Duration in milliseconds

  • start (int, optional): Start time (Unix ms, defaults to now)

  • description (string, optional): Time entry description

Example:

# Log 2 hours of work two_hours_ms = 2 * 60 * 60 * 1000 time_entry = await create_time_entry( task_id="xyz789", duration=two_hours_ms, description="Implemented OAuth integration" ) # Log time with specific start time import time start_time = int((time.time() - 7200) * 1000) # 2 hours ago time_entry = await create_time_entry( task_id="xyz789", duration=two_hours_ms, start=start_time )

list_time_entries

Get time tracking entries.

Parameters:

  • workspace_id (string, required): Workspace ID

  • start_date (int, optional): Filter by start date (Unix ms)

  • end_date (int, optional): Filter by end date (Unix ms)

  • assignee (int, optional): Filter by assignee user ID

Example:

# All time entries entries = await list_time_entries(workspace_id="123") # Time entries for this week import time week_ago = int((time.time() - 7 * 86400) * 1000) now = int(time.time() * 1000) entries = await list_time_entries( workspace_id="123", start_date=week_ago, end_date=now ) # Time entries for specific user entries = await list_time_entries( workspace_id="123", assignee=12345 )

Goals

list_goals

List goals in a workspace.

Parameters:

  • workspace_id (string, required): Workspace ID

Example:

goals = await list_goals(workspace_id="123") # Returns: # { # "goals": [ # { # "id": "goal_123", # "name": "Q4 Revenue Target", # "due_date": "1640995200000", # "description": "Reach $1M ARR", # "percent_completed": 75, # "color": "#32a852" # } # ] # }

get_goal

Get goal details and progress.

Parameters:

  • goal_id (string, required): Goal ID

Example:

goal = await get_goal(goal_id="goal_123") # Returns: # { # "goal": { # "id": "goal_123", # "name": "Q4 Revenue Target", # "description": "Reach $1M ARR", # "due_date": "1640995200000", # "color": "#32a852", # "percent_completed": 75, # "key_results": [ # { # "id": "kr_456", # "name": "Close 10 enterprise deals", # "type": "number", # "current": 7, # "target": 10, # "percent_completed": 70 # } # ] # } # }

Custom Fields

list_custom_fields

Get custom fields for a list.

Parameters:

  • list_id (string, required): List ID

Example:

fields = await list_custom_fields(list_id="abc123") # Returns: # { # "fields": [ # { # "id": "field_123", # "name": "Priority", # "type": "drop_down", # "type_config": { # "options": [ # {"id": "opt_1", "name": "High", "color": "#FF0000"}, # {"id": "opt_2", "name": "Low", "color": "#00FF00"} # ] # } # }, # { # "id": "field_456", # "name": "Story Points", # "type": "number" # } # ] # }

Custom Field Types:

  • text: Text input

  • number: Numeric input

  • drop_down: Dropdown selection

  • date: Date picker

  • checkbox: Boolean checkbox

  • url: URL input

  • email: Email input

  • phone: Phone number

  • currency: Currency value

Search

search_tasks

Search tasks across workspace.

Parameters:

  • workspace_id (string, required): Workspace ID

  • query (string, required): Search query text

  • start_date (int, optional): Filter by start date (Unix ms)

  • end_date (int, optional): Filter by end date (Unix ms)

  • assignees (list, optional): Filter by assignee user IDs

  • statuses (list, optional): Filter by status names

  • tags (list, optional): Filter by tag names

Example:

# Search by keyword tasks = await search_tasks( workspace_id="123", query="authentication" ) # Advanced search with filters tasks = await search_tasks( workspace_id="123", query="bug", assignees=[12345], statuses=["in progress"], tags=["urgent"] )

Common Workflows

Project Setup

# 1. Get workspace workspaces = await list_workspaces() workspace_id = workspaces["teams"][0]["id"] # 2. Create or get space spaces = await list_spaces(workspace_id=workspace_id) space_id = spaces["spaces"][0]["id"] # 3. Get lists lists = await list_lists(space_id=space_id) list_id = lists["lists"][0]["id"] # 4. Create tasks await create_task( list_id=list_id, name="Set up development environment", priority=2 ) await create_task( list_id=list_id, name="Write technical documentation", priority=3 )

Sprint Planning

# Get all tasks tasks = await list_tasks(list_id="abc123") # Sort by priority sorted_tasks = sorted( tasks["tasks"], key=lambda t: t.get("priority", 3) ) # Assign to team members team_members = [12345, 67890, 11111] for i, task in enumerate(sorted_tasks[:10]): assignee = team_members[i % len(team_members)] await update_task( task_id=task["id"], assignees={"add": [assignee]}, status="todo" )

Time Tracking Report

import time # Get this week's time entries week_ago = int((time.time() - 7 * 86400) * 1000) now = int(time.time() * 1000) entries = await list_time_entries( workspace_id="123", start_date=week_ago, end_date=now ) # Calculate total hours total_ms = sum(entry["duration"] for entry in entries["data"]) total_hours = total_ms / (1000 * 60 * 60) print(f"Total hours this week: {total_hours:.2f}")

Goal Tracking

# List all goals goals = await list_goals(workspace_id="123") # Check progress on each goal for goal in goals["goals"]: goal_detail = await get_goal(goal_id=goal["id"]) print(f"Goal: {goal_detail['goal']['name']}") print(f"Progress: {goal_detail['goal']['percent_completed']}%") for kr in goal_detail['goal']['key_results']: print(f" - {kr['name']}: {kr['current']}/{kr['target']}")

Best Practices

  1. Use hierarchy effectively: Organize with Spaces → Folders → Lists

  2. Custom statuses: Set up workflows per list

  3. Custom fields: Add metadata for filtering and reporting

  4. Time tracking: Log time regularly for accurate estimates

  5. Tags: Use tags for cross-list categorization

  6. Goals: Set measurable goals with key results

  7. Priorities: Use priority levels consistently

  8. Assignees: Assign tasks for accountability

  9. Comments: Communicate within tasks

  10. Search: Use search for cross-workspace queries

Rate Limit Handling

import asyncio async def make_request_with_retry(): try: return await list_tasks(list_id="abc123") except httpx.HTTPStatusError as e: if e.response.status_code == 429: # Wait and retry await asyncio.sleep(60) return await list_tasks(list_id="abc123") raise

Error Handling

Common errors:

  • 401 Unauthorized: Invalid API token

  • 403 Forbidden: Insufficient permissions

  • 404 Not Found: Resource not found

  • 429 Too Many Requests: Rate limit exceeded (100 req/min)

  • 500 Internal Server Error: ClickUp service issue

API Documentation

Support

-
security - not tested
A
license - permissive license
-
quality - not tested

remote-capable server

The server can be hosted and run remotely because it primarily relies on remote services or has no dependency on the local environment.

Enables comprehensive project management through ClickUp's API, supporting task creation and updates, time tracking, goal management, and team collaboration within ClickUp's hierarchical workspace structure.

  1. Features
    1. Setup
      1. Prerequisites
      2. Environment Variables
    2. Rate Limits
      1. Hierarchy Overview
        1. Available Tools
          1. Workspace & Space Management
          2. Folder & List Management
          3. Task Management
          4. Comments
          5. Time Tracking
          6. Goals
          7. Custom Fields
          8. Search
        2. Common Workflows
          1. Project Setup
          2. Sprint Planning
          3. Time Tracking Report
          4. Goal Tracking
        3. Best Practices
          1. Rate Limit Handling
            1. Error Handling
              1. API Documentation
                1. Support

                  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/NimbleBrainInc/mcp-clickup'

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