ClickUp MCP Server
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.
README
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:
- Go to app.clickup.com
 - Log in to your account
 - Click your avatar → Settings
 - Go to "Apps" in the sidebar
 - Click "Generate" under "API Token"
 - Copy the token (starts with 
pk_) - 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 IDarchived(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 IDarchived(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 IDspace_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 IDarchived(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 namesinclude_closed(bool, optional): Include closed tasks (default: false)assignees(list, optional): Filter by assignee user IDstags(list, optional): Filter by tag namesdue_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 IDname(string, required): Task namedescription(string, optional): Task descriptionassignees(list, optional): Assignee user IDstags(list, optional): Tag namesstatus(string, optional): Status namepriority(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 millisecondsstart_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 IDname(string, optional): Updated namedescription(string, optional): Updated descriptionstatus(string, optional): Updated statuspriority(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 IDcomment_text(string, required): Comment textassignee(int, optional): Assign comment to user IDnotify_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 IDduration(int, required): Duration in millisecondsstart(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 IDstart_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 inputnumber: Numeric inputdrop_down: Dropdown selectiondate: Date pickercheckbox: Boolean checkboxurl: URL inputemail: Email inputphone: Phone numbercurrency: Currency value
Search
search_tasks
Search tasks across workspace.
Parameters:
workspace_id(string, required): Workspace IDquery(string, required): Search query textstart_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 IDsstatuses(list, optional): Filter by status namestags(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
- Use hierarchy effectively: Organize with Spaces → Folders → Lists
 - Custom statuses: Set up workflows per list
 - Custom fields: Add metadata for filtering and reporting
 - Time tracking: Log time regularly for accurate estimates
 - Tags: Use tags for cross-list categorization
 - Goals: Set measurable goals with key results
 - Priorities: Use priority levels consistently
 - Assignees: Assign tasks for accountability
 - Comments: Communicate within tasks
 - 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
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.