NimbleBrainInc/mcp-todoist
If you are the rightful owner of mcp-todoist and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
MCP server for Todoist API. Manage tasks, projects, labels, and productivity workflows with natural language date parsing and advanced organization features.
Todoist MCP Server
MCP server for Todoist API. Manage tasks, projects, labels, and productivity workflows with natural language date parsing and advanced organization features.
Features
- Task Management: Create, update, complete, and delete tasks
- Projects: Organize tasks into projects with nested hierarchies
- Labels: Tag and categorize tasks with labels
- Sections: Group tasks within projects
- Natural Language: Parse due dates with natural language ("tomorrow at 3pm")
- Priorities: Set task priority from normal to urgent
- Subtasks: Create task hierarchies with parent tasks
- Comments: Collaborate with task and project comments
- Filters: Advanced task filtering and search
Setup
Prerequisites
- Todoist account (free or premium)
- API token
Environment Variables
TODOIST_API_TOKEN
(required): Your Todoist API token
How to get credentials:
- Go to todoist.com
- Log in to your account
- Go to Settings → Integrations → Developer
- Find your API token under "API token"
- Copy the token and store as
TODOIST_API_TOKEN
Direct link: https://todoist.com/app/settings/integrations/developer
Rate Limits
- Free & Premium: 450 requests per 15 minutes
- Rate limit resets every 15 minutes
- HTTP 429 response when limit exceeded
Available Tools
Task Management
list_tasks
List all active tasks with optional filters.
Parameters:
project_id
(string, optional): Filter by project IDlabel
(string, optional): Filter by label namefilter
(string, optional): Filter string (today, p1, overdue, etc.)lang
(string, optional): Language for filter parsing (default: en)
Example:
# All tasks
tasks = await list_tasks()
# Tasks for today
today_tasks = await list_tasks(filter="today")
# High priority tasks
urgent = await list_tasks(filter="p1")
# Tasks in a specific project
project_tasks = await list_tasks(project_id="2203306141")
# Tasks with a specific label
work_tasks = await list_tasks(label="work")
Common Filters:
today
: Tasks due todaytomorrow
: Tasks due tomorrowoverdue
: Overdue tasksp1
: Priority 1 (urgent) tasksp2
: Priority 2 (high) tasksno date
: Tasks with no due dateassigned to: me
: Tasks assigned to you@label_name
: Tasks with specific label
get_task
Get specific task details.
Parameters:
task_id
(string, required): Task ID
Example:
task = await get_task(task_id="7498765432")
# Returns:
# - id, content, description
# - project_id, section_id, parent_id
# - order, priority, labels
# - due (date, datetime, string, timezone)
# - url, comment_count
# - created_at, creator_id
# - assignee_id, assigner_id
# - is_completed
create_task
Create a new task.
Parameters:
content
(string, required): Task contentdescription
(string, optional): Task descriptionproject_id
(string, optional): Project IDsection_id
(string, optional): Section IDparent_id
(string, optional): Parent task ID (for subtasks)order
(int, optional): Task position orderlabels
(list, optional): List of label namespriority
(int, optional): Priority 1-4 (default: 1)due_string
(string, optional): Natural language due datedue_date
(string, optional): Due date (YYYY-MM-DD)due_datetime
(string, optional): Due datetime (RFC 3339)due_lang
(string, optional): Language for parsing (default: en)assignee_id
(string, optional): User ID to assign to
Priority Levels:
- 1: Normal (default)
- 2: High
- 3: Very High
- 4: Urgent
Example:
# Simple task
task = await create_task(
content="Buy groceries"
)
# Task with natural language due date
task = await create_task(
content="Team meeting",
due_string="tomorrow at 3pm",
priority=3,
labels=["work", "meetings"]
)
# Task with specific due date
task = await create_task(
content="Submit report",
due_date="2025-10-15",
project_id="2203306141",
priority=4
)
# Subtask
subtask = await create_task(
content="Review draft",
parent_id="7498765432",
priority=2
)
# Task with description and labels
task = await create_task(
content="Project planning",
description="Outline Q4 goals and milestones",
labels=["planning", "important"],
project_id="2203306141",
section_id="123456"
)
Natural Language Date Examples:
- "today"
- "tomorrow"
- "next Monday"
- "tomorrow at 3pm"
- "every day"
- "every Monday"
- "every other week"
- "every 3 days"
- "1st of every month"
update_task
Update task details.
Parameters:
task_id
(string, required): Task IDcontent
(string, optional): Updated contentdescription
(string, optional): Updated descriptionlabels
(list, optional): Updated labelspriority
(int, optional): Updated priority (1-4)due_string
(string, optional): Natural language due datedue_date
(string, optional): Due date (YYYY-MM-DD)due_datetime
(string, optional): Due datetime (RFC 3339)due_lang
(string, optional): Language for parsingassignee_id
(string, optional): User ID to assign to
Example:
# Update content and priority
task = await update_task(
task_id="7498765432",
content="Buy groceries (urgent!)",
priority=4
)
# Update due date
task = await update_task(
task_id="7498765432",
due_string="next Monday at 2pm"
)
# Update labels
task = await update_task(
task_id="7498765432",
labels=["shopping", "urgent"]
)
complete_task
Mark task as completed.
Parameters:
task_id
(string, required): Task ID
Example:
result = await complete_task(task_id="7498765432")
reopen_task
Reopen a completed task.
Parameters:
task_id
(string, required): Task ID
Example:
result = await reopen_task(task_id="7498765432")
delete_task
Delete a task.
Parameters:
task_id
(string, required): Task ID
Example:
result = await delete_task(task_id="7498765432")
Project Management
list_projects
List all projects.
Example:
projects = await list_projects()
# Returns array of projects with:
# - id, name, color
# - parent_id (for nested projects)
# - order, comment_count
# - is_shared, is_favorite, is_inbox_project
# - view_style (list or board)
# - url
get_project
Get project details.
Parameters:
project_id
(string, required): Project ID
Example:
project = await get_project(project_id="2203306141")
create_project
Create a new project.
Parameters:
name
(string, required): Project nameparent_id
(string, optional): Parent project ID (for nested projects)color
(string, optional): Color nameis_favorite
(bool, optional): Mark as favorite (default: false)view_style
(string, optional): "list" or "board" (default: list)
Colors:
- berry_red, red, orange, yellow, olive_green
- lime_green, green, mint_green, teal, sky_blue
- light_blue, blue, grape, violet, lavender
- magenta, salmon, charcoal, grey, taupe
Example:
# Simple project
project = await create_project(name="Work Projects")
# Project with color and favorite
project = await create_project(
name="Personal Goals",
color="blue",
is_favorite=True,
view_style="list"
)
# Nested project (subproject)
subproject = await create_project(
name="Q4 Goals",
parent_id="2203306141",
color="green"
)
# Board-style project
board = await create_project(
name="Sprint Planning",
view_style="board"
)
update_project
Update project details.
Parameters:
project_id
(string, required): Project IDname
(string, optional): Updated namecolor
(string, optional): Updated coloris_favorite
(bool, optional): Updated favorite statusview_style
(string, optional): Updated view style
Example:
project = await update_project(
project_id="2203306141",
name="Work - 2025",
color="red",
is_favorite=True
)
delete_project
Delete a project.
Parameters:
project_id
(string, required): Project ID
Example:
result = await delete_project(project_id="2203306141")
Section Management
list_sections
List sections in a project.
Parameters:
project_id
(string, optional): Project ID (returns all sections if not provided)
Example:
# All sections
sections = await list_sections()
# Sections in specific project
sections = await list_sections(project_id="2203306141")
# Returns:
# - id, project_id, order
# - name
create_section
Create a new section.
Parameters:
name
(string, required): Section nameproject_id
(string, required): Project IDorder
(int, optional): Section position order
Example:
section = await create_section(
name="In Progress",
project_id="2203306141",
order=1
)
# Common section names:
# - "To Do", "In Progress", "Done"
# - "Backlog", "This Week", "Completed"
# - "High Priority", "Medium Priority", "Low Priority"
Label Management
list_labels
List all labels.
Example:
labels = await list_labels()
# Returns array of labels with:
# - id, name, color
# - order, is_favorite
create_label
Create a new label.
Parameters:
name
(string, required): Label namecolor
(string, optional): Color nameorder
(int, optional): Label position orderis_favorite
(bool, optional): Mark as favorite (default: false)
Example:
# Simple label
label = await create_label(name="urgent")
# Label with color
label = await create_label(
name="work",
color="blue",
is_favorite=True
)
# Common labels:
# - urgent, important, low-priority
# - work, personal, home
# - waiting, next, someday
# - errand, call, email, meeting
Comments
list_comments
Get comments for a task or project.
Parameters:
task_id
(string, optional): Task IDproject_id
(string, optional): Project ID
Example:
# Task comments
comments = await list_comments(task_id="7498765432")
# Project comments
comments = await list_comments(project_id="2203306141")
# Returns:
# - id, task_id, project_id
# - content
# - posted_at
# - attachment (file info if present)
create_comment
Add a comment to a task or project.
Parameters:
content
(string, required): Comment contenttask_id
(string, optional): Task IDproject_id
(string, optional): Project IDattachment
(dict, optional): File attachment object
Example:
# Task comment
comment = await create_comment(
content="Started working on this",
task_id="7498765432"
)
# Project comment
comment = await create_comment(
content="Project kickoff meeting notes",
project_id="2203306141"
)
# Comment with attachment
comment = await create_comment(
content="See attached file",
task_id="7498765432",
attachment={
"file_name": "report.pdf",
"file_type": "application/pdf",
"file_url": "https://example.com/report.pdf"
}
)
Common Workflows
Daily Task Management
# Get today's tasks
today = await list_tasks(filter="today")
# Create a task for today
task = await create_task(
content="Review PRs",
due_string="today at 2pm",
labels=["work"],
priority=3
)
# Complete a task
await complete_task(task_id=task["id"])
Project Setup
# Create a project
project = await create_project(
name="Website Redesign",
color="blue",
view_style="board"
)
# Create sections
await create_section(name="To Do", project_id=project["id"], order=1)
await create_section(name="In Progress", project_id=project["id"], order=2)
await create_section(name="Done", project_id=project["id"], order=3)
# Create labels
await create_label(name="frontend", color="red")
await create_label(name="backend", color="green")
await create_label(name="design", color="blue")
# Add tasks
await create_task(
content="Design homepage mockup",
project_id=project["id"],
labels=["design"],
priority=4,
due_string="next Monday"
)
Weekly Planning
# Get overdue tasks
overdue = await list_tasks(filter="overdue")
# Get this week's tasks
week_tasks = await list_tasks(filter="7 days")
# Create recurring weekly task
weekly = await create_task(
content="Weekly team meeting",
due_string="every Monday at 10am",
labels=["meetings"],
priority=3
)
Subtask Management
# Create parent task
parent = await create_task(
content="Launch marketing campaign",
project_id="2203306141",
priority=4
)
# Create subtasks
await create_task(
content="Design email template",
parent_id=parent["id"],
priority=3
)
await create_task(
content="Write copy",
parent_id=parent["id"],
priority=3
)
await create_task(
content="Set up automation",
parent_id=parent["id"],
priority=2
)
Due Date Formats
Natural Language (due_string)
- "today"
- "tomorrow"
- "next Monday"
- "in 3 days"
- "next week"
- "tomorrow at 3pm"
- "Monday at 9am"
- "every day"
- "every Monday"
- "every other week"
- "every 3 months"
- "1st of every month"
Specific Date (due_date)
- Format: YYYY-MM-DD
- Example: "2025-10-15"
- Time not included
Specific DateTime (due_datetime)
- Format: RFC 3339 (ISO 8601)
- Example: "2025-10-15T15:00:00Z"
- Includes timezone
Priority Levels
Todoist uses priority levels 1-4:
- Priority 1: Normal (default, grey flag)
- Priority 2: High (blue flag)
- Priority 3: Very High (orange flag)
- Priority 4: Urgent (red flag)
Best Practices
- Use natural language dates: More intuitive than specific dates
- Organize with projects: Group related tasks
- Use sections: Further organize tasks within projects
- Label consistently: Create a labeling system and stick to it
- Set priorities: Focus on what matters most
- Create subtasks: Break down complex tasks
- Add descriptions: Provide context and details
- Use comments: Collaborate and track progress
- Review regularly: Use filters to see overdue and upcoming tasks
- Recurring tasks: Automate repetitive tasks
Productivity Tips
GTD (Getting Things Done)
# Inbox (capture everything)
await create_task(content="Random idea", project_id="inbox_id")
# Process inbox (organize)
await update_task(
task_id="...",
project_id="work_id",
labels=["next-action"],
due_string="tomorrow"
)
# Next actions filter
next_actions = await list_tasks(label="next-action")
Time Blocking
# Morning tasks
await create_task(
content="Deep work: Write report",
due_string="today at 9am",
priority=4
)
# Afternoon tasks
await create_task(
content="Meetings and collaboration",
due_string="today at 2pm",
priority=3
)
Weekly Review
# What was completed this week?
completed = await list_tasks(filter="completed & 7 days")
# What's overdue?
overdue = await list_tasks(filter="overdue")
# What's coming up?
upcoming = await list_tasks(filter="7 days")
Error Handling
Common errors:
- 401 Unauthorized: Invalid API token
- 403 Forbidden: Insufficient permissions
- 404 Not Found: Task, project, or resource not found
- 429 Too Many Requests: Rate limit exceeded (450 per 15 min)
- 500 Internal Server Error: Todoist service issue