tick-mcp
Provides tools for managing tasks, projects, habits, tags, focus stats, and more on TickTick through both official and unofficial APIs.
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., "@tick-mcp show my overdue tasks from this week"
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.
tick-mcp
MCP server for TickTick — manage tasks, projects, habits, tags, focus stats, and more through the Model Context Protocol.
71 tools exposed over MCP, covering both the official TickTick Open API (V1) and the unofficial web API (V2) for features not yet available publicly.
Features
Category | Tools |
Tasks |
|
Batch |
|
Projects |
|
Query / Search |
|
Views |
|
Verified Actions |
|
Tags |
|
Habits |
|
Kanban |
|
Folders |
|
Focus |
|
History |
|
Subtasks |
|
Sync / Stats |
|
Utilities |
|
Query / Search highlights
Structured task filtering — folders, projects, tags, parent/subtask shape, reminders, recurrence, checklist presence, and priorities.
Time-aware agenda access — query by date range, datetime range, and HH:MM time windows without forcing a full sync first.
Grep-like matching — substring search,
any/all/phrasekeyword modes, regex, and exclusion regex across chosen fields.Targeted note search — notes are fetched only from NOTE projects in scope instead of materializing the whole workspace.
Workspace navigation — folder/project map with optional active task counts to inspect the account structure before acting.
Ready-made operational views — day view, week window, upcoming due tasks, overdue/stale detection, and priority summaries built on the same filter engine.
Saved query presets — persist reusable task/note/agenda/history/week-overview queries and execute them later without rebuilding the filter set.
Verified workflow helpers
Subtask-safe creation —
create_subtaskcreates the child, links it, then verifiesparentIdandchildIds.Move verification —
verified_move_tasksre-reads destination projects and confirms every moved task is actually there.Folder assignment verification —
verified_assign_project_folderverifies the persistedgroupIdthrough V2 sync, not through the misleading V1 response.
Intent-first discovery
ticktick_guide() supports both technical categories and real user goals.
Category-oriented:
ticktick_guide(category="tasks")
Intent-oriented:
ticktick_guide(intent="know_what_to_do_today")ticktick_guide(intent="plan_the_week")ticktick_guide(intent="find_a_note")ticktick_guide(intent="reorganize_projects")ticktick_guide(intent="clean_up_tasks")
Related MCP server: TickTick MCP
Package Layout
src/tick_mcp/
├── mcp_api/
│ ├── core.py # shared FastMCP instance, catalog, helpers
│ ├── utilities.py # discovery + helper tools
│ ├── projects.py # project CRUD tools
│ ├── tasks_read.py # inbox / project / task reads
│ ├── tasks_write.py # task mutation tools
│ ├── tasks_batch.py # batch + structural task operations
│ ├── read.py # high-level query/search, views, and saved presets
│ ├── verified.py # safe wrappers with read-back verification + rollback hints
│ ├── folders.py # folders + kanban columns
│ ├── tags.py # tag tools
│ ├── habits.py # habit tools
│ ├── history.py # completed / deleted history
│ └── stats.py # focus and user/productivity stats
├── services/
│ └── query.py # reusable filtering, range and grep-like planning
├── client_api/
│ ├── transport.py # auth, sessions, low-level V1/V2 HTTP helpers
│ ├── projects.py # projects, folders, columns, tags
│ ├── tasks.py # tasks, sync, batch, history
│ ├── habits.py # habits and check-ins
│ └── stats.py # focus and user/productivity stats
├── client.py # stable public facade over client_api/*
├── models.py # pydantic contracts
├── server.py # stable public import surface for the MCP server
└── main.py # CLI entrypointInstallation
# recommended — installs as a standalone tool
uv tool install tick-mcp
# or via pip
pip install tick-mcpThis provides two commands:
Command | Description |
| Start the MCP server (stdio transport) |
| CLI helper — session refresh, diagnostics |
Configuration
1. Environment variables
Copy the example file and fill in your tokens:
cp src/tick_mcp/.env.example src/tick_mcp/.envVariable | Required | Description |
| Yes | V1 Open API bearer token (PAT or OAuth2) |
| No | V2 session cookie for extended features |
Getting a V1 token (simplest):
Open TickTick → Settings → Integrations → API
Copy the displayed Personal Access Token
Getting a V2 session token:
Log in to ticktick.com in your browser
DevTools → Application → Cookies → copy the
tcookie value
Or use the CLI to auto-login:
tick-admin session refresh2. Server config
Runtime settings live in src/tick_mcp/config.yaml — API endpoints, timeouts, and user-agent are all externalised there.
MCP Client Integration
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or ~/.config/Claude/claude_desktop_config.json (Linux):
{
"mcpServers": {
"ticktick": {
"command": "tick-mcp",
"env": {
"TICKTICK_API_TOKEN": "your-v1-token",
"TICKTICK_SESSION_TOKEN": "your-v2-token"
}
}
}
}VS Code (GitHub Copilot)
Add to .vscode/mcp.json:
{
"servers": {
"ticktick": {
"command": "tick-mcp",
"env": {
"TICKTICK_API_TOKEN": "your-v1-token",
"TICKTICK_SESSION_TOKEN": "your-v2-token"
}
}
}
}Other MCP clients
Any client that supports the stdio transport can launch tick-mcp as a subprocess.
Development
# Clone & install dev deps
git clone https://github.com/kpihx/tick-mcp.git
cd tick-mcp
uv sync --group dev
# Unit tests (155 selected unit tests, no network)
uv run pytest
# Live tests against real TickTick API (requires tokens in .env)
uv run pytest -m liveTest suite
155 selected unit tests — pure logic, mocked HTTP, zero network
12 live integration scripts — 508 assertions against the real TickTick API
License
MIT © 2025 Ivann KAMDEM
Available Tools
71 toolsbatch_create_tasksA
Create multiple tasks at once via V2 batch.
[Category: Tasks — Batch] [Auth: V2]
[Related: create_task, batch_update_tasks, batch_delete_tasks]
⚠️ SUBTASK TRAP — parentId in the task dict is SILENTLY IGNORED here too (V2 batch).
Do NOT pass parentId expecting subtask relationships to be created automatically.
ALWAYS call set_subtask_parent for each child AFTER this call.
Args:
tasks: List of task dicts. Each needs at least {"title": "..."}.
Optional: projectId, content, priority, dueDate, startDate,
timeZone, tags, allDay, kind, items, columnId.
⚠️ Do NOT include parentId — use set_subtask_parent instead.
Returns: {id2etag: {id: etag}, id2error: {id: error}} — check id2error for failures.
Inputs: tasks (required).
batch_delete_tasksA
Delete multiple tasks at once via V2 batch.
[Category: Tasks — Batch] [Auth: V2]
[Related: delete_task, batch_create_tasks]
Args:
tasks: List of {"taskId": "...", "projectId": "..."}.
Inputs: tasks (required).
batch_update_tasksA
Update multiple tasks at once via V2 batch.
[Category: Tasks — Batch] [Auth: V2]
[Related: update_task, batch_create_tasks, batch_delete_tasks]
Args:
tasks: List of task dicts. Each MUST include "id" and "projectId"
plus fields to change. ⚠️ No read-modify-write — provide full field values.
⚠️ REMINDER RELIABILITY — DO NOT USE THIS TOOL FOR REMINDER UPDATES:
batch_update_tasks() uses the V2 batch endpoint which cannot reliably set reminders
on existing tasks, for two compounding reasons:
1. V2-created tasks may have dueDate invisible to V1 (null), breaking reminder anchoring.
2. Reminder object format {"trigger": "TRIGGER:-P2DT0H0M0S"} is silently rejected by the
V2 batch endpoint — no error returned, but reminders are never saved.
PREFERRED PATTERN: use update_task() (V1) with explicit due_date + time_zone + reminder_minutes.
See the "Add/update reminders" workflow in ticktick_guide(show_workflows=True).
Returns: {id2etag, id2error}.
Inputs: tasks (required).
build_recurrence_ruleA
Build an iCalendar RRULE string for recurring tasks or habits.
[Category: Utilities] [Auth: none]
[Related: create_task, update_task, create_habit]
Args:
frequency: "DAILY", "WEEKLY", "MONTHLY", or "YEARLY".
interval: Repeat every N units (default 1).
by_day: Weekday codes for WEEKLY, e.g. ["MO","WE","FR"].
by_month_day: Day of month (1-31) for MONTHLY.
by_month: Month number (1-12) for YEARLY.
count: End after N occurrences.
until: End date UTC: "20261231T000000Z".
Examples:
Every day → frequency="DAILY"
Mon/Wed/Fri → frequency="WEEKLY", by_day=["MO","WE","FR"]
15th of each month → frequency="MONTHLY", by_month_day=15
Every 2 weeks → frequency="WEEKLY", interval=2
3 times then stop → frequency="DAILY", count=3
Returns {"rrule": "RRULE:FREQ=..."} — pass the rrule value as the
'recurrence' parameter in create_task/update_task.
Inputs: frequency (required), interval, by_day, by_month_day, +3 more.
build_reminderA
Convert minutes into an iCalendar TRIGGER string for reminders.
[Category: Utilities] [Auth: none]
[Related: create_task, update_task]
Args:
minutes_before: 0=at due time, 30=30min before, 60=1hr, 1440=1day, 2880=2days.
Usually you don't need this — use the reminder_minutes parameter in create_task
/ update_task directly. This tool is for inspection or manual trigger building.
Inputs: minutes_before (required).
check_v2_availabilityA
Check whether V2 API features are available (session token configured).
[Category: Utilities] [Auth: none]
[Related: ticktick_guide]
Returns availability status and lists all V2-only feature categories.
Inputs: no named parameters.
complete_taskA
Mark a task as completed (status → 2). Uses V1 dedicated endpoint.
[Category: Tasks — Write] [Auth: V1]
[Related: reopen_task, get_task_detail, get_completed_tasks]
Args:
project_id: The project containing the task.
task_id: The task to complete.
Inputs: project_id (required), task_id (required).
create_habitA
Create a new habit.
[Category: Habits] [Auth: V2]
[Related: list_habits, update_habit, habit_checkin, build_recurrence_rule]
[Workflow: create_habit → habit_checkin daily → get_habit_records to review]
Args:
name: Habit name (required).
habit_type: "Boolean" (done/not done) or "Real" (measurable, needs goal).
goal: Target value for Real habits (e.g., 2.0 for "2L water").
step: Increment step for Real (e.g., 0.25 for quarter-liter).
unit: Measurement unit for Real (e.g., "L", "pages", "min").
color: Hex color, e.g. "#4DB6AC".
icon: Icon resource name.
section_id: Section ID (from list_habit_sections) for time-of-day grouping.
repeat_rule: RRULE string (use build_recurrence_rule). Default = daily.
reminders: Time strings, e.g. ["08:00", "20:00"].
encouragement: Message shown on completion.
target_days: Target days for the habit goal cycle.
start_date: "yyyy-MM-dd".
Examples:
Boolean: create_habit(name="Meditate", color="#7E57C2")
Real: create_habit(name="Read", habit_type="Real", goal=30, step=5, unit="pages")
Inputs: name (required), habit_type, goal, step, +9 more.
create_projectA
Create a new TickTick project (list).
[Category: Projects] [Auth: V1 + V2 when group_id is provided]
[Related: list_projects, update_project, delete_project, list_project_folders]
[Workflow: Create project → manage_columns (for kanban) → create_task]
Args:
name: Project name (required).
color: Hex color, e.g. "#F18181".
kind: "TASK" (default) or "NOTE".
view_mode: "list", "kanban", or "timeline".
group_id: Folder ID to file project in (from list_project_folders).
⚠️ group_id ALWAYS requires a V2 follow-up — handled automatically here:
The V1 create endpoint silently ignores groupId in the payload (no error,
no warning — it just doesn't persist). This tool works around it by:
1. Creating the project via V1 to obtain the new project ID.
2. Immediately calling V2 POST /batch/project to assign the groupId.
The returned dict reflects groupId correctly. Verify with full_sync()
if needed — V1 list_projects always shows groupId=null regardless.
⚠️ Never try to assign group_id via a raw V1 update — it silently fails.
Always go through update_project(group_id=...) which also uses V2.
Inputs: name (required), color, kind, view_mode, +1 more.
create_subtaskA
Create a child task and verify the parent-child relationship afterwards.
[Category: Verified Actions] [Auth: V1 + V2]
[Related: create_task, set_subtask_parent, verified_set_subtask_parent]
Inputs: title (required), project_id (required), parent_id (required), content, +12 more.
create_tagA
Create a new tag.
[Category: Tags] [Auth: V2]
[Related: list_tags, update_tag, rename_tag, delete_tag]
Args:
name: Tag name/label.
color: Hex color, e.g. "#FF6B6B".
parent: Parent tag name (for nested/hierarchical tags).
sort_type: "project", "dueDate", "title", or "priority".
Inputs: name (required), color, parent, sort_type.
create_taskA
Create a new TickTick task.
[Category: Tasks — Write] [Auth: V1]
[Related: update_task, complete_task, set_subtask_parent, build_recurrence_rule]
[Workflow: For subtasks → create_task then set_subtask_parent]
⚠️ SUBTASK TRAP — parentId is SILENTLY IGNORED by the V1 creation endpoint.
Passing parentId in the payload creates a standalone task with no error or warning.
ALWAYS use set_subtask_parent AFTER creation to establish the relationship.
Correct sequence: create_task (parent) → create_task / batch_create_tasks (children) → set_subtask_parent × N
Args:
title: Task title (required).
project_id: Target project ID. Omit → Inbox.
content: Body / description (plain text or markdown).
desc: Alt description field (used by some TickTick views).
priority: 0=none, 1=low, 3=medium, 5=high (Eisenhower: 5=urgent+important).
due_date: ISO 8601, e.g. "2026-03-10T09:00:00+0000".
start_date: ISO 8601.
time_zone: IANA timezone, e.g. "Europe/Paris". Recommended with dates.
tags: Tag strings, e.g. ["work", "urgent"].
checklist_items: Strings → each becomes a checklist item. Auto-sets kind=CHECKLIST.
all_day: True for all-day (no specific time).
kind: "TEXT", "NOTE", or "CHECKLIST". Auto-set if checklist_items given.
reminder_minutes: Minutes before due to remind, e.g. [0, 30, 1440].
0=at time, 30=30min before, 1440=1 day before.
recurrence: RRULE string (use build_recurrence_rule to generate).
column_id: Kanban column ID (for kanban-view projects).
Returns the created task with its assigned id.
Inputs: title (required), project_id, content, desc, +11 more.
delete_habitA
Delete a habit permanently.
[Category: Habits] [Auth: V2]
[Related: list_habits, update_habit]
Args:
habit_id: The habit ID to delete.
Inputs: habit_id (required).
delete_projectA
Permanently delete a project and ALL its tasks. ⚠️ IRREVERSIBLE.
[Category: Projects] [Auth: V1]
[Related: list_projects, update_project]
Args:
project_id: The project to delete.
Inputs: project_id (required).
delete_query_presetB
Delete a saved query preset.
[Category: Query & Search] [Auth: none]
[Related: list_query_presets, save_query_preset, run_query_preset]
Inputs: name (required).
delete_tagB
Delete a tag. Removes it from all tasks.
[Category: Tags] [Auth: V2]
[Related: list_tags, merge_tags]
Args:
tag_name: The tag name to delete.
Inputs: tag_name (required).
delete_taskA
Permanently delete a task. ⚠️ IRREVERSIBLE.
[Category: Tasks — Write] [Auth: V1]
[Related: complete_task, get_deleted_tasks]
Args:
project_id: The project containing the task.
task_id: The task to delete.
Inputs: project_id (required), task_id (required).
events_of_todayA
Return timed scheduled items for a given local day.
[Category: Query & Search] [Auth: V1 + V2]
[Related: tasks_of_today, query_agenda]
Multi-value filters accept either a list or a single string.
Inputs: local_date, project_ids, project_names, folder_ids, +6 more.
full_syncA
Full V2 sync — all projects, tasks, tags, folders in ONE call.
[Category: Sync] [Auth: V2]
[Related: get_all_tasks, list_projects, list_tags, list_project_folders]
Returns: {inboxId, projects, tasks, tags, folders, task_count}.
Best for getting a complete overview of the account.
Inputs: no named parameters.
get_all_tasksA
Get ALL active tasks across all projects in one call via V2 sync.
[Category: Sync] [Auth: V2]
[Related: full_sync, get_inbox, get_project_tasks]
Much faster than iterating projects one by one. Returns a flat list.
Inputs: no named parameters. Returns: result
get_completed_tasksA
Get completed or abandoned tasks within a date range.
[Category: Completed & Trash] [Auth: V2]
[Related: complete_task, get_deleted_tasks, get_productivity_stats]
Args:
from_date: "yyyy-MM-dd HH:mm:ss", e.g. "2026-01-01 00:00:00".
to_date: "yyyy-MM-dd HH:mm:ss", e.g. "2026-12-31 23:59:59".
status: "Completed" or "Abandoned" (default: "Completed").
limit: Max results (default 100).
Inputs: from_date (required), to_date (required), status, limit. Returns: result
get_deleted_tasksA
Get deleted tasks from the trash.
[Category: Completed & Trash] [Auth: V2]
[Related: delete_task, get_completed_tasks]
Args:
start: Pagination offset (default 0).
limit: Max results (default 50).
Inputs: start, limit. Returns: result
get_focus_statsA
Get focus/pomodoro statistics for a date range.
[Category: Focus / Pomodoro] [Auth: V2]
[Related: get_productivity_stats]
Args:
from_date: Start date YYYYMMDD, e.g. "20260101".
to_date: End date YYYYMMDD, e.g. "20260306".
stat_type: "heatmap" (daily durations) or "distribution" (per-tag breakdown).
Returns:
heatmap: List of {date, duration} entries.
distribution: {"tagDurations": {"tag_name": seconds, ...}}
Inputs: from_date (required), to_date (required), stat_type.
get_habit_recordsB
Get check-in records for one or more habits.
[Category: Habits] [Auth: V2]
[Related: list_habits, habit_checkin]
Args:
habit_ids: List of habit IDs to query.
after_stamp: Only return check-ins after this date (YYYYMMDD, e.g. 20260101).
Use 0 for all history.
Returns: {"checkins": {"habitId": [record, ...]}}
Inputs: habit_ids (required), after_stamp.
get_inboxA
Return tasks from the TickTick Inbox.
[Category: Tasks — Read] [Auth: V1]
[Related: get_project_tasks, get_all_tasks, create_task]
Args:
include_completed: If True, include completed tasks (default: False).
Inputs: include_completed. Returns: result
get_productivity_statsA
Get productivity statistics — score, level, streaks, completion counts.
[Category: User & Stats] [Auth: V2]
[Related: get_user_status, get_completed_tasks, get_focus_stats]
Returns: score, level, completedToday, completedYesterday, completedThisWeek,
completedThisMonth, currentStreak, maxStreak.
Inputs: no named parameters.
get_project_detailA
Get full details of a single project.
[Category: Projects] [Auth: V1]
[Related: list_projects, get_project_tasks, update_project]
Args:
project_id: The project ID (from list_projects).
Inputs: project_id (required).
get_project_tasksA
Return all tasks from a specific project, with kanban columns if available.
[Category: Tasks — Read] [Auth: V1]
[Related: list_projects, get_task_detail, get_inbox, list_columns]
Args:
project_id: The project ID (use list_projects to find it).
include_completed: If True, include completed tasks (default: False).
Inputs: project_id (required), include_completed. Returns: result
get_task_detailA
Return full detail of a specific task: checklist, reminders, recurrence,
tags, dates, subtask info, focus summaries, and all metadata.
[Category: Tasks — Read] [Auth: V1]
[Related: get_project_tasks, update_task, complete_task]
Args:
project_id: The project containing the task.
task_id: The task ID.
Inputs: project_id (required), task_id (required).
get_user_statusA
Get account status — inbox ID, Pro subscription, team membership.
[Category: User & Stats] [Auth: V2]
[Related: get_productivity_stats, full_sync]
Returns: userId, username, inboxId, pro, proStartDate, proEndDate, teamUser, etc.
Inputs: no named parameters.
habit_checkinA
Record a habit check-in (mark as done for a specific day).
[Category: Habits] [Auth: V2]
[Related: list_habits, get_habit_records, create_habit]
Args:
habit_id: The habit ID.
checkin_stamp: Date as YYYYMMDD integer, e.g. 20260306 for today.
value: Value for Real habits (e.g., 1.5 for "1.5 liters"). Omit for Boolean.
status: 0=unchecked, 2=completed (default: 2).
checkin_time: ISO datetime for exact time (optional).
Inputs: habit_id (required), checkin_stamp (required), value, status, +1 more.
list_columnsA
List kanban columns for a project.
[Category: Kanban Columns] [Auth: V2]
[Related: manage_columns, get_project_tasks, create_task]
Args:
project_id: The project with kanban view mode.
Inputs: project_id (required). Returns: result
list_habitsA
List all habits with stats (streaks, total check-ins, etc.).
[Category: Habits] [Auth: V2]
[Related: create_habit, update_habit, habit_checkin, get_habit_records, list_habit_sections]
Returns: id, name, status, type (Boolean/Real), goal, step, unit, color,
totalCheckIns, currentStreak, maxStreak, repeatRule, sectionId, etc.
Inputs: no named parameters. Returns: result
list_habit_sectionsA
List habit sections (e.g., Morning, Afternoon, Evening).
[Category: Habits] [Auth: V2]
[Related: list_habits, create_habit]
Use section IDs in create_habit/update_habit to organize habits by time of day.
Inputs: no named parameters. Returns: result
list_project_foldersA
List all project folders (groups).
[Category: Folders] [Auth: V2]
[Related: manage_project_folders, create_project, list_projects]
Returns: id, name, sortOrder. Use folder IDs as group_id in create/update_project.
Inputs: no named parameters. Returns: result
list_projectsA
List all TickTick projects (lists).
[Category: Projects] [Auth: V1]
[Related: get_project_detail, create_project, get_project_tasks, list_project_folders]
Returns: id, name, kind (TASK/NOTE), closed, color, sortOrder, groupId.
Use the returned 'id' as project_id in task tools.
⚠️ V1 limitation: groupId is ALWAYS null in V1 responses, even when a
folder assignment exists. Use full_sync() to see real groupId values.
Inputs: no named parameters. Returns: result
list_query_presetsA
List saved reusable query presets.
[Category: Query & Search] [Auth: none]
[Related: save_query_preset, run_query_preset, delete_query_preset]
Inputs: no named parameters.
list_tagsA
List all tags.
[Category: Tags] [Auth: V2]
[Related: create_tag, update_tag, rename_tag, merge_tags, delete_tag]
Returns: name (internal key, lowercase), label (display), color, parent, sortOrder.
Use tag names in create_task/update_task tags parameter.
Inputs: no named parameters. Returns: result
manage_columnsA
Create, update, or delete kanban columns in batch.
[Category: Kanban Columns] [Auth: V2]
[Related: list_columns, create_task, update_task]
[Workflow: Create kanban project → manage_columns → create_task with column_id]
Args:
project_id: The project these columns belong to.
add: New columns: [{"name": "To Do", "sortOrder": 0}, {"name": "In Progress", "sortOrder": 1}].
projectId is auto-filled.
update: Column updates: [{"id": "...", "name": "New Name"}].
delete: Column IDs to delete.
Inputs: project_id (required), add, update, delete.
manage_project_foldersA
Create, update, or delete project folders in batch.
[Category: Folders] [Auth: V2]
[Related: list_project_folders, create_project]
Args:
add: New folders: [{"name": "Work"}, {"name": "Personal"}].
update: Updates: [{"id": "...", "name": "New Name"}].
delete: Folder IDs to delete: ["id1", "id2"].
Inputs: add, update, delete.
merge_tagsA
Merge one tag into another. Tasks with source get target instead; source is deleted.
[Category: Tags] [Auth: V2]
[Related: list_tags, rename_tag, delete_tag]
Args:
source_name: Tag to merge FROM (will be deleted).
target_name: Tag to merge INTO (will remain).
Inputs: source_name (required), target_name (required).
move_tasksA
Move tasks between projects via V2 batch.
[Category: Tasks — Batch] [Auth: V2]
[Related: batch_update_tasks, list_projects, set_subtask_parent]
⚠️ ORPHAN TRAP — The V2 API moves tasks individually, never cascading to children.
Moving a parent task leaves its subtasks stranded in the old project.
The parent-child relationship (parentId/childIds) is preserved in the metadata,
but TickTick won't display subtasks correctly if they're in a different project.
This tool automatically detects and cascades to children:
For each unique source project, it fetches the full project data once via
/project/{id}/data (which correctly returns childIds, unlike /project/{id}/task/{id}).
A {task_id: childIds} index is built per source project — O(1) API calls per project,
not per task. Children are appended to the move batch automatically (same destination).
The returned dict includes `cascaded_children` listing any auto-added child moves.
Args:
moves: List of {"taskId": "...", "fromProjectId": "...", "toProjectId": "..."}.
Only provide parent tasks — children are fetched and moved automatically.
Inputs: moves (required).
overdue_tasksB
Return active tasks whose due date is already in the past.
[Category: Query & Search] [Auth: V1 + V2]
[Related: tasks_of_today, query_tasks, stale_tasks]
Multi-value filters accept either a list or a single string.
Inputs: before_dt, project_ids, project_names, folder_ids, +4 more.
priority_dashboardB
Summarize active tasks by priority with top items per bucket.
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_tasks, tasks_of_today, overdue_tasks]
Multi-value filters accept either a list or a single string.
Inputs: project_ids, project_names, folder_ids, folder_names, +3 more.
query_agendaC
Query scheduled items inside a date/time window.
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_tasks, get_all_tasks, get_project_tasks]
Multi-value filters accept either a list or a single string.
Inputs: from_dt (required), to_dt (required), date_field, project_ids, +24 more.
query_foldersB
Search/filter project folders with optional project counts.
[Category: Query & Search] [Auth: V1 + V2 when include_project_counts=True]
[Related: workspace_map, list_project_folders, query_projects]
Inputs: name_query, regex, include_project_counts, limit.
query_notesB
Query notes with folder/project scope and grep-like content search.
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_tasks, workspace_map, get_project_tasks]
Multi-value filters accept either a list or a single string.
Inputs: project_ids, project_names, folder_ids, folder_names, +12 more.
query_projectsC
Search/filter projects with folder-aware metadata.
[Category: Query & Search] [Auth: V1 + V2]
[Related: workspace_map, list_projects, list_project_folders, query_folders]
Multi-value filters accept either a list or a single string.
Inputs: name_query, regex, folder_ids, folder_names, +5 more.
query_task_historyC
Query completed, abandoned, or deleted task history with the same fine filters.
[Category: Query & Search] [Auth: V2]
[Related: get_completed_tasks, get_deleted_tasks, query_tasks]
Multi-value filters accept either a list or a single string.
Inputs: history_source (required), from_date, to_date, project_ids, +32 more.
query_tasksB
Query active tasks with fine-grained filters, date/hour ranges, and grep-like matching.
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_notes, query_agenda, get_all_tasks, get_project_tasks]
Multi-value filters accept either a list or a single string.
Inputs: project_ids, project_names, folder_ids, folder_names, +29 more.
rename_tagB
Rename a tag. All tasks using it are updated automatically.
[Category: Tags] [Auth: V2]
[Related: list_tags, merge_tags]
Args:
old_name: Current tag name.
new_name: New tag name.
Inputs: old_name (required), new_name (required).
reopen_taskA
Reopen a completed task (status → 0).
[Category: Tasks — Write] [Auth: V1]
[Related: complete_task, update_task]
Args:
project_id: The project containing the task.
task_id: The task to reopen.
Inputs: project_id (required), task_id (required).
run_query_presetC
Execute a saved query preset.
[Category: Query & Search] [Auth: depends on preset query type]
[Related: list_query_presets, save_query_preset, delete_query_preset]
Inputs: name (required), limit_override.
save_query_presetB
Save a reusable query preset.
[Category: Query & Search] [Auth: none]
[Related: list_query_presets, run_query_preset, delete_query_preset]
Inputs: name (required), query_type (required), filters (required), description.
set_subtask_parentA
Set or unset a task's parent (subtask relationship).
[Category: Tasks — Batch] [Auth: V2]
[Related: create_task, get_task_detail]
[Workflow: create_task → set_subtask_parent (TickTick ignores parentId on creation)]
Args:
task_id: The child task ID.
project_id: The project both tasks belong to.
parent_id: New parent task ID (to make subtask). Provide THIS to SET.
old_parent_id: Previous parent ID (to remove). Provide THIS to UNSET.
⚠️ Provide EITHER parent_id OR old_parent_id, not both.
Inputs: task_id (required), project_id (required), parent_id, old_parent_id.
stale_tasksA
Return active tasks that have not been modified recently.
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_tasks, overdue_tasks]
Multi-value filters accept either a list or a single string.
Inputs: older_than_days, project_ids, project_names, folder_ids, +4 more.
tasks_of_todayA
Return active tasks scheduled for a given local day.
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_agenda, events_of_today, overdue_tasks]
Multi-value filters accept either a list or a single string.
Inputs: local_date, project_ids, project_names, folder_ids, +4 more.
ticktick_guideA
Interactive guide to all TickTick MCP tools — START HERE.
[Category: Utilities] [Auth: none]
[Related: check_v2_availability]
Call with no args to see all categories and tool names.
Call with a category name to see tools in that category.
Call with an intent name to see the recommended tool path for a real user goal.
Call with show_workflows=True to see common multi-step patterns.
Args:
category: Filter by category name (partial match, case-insensitive).
Examples: "task", "tag", "habit", "project", "sync", "focus".
intent: Filter by user intent, e.g. "know_what_to_do_today", "find_a_note",
"reorganize_projects", or "clean_up_tasks".
show_workflows: If True, return common multi-step workflow recipes.
Tip: Call check_v2_availability() to see which features need a session token.
Query filter ergonomics: for multi-value string filters (project/folder IDs or
names, tags, search_fields, kinds), tools accept either a single string or a list.
── AGENT OPERATING CONTRACT ─────────────────────────────────────────────────
The TickTick API is dual-layer (V1 official + V2 unofficial) with silent failure
modes. Agents MUST apply the following discipline on every interaction:
1. VERIFY AFTER EVERY WRITE: After create/update/delete operations, always call
get_task_detail() (or equivalent read tool) to confirm the server state
matches the intent. Do not trust API response codes alone — silent partial
failures are common (reminders, parentId, groupId).
2. RETRY UNTIL CONFIRMED: If verification reveals a mismatch, diagnose the root
cause (V1/V2 API duality, missing anchor field, wrong format), adjust the
call strategy, and retry. Repeat verify → fix → retry until state is correct.
3. PROACTIVE USER FEEDBACK: After completing a multi-step task or recovering
from a silent failure, report to the user:
- What was attempted and what the API actually accepted.
- Any workaround applied (e.g., switched from V2 batch to V1 update_task).
- Recommendations for future similar operations.
4. KNOWN SILENT FAILURE PATTERNS (see individual tool docs for details):
- reminder_minutes on V2-created tasks → requires explicit due_date anchor
in update_task() V1; batch_update_tasks() V2 cannot anchor reminders.
- parentId at task creation → always silently ignored; use set_subtask_parent.
- groupId at project creation → use V2 batch/project to set folder after.
- reminder object format {trigger:} → silently rejected; use update_task V1.
─────────────────────────────────────────────────────────────────────────────
Inputs: category, intent, show_workflows.
upcoming_tasksB
Return active tasks due within a local upcoming window.
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_tasks, week_agenda, overdue_tasks]
Multi-value filters accept either a list or a single string.
Inputs: local_date, days, project_ids, project_names, +7 more.
update_habitA
Update an existing habit. Only provided fields are changed
(read-modify-write under the hood — safe for partial updates).
[Category: Habits] [Auth: V2]
[Related: list_habits, create_habit, delete_habit]
Args:
habit_id: The habit ID to update.
name: New name.
goal: New target value (Real habits).
step: New increment step.
unit: New measurement unit.
color: New hex color.
status: 0=active, 2=archived.
section_id: Move to a different section.
repeat_rule: New RRULE (use build_recurrence_rule).
reminders: New reminder times list, e.g. ["08:00", "20:00"].
Pass [] to clear all reminders.
encouragement: New completion message.
target_days: New target days.
⚠️ CRITICAL — V2 /habits/batch is a FULL REPLACEMENT, not a PATCH:
Sending only {"id": ..., "reminders": [...]} will wipe name, color,
status and every other field to null/default. This tool prevents that
by fetching the current habit state first, then merging your changes
before sending the complete object. Never call client.batch_habits
with a partial habit dict directly.
Common uses:
Archive: update_habit(habit_id="...", status=2)
Rename: update_habit(habit_id="...", name="New Name")
Add reminders: update_habit(habit_id="...", reminders=["08:00", "20:00"])
Clear reminders: update_habit(habit_id="...", reminders=[])
Inputs: habit_id (required), name, goal, step, +8 more.
update_projectA
Update an existing project. Only provided fields are changed.
[Category: Projects] [Auth: V1 / V2 when group_id is provided]
[Related: get_project_detail, create_project, delete_project, list_project_folders]
Args:
project_id: The project to update.
name: New name.
color: Hex color.
kind: "TASK" or "NOTE".
view_mode: "list", "kanban", or "timeline".
group_id: Move to a different folder (from list_project_folders).
closed: True=archive, False=unarchive.
⚠️ group_id uses V2 internally (read-modify-write):
The V1 update endpoint silently ignores groupId. When group_id is
provided, this tool fetches the current project state first, then
applies all changes via V2 POST /batch/project so no other fields
(name, color, kind, …) are accidentally wiped.
⚠️ V1 responses always return groupId=null:
After a successful folder assignment, V1 get_project_detail still
shows groupId=null. Use full_sync() to verify the real value via V2.
Inputs: project_id (required), name, color, kind, +3 more.
update_tagA
Update an existing tag's properties.
[Category: Tags] [Auth: V2]
[Related: list_tags, create_tag, rename_tag]
Args:
name: The tag's internal name (from list_tags).
color: New hex color.
parent: New parent tag. Pass "" to remove parent.
sort_type: "project", "dueDate", "title", or "priority".
sort_order: Numeric sort order.
Inputs: name (required), color, parent, sort_type, +1 more.
update_taskA
Update any fields of an existing task. Only provided fields are changed
(read-modify-write under the hood — safe for partial updates).
[Category: Tasks — Write] [Auth: V1]
[Related: get_task_detail, create_task, complete_task, reopen_task]
Args:
task_id: The task to update.
project_id: The project containing the task (required by API).
title: New title.
content: New body/description.
desc: Alt description field.
priority: 0=none, 1=low, 3=medium, 5=high.
due_date: ISO 8601. Pass "" to clear.
start_date: ISO 8601. Pass "" to clear.
time_zone: IANA timezone.
tags: Full replacement list. Pass [] to clear all tags.
status: 0=active, 2=completed, -1=abandoned (V2).
all_day: True/False.
column_id: Move to a kanban column.
reminder_minutes: List of minutes-before. Pass [] to clear reminders.
⚠️ V1/V2 GOTCHA — REMINDER ANCHOR REQUIRED:
Tasks created via V2 batch may have dueDate invisible to V1 (returns null).
V1 uses dueDate as the anchor to compute reminder trigger offsets (TRIGGER:-P2D).
If due_date is null, reminder_minutes is silently ignored — no error, no reminder.
FIX: ALWAYS pass due_date + time_zone explicitly alongside reminder_minutes,
even if you are not changing the due date. Read the existing due date from
get_task_detail() first, then pass it through. Example:
update_task(task_id='...', project_id='...', due_date='2026-06-03T21:00:00+0000',
time_zone='Europe/Paris', reminder_minutes=[2880, 1440])
Returns reminders: ['TRIGGER:-P2D', 'TRIGGER:-P1D'] when correctly anchored.
recurrence: RRULE string (use build_recurrence_rule). Pass "" to clear.
progress: 0-100 percentage (V2).
sort_order: Custom sort order.
kind: "TEXT", "NOTE", or "CHECKLIST".
Inputs: task_id (required), project_id (required), title, content, +14 more.
verified_assign_project_folderB
Assign a project to a folder and verify the persisted groupId through V2 sync.
[Category: Verified Actions] [Auth: V1 + V2]
[Related: update_project, list_project_folders, full_sync]
Inputs: project_id (required), group_id (required).
verified_batch_moveC
Verified batch move wrapper with rollback hints if verification fails.
[Category: Verified Actions] [Auth: V2]
[Related: verified_move_tasks, move_tasks]
Inputs: moves (required).
verified_create_projectA
Create a project, then verify that it exists and that folder assignment persisted if requested.
[Category: Verified Actions] [Auth: V1 + V2 when group_id is provided]
[Related: create_project, verified_assign_project_folder]
Inputs: name (required), color, kind, view_mode, +1 more.
verified_move_tasksB
Move tasks, then verify that each moved task is present in the destination project.
[Category: Verified Actions] [Auth: V2]
[Related: move_tasks, set_subtask_parent]
Inputs: moves (required).
verified_set_subtask_parentC
Set or unset a parent relationship, then verify the resulting structure.
[Category: Verified Actions] [Auth: V2]
[Related: set_subtask_parent, create_subtask]
Inputs: task_id (required), project_id (required), parent_id, old_parent_id.
week_agendaC
Return scheduled items for a local multi-day window (default: 7 days).
[Category: Query & Search] [Auth: V1 + V2]
[Related: query_agenda, tasks_of_today, events_of_today]
Multi-value filters accept either a list or a single string.
Inputs: local_date, days, project_ids, project_names, +8 more.
week_overviewB
Return a planning-oriented overview split into events, due tasks, and overdue tasks.
[Category: Query & Search] [Auth: V1 + V2]
[Related: week_agenda, upcoming_tasks, overdue_tasks]
Multi-value filters accept either a list or a single string.
Inputs: local_date, days, project_ids, project_names, +7 more.
workspace_mapB
Return a navigable map of folders and projects, optionally with active task counts.
[Category: Query & Search] [Auth: V1 + V2 when include_counts=True]
[Related: list_projects, list_project_folders, full_sync, query_projects]
Inputs: include_closed, include_counts, project_name_query, project_regex, +2 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 71 tools
Most tools have distinct purposes, but there are many overlapping query tools (e.g., tasks_of_today, week_agenda, week_overview) that could cause confusion despite detailed descriptions.
Tool names follow a consistent snake_case verb_noun pattern (e.g., create_task, list_projects), with predictable structure throughout.
71 tools is excessive for the domain; many query variants and verified wrappers are redundant, making the surface feel bloated.
Covers all major TickTick features (tasks, projects, habits, tags, sync, stats) with CRUD, batch, and verification actions, leaving few gaps.
Related MCP Connectors
Manage tasks, Focus Zone, notes, projects, and task history from compatible AI assistants.
AI-native task management: list, create, update and archive tasks with rich context for AI agents
Manage your MakeMeBetter AI tasks, habits, and goals from your AI assistant.
Manage Superlist tasks and lists in plain language from any MCP-compatible AI agent.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI integration with TickTick to manage tasks, projects, and tags through the Model Context Protocol. It allows users to import from Markdown, export project data to multiple formats, and perform task operations using natural language.MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage TickTick tasks through natural language, including creating, updating, completing, and deleting tasks, as well as managing projects.14MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage tasks and projects in TickTick through the TickTick Open API, supporting CRUD operations on tasks and projects.6 npm4MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage TickTick tasks, projects, habits, and focus sessions through the MCP server.37 PyPI147MIT