@brigid/mcp-todoist 0.0.2
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.
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/package.json +24 -0
- package/src/bin.d.ts +3 -0
- package/src/bin.d.ts.map +1 -0
- package/src/bin.js +22 -0
- package/src/bin.js.map +1 -0
- package/src/index.d.ts +13 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +241 -0
- package/src/index.js.map +1 -0
- package/src/todoist.d.ts +100 -0
- package/src/todoist.d.ts.map +1 -0
- package/src/todoist.js +217 -0
- package/src/todoist.js.map +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 shadowgate15
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @brigid/mcp-todoist
|
|
2
|
+
|
|
3
|
+
A lean [Todoist](https://todoist.com) [Model Context Protocol](https://modelcontextprotocol.io)
|
|
4
|
+
(MCP) server. It is the **reference implementation** of brigid's
|
|
5
|
+
[task-manager capability contract](../../docs/contracts/task-manager.md) — it exposes only the tools
|
|
6
|
+
the brigid GTD skills need, using the contract's canonical tool names so the skills detect and use it
|
|
7
|
+
automatically.
|
|
8
|
+
|
|
9
|
+
## Conformance
|
|
10
|
+
|
|
11
|
+
| Capability group | Status |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **Core** (task create / query / lifecycle) | ✅ implemented |
|
|
14
|
+
| `projects-labels` | ✅ implemented |
|
|
15
|
+
| `filters` | ✅ implemented |
|
|
16
|
+
| `analytics` | ⬜ not yet (skills degrade — e.g. `weekly-review` computes from Core data) |
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
The server authenticates to the Todoist API with a personal API token, read from the environment:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
export TODOIST_API_TOKEN="<your Todoist API token>"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Find your token in Todoist under **Settings → Integrations → Developer**. The server exits with an
|
|
27
|
+
error on stderr if the variable is unset.
|
|
28
|
+
|
|
29
|
+
## Structure
|
|
30
|
+
|
|
31
|
+
- `src/index.ts` — `createServer()`, the reusable/testable server factory (registers tools, no transport).
|
|
32
|
+
- `src/bin.ts` — the executable entry (`bin`), which attaches the stdio transport and runs the server.
|
|
33
|
+
- `src/todoist.ts` — the thin Todoist REST client and the structured-filter → Todoist-filter translation.
|
|
34
|
+
|
|
35
|
+
## Develop
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
nx build mcp-todoist # compile to dist/packages/mcp-todoist
|
|
39
|
+
nx lint mcp-todoist --fix # lint + sync package.json deps from the root (single-version policy)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Run
|
|
43
|
+
|
|
44
|
+
After building, launch the server over stdio:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
TODOIST_API_TOKEN=... node dist/packages/mcp-todoist/src/bin.js
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or, once published, via `npx @brigid/mcp-todoist`.
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brigid/mcp-todoist",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Lean Todoist MCP server — the reference implementation of brigid's task-manager capability contract.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./src/index.js",
|
|
8
|
+
"types": "./src/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"mcp-todoist": "./src/bin.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
21
|
+
"zod": "^4.4.3"
|
|
22
|
+
},
|
|
23
|
+
"module": "./src/index.js"
|
|
24
|
+
}
|
package/src/bin.d.ts
ADDED
package/src/bin.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../../../../packages/mcp-todoist/src/bin.ts"],"names":[],"mappings":""}
|
package/src/bin.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { createServer } from './index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Executable entry point: runs the Todoist MCP server over stdio.
|
|
6
|
+
* Registered as the package `bin`, so it can be launched via `npx @brigid/mcp-todoist`.
|
|
7
|
+
*/
|
|
8
|
+
async function main() {
|
|
9
|
+
if (!process.env['TODOIST_API_TOKEN']) {
|
|
10
|
+
console.error('TODOIST_API_TOKEN is not set. Export a Todoist API token before starting mcp-todoist.');
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const server = createServer();
|
|
14
|
+
const transport = new StdioServerTransport();
|
|
15
|
+
await server.connect(transport);
|
|
16
|
+
}
|
|
17
|
+
main().catch((error) => {
|
|
18
|
+
// stderr only — stdout is reserved for the JSON-RPC protocol stream.
|
|
19
|
+
console.error('Fatal error running mcp-todoist server:', error);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=bin.js.map
|
package/src/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../../../../packages/mcp-todoist/src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;;GAGG;AACH,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CACX,uFAAuF,CACxF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,qEAAqE;IACrE,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Package version, kept in sync with package.json by `nx release`.
|
|
4
|
+
* Bump lives in package.json; this constant is the runtime source.
|
|
5
|
+
*/
|
|
6
|
+
export declare const version = "0.0.1";
|
|
7
|
+
/**
|
|
8
|
+
* Create and configure the Todoist MCP server — the reference implementation of the
|
|
9
|
+
* task-manager capability contract. Registers the Core tools under their canonical names; no
|
|
10
|
+
* transport is attached here, so callers (bin, tests) decide how to run it.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createServer(): McpServer;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/mcp-todoist/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE;;;GAGG;AACH,eAAO,MAAM,OAAO,UAAU,CAAC;AAe/B;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,SAAS,CA0QxC"}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { TodoistClient } from './todoist.js';
|
|
4
|
+
/**
|
|
5
|
+
* Package version, kept in sync with package.json by `nx release`.
|
|
6
|
+
* Bump lives in package.json; this constant is the runtime source.
|
|
7
|
+
*/
|
|
8
|
+
export const version = '0.0.1';
|
|
9
|
+
const priority = z.enum(['p1', 'p2', 'p3', 'p4']);
|
|
10
|
+
/** Serialize a successful tool result as JSON text (skills read the JSON). */
|
|
11
|
+
function ok(value) {
|
|
12
|
+
return { content: [{ type: 'text', text: JSON.stringify(value, null, 2) }] };
|
|
13
|
+
}
|
|
14
|
+
/** Turn a thrown error into a readable, non-fatal tool error for the skill to handle. */
|
|
15
|
+
function fail(error) {
|
|
16
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
17
|
+
return { content: [{ type: 'text', text: message }], isError: true };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create and configure the Todoist MCP server — the reference implementation of the
|
|
21
|
+
* task-manager capability contract. Registers the Core tools under their canonical names; no
|
|
22
|
+
* transport is attached here, so callers (bin, tests) decide how to run it.
|
|
23
|
+
*/
|
|
24
|
+
export function createServer() {
|
|
25
|
+
const server = new McpServer({ name: 'mcp-todoist', version });
|
|
26
|
+
const todoist = new TodoistClient();
|
|
27
|
+
server.registerTool('add-tasks', {
|
|
28
|
+
title: 'Add tasks',
|
|
29
|
+
description: 'Create one or more tasks in a single call.',
|
|
30
|
+
inputSchema: {
|
|
31
|
+
tasks: z
|
|
32
|
+
.array(z.object({
|
|
33
|
+
content: z.string().min(1).describe('The concrete, verb-first next action'),
|
|
34
|
+
description: z.string().optional(),
|
|
35
|
+
priority: priority.optional().describe('p1 (highest) .. p4 (default)'),
|
|
36
|
+
labels: z.array(z.string()).optional().describe('Context labels, e.g. @calls'),
|
|
37
|
+
dueString: z.string().optional().describe('Natural-language movable due date'),
|
|
38
|
+
deadlineDate: z.string().optional().describe('YYYY-MM-DD immovable deadline'),
|
|
39
|
+
project: z.string().optional().describe('Project id or name'),
|
|
40
|
+
}))
|
|
41
|
+
.min(1),
|
|
42
|
+
},
|
|
43
|
+
}, async ({ tasks }) => {
|
|
44
|
+
try {
|
|
45
|
+
const created = [];
|
|
46
|
+
for (const task of tasks)
|
|
47
|
+
created.push(await todoist.createTask(task));
|
|
48
|
+
return ok({ created });
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return fail(error);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
server.registerTool('find-tasks', {
|
|
55
|
+
title: 'Find tasks',
|
|
56
|
+
description: 'Query open tasks with a backend-neutral structured filter.',
|
|
57
|
+
inputSchema: {
|
|
58
|
+
labels: z.array(z.string()).optional().describe('Include tasks with ALL of these labels'),
|
|
59
|
+
excludeLabels: z.array(z.string()).optional().describe('Exclude tasks with ANY of these'),
|
|
60
|
+
project: z.string().optional().describe('Project id or name'),
|
|
61
|
+
date: z.string().optional().describe('YYYY-MM-DD — due/scheduled on this day'),
|
|
62
|
+
dateRange: z
|
|
63
|
+
.object({ from: z.string(), to: z.string() })
|
|
64
|
+
.optional()
|
|
65
|
+
.describe('Inclusive YYYY-MM-DD span'),
|
|
66
|
+
sort: z.literal('priority').optional().describe('p1 first'),
|
|
67
|
+
rawFilter: z
|
|
68
|
+
.string()
|
|
69
|
+
.optional()
|
|
70
|
+
.describe('filters group: backend-native query; overrides the structured fields'),
|
|
71
|
+
},
|
|
72
|
+
}, async (filter) => {
|
|
73
|
+
try {
|
|
74
|
+
return ok({ tasks: await todoist.findTasks(filter) });
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return fail(error);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
server.registerTool('update-tasks', {
|
|
81
|
+
title: 'Update tasks',
|
|
82
|
+
description: "Modify a task's non-schedule fields. Never moves due dates — use reschedule-tasks.",
|
|
83
|
+
inputSchema: {
|
|
84
|
+
id: z.string().describe('Task id'),
|
|
85
|
+
content: z.string().optional(),
|
|
86
|
+
description: z.string().optional(),
|
|
87
|
+
priority: priority.optional(),
|
|
88
|
+
labels: z.array(z.string()).optional(),
|
|
89
|
+
deadlineDate: z.string().optional().describe('YYYY-MM-DD'),
|
|
90
|
+
},
|
|
91
|
+
}, async (patch) => {
|
|
92
|
+
try {
|
|
93
|
+
return ok({ updated: await todoist.updateTask(patch) });
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
return fail(error);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
server.registerTool('complete-tasks', {
|
|
100
|
+
title: 'Complete tasks',
|
|
101
|
+
description: 'Mark tasks done. Recurring tasks advance to their next occurrence.',
|
|
102
|
+
inputSchema: { ids: z.array(z.string()).min(1) },
|
|
103
|
+
}, async ({ ids }) => {
|
|
104
|
+
try {
|
|
105
|
+
for (const id of ids)
|
|
106
|
+
await todoist.completeTask(id);
|
|
107
|
+
return ok({ completed: ids });
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return fail(error);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
server.registerTool('uncomplete-tasks', {
|
|
114
|
+
title: 'Uncomplete tasks',
|
|
115
|
+
description: 'Reopen tasks completed by mistake.',
|
|
116
|
+
inputSchema: { ids: z.array(z.string()).min(1) },
|
|
117
|
+
}, async ({ ids }) => {
|
|
118
|
+
try {
|
|
119
|
+
for (const id of ids)
|
|
120
|
+
await todoist.uncompleteTask(id);
|
|
121
|
+
return ok({ reopened: ids });
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
return fail(error);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
server.registerTool('reschedule-tasks', {
|
|
128
|
+
title: 'Reschedule tasks',
|
|
129
|
+
description: 'Move tasks to a new due date, preserving recurrence and time-of-day. The only tool that changes due dates.',
|
|
130
|
+
inputSchema: {
|
|
131
|
+
ids: z.array(z.string()).min(1),
|
|
132
|
+
date: z.string().describe('YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS'),
|
|
133
|
+
},
|
|
134
|
+
}, async ({ ids, date }) => {
|
|
135
|
+
try {
|
|
136
|
+
const rescheduled = [];
|
|
137
|
+
for (const id of ids)
|
|
138
|
+
rescheduled.push(await todoist.rescheduleTask(id, date));
|
|
139
|
+
return ok({ rescheduled });
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
return fail(error);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
// --- projects-labels group ---
|
|
146
|
+
server.registerTool('find-projects', {
|
|
147
|
+
title: 'Find projects',
|
|
148
|
+
description: 'List the active projects.',
|
|
149
|
+
inputSchema: {},
|
|
150
|
+
}, async () => {
|
|
151
|
+
try {
|
|
152
|
+
return ok({ projects: await todoist.findProjects() });
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
return fail(error);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
server.registerTool('add-projects', {
|
|
159
|
+
title: 'Add projects',
|
|
160
|
+
description: 'Create one or more projects.',
|
|
161
|
+
inputSchema: {
|
|
162
|
+
projects: z
|
|
163
|
+
.array(z.object({
|
|
164
|
+
name: z.string().min(1),
|
|
165
|
+
parent: z.string().optional().describe('Parent project id or name'),
|
|
166
|
+
}))
|
|
167
|
+
.min(1),
|
|
168
|
+
},
|
|
169
|
+
}, async ({ projects }) => {
|
|
170
|
+
try {
|
|
171
|
+
const created = [];
|
|
172
|
+
for (const project of projects)
|
|
173
|
+
created.push(await todoist.createProject(project));
|
|
174
|
+
return ok({ created });
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
return fail(error);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
server.registerTool('find-labels', {
|
|
181
|
+
title: 'Find labels',
|
|
182
|
+
description: 'List the existing context labels.',
|
|
183
|
+
inputSchema: {},
|
|
184
|
+
}, async () => {
|
|
185
|
+
try {
|
|
186
|
+
return ok({ labels: await todoist.findLabels() });
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
return fail(error);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
server.registerTool('add-labels', {
|
|
193
|
+
title: 'Add labels',
|
|
194
|
+
description: "Create one or more context labels. Use only after find-labels shows it's missing.",
|
|
195
|
+
inputSchema: {
|
|
196
|
+
names: z.array(z.string().min(1)).min(1),
|
|
197
|
+
},
|
|
198
|
+
}, async ({ names }) => {
|
|
199
|
+
try {
|
|
200
|
+
const created = [];
|
|
201
|
+
for (const name of names)
|
|
202
|
+
created.push(await todoist.createLabel(name));
|
|
203
|
+
return ok({ created });
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
return fail(error);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
// --- filters group ---
|
|
210
|
+
server.registerTool('find-filters', {
|
|
211
|
+
title: 'Find filters',
|
|
212
|
+
description: 'List the user’s saved filters.',
|
|
213
|
+
inputSchema: {},
|
|
214
|
+
}, async () => {
|
|
215
|
+
try {
|
|
216
|
+
return ok({ filters: await todoist.findFilters() });
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
return fail(error);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
server.registerTool('find-completed-tasks', {
|
|
223
|
+
title: 'Find completed tasks',
|
|
224
|
+
description: 'Query recently completed tasks (distinct from find-tasks, which sees only open tasks).',
|
|
225
|
+
inputSchema: {
|
|
226
|
+
since: z.string().optional().describe('YYYY-MM-DD lower bound'),
|
|
227
|
+
until: z.string().optional().describe('YYYY-MM-DD upper bound'),
|
|
228
|
+
project: z.string().optional().describe('Project id or name'),
|
|
229
|
+
limit: z.number().int().positive().optional(),
|
|
230
|
+
},
|
|
231
|
+
}, async (query) => {
|
|
232
|
+
try {
|
|
233
|
+
return ok({ tasks: await todoist.findCompletedTasks(query) });
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
return fail(error);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
return server;
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/mcp-todoist/src/index.ts"],"names":[],"mappings":"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"}
|
package/src/todoist.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin Todoist REST v2 client and the structured-filter -> Todoist-filter translation.
|
|
3
|
+
*
|
|
4
|
+
* This module is the ONLY place that knows Todoist's wire format and filter DSL; the tools in
|
|
5
|
+
* index.ts speak the neutral capability-contract shapes. See
|
|
6
|
+
* docs/contracts/task-manager.md for the contract this implements.
|
|
7
|
+
*/
|
|
8
|
+
export type Priority = 'p1' | 'p2' | 'p3' | 'p4';
|
|
9
|
+
export interface StructuredFilter {
|
|
10
|
+
labels?: string[];
|
|
11
|
+
excludeLabels?: string[];
|
|
12
|
+
project?: string;
|
|
13
|
+
date?: string;
|
|
14
|
+
dateRange?: {
|
|
15
|
+
from: string;
|
|
16
|
+
to: string;
|
|
17
|
+
};
|
|
18
|
+
sort?: 'priority';
|
|
19
|
+
/** filters group: backend-native query passed through, bypassing the structured fields. */
|
|
20
|
+
rawFilter?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface CompletedQuery {
|
|
23
|
+
since?: string;
|
|
24
|
+
until?: string;
|
|
25
|
+
project?: string;
|
|
26
|
+
limit?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface SavedFilter {
|
|
29
|
+
name: string;
|
|
30
|
+
query: string;
|
|
31
|
+
}
|
|
32
|
+
export interface CompletedTask {
|
|
33
|
+
id: string;
|
|
34
|
+
content: string;
|
|
35
|
+
completedAt: string;
|
|
36
|
+
}
|
|
37
|
+
export interface TaskInput {
|
|
38
|
+
content: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
priority?: Priority;
|
|
41
|
+
labels?: string[];
|
|
42
|
+
dueString?: string;
|
|
43
|
+
deadlineDate?: string;
|
|
44
|
+
project?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface TaskPatch {
|
|
47
|
+
id: string;
|
|
48
|
+
content?: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
priority?: Priority;
|
|
51
|
+
labels?: string[];
|
|
52
|
+
deadlineDate?: string;
|
|
53
|
+
}
|
|
54
|
+
/** The minimum-guaranteed task shape the contract promises to skills. */
|
|
55
|
+
export interface ContractTask {
|
|
56
|
+
id: string;
|
|
57
|
+
content: string;
|
|
58
|
+
priority: Priority;
|
|
59
|
+
due: {
|
|
60
|
+
date: string;
|
|
61
|
+
recurring: boolean;
|
|
62
|
+
datetime?: string;
|
|
63
|
+
} | null;
|
|
64
|
+
labels: string[];
|
|
65
|
+
project: string | null;
|
|
66
|
+
}
|
|
67
|
+
export interface ContractProject {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
}
|
|
71
|
+
export interface ContractLabel {
|
|
72
|
+
name: string;
|
|
73
|
+
}
|
|
74
|
+
export interface ProjectInput {
|
|
75
|
+
name: string;
|
|
76
|
+
parent?: string;
|
|
77
|
+
}
|
|
78
|
+
/** A single request's typed result; `null` for 204 No Content responses. */
|
|
79
|
+
export declare class TodoistClient {
|
|
80
|
+
#private;
|
|
81
|
+
createTask(input: TaskInput): Promise<{
|
|
82
|
+
id: string;
|
|
83
|
+
content: string;
|
|
84
|
+
}>;
|
|
85
|
+
findTasks(filter: StructuredFilter): Promise<ContractTask[]>;
|
|
86
|
+
updateTask(patch: TaskPatch): Promise<ContractTask>;
|
|
87
|
+
completeTask(id: string): Promise<void>;
|
|
88
|
+
uncompleteTask(id: string): Promise<void>;
|
|
89
|
+
/** Move a due date while preserving recurrence: update due_date/due_datetime, never due_string. */
|
|
90
|
+
rescheduleTask(id: string, date: string): Promise<ContractTask>;
|
|
91
|
+
findProjects(): Promise<ContractProject[]>;
|
|
92
|
+
createProject(input: ProjectInput): Promise<ContractProject>;
|
|
93
|
+
findLabels(): Promise<ContractLabel[]>;
|
|
94
|
+
createLabel(name: string): Promise<ContractLabel>;
|
|
95
|
+
/** Saved filters live in the Sync API, not REST. */
|
|
96
|
+
findFilters(): Promise<SavedFilter[]>;
|
|
97
|
+
/** Completed tasks come from the Sync API's completed history. */
|
|
98
|
+
findCompletedTasks(query: CompletedQuery): Promise<CompletedTask[]>;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=todoist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todoist.d.ts","sourceRoot":"","sources":["../../../../packages/mcp-todoist/src/todoist.ts"],"names":[],"mappings":"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"}
|
package/src/todoist.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin Todoist REST v2 client and the structured-filter -> Todoist-filter translation.
|
|
3
|
+
*
|
|
4
|
+
* This module is the ONLY place that knows Todoist's wire format and filter DSL; the tools in
|
|
5
|
+
* index.ts speak the neutral capability-contract shapes. See
|
|
6
|
+
* docs/contracts/task-manager.md for the contract this implements.
|
|
7
|
+
*/
|
|
8
|
+
const API_BASE = 'https://api.todoist.com/rest/v2';
|
|
9
|
+
const SYNC_BASE = 'https://api.todoist.com/sync/v9';
|
|
10
|
+
/** Contract priorities are p1 (highest) .. p4 (default). Todoist's API is 4 (highest) .. 1. */
|
|
11
|
+
const PRIORITY_TO_API = { p1: 4, p2: 3, p3: 2, p4: 1 };
|
|
12
|
+
const API_TO_PRIORITY = { 4: 'p1', 3: 'p2', 2: 'p3', 1: 'p4' };
|
|
13
|
+
/** A leading "@" is display sugar; Todoist stores label names without it. */
|
|
14
|
+
function bareLabel(label) {
|
|
15
|
+
return label.replace(/^@/, '');
|
|
16
|
+
}
|
|
17
|
+
/** Shift a YYYY-MM-DD date by whole days, in UTC, to build inclusive range bounds. */
|
|
18
|
+
function shiftDay(iso, delta) {
|
|
19
|
+
const d = new Date(`${iso}T00:00:00Z`);
|
|
20
|
+
d.setUTCDate(d.getUTCDate() + delta);
|
|
21
|
+
return d.toISOString().slice(0, 10);
|
|
22
|
+
}
|
|
23
|
+
const isNumericId = (value) => /^\d+$/.test(value);
|
|
24
|
+
/**
|
|
25
|
+
* Translate a neutral StructuredFilter into a Todoist filter string plus (when a numeric project
|
|
26
|
+
* id is given) a separate `project_id` query param — ids can't go in the filter DSL.
|
|
27
|
+
*/
|
|
28
|
+
function buildQuery(filter) {
|
|
29
|
+
// Raw escape hatch (filters group) wins over the structured fields.
|
|
30
|
+
if (filter.rawFilter)
|
|
31
|
+
return { filter: filter.rawFilter };
|
|
32
|
+
const parts = [];
|
|
33
|
+
for (const label of filter.labels ?? [])
|
|
34
|
+
parts.push(`@${bareLabel(label)}`);
|
|
35
|
+
for (const label of filter.excludeLabels ?? [])
|
|
36
|
+
parts.push(`!@${bareLabel(label)}`);
|
|
37
|
+
let projectId;
|
|
38
|
+
if (filter.project) {
|
|
39
|
+
if (isNumericId(filter.project))
|
|
40
|
+
projectId = filter.project;
|
|
41
|
+
else
|
|
42
|
+
parts.push(`#${filter.project}`);
|
|
43
|
+
}
|
|
44
|
+
if (filter.date)
|
|
45
|
+
parts.push(`(date: ${filter.date})`);
|
|
46
|
+
else if (filter.dateRange) {
|
|
47
|
+
parts.push(`(due after: ${shiftDay(filter.dateRange.from, -1)} & due before: ${shiftDay(filter.dateRange.to, 1)})`);
|
|
48
|
+
}
|
|
49
|
+
const query = {};
|
|
50
|
+
if (parts.length > 0)
|
|
51
|
+
query.filter = parts.join(' & ');
|
|
52
|
+
if (projectId)
|
|
53
|
+
query.project_id = projectId;
|
|
54
|
+
return query;
|
|
55
|
+
}
|
|
56
|
+
function toContractTask(task) {
|
|
57
|
+
return {
|
|
58
|
+
id: task.id,
|
|
59
|
+
content: task.content,
|
|
60
|
+
priority: API_TO_PRIORITY[task.priority] ?? 'p4',
|
|
61
|
+
due: task.due
|
|
62
|
+
? {
|
|
63
|
+
date: task.due.date,
|
|
64
|
+
recurring: task.due.is_recurring ?? false,
|
|
65
|
+
...(task.due.datetime ? { datetime: task.due.datetime } : {}),
|
|
66
|
+
}
|
|
67
|
+
: null,
|
|
68
|
+
labels: task.labels ?? [],
|
|
69
|
+
project: task.project_id ?? null,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** A single request's typed result; `null` for 204 No Content responses. */
|
|
73
|
+
export class TodoistClient {
|
|
74
|
+
#cachedToken;
|
|
75
|
+
/** Read (and validate) the API token lazily so createServer() needs no token to construct. */
|
|
76
|
+
#token() {
|
|
77
|
+
if (this.#cachedToken)
|
|
78
|
+
return this.#cachedToken;
|
|
79
|
+
const token = process.env['TODOIST_API_TOKEN'];
|
|
80
|
+
if (!token) {
|
|
81
|
+
throw new Error('TODOIST_API_TOKEN is not set. Export a Todoist API token (Settings → Integrations → Developer).');
|
|
82
|
+
}
|
|
83
|
+
this.#cachedToken = token;
|
|
84
|
+
return token;
|
|
85
|
+
}
|
|
86
|
+
async #request(method, path, opts = {}) {
|
|
87
|
+
const url = new URL(`${opts.base ?? API_BASE}${path}`);
|
|
88
|
+
for (const [key, value] of Object.entries(opts.query ?? {}))
|
|
89
|
+
url.searchParams.set(key, value);
|
|
90
|
+
const response = await fetch(url, {
|
|
91
|
+
method,
|
|
92
|
+
headers: {
|
|
93
|
+
Authorization: `Bearer ${this.#token()}`,
|
|
94
|
+
...(opts.body !== undefined ? { 'Content-Type': 'application/json' } : {}),
|
|
95
|
+
},
|
|
96
|
+
...(opts.body !== undefined ? { body: JSON.stringify(opts.body) } : {}),
|
|
97
|
+
});
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
const detail = await response.text();
|
|
100
|
+
throw new Error(`Todoist API ${method} ${path} failed (${response.status}): ${detail}`);
|
|
101
|
+
}
|
|
102
|
+
if (response.status === 204)
|
|
103
|
+
return null;
|
|
104
|
+
return (await response.json());
|
|
105
|
+
}
|
|
106
|
+
/** Resolve a project reference (id or name) to its Todoist id. */
|
|
107
|
+
async #resolveProjectId(project) {
|
|
108
|
+
if (isNumericId(project))
|
|
109
|
+
return project;
|
|
110
|
+
const projects = await this.#request('GET', '/projects');
|
|
111
|
+
const match = projects.find((p) => p.name.toLowerCase() === project.toLowerCase());
|
|
112
|
+
if (!match)
|
|
113
|
+
throw new Error(`No Todoist project named "${project}".`);
|
|
114
|
+
return match.id;
|
|
115
|
+
}
|
|
116
|
+
async createTask(input) {
|
|
117
|
+
const body = { content: input.content };
|
|
118
|
+
if (input.description !== undefined)
|
|
119
|
+
body['description'] = input.description;
|
|
120
|
+
if (input.priority !== undefined)
|
|
121
|
+
body['priority'] = PRIORITY_TO_API[input.priority];
|
|
122
|
+
if (input.labels !== undefined)
|
|
123
|
+
body['labels'] = input.labels.map(bareLabel);
|
|
124
|
+
if (input.dueString !== undefined)
|
|
125
|
+
body['due_string'] = input.dueString;
|
|
126
|
+
if (input.deadlineDate !== undefined)
|
|
127
|
+
body['deadline_date'] = input.deadlineDate;
|
|
128
|
+
if (input.project !== undefined)
|
|
129
|
+
body['project_id'] = await this.#resolveProjectId(input.project);
|
|
130
|
+
const task = await this.#request('POST', '/tasks', { body });
|
|
131
|
+
return { id: task.id, content: task.content };
|
|
132
|
+
}
|
|
133
|
+
async findTasks(filter) {
|
|
134
|
+
const query = buildQuery(filter);
|
|
135
|
+
const tasks = await this.#request('GET', '/tasks', {
|
|
136
|
+
query: query,
|
|
137
|
+
});
|
|
138
|
+
const mapped = tasks.map(toContractTask);
|
|
139
|
+
if (filter.sort === 'priority') {
|
|
140
|
+
// p1 first == highest Todoist priority number first.
|
|
141
|
+
mapped.sort((a, b) => PRIORITY_TO_API[b.priority] - PRIORITY_TO_API[a.priority]);
|
|
142
|
+
}
|
|
143
|
+
return mapped;
|
|
144
|
+
}
|
|
145
|
+
async updateTask(patch) {
|
|
146
|
+
const body = {};
|
|
147
|
+
if (patch.content !== undefined)
|
|
148
|
+
body['content'] = patch.content;
|
|
149
|
+
if (patch.description !== undefined)
|
|
150
|
+
body['description'] = patch.description;
|
|
151
|
+
if (patch.priority !== undefined)
|
|
152
|
+
body['priority'] = PRIORITY_TO_API[patch.priority];
|
|
153
|
+
if (patch.labels !== undefined)
|
|
154
|
+
body['labels'] = patch.labels.map(bareLabel);
|
|
155
|
+
if (patch.deadlineDate !== undefined)
|
|
156
|
+
body['deadline_date'] = patch.deadlineDate;
|
|
157
|
+
const task = await this.#request('POST', `/tasks/${patch.id}`, { body });
|
|
158
|
+
return toContractTask(task);
|
|
159
|
+
}
|
|
160
|
+
async completeTask(id) {
|
|
161
|
+
await this.#request('POST', `/tasks/${id}/close`);
|
|
162
|
+
}
|
|
163
|
+
async uncompleteTask(id) {
|
|
164
|
+
await this.#request('POST', `/tasks/${id}/reopen`);
|
|
165
|
+
}
|
|
166
|
+
/** Move a due date while preserving recurrence: update due_date/due_datetime, never due_string. */
|
|
167
|
+
async rescheduleTask(id, date) {
|
|
168
|
+
const body = date.includes('T') ? { due_datetime: date } : { due_date: date };
|
|
169
|
+
const task = await this.#request('POST', `/tasks/${id}`, { body });
|
|
170
|
+
return toContractTask(task);
|
|
171
|
+
}
|
|
172
|
+
async findProjects() {
|
|
173
|
+
const projects = await this.#request('GET', '/projects');
|
|
174
|
+
return projects.map((p) => ({ id: p.id, name: p.name }));
|
|
175
|
+
}
|
|
176
|
+
async createProject(input) {
|
|
177
|
+
const body = { name: input.name };
|
|
178
|
+
if (input.parent !== undefined)
|
|
179
|
+
body['parent_id'] = await this.#resolveProjectId(input.parent);
|
|
180
|
+
const project = await this.#request('POST', '/projects', { body });
|
|
181
|
+
return { id: project.id, name: project.name };
|
|
182
|
+
}
|
|
183
|
+
async findLabels() {
|
|
184
|
+
const labels = await this.#request('GET', '/labels');
|
|
185
|
+
return labels.map((l) => ({ name: l.name }));
|
|
186
|
+
}
|
|
187
|
+
async createLabel(name) {
|
|
188
|
+
const label = await this.#request('POST', '/labels', {
|
|
189
|
+
body: { name: bareLabel(name) },
|
|
190
|
+
});
|
|
191
|
+
return { name: label.name };
|
|
192
|
+
}
|
|
193
|
+
/** Saved filters live in the Sync API, not REST. */
|
|
194
|
+
async findFilters() {
|
|
195
|
+
const data = await this.#request('GET', '/sync', { base: SYNC_BASE, query: { sync_token: '*', resource_types: '["filters"]' } });
|
|
196
|
+
return (data.filters ?? []).map((f) => ({ name: f.name, query: f.query }));
|
|
197
|
+
}
|
|
198
|
+
/** Completed tasks come from the Sync API's completed history. */
|
|
199
|
+
async findCompletedTasks(query) {
|
|
200
|
+
const params = {};
|
|
201
|
+
if (query.since)
|
|
202
|
+
params['since'] = `${query.since}T00:00:00`;
|
|
203
|
+
if (query.until)
|
|
204
|
+
params['until'] = `${query.until}T23:59:59`;
|
|
205
|
+
if (query.limit !== undefined)
|
|
206
|
+
params['limit'] = String(query.limit);
|
|
207
|
+
if (query.project)
|
|
208
|
+
params['project_id'] = await this.#resolveProjectId(query.project);
|
|
209
|
+
const data = await this.#request('GET', '/completed/get_all', { base: SYNC_BASE, query: params });
|
|
210
|
+
return (data.items ?? []).map((item) => ({
|
|
211
|
+
id: item.task_id ?? item.id ?? '',
|
|
212
|
+
content: item.content,
|
|
213
|
+
completedAt: item.completed_at,
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=todoist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todoist.js","sourceRoot":"","sources":["../../../../packages/mcp-todoist/src/todoist.ts"],"names":[],"mappings":"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"}
|