unofficial-anydo-mcp
v1.0.0
Published
Unofficial MCP server for Any.do task management with 2FA support. Not affiliated with Any.do Inc.
Downloads
142
Maintainers
Readme
Unofficial Any.do MCP
Unofficial MCP (Model Context Protocol) server that connects AI assistants to your Any.do tasks. Supports accounts with 2FA.
Disclaimer: This is an unofficial, community-built project. It is not affiliated with, endorsed by, or connected to Any.do Inc. in any way. "Any.do" is a trademark of Any.do Inc., used here only nominatively to identify the third-party service this software interoperates with. The API endpoints used are reverse-engineered from the Any.do web application and are not officially documented or supported. This work is provided for interoperability purposes pursuant to Article 6 of Directive 2009/24/EC of the European Parliament. Use at your own risk — the API may change without notice, and your account could be affected. Users are responsible for ensuring their use complies with Any.do's Terms of Service.
Privacy & no telemetry: This tool processes your Any.do data locally on your machine. No data, telemetry, or analytics is transmitted to the package author or any third party. Task content — including notes and any location data stored in Any.do — passes directly between your device and Any.do's servers. This is a hard guarantee: if telemetry is ever introduced, it will require a major version bump and explicit opt-in.
Features
- Full task CRUD (create, read, update, delete)
- Subtask support (create, update, delete)
- Category/list management
- Mark tasks done/undone, archive/unarchive
- Due dates, priorities, notes, labels
- Filter tasks by category
Installation
# Global install (recommended)
npm install -g unofficial-anydo-mcp
# Or run without installing
npx unofficial-anydo-mcpAuthentication (with 2FA support)
The server uses an X-Anydo-Auth token. Run the included helper to capture it:
Requirements:
- Node.js ≥ 18 and a graphical environment (does not work over headless SSH).
- Puppeteer is needed by the token-capture helper. It is listed as an optional npm dependency because the MCP server itself does not need it — only
mcp-anydo-tokendoes. Ifnpm install -g unofficial-anydo-mcpskipped puppeteer (e.g. behind a firewall or due to the ~170 MB Chromium download), install it explicitly:npm install -g puppeteer.- On Linux, install Chromium system dependencies first:
sudo apt-get install -y libgbm1 libnss3 libatk-bridge2.0-0
mcp-anydo-token- A browser window opens — log in to Any.do (including 2FA if prompted)
- The token is automatically captured and saved to
.envasANYDO_AUTH_TOKEN
Note: Tokens expire periodically. When expired the server returns:
Authentication failed. Your token may have expired.Re-runmcp-anydo-token, then updateANYDO_AUTH_TOKENin your MCP client config and restart the client.
Security & threat model: The token is saved as plaintext in
.env. Anyone with read access to that file can act as you in Any.do until the token is rotated. On a shared system, restrict permissions:chmod 600 .env. If you suspect leakage, change your Any.do password — that invalidates issued tokens.
Troubleshooting
| Problem | Solution |
|---------|----------|
| Authentication failed | Token expired — run mcp-anydo-token |
| Missing ANYDO_AUTH_TOKEN | .env file missing — run mcp-anydo-token |
Configuration
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"anydo": {
"command": "unofficial-anydo-mcp",
"env": {
"ANYDO_AUTH_TOKEN": "<your-token>"
}
}
}
}OpenCode
Add to opencode.json in your project root or ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"anydo": {
"type": "local",
"command": ["unofficial-anydo-mcp"],
"enabled": true,
"env": {
"ANYDO_AUTH_TOKEN": "<your-token>"
}
}
}
}Cursor
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"anydo": {
"command": "unofficial-anydo-mcp",
"env": {
"ANYDO_AUTH_TOKEN": "<your-token>"
}
}
}
}Continue.dev
Add to ~/.continue/config.json:
{
"mcpServers": [
{
"name": "anydo",
"command": "unofficial-anydo-mcp",
"env": {
"ANYDO_AUTH_TOKEN": "<your-token>"
}
}
]
}Other MCP clients
Any client that supports MCP stdio servers works with unofficial-anydo-mcp (global install) or npx unofficial-anydo-mcp as the command, with ANYDO_AUTH_TOKEN passed as an environment variable.
Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| ANYDO_AUTH_TOKEN | Yes | — | Auth token from Any.do (obtain via mcp-anydo-token) |
| ANYDO_TIMEZONE | No | Europe/Bratislava | Timezone for reminder calculations — set to your local zone (e.g. America/New_York, Europe/London) to ensure reminders fire at the correct local time |
| ANYDO_DEFAULT_REMINDER_HOUR | No | 9 | Default hour (0–23) used for reminders when alert=true and no reminderTime is specified |
Contributing / Development
git clone https://github.com/branislav-remen/unofficial-anydo-mcp
cd unofficial-anydo-mcp
npm install
npm run build| Command | Description |
|--------|-------|
| npm run build | Compile TypeScript to dist/ |
| npm start | Run compiled server |
| npm run dev | Run directly via ts-node |
| npm test | Run tests |
| npm run test:watch | Run tests in watch mode |
| npm run test:coverage | Run tests with coverage |
| npm run typecheck | TypeScript type checking |
| npm run lint / lint:fix | ESLint check / auto-fix |
Available Tools (16 total)
Tasks
| Tool | Description |
|------|-------------|
| list_tasks | List tasks (includeDone, includeDeleted, categoryId filter) |
| get_task | Get task details by ID |
| create_task | Create a task (title, priority, note, categoryId, dueDate, labels) |
| update_task | Update a task (title, priority, note, categoryId, dueDate, labels) |
| delete_task | Delete a task by ID |
| mark_task_done | Mark a task as completed (CHECKED) |
| mark_task_undone | Mark a task as not completed (UNCHECKED) |
| archive_task | Archive a task (DONE — hidden from active list) |
| unarchive_task | Unarchive a task (restores to UNCHECKED) |
Subtasks
| Tool | Description |
|------|-------------|
| create_subtask | Create a subtask under a parent task |
| update_subtask | Update a subtask |
| delete_subtask | Delete a subtask |
Categories / Lists
| Tool | Description |
|------|-------------|
| get_categories | List all categories/lists |
| create_category | Create a new category/list |
| update_category | Rename a category/list |
| delete_category | Delete a category/list |
Usage Examples
- "Show me my todos"
- "Create a task 'Buy groceries' in the Personal list"
- "Mark task xyz as done"
- "Change priority of task abc to High"
- "Show me all my lists"
- "Create a new list called 'Work'"
- "Move task to the Work category"
- "Show me tasks only from the Work category"
How It Works
The server intercepts Any.do web app API calls to understand their endpoints. No official API documentation exists — all endpoints are reverse-engineered from the web application.
- Base URL:
https://sm-prod2.any.do - Auth:
X-Anydo-Authheader (extracted via Puppeteer after browser login) - Endpoints:
/me/tasks,/me/categories,/me/tasks/:id,/me/categories/:id
Known Limitations
- Category rename is destructive:
update_categorycreates a new category, migrates all tasks, then deletes the old one. If interrupted mid-operation, both categories may exist with tasks partially migrated. - Recurring task deletion: Deleting a recurring task causes Any.do to automatically create the next occurrence. Always call
update_taskwithrepeatingMethod: "TASK_REPEAT_OFF"before deleting a recurring task. - No rate-limit handling: Bulk operations such as renaming a large category fire multiple API requests. Very large task lists may trigger Any.do's API rate limits.
- Unofficial API: All endpoints are reverse-engineered from the web app. Any.do may change them without notice.
License
ISC © Branislav Remen
