todoist-mcp-server
A custom MCP server that connects Claude to Todoist using a permanent API token, avoiding OAuth re-authentication issues across all Claude surfaces.
README
todoist-mcp-server
A custom Node.js Model Context Protocol (MCP) server that connects Claude to Todoist using a permanent API token. No OAuth, no re-authentication, works identically on Claude web, Claude Code, and Claude mobile.
Why this exists
The problem
Todoist needs to work across three Claude surfaces:
- Claude web (claude.ai) on PC
- Claude Code on PC and Linux
- Claude mobile on iPhone
Every existing solution fails at least one of these. The core issue is authentication. Todoist's official MCP server (ai.todoist.net/mcp) uses OAuth, but Todoist does not issue OAuth refresh tokens. When the access token expires, Claude cannot silently refresh it and forces manual re-authentication. On Claude mobile this is impossible to fix: you cannot re-authenticate from the iOS app. This is a confirmed bug tracked in the Claude Code issue tracker: #5706, #12447, #19456, #28256.
What we evaluated
| Option | Why it failed |
|---|---|
| Todoist official MCP | OAuth with no refresh token. Re-auths daily. Broken on mobile. |
| ClickUp | Official MCP in Claude directory but free tier caps at 300 MCP calls/day. |
| Microsoft To Do | M365 connector requires a business Entra tenant. Personal Microsoft accounts explicitly blocked. |
| Trello | No hosted MCP URL. All implementations are local stdio only, which don't work on Claude web or mobile. |
| TickTick | Local stdio only, no hosted URL. |
| Apple Reminders via CalDAV | iOS 13+ broke all third-party CalDAV write access to the native Reminders app. Items written via CalDAV do not appear in the app. Not fixable. |
| Zapier MCP | Free tier: 100 tasks/month. Each MCP call costs 2 tasks = 50 calls/month total. |
| n8n cloud | No meaningful free tier. $24/month plan exhausted in ~9 days by polling. |
| Composio | Works for Claude Code only via local config. Cannot be used as a remote connector for Claude web or mobile. |
| Bindify | Unverified indie credential proxy. No GitHub presence, no security audit. |
| Asana | Team-focused. Missing personal task richness, no Todoist import. |
Why a custom server works
Todoist issues a permanent API token (Settings > Integrations > Developer). This token never expires unless manually revoked. It is not an OAuth token and requires no refresh.
A custom MCP server that authenticates to Todoist using this token (stored as an Azure environment variable, never in code) gives a hosted remote MCP URL that:
- Never requires re-authentication on any surface
- Works on Claude web, Claude Code, and Claude mobile identically
- Has no rate limits from a middleware layer
- Is fully under the owner's control
- Updates by editing one file in GitHub (Azure redeploys automatically)
API version note
Todoist REST API v2 and Sync API v9 are deprecated as of early 2026. This server uses the unified Todoist API v1 at https://api.todoist.com/api/v1.
Architecture
flowchart TD
A["🖥️ Claude web (claude.ai)"] --> D
B["💻 Claude Code (PC / Linux)"] --> D
C["📱 Claude mobile (iOS)"] --> D
D["todoist-mcp-server\nNode.js · Azure App Service"]
D -->|"Todoist API v1\npermanent Bearer token, never expires"| E["api.todoist.com"]
style D fill:#0078d4,color:#fff,stroke:none
style E fill:#db4035,color:#fff,stroke:none
Key design decisions:
- Stateless HTTP transport:
StreamableHTTPServerTransportwith no session ID generator. Each request is self-contained. Safe on any platform that recycles processes (Azure App Service, Cloud Run, etc.). - Native fetch: Node 20+ has built-in
fetch. No axios, no node-fetch at runtime. X-Request-Idon mutations: Todoist uses this for idempotency on POST/DELETE. Generated per request withcrypto.randomUUID().- Tool-per-operation: Each API endpoint is its own MCP tool with typed Zod parameters. Gives Claude precise descriptions and significantly improves how reliably it picks the right tool.
- No Express: Node's built-in
httpmodule keeps dependencies minimal and startup fast.
Tools (33 total)
Tasks (8)
| Tool | Description |
|---|---|
get_tasks |
List active tasks. Filter by project, section, label, or Todoist filter query (e.g. today, overdue, p1, #ProjectName) |
get_task |
Get a single task by ID |
create_task |
Create a task with content, description, project, section, parent, labels, priority (1-4), due date, assignee |
update_task |
Update any field of an existing task |
complete_task |
Mark a task as done |
reopen_task |
Reopen a completed task |
delete_task |
Permanently delete a task |
move_task |
Move a task to a different project, section, or parent task |
Priority scale: 4 = urgent (red), 3 = high (orange), 2 = medium (blue), 1 = normal.
Projects (5)
| Tool | Description |
|---|---|
get_projects |
List all projects |
get_project |
Get a single project by ID |
create_project |
Create a project with optional color, favorite flag, and view style (list or board) |
update_project |
Update project name, color, favorite status, or view style |
delete_project |
Delete a project and all its tasks |
Sections (5)
| Tool | Description |
|---|---|
get_sections |
List all sections, optionally filtered by project |
get_section |
Get a single section by ID |
create_section |
Create a section inside a project |
update_section |
Rename a section |
delete_section |
Delete a section and all its tasks |
Labels (5)
| Tool | Description |
|---|---|
get_labels |
List all personal labels |
get_label |
Get a single label by ID |
create_label |
Create a label with optional color, order, and favorite flag |
update_label |
Update a label's name, color, or favorite status |
delete_label |
Delete a label |
Comments (5)
| Tool | Description |
|---|---|
get_comments |
Get all comments on a task or project (one of task_id or project_id required) |
get_comment |
Get a single comment by ID |
create_comment |
Add a comment to a task or project |
update_comment |
Edit the text of a comment |
delete_comment |
Delete a comment |
Reminders (4)
Requires Todoist Pro. Reminders fire a notification at a specific time or relative to a task's due date.
| Tool | Description |
|---|---|
get_reminders |
Get all reminders, optionally filtered by task |
create_reminder |
Create a reminder: absolute (specific datetime) or relative (N minutes before due) |
update_reminder |
Update an existing reminder's time |
delete_reminder |
Delete a reminder |
Productivity stats (1)
| Tool | Description |
|---|---|
get_productivity_stats |
Karma score, task completion counts, streaks, and daily/weekly goal progress |
Adding to Claude
claude.ai (web and mobile)
- Go to claude.ai and sign in.
- Click your profile icon, then Customize.
- Go to Connectors and click +.
- Select Add custom connector and fill in:
- Name: Todoist
- Remote MCP server URL:
https://your-deployed-app-url/mcp - Leave all OAuth fields blank.
- Click Add.
Syncs automatically to the Claude mobile app and Claude Code. No re-authentication ever.
Claude Code (.mcp.json)
{
"mcpServers": {
"todoist": {
"type": "http",
"url": "https://your-deployed-app-url/mcp"
}
}
}
Local development
npm install
export TODOIST_API_TOKEN=your_token_here
npm start
Health check: http://localhost:8080/health
MCP endpoint: http://localhost:8080/mcp
Get your API token from: todoist.com/app/settings/integrations/developer
A note
This server exists because I love both Claude and Todoist, and the broken OAuth re-authentication flow was ruining the experience of using them together. Hopefully this workaround becomes unnecessary someday. If Anthropic fixes Claude's MCP OAuth token refresh (#5706, #12447, #19456, #28256) or Todoist issues proper refresh tokens, the official MCP server at ai.todoist.net/mcp would make this redundant. Until then, this works.
License
MIT. Copyright (c) 2026 Shashank Vadrevu. See LICENSE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.