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
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。