tick-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tick_mcp-0.1.0/PKG-INFO +237 -0
- tick_mcp-0.1.0/README.md +210 -0
- tick_mcp-0.1.0/pyproject.toml +59 -0
- tick_mcp-0.1.0/src/tick_mcp/.env +1 -0
- tick_mcp-0.1.0/src/tick_mcp/.env.example +59 -0
- tick_mcp-0.1.0/src/tick_mcp/__init__.py +3 -0
- tick_mcp-0.1.0/src/tick_mcp/cli.py +479 -0
- tick_mcp-0.1.0/src/tick_mcp/client.py +22 -0
- tick_mcp-0.1.0/src/tick_mcp/client_api/__init__.py +3 -0
- tick_mcp-0.1.0/src/tick_mcp/client_api/habits.py +72 -0
- tick_mcp-0.1.0/src/tick_mcp/client_api/projects.py +163 -0
- tick_mcp-0.1.0/src/tick_mcp/client_api/stats.py +54 -0
- tick_mcp-0.1.0/src/tick_mcp/client_api/tasks.py +222 -0
- tick_mcp-0.1.0/src/tick_mcp/client_api/transport.py +262 -0
- tick_mcp-0.1.0/src/tick_mcp/config.py +443 -0
- tick_mcp-0.1.0/src/tick_mcp/config.yaml +57 -0
- tick_mcp-0.1.0/src/tick_mcp/daemon.py +48 -0
- tick_mcp-0.1.0/src/tick_mcp/main.py +60 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/__init__.py +10 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/core.py +328 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/folders.py +118 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/habits.py +270 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/history.py +68 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/projects.py +210 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/read.py +849 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/stats.py +88 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/sync_api.py +69 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/tags.py +161 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/tasks_batch.py +201 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/tasks_read.py +90 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/tasks_write.py +242 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/utilities.py +206 -0
- tick_mcp-0.1.0/src/tick_mcp/mcp_api/verified.py +316 -0
- tick_mcp-0.1.0/src/tick_mcp/models.py +579 -0
- tick_mcp-0.1.0/src/tick_mcp/server.py +137 -0
- tick_mcp-0.1.0/src/tick_mcp/services/__init__.py +6 -0
- tick_mcp-0.1.0/src/tick_mcp/services/query.py +754 -0
- tick_mcp-0.1.0/src/tick_mcp/services/query_presets.py +81 -0
tick_mcp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: tick-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for TickTick — task and notes access via Model Context Protocol.
|
|
5
|
+
Keywords: ticktick,mcp,model-context-protocol,tasks,productivity
|
|
6
|
+
Author: Ivann KAMDEM
|
|
7
|
+
Author-email: Ivann KAMDEM <kapoivha@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Topic :: Office/Business :: Scheduling
|
|
14
|
+
Requires-Dist: mcp>=1.26.0
|
|
15
|
+
Requires-Dist: httpx>=0.27.0
|
|
16
|
+
Requires-Dist: pyyaml>=6.0
|
|
17
|
+
Requires-Dist: rich>=13.0
|
|
18
|
+
Requires-Dist: typer>=0.12.0
|
|
19
|
+
Requires-Dist: pydantic>=2.0
|
|
20
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Project-URL: Homepage, https://github.com/kpihx/tick-mcp
|
|
23
|
+
Project-URL: Repository, https://github.com/kpihx/tick-mcp
|
|
24
|
+
Project-URL: Issues, https://github.com/kpihx/tick-mcp/issues
|
|
25
|
+
Project-URL: Changelog, https://github.com/kpihx/tick-mcp/blob/main/CHANGELOG.md
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# tick-mcp
|
|
29
|
+
|
|
30
|
+
[](https://pypi.org/project/tick-mcp/)
|
|
31
|
+
[](https://pypi.org/project/tick-mcp/)
|
|
32
|
+
[](LICENSE)
|
|
33
|
+
|
|
34
|
+
**MCP server for TickTick** — manage tasks, projects, habits, tags, focus stats, and more through the [Model Context Protocol](https://modelcontextprotocol.io/).
|
|
35
|
+
|
|
36
|
+
**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.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
| Category | Tools |
|
|
43
|
+
|---|---|
|
|
44
|
+
| **Tasks** | `create_task` · `update_task` · `complete_task` · `reopen_task` · `delete_task` · `get_task_detail` · `get_project_tasks` · `get_inbox` · `get_all_tasks` |
|
|
45
|
+
| **Batch** | `batch_create_tasks` · `batch_update_tasks` · `batch_delete_tasks` · `move_tasks` |
|
|
46
|
+
| **Projects** | `create_project` · `update_project` · `delete_project` · `get_project_detail` · `list_projects` |
|
|
47
|
+
| **Query / Search** | `workspace_map` · `query_projects` · `query_folders` · `query_tasks` · `query_notes` · `query_agenda` · `query_task_history` · `list_query_presets` · `save_query_preset` · `run_query_preset` · `delete_query_preset` |
|
|
48
|
+
| **Views** | `tasks_of_today` · `events_of_today` · `week_agenda` · `week_overview` · `upcoming_tasks` · `overdue_tasks` · `stale_tasks` · `priority_dashboard` |
|
|
49
|
+
| **Verified Actions** | `create_subtask` · `verified_create_project` · `verified_set_subtask_parent` · `verified_move_tasks` · `verified_batch_move` · `verified_assign_project_folder` |
|
|
50
|
+
| **Tags** | `create_tag` · `update_tag` · `rename_tag` · `merge_tags` · `delete_tag` · `list_tags` |
|
|
51
|
+
| **Habits** | `create_habit` · `update_habit` · `delete_habit` · `list_habits` · `habit_checkin` · `get_habit_records` · `list_habit_sections` |
|
|
52
|
+
| **Kanban** | `list_columns` · `manage_columns` |
|
|
53
|
+
| **Folders** | `list_project_folders` · `manage_project_folders` |
|
|
54
|
+
| **Focus** | `get_focus_stats` |
|
|
55
|
+
| **History** | `get_completed_tasks` · `get_deleted_tasks` |
|
|
56
|
+
| **Subtasks** | `set_subtask_parent` |
|
|
57
|
+
| **Sync / Stats** | `full_sync` · `get_user_status` · `get_productivity_stats` |
|
|
58
|
+
| **Utilities** | `ticktick_guide` · `check_v2_availability` · `build_recurrence_rule` · `build_reminder` |
|
|
59
|
+
|
|
60
|
+
### Query / Search highlights
|
|
61
|
+
|
|
62
|
+
- **Structured task filtering** — folders, projects, tags, parent/subtask shape, reminders, recurrence, checklist presence, and priorities.
|
|
63
|
+
- **Time-aware agenda access** — query by date range, datetime range, and HH:MM time windows without forcing a full sync first.
|
|
64
|
+
- **Grep-like matching** — substring search, `any` / `all` / `phrase` keyword modes, regex, and exclusion regex across chosen fields.
|
|
65
|
+
- **Targeted note search** — notes are fetched only from NOTE projects in scope instead of materializing the whole workspace.
|
|
66
|
+
- **Workspace navigation** — folder/project map with optional active task counts to inspect the account structure before acting.
|
|
67
|
+
- **Ready-made operational views** — day view, week window, upcoming due tasks, overdue/stale detection, and priority summaries built on the same filter engine.
|
|
68
|
+
- **Saved query presets** — persist reusable task/note/agenda/history/week-overview queries and execute them later without rebuilding the filter set.
|
|
69
|
+
|
|
70
|
+
### Verified workflow helpers
|
|
71
|
+
|
|
72
|
+
- **Subtask-safe creation** — `create_subtask` creates the child, links it, then verifies `parentId` and `childIds`.
|
|
73
|
+
- **Move verification** — `verified_move_tasks` re-reads destination projects and confirms every moved task is actually there.
|
|
74
|
+
- **Folder assignment verification** — `verified_assign_project_folder` verifies the persisted `groupId` through V2 sync, not through the misleading V1 response.
|
|
75
|
+
|
|
76
|
+
### Intent-first discovery
|
|
77
|
+
|
|
78
|
+
`ticktick_guide()` supports both technical categories and real user goals.
|
|
79
|
+
|
|
80
|
+
- Category-oriented:
|
|
81
|
+
- `ticktick_guide(category="tasks")`
|
|
82
|
+
- Intent-oriented:
|
|
83
|
+
- `ticktick_guide(intent="know_what_to_do_today")`
|
|
84
|
+
- `ticktick_guide(intent="plan_the_week")`
|
|
85
|
+
- `ticktick_guide(intent="find_a_note")`
|
|
86
|
+
- `ticktick_guide(intent="reorganize_projects")`
|
|
87
|
+
- `ticktick_guide(intent="clean_up_tasks")`
|
|
88
|
+
|
|
89
|
+
## Package Layout
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
src/tick_mcp/
|
|
93
|
+
├── mcp_api/
|
|
94
|
+
│ ├── core.py # shared FastMCP instance, catalog, helpers
|
|
95
|
+
│ ├── utilities.py # discovery + helper tools
|
|
96
|
+
│ ├── projects.py # project CRUD tools
|
|
97
|
+
│ ├── tasks_read.py # inbox / project / task reads
|
|
98
|
+
│ ├── tasks_write.py # task mutation tools
|
|
99
|
+
│ ├── tasks_batch.py # batch + structural task operations
|
|
100
|
+
│ ├── read.py # high-level query/search, views, and saved presets
|
|
101
|
+
│ ├── verified.py # safe wrappers with read-back verification + rollback hints
|
|
102
|
+
│ ├── folders.py # folders + kanban columns
|
|
103
|
+
│ ├── tags.py # tag tools
|
|
104
|
+
│ ├── habits.py # habit tools
|
|
105
|
+
│ ├── history.py # completed / deleted history
|
|
106
|
+
│ └── stats.py # focus and user/productivity stats
|
|
107
|
+
├── services/
|
|
108
|
+
│ └── query.py # reusable filtering, range and grep-like planning
|
|
109
|
+
├── client_api/
|
|
110
|
+
│ ├── transport.py # auth, sessions, low-level V1/V2 HTTP helpers
|
|
111
|
+
│ ├── projects.py # projects, folders, columns, tags
|
|
112
|
+
│ ├── tasks.py # tasks, sync, batch, history
|
|
113
|
+
│ ├── habits.py # habits and check-ins
|
|
114
|
+
│ └── stats.py # focus and user/productivity stats
|
|
115
|
+
├── client.py # stable public facade over client_api/*
|
|
116
|
+
├── models.py # pydantic contracts
|
|
117
|
+
├── server.py # stable public import surface for the MCP server
|
|
118
|
+
└── main.py # CLI entrypoint
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Installation
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# recommended — installs as a standalone tool
|
|
125
|
+
uv tool install tick-mcp
|
|
126
|
+
|
|
127
|
+
# or via pip
|
|
128
|
+
pip install tick-mcp
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
This provides two commands:
|
|
132
|
+
|
|
133
|
+
| Command | Description |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `tick-mcp` | Start the MCP server (stdio transport) |
|
|
136
|
+
| `tick-admin` | CLI helper — session refresh, diagnostics |
|
|
137
|
+
|
|
138
|
+
## Configuration
|
|
139
|
+
|
|
140
|
+
### 1. Environment variables
|
|
141
|
+
|
|
142
|
+
Copy the example file and fill in your tokens:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
cp src/tick_mcp/.env.example src/tick_mcp/.env
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Variable | Required | Description |
|
|
149
|
+
|---|---|---|
|
|
150
|
+
| `TICKTICK_API_TOKEN` | **Yes** | V1 Open API bearer token (PAT or OAuth2) |
|
|
151
|
+
| `TICKTICK_SESSION_TOKEN` | No | V2 session cookie for extended features |
|
|
152
|
+
|
|
153
|
+
**Getting a V1 token (simplest):**
|
|
154
|
+
|
|
155
|
+
1. Open TickTick → Settings → Integrations → API
|
|
156
|
+
2. Copy the displayed Personal Access Token
|
|
157
|
+
|
|
158
|
+
**Getting a V2 session token:**
|
|
159
|
+
|
|
160
|
+
1. Log in to [ticktick.com](https://ticktick.com) in your browser
|
|
161
|
+
2. DevTools → Application → Cookies → copy the `t` cookie value
|
|
162
|
+
|
|
163
|
+
Or use the CLI to auto-login:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
tick-admin session refresh
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 2. Server config
|
|
170
|
+
|
|
171
|
+
Runtime settings live in `src/tick_mcp/config.yaml` — API endpoints, timeouts, and user-agent are all externalised there.
|
|
172
|
+
|
|
173
|
+
## MCP Client Integration
|
|
174
|
+
|
|
175
|
+
### Claude Desktop
|
|
176
|
+
|
|
177
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `~/.config/Claude/claude_desktop_config.json` (Linux):
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"mcpServers": {
|
|
182
|
+
"ticktick": {
|
|
183
|
+
"command": "tick-mcp",
|
|
184
|
+
"env": {
|
|
185
|
+
"TICKTICK_API_TOKEN": "your-v1-token",
|
|
186
|
+
"TICKTICK_SESSION_TOKEN": "your-v2-token"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### VS Code (GitHub Copilot)
|
|
194
|
+
|
|
195
|
+
Add to `.vscode/mcp.json`:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"servers": {
|
|
200
|
+
"ticktick": {
|
|
201
|
+
"command": "tick-mcp",
|
|
202
|
+
"env": {
|
|
203
|
+
"TICKTICK_API_TOKEN": "your-v1-token",
|
|
204
|
+
"TICKTICK_SESSION_TOKEN": "your-v2-token"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Other MCP clients
|
|
212
|
+
|
|
213
|
+
Any client that supports the stdio transport can launch `tick-mcp` as a subprocess.
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Clone & install dev deps
|
|
219
|
+
git clone https://github.com/kpihx/tick-mcp.git
|
|
220
|
+
cd tick-mcp
|
|
221
|
+
uv sync --group dev
|
|
222
|
+
|
|
223
|
+
# Unit tests (155 selected unit tests, no network)
|
|
224
|
+
uv run pytest
|
|
225
|
+
|
|
226
|
+
# Live tests against real TickTick API (requires tokens in .env)
|
|
227
|
+
uv run pytest -m live
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Test suite
|
|
231
|
+
|
|
232
|
+
- **155 selected unit tests** — pure logic, mocked HTTP, zero network
|
|
233
|
+
- **12 live integration scripts** — 508 assertions against the real TickTick API
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
[MIT](LICENSE) © 2025 Ivann KAMDEM
|
tick_mcp-0.1.0/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# tick-mcp
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/tick-mcp/)
|
|
4
|
+
[](https://pypi.org/project/tick-mcp/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
**MCP server for TickTick** — manage tasks, projects, habits, tags, focus stats, and more through the [Model Context Protocol](https://modelcontextprotocol.io/).
|
|
8
|
+
|
|
9
|
+
**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.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
| Category | Tools |
|
|
16
|
+
|---|---|
|
|
17
|
+
| **Tasks** | `create_task` · `update_task` · `complete_task` · `reopen_task` · `delete_task` · `get_task_detail` · `get_project_tasks` · `get_inbox` · `get_all_tasks` |
|
|
18
|
+
| **Batch** | `batch_create_tasks` · `batch_update_tasks` · `batch_delete_tasks` · `move_tasks` |
|
|
19
|
+
| **Projects** | `create_project` · `update_project` · `delete_project` · `get_project_detail` · `list_projects` |
|
|
20
|
+
| **Query / Search** | `workspace_map` · `query_projects` · `query_folders` · `query_tasks` · `query_notes` · `query_agenda` · `query_task_history` · `list_query_presets` · `save_query_preset` · `run_query_preset` · `delete_query_preset` |
|
|
21
|
+
| **Views** | `tasks_of_today` · `events_of_today` · `week_agenda` · `week_overview` · `upcoming_tasks` · `overdue_tasks` · `stale_tasks` · `priority_dashboard` |
|
|
22
|
+
| **Verified Actions** | `create_subtask` · `verified_create_project` · `verified_set_subtask_parent` · `verified_move_tasks` · `verified_batch_move` · `verified_assign_project_folder` |
|
|
23
|
+
| **Tags** | `create_tag` · `update_tag` · `rename_tag` · `merge_tags` · `delete_tag` · `list_tags` |
|
|
24
|
+
| **Habits** | `create_habit` · `update_habit` · `delete_habit` · `list_habits` · `habit_checkin` · `get_habit_records` · `list_habit_sections` |
|
|
25
|
+
| **Kanban** | `list_columns` · `manage_columns` |
|
|
26
|
+
| **Folders** | `list_project_folders` · `manage_project_folders` |
|
|
27
|
+
| **Focus** | `get_focus_stats` |
|
|
28
|
+
| **History** | `get_completed_tasks` · `get_deleted_tasks` |
|
|
29
|
+
| **Subtasks** | `set_subtask_parent` |
|
|
30
|
+
| **Sync / Stats** | `full_sync` · `get_user_status` · `get_productivity_stats` |
|
|
31
|
+
| **Utilities** | `ticktick_guide` · `check_v2_availability` · `build_recurrence_rule` · `build_reminder` |
|
|
32
|
+
|
|
33
|
+
### Query / Search highlights
|
|
34
|
+
|
|
35
|
+
- **Structured task filtering** — folders, projects, tags, parent/subtask shape, reminders, recurrence, checklist presence, and priorities.
|
|
36
|
+
- **Time-aware agenda access** — query by date range, datetime range, and HH:MM time windows without forcing a full sync first.
|
|
37
|
+
- **Grep-like matching** — substring search, `any` / `all` / `phrase` keyword modes, regex, and exclusion regex across chosen fields.
|
|
38
|
+
- **Targeted note search** — notes are fetched only from NOTE projects in scope instead of materializing the whole workspace.
|
|
39
|
+
- **Workspace navigation** — folder/project map with optional active task counts to inspect the account structure before acting.
|
|
40
|
+
- **Ready-made operational views** — day view, week window, upcoming due tasks, overdue/stale detection, and priority summaries built on the same filter engine.
|
|
41
|
+
- **Saved query presets** — persist reusable task/note/agenda/history/week-overview queries and execute them later without rebuilding the filter set.
|
|
42
|
+
|
|
43
|
+
### Verified workflow helpers
|
|
44
|
+
|
|
45
|
+
- **Subtask-safe creation** — `create_subtask` creates the child, links it, then verifies `parentId` and `childIds`.
|
|
46
|
+
- **Move verification** — `verified_move_tasks` re-reads destination projects and confirms every moved task is actually there.
|
|
47
|
+
- **Folder assignment verification** — `verified_assign_project_folder` verifies the persisted `groupId` through V2 sync, not through the misleading V1 response.
|
|
48
|
+
|
|
49
|
+
### Intent-first discovery
|
|
50
|
+
|
|
51
|
+
`ticktick_guide()` supports both technical categories and real user goals.
|
|
52
|
+
|
|
53
|
+
- Category-oriented:
|
|
54
|
+
- `ticktick_guide(category="tasks")`
|
|
55
|
+
- Intent-oriented:
|
|
56
|
+
- `ticktick_guide(intent="know_what_to_do_today")`
|
|
57
|
+
- `ticktick_guide(intent="plan_the_week")`
|
|
58
|
+
- `ticktick_guide(intent="find_a_note")`
|
|
59
|
+
- `ticktick_guide(intent="reorganize_projects")`
|
|
60
|
+
- `ticktick_guide(intent="clean_up_tasks")`
|
|
61
|
+
|
|
62
|
+
## Package Layout
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
src/tick_mcp/
|
|
66
|
+
├── mcp_api/
|
|
67
|
+
│ ├── core.py # shared FastMCP instance, catalog, helpers
|
|
68
|
+
│ ├── utilities.py # discovery + helper tools
|
|
69
|
+
│ ├── projects.py # project CRUD tools
|
|
70
|
+
│ ├── tasks_read.py # inbox / project / task reads
|
|
71
|
+
│ ├── tasks_write.py # task mutation tools
|
|
72
|
+
│ ├── tasks_batch.py # batch + structural task operations
|
|
73
|
+
│ ├── read.py # high-level query/search, views, and saved presets
|
|
74
|
+
│ ├── verified.py # safe wrappers with read-back verification + rollback hints
|
|
75
|
+
│ ├── folders.py # folders + kanban columns
|
|
76
|
+
│ ├── tags.py # tag tools
|
|
77
|
+
│ ├── habits.py # habit tools
|
|
78
|
+
│ ├── history.py # completed / deleted history
|
|
79
|
+
│ └── stats.py # focus and user/productivity stats
|
|
80
|
+
├── services/
|
|
81
|
+
│ └── query.py # reusable filtering, range and grep-like planning
|
|
82
|
+
├── client_api/
|
|
83
|
+
│ ├── transport.py # auth, sessions, low-level V1/V2 HTTP helpers
|
|
84
|
+
│ ├── projects.py # projects, folders, columns, tags
|
|
85
|
+
│ ├── tasks.py # tasks, sync, batch, history
|
|
86
|
+
│ ├── habits.py # habits and check-ins
|
|
87
|
+
│ └── stats.py # focus and user/productivity stats
|
|
88
|
+
├── client.py # stable public facade over client_api/*
|
|
89
|
+
├── models.py # pydantic contracts
|
|
90
|
+
├── server.py # stable public import surface for the MCP server
|
|
91
|
+
└── main.py # CLI entrypoint
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Installation
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# recommended — installs as a standalone tool
|
|
98
|
+
uv tool install tick-mcp
|
|
99
|
+
|
|
100
|
+
# or via pip
|
|
101
|
+
pip install tick-mcp
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This provides two commands:
|
|
105
|
+
|
|
106
|
+
| Command | Description |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `tick-mcp` | Start the MCP server (stdio transport) |
|
|
109
|
+
| `tick-admin` | CLI helper — session refresh, diagnostics |
|
|
110
|
+
|
|
111
|
+
## Configuration
|
|
112
|
+
|
|
113
|
+
### 1. Environment variables
|
|
114
|
+
|
|
115
|
+
Copy the example file and fill in your tokens:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cp src/tick_mcp/.env.example src/tick_mcp/.env
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| Variable | Required | Description |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `TICKTICK_API_TOKEN` | **Yes** | V1 Open API bearer token (PAT or OAuth2) |
|
|
124
|
+
| `TICKTICK_SESSION_TOKEN` | No | V2 session cookie for extended features |
|
|
125
|
+
|
|
126
|
+
**Getting a V1 token (simplest):**
|
|
127
|
+
|
|
128
|
+
1. Open TickTick → Settings → Integrations → API
|
|
129
|
+
2. Copy the displayed Personal Access Token
|
|
130
|
+
|
|
131
|
+
**Getting a V2 session token:**
|
|
132
|
+
|
|
133
|
+
1. Log in to [ticktick.com](https://ticktick.com) in your browser
|
|
134
|
+
2. DevTools → Application → Cookies → copy the `t` cookie value
|
|
135
|
+
|
|
136
|
+
Or use the CLI to auto-login:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
tick-admin session refresh
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 2. Server config
|
|
143
|
+
|
|
144
|
+
Runtime settings live in `src/tick_mcp/config.yaml` — API endpoints, timeouts, and user-agent are all externalised there.
|
|
145
|
+
|
|
146
|
+
## MCP Client Integration
|
|
147
|
+
|
|
148
|
+
### Claude Desktop
|
|
149
|
+
|
|
150
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `~/.config/Claude/claude_desktop_config.json` (Linux):
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"mcpServers": {
|
|
155
|
+
"ticktick": {
|
|
156
|
+
"command": "tick-mcp",
|
|
157
|
+
"env": {
|
|
158
|
+
"TICKTICK_API_TOKEN": "your-v1-token",
|
|
159
|
+
"TICKTICK_SESSION_TOKEN": "your-v2-token"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### VS Code (GitHub Copilot)
|
|
167
|
+
|
|
168
|
+
Add to `.vscode/mcp.json`:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"servers": {
|
|
173
|
+
"ticktick": {
|
|
174
|
+
"command": "tick-mcp",
|
|
175
|
+
"env": {
|
|
176
|
+
"TICKTICK_API_TOKEN": "your-v1-token",
|
|
177
|
+
"TICKTICK_SESSION_TOKEN": "your-v2-token"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Other MCP clients
|
|
185
|
+
|
|
186
|
+
Any client that supports the stdio transport can launch `tick-mcp` as a subprocess.
|
|
187
|
+
|
|
188
|
+
## Development
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Clone & install dev deps
|
|
192
|
+
git clone https://github.com/kpihx/tick-mcp.git
|
|
193
|
+
cd tick-mcp
|
|
194
|
+
uv sync --group dev
|
|
195
|
+
|
|
196
|
+
# Unit tests (155 selected unit tests, no network)
|
|
197
|
+
uv run pytest
|
|
198
|
+
|
|
199
|
+
# Live tests against real TickTick API (requires tokens in .env)
|
|
200
|
+
uv run pytest -m live
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Test suite
|
|
204
|
+
|
|
205
|
+
- **155 selected unit tests** — pure logic, mocked HTTP, zero network
|
|
206
|
+
- **12 live integration scripts** — 508 assertions against the real TickTick API
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
[MIT](LICENSE) © 2025 Ivann KAMDEM
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tick-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "MCP server for TickTick — task and notes access via Model Context Protocol."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Ivann KAMDEM", email = "kapoivha@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
license = {text = "MIT"}
|
|
10
|
+
keywords = ["ticktick", "mcp", "model-context-protocol", "tasks", "productivity"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"License :: OSI Approved :: MIT License",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.12",
|
|
16
|
+
"Topic :: Office/Business :: Scheduling",
|
|
17
|
+
]
|
|
18
|
+
requires-python = ">=3.12"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"mcp>=1.26.0",
|
|
21
|
+
"httpx>=0.27.0",
|
|
22
|
+
"pyyaml>=6.0",
|
|
23
|
+
"rich>=13.0",
|
|
24
|
+
"typer>=0.12.0",
|
|
25
|
+
"pydantic>=2.0",
|
|
26
|
+
"python-dotenv>=1.0.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
tick-mcp = "tick_mcp:main"
|
|
31
|
+
tick-admin = "tick_mcp.cli:main"
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/kpihx/tick-mcp"
|
|
35
|
+
Repository = "https://github.com/kpihx/tick-mcp"
|
|
36
|
+
Issues = "https://github.com/kpihx/tick-mcp/issues"
|
|
37
|
+
Changelog = "https://github.com/kpihx/tick-mcp/blob/main/CHANGELOG.md"
|
|
38
|
+
|
|
39
|
+
[dependency-groups]
|
|
40
|
+
dev = [
|
|
41
|
+
"pytest>=8.0",
|
|
42
|
+
"pytest-timeout>=2.2",
|
|
43
|
+
"respx>=0.22", # httpx mock transport (non-intrusive)
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[tool.pytest.ini_options]
|
|
47
|
+
testpaths = ["tests"]
|
|
48
|
+
markers = [
|
|
49
|
+
"unit: pure logic, no I/O, no network, no secrets (fast)",
|
|
50
|
+
"integration: needs bw-env on PATH and real secrets in vault",
|
|
51
|
+
"live: hits the real TickTick API (slow, rate-limited)",
|
|
52
|
+
]
|
|
53
|
+
# Default: run unit + integration. Use `pytest -m live` for live tests.
|
|
54
|
+
addopts = "-v --tb=short -m 'not live'"
|
|
55
|
+
timeout = 30
|
|
56
|
+
|
|
57
|
+
[build-system]
|
|
58
|
+
requires = ["uv_build>=0.10.3,<0.11.0"]
|
|
59
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TICKTICK_SESSION_TOKEN=0CAB80045A64122B0ECB7493DFFD334BFA3469A7C7933C1A7529592831BA123E381794D9023A6741EA70BFB8A3850AD53F9BD3732B61AC70D57703CDB39A419D9A1D95346CE2334EE55972BE9A423E1ED285B290342C2919CA06CD165860442C0FA432A6D7B1B92022F3B04295855CD5711F9CAEDB907858368E60D28CADEC360FA432A6D7B1B92045E034618F9E671A14BAE6DD8FFB527E04CB8D883175EAC591241BF011C106237353686E6CEE8A83
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# TickTick MCP — Environment Variables
|
|
2
|
+
# Copy this file to .env (same directory) and fill in your tokens.
|
|
3
|
+
# .env is gitignored and takes priority over system environment variables.
|
|
4
|
+
#
|
|
5
|
+
# Alternatively, export these variables in your shell profile:
|
|
6
|
+
# echo 'export TICKTICK_API_TOKEN="your_token"' >> ~/.bashrc # or ~/.zshrc
|
|
7
|
+
# source ~/.bashrc
|
|
8
|
+
|
|
9
|
+
# ──────────────────────────────────────────────────────────────────────
|
|
10
|
+
# [REQUIRED] V1 — Official Open API (OAuth2 Bearer token)
|
|
11
|
+
# Docs: https://developer.ticktick.com/docs#/openapi
|
|
12
|
+
# ──────────────────────────────────────────────────────────────────────
|
|
13
|
+
# There are 2 ways to get this token:
|
|
14
|
+
#
|
|
15
|
+
# ── Method A: Personal Access Token (PAT) — simplest, recommended ────
|
|
16
|
+
# Works directly from the TickTick app, no OAuth dance needed.
|
|
17
|
+
# 1. Open TickTick → Settings → Integrations (or About) → API
|
|
18
|
+
# 2. A token is displayed there — copy it directly.
|
|
19
|
+
# Note: full scope, no known expiration, ideal for personal use.
|
|
20
|
+
#
|
|
21
|
+
# ── Method B: OAuth2 Authorization Code Flow ─────────────────────────
|
|
22
|
+
# Use this if you registered an app on developer.ticktick.com
|
|
23
|
+
# and have a client_id + client_secret + redirect_uri.
|
|
24
|
+
# Step 1 — Open in browser (replace values):
|
|
25
|
+
# https://ticktick.com/oauth/authorize
|
|
26
|
+
# ?response_type=code
|
|
27
|
+
# &client_id=<YOUR_CLIENT_ID>
|
|
28
|
+
# &redirect_uri=http://localhost:8080
|
|
29
|
+
# &scope=tasks:read%20tasks:write
|
|
30
|
+
# Step 2 — Exchange the ?code= param for a token:
|
|
31
|
+
# curl -X POST https://ticktick.com/oauth/token \
|
|
32
|
+
# -u "<CLIENT_ID>:<CLIENT_SECRET>" \
|
|
33
|
+
# -d "grant_type=authorization_code" \
|
|
34
|
+
# -d "code=<CODE_FROM_STEP1>" \
|
|
35
|
+
# -d "redirect_uri=http://localhost:8080"
|
|
36
|
+
# Step 3 — Copy access_token from the JSON response.
|
|
37
|
+
# Note: expires periodically; refresh with grant_type=refresh_token.
|
|
38
|
+
TICKTICK_API_TOKEN=
|
|
39
|
+
|
|
40
|
+
# ──────────────────────────────────────────────────────────────────────
|
|
41
|
+
# [OPTIONAL] V2 — Unofficial Web API
|
|
42
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
# Unlocks: tags, habits, focus/pomodoro, folders, columns, batch ops,
|
|
44
|
+
# completed/deleted tasks, user stats, sync, and more.
|
|
45
|
+
#
|
|
46
|
+
# Two auth strategies — pick ONE (token takes priority if both are set):
|
|
47
|
+
#
|
|
48
|
+
# ── Strategy 1: Session token (manual, no expiry concern during session) ──────
|
|
49
|
+
# 1. Log in to https://ticktick.com in your browser
|
|
50
|
+
# 2. Open DevTools → Application → Cookies → ticktick.com
|
|
51
|
+
# 3. Copy the value of the 't' cookie (~30 day validity)
|
|
52
|
+
TICKTICK_SESSION_TOKEN=
|
|
53
|
+
|
|
54
|
+
# ── Strategy 2: Auto-refresh via CLI ─────────────────────────────────────────
|
|
55
|
+
# When your session token expires, run:
|
|
56
|
+
# ticktick-admin session refresh
|
|
57
|
+
# The CLI will prompt for username + password interactively (never stored),
|
|
58
|
+
# call POST /api/v2/user/signon, and write the new token above automatically.
|
|
59
|
+
# Credentials are discarded immediately after the login call.
|