Provides comprehensive project management capabilities including hierarchical organization (workspaces, spaces, folders, lists, tasks), task management with custom fields, time tracking, goal setting and progress monitoring, team collaboration through comments and assignments, and search functionality across workspaces.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ClickUp MCP Servershow me open tasks assigned to me in the Sprint Backlog list"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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)
└─ TaskAvailable 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")
raiseError 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
This server cannot be installed
Resources
Looking for Admin?
Admins can modify the Dockerfile, update the server description, and track usage metrics. If you are the server author, to access the admin panel.