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.
Files changed (38) hide show
  1. tick_mcp-0.1.0/PKG-INFO +237 -0
  2. tick_mcp-0.1.0/README.md +210 -0
  3. tick_mcp-0.1.0/pyproject.toml +59 -0
  4. tick_mcp-0.1.0/src/tick_mcp/.env +1 -0
  5. tick_mcp-0.1.0/src/tick_mcp/.env.example +59 -0
  6. tick_mcp-0.1.0/src/tick_mcp/__init__.py +3 -0
  7. tick_mcp-0.1.0/src/tick_mcp/cli.py +479 -0
  8. tick_mcp-0.1.0/src/tick_mcp/client.py +22 -0
  9. tick_mcp-0.1.0/src/tick_mcp/client_api/__init__.py +3 -0
  10. tick_mcp-0.1.0/src/tick_mcp/client_api/habits.py +72 -0
  11. tick_mcp-0.1.0/src/tick_mcp/client_api/projects.py +163 -0
  12. tick_mcp-0.1.0/src/tick_mcp/client_api/stats.py +54 -0
  13. tick_mcp-0.1.0/src/tick_mcp/client_api/tasks.py +222 -0
  14. tick_mcp-0.1.0/src/tick_mcp/client_api/transport.py +262 -0
  15. tick_mcp-0.1.0/src/tick_mcp/config.py +443 -0
  16. tick_mcp-0.1.0/src/tick_mcp/config.yaml +57 -0
  17. tick_mcp-0.1.0/src/tick_mcp/daemon.py +48 -0
  18. tick_mcp-0.1.0/src/tick_mcp/main.py +60 -0
  19. tick_mcp-0.1.0/src/tick_mcp/mcp_api/__init__.py +10 -0
  20. tick_mcp-0.1.0/src/tick_mcp/mcp_api/core.py +328 -0
  21. tick_mcp-0.1.0/src/tick_mcp/mcp_api/folders.py +118 -0
  22. tick_mcp-0.1.0/src/tick_mcp/mcp_api/habits.py +270 -0
  23. tick_mcp-0.1.0/src/tick_mcp/mcp_api/history.py +68 -0
  24. tick_mcp-0.1.0/src/tick_mcp/mcp_api/projects.py +210 -0
  25. tick_mcp-0.1.0/src/tick_mcp/mcp_api/read.py +849 -0
  26. tick_mcp-0.1.0/src/tick_mcp/mcp_api/stats.py +88 -0
  27. tick_mcp-0.1.0/src/tick_mcp/mcp_api/sync_api.py +69 -0
  28. tick_mcp-0.1.0/src/tick_mcp/mcp_api/tags.py +161 -0
  29. tick_mcp-0.1.0/src/tick_mcp/mcp_api/tasks_batch.py +201 -0
  30. tick_mcp-0.1.0/src/tick_mcp/mcp_api/tasks_read.py +90 -0
  31. tick_mcp-0.1.0/src/tick_mcp/mcp_api/tasks_write.py +242 -0
  32. tick_mcp-0.1.0/src/tick_mcp/mcp_api/utilities.py +206 -0
  33. tick_mcp-0.1.0/src/tick_mcp/mcp_api/verified.py +316 -0
  34. tick_mcp-0.1.0/src/tick_mcp/models.py +579 -0
  35. tick_mcp-0.1.0/src/tick_mcp/server.py +137 -0
  36. tick_mcp-0.1.0/src/tick_mcp/services/__init__.py +6 -0
  37. tick_mcp-0.1.0/src/tick_mcp/services/query.py +754 -0
  38. tick_mcp-0.1.0/src/tick_mcp/services/query_presets.py +81 -0
@@ -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
+ [![PyPI](https://img.shields.io/pypi/v/tick-mcp)](https://pypi.org/project/tick-mcp/)
31
+ [![Python](https://img.shields.io/pypi/pyversions/tick-mcp)](https://pypi.org/project/tick-mcp/)
32
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
@@ -0,0 +1,210 @@
1
+ # tick-mcp
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/tick-mcp)](https://pypi.org/project/tick-mcp/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/tick-mcp)](https://pypi.org/project/tick-mcp/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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.
@@ -0,0 +1,3 @@
1
+ def main() -> None:
2
+ from .main import main as _main
3
+ _main()