Skip to main content
Glama
Todoist AI MCP Server
by todoist

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/mcp

This 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-mcp

Setup 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

  1. Open Settings → Connectors → Add custom connector

  2. Enter https://ai.todoist.net/mcp and complete OAuth authentication

Cursor

Create a configuration file:

  • Global: ~/.cursor/mcp.json

  • Project-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@doist

OAuth 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/mcp

Then 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-mcp

Start 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

  1. Open Command Palette → MCP: Add Server

  2. 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/mcp

For 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 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 testing

  • npm run dev - Development mode with auto-rebuild and restart

  • npm run tool:list - List available tools for direct execution

  • npm 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.ts

  • Testing and quality checks

  • Commit conventions

Releasing

This project uses release-please to automate version management and package publishing.

How it works

  1. Make your changes using Conventional Commits:

    • feat: for new features (minor version bump)

    • fix: for bug fixes (patch version bump)

    • feat!: or fix!: for breaking changes (major version bump)

    • docs: for documentation changes

    • chore: for maintenance tasks

    • ci: for CI changes

  2. 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

  3. After merging the release PR:

    • A new GitHub release is automatically created

    • A new tag is created

    • The publish workflow is triggered

    • The package is published to npm

Available Tools

49 tools
add-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-healthA
Idempotent

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-tasksA
Destructive

Complete one or more tasks by their IDs.

Inputs: ids (required). Returns: failures, completed, failureCount, successCount, +1 more

delete-objectA
DestructiveIdempotent

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-templateA
Idempotent

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

fetchA
Read-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-objectA
Read-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-activityA
Read-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-commentsA
Read-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-tasksA
Read-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-filtersA
Read-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-labelsA
Read-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-collaboratorsA
Read-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-projectsA
Read-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-remindersA
Read-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-sectionsA
Read-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-tasksA
Read-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-dateA
Read-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-overviewA
Read-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-statsA
Read-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-statsA
Read-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-healthB
Read-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-statusA
Read-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-insightsA
Read-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-workspacesA
Read-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-assignmentsA
Destructive

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-managementA
Idempotent

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-moveC
DestructiveIdempotent

Move a project between personal and workspace contexts.

Inputs: action (required), projectId (required), folderId, visibility, +1 more. Returns: project, success

reorder-objectsA
Idempotent

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-tasksA
Destructive

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

set-user-statusA
DestructiveIdempotent

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-commentsC
Destructive

Update multiple existing comments with new content.

Inputs: comments (required). Returns: comments, failures, totalCount, appliedOperations, +1 more

update-filtersB
Destructive

Update one or more existing personal filters with new values.

Inputs: filters (required). Returns: filters, failures, totalCount, updatedFilterIds, +1 more

update-labelsA
Destructive

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-projectsC
Destructive

Update multiple existing projects with new values.

Inputs: projects (required). Returns: failures, projects, totalCount, appliedOperations, +1 more

update-remindersB
DestructiveIdempotent

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-sectionsB
Destructive

Update multiple existing sections with new values.

Inputs: sections (required). Returns: failures, sections, totalCount, appliedOperations, +1 more

update-tasksA
Destructive

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-infoB
Read-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-attachmentA
Read-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

    A3.5/5.0

    Scored across 49 tools

    Disambiguation4/5

    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.

    Naming Consistency4/5

    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'.

    Tool Count2/5

    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.

    Completeness5/5

    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

    ActivityActive
    ResponsivenessUsually handled

    Related MCP Connectors

    Related MCP Servers