Todoist AI MCP Server
OfficialAn MCP server and importable tool library that lets AI agents read and modify a Todoist account.
Manage tasks: add, update, complete/uncomplete, reschedule, find/search by text/date/project/section/label/filter, view completed tasks, and delete tasks.
Manage projects and sections: create, update, find, archive/unarchive, join, move, reorder, get health/insights/overview, and export/import templates.
Manage comments and reminders: add/find/update comments, view attachments, and add/find/update relative, absolute, or location reminders.
Manage labels and filters: create/update/find personal and shared labels, and list/add/update saved filters.
Read analytics and account data: activity logs, productivity stats, project activity stats, workspace insights, user info, user status, and workspaces.
Support collaboration: find project collaborators and assign, unassign, or reassign tasks.
Provide OpenAI MCP compatibility with search and fetch tools, plus generic object fetch/delete/reorder operations.
Enables AI agents to access and modify Todoist accounts, allowing for actions such as finding tasks by date and adding new tasks to manage personal or team projects.
Click on "Deploy 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., "@Todoist AI MCP Server Add a task to buy milk tomorrow morning"
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.
Todoist MCP Server
Library for connecting AI agents to Todoist. Includes tools that can be integrated into LLMs, enabling them to access and modify a Todoist account on the user's behalf.
These tools can be used both through an MCP server, or imported directly in other projects to integrate them to your own AI conversational interfaces.
Using tools
1. Add this repository as a dependency
npm install @todoist/mcpThis package was previously published as @doist/todoist-mcp.
2. Import the tools and plug them to an AI
Here's an example using Vercel's AI SDK.
import { findTasksByDate, addTasks } from '@todoist/mcp'
import { TodoistApi } from '@todoist/sdk'
import { streamText } from 'ai'
// Create Todoist API client
const client = new TodoistApi(process.env.TODOIST_API_KEY)
// Helper to wrap tools with the client
function wrapTool(tool, todoistClient) {
return {
...tool,
execute(args) {
return tool.execute(args, todoistClient)
},
}
}
const result = streamText({
model: yourModel,
system: 'You are a helpful Todoist assistant',
tools: {
findTasksByDate: wrapTool(findTasksByDate, client),
addTasks: wrapTool(addTasks, client),
},
})Related MCP server: Todoist MCP Server
Using as an MCP server
Quick Start
You can run the MCP server directly with npx:
npx -p @todoist/mcp todoist-mcpSetup Guide
The Todoist MCP server is available as a streamable HTTP service for easy integration with various AI clients:
Primary URL (Streamable HTTP): https://ai.todoist.net/mcp
Claude Desktop
Open Settings → Connectors → Add custom connector
Enter
https://ai.todoist.net/mcpand complete OAuth authentication
Cursor
Create a configuration file:
Global:
~/.cursor/mcp.jsonProject-specific:
.cursor/mcp.json
{
"mcpServers": {
"todoist": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://ai.todoist.net/mcp"]
}
}
}Then enable the server in Cursor settings if prompted.
Claude Code (CLI)
The fastest setup is the official Todoist plugin, which wires up the MCP server for you:
/plugin marketplace add todoist/todoist-mcp
/plugin install todoist@doistOAuth runs in your browser the first time you use a Todoist tool. See Anthropic's plugin docs for more.
If you'd rather configure the MCP server manually, run:
claude mcp add --transport http todoist https://ai.todoist.net/mcpThen launch claude, execute /mcp, and select the todoist MCP server to authenticate.
Gemini CLI
Install the official Todoist extension with Gemini CLI 0.67.0 or later:
gemini extensions install https://github.com/todoist/todoist-mcpStart or restart Gemini CLI, then run /mcp auth todoist and sign in with your Todoist account. Todoist hosts the server; no API key or local server is needed.
The assistant can read and change your Todoist tasks and projects. Revoke access at any time in Todoist under Settings → Integrations.
Visual Studio Code
Open Command Palette → MCP: Add Server
Select HTTP transport and use:
{
"servers": {
"todoist": {
"type": "http",
"url": "https://ai.todoist.net/mcp"
}
}
}Other MCP Clients
npx -y mcp-remote https://ai.todoist.net/mcpFor more details on setting up and using the MCP server, including creating custom servers, see docs/mcp-server.md.
Features
A key feature of this project is that tools can be reused, and are not written specifically for use in an MCP server. They can be hooked up as tools to other conversational AI interfaces (e.g. Vercel's AI SDK).
This project is in its early stages. Expect more and/or better tools soon.
Nevertheless, our goal is to provide a small set of tools that enable complete workflows, rather than just atomic actions, striking a balance between flexibility and efficiency for LLMs.
For our design philosophy, guidelines, and development patterns, see docs/tool-design.md.
Available Tools
For a complete list of available tools, see the src/tools directory.
OpenAI MCP Compatibility
This server includes search and fetch tools that follow the OpenAI MCP specification, enabling seamless integration with OpenAI's MCP protocol. These tools return JSON-encoded results optimized for OpenAI's requirements while maintaining compatibility with the broader MCP ecosystem.
Dependencies
MCP server using the official @modelcontextprotocol/server
Todoist Typescript API client @todoist/sdk
MCP Server Setup
See docs/mcp-server.md for full instructions on setting up the MCP server.
Local Development Setup
See docs/dev-setup.md for full setup instructions and CONTRIBUTING.md for contributor workflows and quality checks.
MCP Apps
This project includes support for MCP Apps – interactive UI widgets rendered inline in AI chat interfaces. Widgets provide rich visual representations of tool outputs (e.g., task lists) instead of plain text.
See docs/mcp-apps.md for the widget architecture, build pipeline, and development workflow.
Quick Start
After cloning and setting up the repository:
npm start- Build and run the MCP inspector for testingnpm run dev- Development mode with auto-rebuild and restartnpm run tool:list- List available tools for direct executionnpm run tool -- <tool-name> '<json-args>'- Run a tool directly without MCP
When using npm run tool, include -- before tool arguments so npm forwards them to scripts/run-tool.ts.
Example check before write operations:
npm run tool -- user-info '{}'
This confirms which Todoist account the current TODOIST_API_KEY is connected to.
run-tool uses TODOIST_API_KEY from your .env file (created from .env.example by npm run setup). Use a test account or a temporary project when running write operations to avoid modifying real data.
Contributing
See CONTRIBUTING.md for:
Development workflow
Running tools directly with
scripts/run-tool.tsTesting and quality checks
Commit conventions
Releasing
This project uses release-please to automate version management and package publishing.
How it works
Make your changes using Conventional Commits:
feat:for new features (minor version bump)fix:for bug fixes (patch version bump)feat!:orfix!:for breaking changes (major version bump)docs:for documentation changeschore:for maintenance tasksci:for CI changes
When commits are pushed to
main:Release-please automatically creates/updates a release PR
The PR includes version bump and changelog updates
Review the PR and merge when ready
After merging the release PR:
A new GitHub release is automatically created
A new tag is created
The
publishworkflow is triggeredThe package is published to npm
Available Tools
49 toolsadd-commentsA
Add multiple comments to tasks or projects, optionally notifying collaborators. Each comment must specify either taskId or projectId.
Inputs: comments (required). Returns: comments, failures, totalCount, failureCount, +3 more
add-filtersA
Add one or more new personal filters. Filters are saved custom views using query syntax to organize tasks.
Inputs: filters (required). Returns: filters, failures, totalCount, failureCount, +2 more
add-labelsC
Add one or more new personal labels.
Inputs: labels (required). Returns: labels, failures, totalCount, failureCount, +2 more
add-projectsC
Add one or more new projects.
Inputs: projects (required). Returns: failures, projects, totalCount, failureCount, +2 more
add-remindersA
Add reminders to tasks. Supports three types: "relative" (minutes before due), "absolute" (specific date/time), or "location" (geofence-triggered). Each reminder must specify a taskId. Reminders notify their creator unless notifyUser says otherwise.
Inputs: reminders (required). Returns: failures, reminders, totalCount, failureCount, +3 more
add-sectionsC
Add one or more new sections to projects.
Inputs: sections (required). Returns: failures, sections, totalCount, failureCount, +2 more
add-tasksB
Add one or more tasks to a project, section, or parent. Supports assignment to project collaborators.
Inputs: tasks (required). Returns: tasks, failures, totalCount, failureCount, +2 more
analyze-project-healthAIdempotent
Trigger a new health analysis for a project. Use this when the health data is stale or you want a fresh assessment. The analysis may take time to complete — use get-project-health afterward to see updated results.
Inputs: projectId (required). Returns: health, message, projectId
complete-tasksADestructive
Complete one or more tasks by their IDs.
Inputs: ids (required). Returns: failures, completed, failureCount, successCount, +1 more
delete-objectADestructiveIdempotent
Delete a project, section, task, comment, label, filter, reminder, or location_reminder by its ID. Projects can be deleted whether active or archived (find archived ones via find-projects with archivedStatus); note a workspace project must be archived before it can be deleted, while personal projects can be deleted regardless.
Inputs: id (required), type (required). Returns: success, deletedEntity
export-project-templateAIdempotent
Export an existing project as a Todoist template, either as CSV content or as a shareable URL. Use it to duplicate a project, share its structure, or hand the CSV to import-project-template. To read a project rather than export it, use find-tasks instead — it returns structured tasks rather than raw CSV. The project itself is not modified, but the "url" format uploads a copy and returns a link that anyone holding it can open.
Inputs: projectId (required), format, useRelativeDates. Returns: format, content, fileUrl, fileName, +1 more
fetchARead-onlyIdempotent
Fetch the full contents of a task or project by its ID. The ID should be in the format "task:{id}" or "project:{id}". (Comments may exist; use find-comments to retrieve them.)
Inputs: id (required). Returns: id, url, text, title, +1 more
fetch-objectARead-onlyIdempotent
Fetch a single task, project, comment, or section by its ID. Use this when you have a specific object ID and want to retrieve its full details. Set includeChildren to also get its direct subtasks or sub-projects.
Inputs: id (required), type (required), includeChildren. Returns: id, type, object, children, +3 more
find-activityARead-onlyIdempotent
Retrieve activity logs to monitor and audit changes in Todoist. Shows events from all users by default (use initiatorId to filter by specific user). To answer what someone completed in a period, including recurring task occurrences, use objectType "task", eventType "completed", and dateFrom/dateTo. For a first-person question ("what did I get done"), also set initiatorId to the current user from user-info, or the answer includes collaborators' completions. Track task completions, updates, deletions, project changes, and more with flexible filtering. Activity history availability and retention depend on the user plan.
Inputs: limit, cursor, dateTo, taskId, +6 more. Returns: events, hasMore, nextCursor, totalCount, +1 more
find-commentsARead-onlyIdempotent
Find comments by task, project, or get a specific comment by ID. Exactly one of taskId, projectId, or commentId must be provided.
Inputs: limit, cursor, taskId, commentId, +1 more. Returns: hasMore, comments, searchId, nextCursor, +2 more
find-completed-tasksARead-onlyIdempotent
Get completed tasks in a date range. Neither getBy mode returns completions of a recurring task that is still active. For "what did I complete/get done" questions, or whenever recurring work should count, use find-activity instead — it reports completion events, including every occurrence of a recurring task. since/until are optional and default to a 7-day window when omitted. Includes all collaborators by default. Person-specific queries (summaries, plans, reports) require responsibleUser.
Inputs: getBy, limit, since, until, +8 more. Returns: tasks, hasMore, nextCursor, totalCount, +1 more
find-filtersARead-onlyIdempotent
List all personal filters or search for filters by name. Filters are saved custom views that use query syntax to organize tasks (e.g. "today & p1", "#Work & overdue").
Inputs: search. Returns: filters, totalCount
find-labelsARead-onlyIdempotent
List personal labels and shared labels. Personal labels have full metadata (id, name, color, order, isFavorite) and support pagination and name search (partial, case insensitive). Shared labels are labels used on tasks shared with you — they are returned as names only (no IDs or metadata). When searching, all matching personal labels are fetched across all pages and returned as a single result set (limit and cursor are ignored). When not searching, personal labels are returned with pagination.
Inputs: limit, cursor, searchText. Returns: labels, hasMore, nextCursor, totalCount, +2 more
find-project-collaboratorsARead-onlyIdempotent
Find Todoist users (collaborators, teammates) by name or email to look up their user ID. Use this whenever the user asks to find, look up, or identify a person — e.g. "find Carrie's user ID", "who is Ernesto", "look up a user". When projectId is omitted, searches across the collaborators of every shared project the authenticated user has access to, plus the authenticated user themselves — an empty result means the person is not a collaborator on any project you share with them, not necessarily that they do not exist in Todoist. When projectId is provided, searches only that project. Partial, case-insensitive match on name and email.
Inputs: projectId, searchTerm. Returns: totalCount, projectInfo, collaborators, appliedFilters, +1 more
find-projectsARead-onlyIdempotent
List or search by name the projects the user has joined. By default only active projects are returned; use archivedStatus ('archived' or 'all') to include archived projects. When searching or when archivedStatus is 'all', all matching projects are returned (pagination is ignored). Otherwise projects are returned with pagination. Workspace projects the user hasn't joined are left out unless includeUnjoined is set, or a search matches no joined project.
Inputs: limit, cursor, searchText, archivedStatus, +1 more. Returns: hasMore, projects, nextCursor, totalCount, +3 more
find-remindersARead-onlyIdempotent
Find reminders by task ID (returns all reminder types), or get a specific reminder by its ID. Use reminderId for time-based reminders and locationReminderId for location reminders.
Inputs: taskId, reminderId, locationReminderId. Returns: searchId, reminders, searchType, totalCount
find-sectionsARead-onlyIdempotent
Search for sections by name or other criteria in a project. When searching, uses server-side search to avoid fetching all sections.
Inputs: projectId (required), searchText. Returns: sections, totalCount, appliedFilters
find-tasksARead-onlyIdempotent
Find tasks by text search, project/section/parent container, responsible user, labels, a raw Todoist filter string, or a saved filter by ID or name (filterIdOrName). At least one filter must be provided.
Inputs: limit, cursor, filter, labels, +8 more. Returns: tasks, hasMore, nextCursor, totalCount, +1 more
find-tasks-by-dateARead-onlyIdempotent
Get tasks by date range. startDate='today' includes overdue items. Default responsibleUserFiltering='unassignedOrMe' excludes others' tasks.
Inputs: limit, cursor, labels, daysCount, +5 more. Returns: tasks, hasMore, nextCursor, totalCount, +1 more
get-overviewARead-onlyIdempotent
Get a Markdown overview. Called without a projectId, returns the account's project and section structure only — no tasks — for navigation. Pass a projectId (or "inbox" for the Inbox) to get that project's tasks grouped by section.
Inputs: projectId. Returns: type, inbox, stats, tasks, +9 more
get-productivity-statsARead-onlyIdempotent
Get comprehensive productivity statistics including daily/weekly completion breakdowns, goal streaks (current, last, max), karma score and trends, and historical karma data. Useful for productivity analysis and tracking goal progress. Reports counts, streaks and karma only, never the tasks themselves — for "what did I complete", use find-activity.
Inputs: no named parameters. Returns: goals, karma, daysItems, weekItems, +6 more
get-project-activity-statsARead-onlyIdempotent
Get daily and optional weekly task completion counts for a project over a configurable time window (1-12 weeks). Useful for identifying completion trends and patterns.
Inputs: projectId (required), weeks, includeWeeklyCounts. Returns: dayItems, projectId, weekItems
get-project-healthBRead-onlyIdempotent
Get a comprehensive health assessment for a project including completion progress, health status (EXCELLENT, ON_TRACK, AT_RISK, CRITICAL), and optional detailed context with project metrics and task-level data. Use includeContext=true for that full detail.
Inputs: projectId (required), includeContext. Returns: health, context, progress, projectId, +1 more
get-user-statusARead-onlyIdempotent
Get the user's status, the message and emoji shown next to their name in Todoist and Comms, with when it ends and whether it pauses Comms notifications or Karma and streaks. Returns no status when none is set or it has expired.
Inputs: no named parameters. Returns: status, hasStatus
get-workspace-insightsARead-onlyIdempotent
Get aggregated health and progress insights across all projects in a workspace. Accepts workspace name or ID, with optional project ID filtering. Useful for a cross-project health overview.
Inputs: workspaceIdOrName (required), projectIds. Returns: workspaceId, workspaceName, projectInsights
import-project-templateA
Import a template into an existing project, adding its tasks, sections and comments to whatever is already there. Source it by template ID/URL or by passing CSV content from export-project-template. To start a new project from a template, create the project with add-projects first, then import into it. This writes immediately and cannot be undone, so only run it against a project the user named.
Inputs: projectId (required), locale, templateId, csvFileContent. Returns: tasks, comments, sections, totalCount
list-workspacesARead-onlyIdempotent
Get all workspaces for the authenticated user. Returns workspace details including ID, name, plan type (STARTER/BUSINESS), user role (ADMIN/MEMBER/GUEST), link sharing settings, guest permissions, creation date, and creator ID.
Inputs: no named parameters. Returns: type, count, workspaces
manage-assignmentsADestructive
Assign, unassign or reassign up to 50 tasks at once. Assigning notifies the new assignee. Each task is updated independently, so one failure does not undo the others; failures are reported per task. Use dryRun to check the changes first.
Inputs: taskIds (required), operation (required), dryRun, responsibleUser, +1 more. Returns: results, summary
project-managementAIdempotent
Archive or unarchive a project by its ID, or join a workspace project the user hasn't joined (see find-projects includeUnjoined) when they ask to.
Inputs: action (required), projectId (required). Returns: project, success
project-moveCDestructiveIdempotent
Move a project between personal and workspace contexts.
Inputs: action (required), projectId (required), folderId, visibility, +1 more. Returns: project, success
reorder-objectsAIdempotent
Reorder projects or sections, and optionally move personal projects to a new parent. Personal projects: order places a project among its siblings; parentId moves it ("root" for top level). Workspace projects: order places a project within its folder, in the shared default ordering every member sees; needs permission to reorder the workspace. Sections: order places a section within its project.
Inputs: type (required), items (required). Returns: type, success, failures, movedCount, +2 more
reschedule-tasksADestructive
Reschedule tasks to new dates while preserving recurring schedules. Unlike update-tasks (which replaces the entire due string and can wipe recurrence), this tool changes only the date (and duration, if given), keeping recurrence patterns intact. Use this when moving recurring tasks to a different date or time without altering their repeat pattern. Without a due date, the deadline moves.
Inputs: tasks (required). Returns: tasks, failures, totalCount, rescheduledTaskIds
searchARead-onlyIdempotent
Search across tasks and projects in Todoist. Returns a list of relevant results with IDs, titles, and URLs.
Inputs: query (required). Returns: results, totalCount
set-user-statusADestructiveIdempotent
Set or clear the user's status, shown next to their name in Todoist and Comms. Replaces the whole status: an omitted emoji, end or effect is removed, not kept. Use clear to remove the status.
Inputs: clear, emoji, message, activeUntil, +2 more. Returns: status, hasStatus
uncomplete-tasksA
Uncomplete (reopen) one or more completed tasks by their IDs.
Inputs: ids (required). Returns: failures, uncompleted, failureCount, successCount, +1 more
update-commentsCDestructive
Update multiple existing comments with new content.
Inputs: comments (required). Returns: comments, failures, totalCount, appliedOperations, +1 more
update-filtersBDestructive
Update one or more existing personal filters with new values.
Inputs: filters (required). Returns: filters, failures, totalCount, updatedFilterIds, +1 more
update-labelsADestructive
Update one or more existing labels. Personal labels (identified by ID) can have their name, color, order, and favorite flag updated. Shared labels (identified by name) can only be renamed.
Inputs: labels (required). Returns: failures, totalCount, updatedLabels, appliedOperations, +1 more
update-projectsCDestructive
Update multiple existing projects with new values.
Inputs: projects (required). Returns: failures, projects, totalCount, appliedOperations, +1 more
update-remindersBDestructiveIdempotent
Update existing reminders. Each reminder must specify its type ("relative", "absolute", or "location") and ID. Only include fields that need to change.
Inputs: reminders (required). Returns: failures, reminders, totalCount, appliedOperations, +1 more
update-sectionsBDestructive
Update multiple existing sections with new values.
Inputs: sections (required). Returns: failures, sections, totalCount, appliedOperations, +1 more
update-tasksADestructive
Update existing tasks including content, dates, priorities, and assignments. Send only the fields that change.
Inputs: tasks (required). Returns: tasks, failures, totalCount, updatedTaskIds, +1 more
user-infoBRead-onlyIdempotent
Get comprehensive user information including user ID, full name, email, timezone with current local time, week start day preferences, current week dates, daily/weekly goal progress, and user plan (Free/Pro/Business).
Inputs: no named parameters. Returns: plan, type, email, userId, +11 more
view-attachmentARead-onlyIdempotent
View a file attachment from a Todoist comment. Pass the fileUrl from a comment's fileAttachment field. Supports images (returned inline), text files (returned as text), and binary files like PDFs (returned as embedded resources).
Inputs: fileUrl (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 49 tools
Most tools have distinct resource+action targets, and the descriptions proactively cross-reference each other (find-activity vs find-completed-tasks, reschedule-tasks vs update-tasks, export vs find-tasks). However a few pairs genuinely overlap: fetch vs fetch-object both retrieve an object by ID, search vs find-tasks both locate tasks, and get-project-health vs analyze-project-health vs get-project-activity-stats require careful reading to distinguish.
The dominant convention is clear verb-noun hyphenated (find-tasks, add-comments, update-labels, delete-object). A handful of outliers break it: bare verbs 'search' and 'fetch', noun-only 'user-info' and the vague 'project-management', and reversed-order 'project-move'.
49 tools is far beyond a well-scoped surface for a task manager; the 3-15 range would be typical. Several tools exist only for narrow variants (get-project-activity-stats, analyze-project-health, project-move, view-attachment) that inflate the set and increase selection cost.
The surface covers full lifecycle CRUD for tasks, projects, sections, comments, reminders, labels, and filters, plus completion/uncompletion, activity logs, productivity stats, templates, workspaces, collaborators, assignments, and attachments. No obvious dead ends remain for the Todoist domain.
Maintenance
Related MCP Connectors
Manage tasks, Focus Zone, notes, projects, and task history from compatible AI assistants.
Manage Superlist tasks and lists in plain language from any MCP-compatible AI agent.
Task management for people and AI agents, with scoped OAuth access to issues, projects, and docs.
Task management for people and AI agents, with scoped OAuth access to issues, projects, and docs.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Todoist tasks, projects, labels, sections, and comments through natural conversation. Supports comprehensive task operations including creation, updates, completion, and organization with natural language quick-add functionality.-
- AlicenseNot gradedqualityDmaintenanceConnects AI assistants to Todoist for comprehensive task management, enabling natural language creation, updating, and organization of tasks, projects, sections, and labels.17 npm3MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Todoist tasks, projects, sections, and labels through natural language, supporting task creation, updates, completion, and intelligent organization of your workflow.17 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Todoist tasks, projects, comments, and labels through natural language commands. Provides complete CRUD operations securely via the Todoist REST API v2.Apache 2.0