@doist/todoist-ai 4.5.1 → 4.6.1

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/dist/index.d.ts CHANGED
@@ -30,6 +30,7 @@ declare const tools: {
30
30
  priority: import("zod").ZodOptional<import("zod").ZodEnum<["p1", "p2", "p3", "p4"]>>;
31
31
  dueString: import("zod").ZodOptional<import("zod").ZodString>;
32
32
  duration: import("zod").ZodOptional<import("zod").ZodString>;
33
+ labels: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
33
34
  projectId: import("zod").ZodOptional<import("zod").ZodString>;
34
35
  sectionId: import("zod").ZodOptional<import("zod").ZodString>;
35
36
  parentId: import("zod").ZodOptional<import("zod").ZodString>;
@@ -40,6 +41,7 @@ declare const tools: {
40
41
  projectId?: string | undefined;
41
42
  parentId?: string | undefined;
42
43
  sectionId?: string | undefined;
44
+ labels?: string[] | undefined;
43
45
  duration?: string | undefined;
44
46
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
45
47
  dueString?: string | undefined;
@@ -50,6 +52,7 @@ declare const tools: {
50
52
  projectId?: string | undefined;
51
53
  parentId?: string | undefined;
52
54
  sectionId?: string | undefined;
55
+ labels?: string[] | undefined;
53
56
  duration?: string | undefined;
54
57
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
55
58
  dueString?: string | undefined;
@@ -63,6 +66,7 @@ declare const tools: {
63
66
  projectId?: string | undefined;
64
67
  parentId?: string | undefined;
65
68
  sectionId?: string | undefined;
69
+ labels?: string[] | undefined;
66
70
  duration?: string | undefined;
67
71
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
68
72
  dueString?: string | undefined;
@@ -157,6 +161,7 @@ declare const tools: {
157
161
  dueString: import("zod").ZodOptional<import("zod").ZodString>;
158
162
  duration: import("zod").ZodOptional<import("zod").ZodString>;
159
163
  responsibleUser: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
164
+ labels: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
160
165
  }, "strip", import("zod").ZodTypeAny, {
161
166
  id: string;
162
167
  content?: string | undefined;
@@ -164,6 +169,7 @@ declare const tools: {
164
169
  projectId?: string | undefined;
165
170
  parentId?: string | undefined;
166
171
  sectionId?: string | undefined;
172
+ labels?: string[] | undefined;
167
173
  duration?: string | undefined;
168
174
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
169
175
  dueString?: string | undefined;
@@ -176,6 +182,7 @@ declare const tools: {
176
182
  projectId?: string | undefined;
177
183
  parentId?: string | undefined;
178
184
  sectionId?: string | undefined;
185
+ labels?: string[] | undefined;
179
186
  duration?: string | undefined;
180
187
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
181
188
  dueString?: string | undefined;
@@ -191,6 +198,7 @@ declare const tools: {
191
198
  projectId?: string | undefined;
192
199
  parentId?: string | undefined;
193
200
  sectionId?: string | undefined;
201
+ labels?: string[] | undefined;
194
202
  duration?: string | undefined;
195
203
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
196
204
  dueString?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -221,6 +221,136 @@ describe(`${ADD_TASKS} tool`, () => {
221
221
  }));
222
222
  }
223
223
  });
224
+ it('should add task with labels', async () => {
225
+ const mockApiResponse = createMockTask({
226
+ id: '8485093755',
227
+ content: 'Task with labels',
228
+ labels: ['urgent', 'work'],
229
+ url: 'https://todoist.com/showTask?id=8485093755',
230
+ addedAt: '2025-08-13T22:09:56.123456Z',
231
+ });
232
+ mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
233
+ const result = await addTasks.execute({
234
+ tasks: [
235
+ {
236
+ content: 'Task with labels',
237
+ labels: ['urgent', 'work'],
238
+ projectId: '6cfCcrrCFg2xP94Q',
239
+ },
240
+ ],
241
+ }, mockTodoistApi);
242
+ expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
243
+ content: 'Task with labels',
244
+ labels: ['urgent', 'work'],
245
+ projectId: '6cfCcrrCFg2xP94Q',
246
+ sectionId: undefined,
247
+ parentId: undefined,
248
+ });
249
+ // Verify structured content includes labels
250
+ const structuredContent = extractStructuredContent(result);
251
+ expect(structuredContent.tasks).toHaveLength(1);
252
+ expect(structuredContent.tasks[0]).toEqual(expect.objectContaining({
253
+ labels: ['urgent', 'work'],
254
+ }));
255
+ });
256
+ it('should add task with empty labels array', async () => {
257
+ const mockApiResponse = createMockTask({
258
+ id: '8485093756',
259
+ content: 'Task with empty labels',
260
+ labels: [],
261
+ url: 'https://todoist.com/showTask?id=8485093756',
262
+ addedAt: '2025-08-13T22:09:56.123456Z',
263
+ });
264
+ mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
265
+ await addTasks.execute({
266
+ tasks: [
267
+ {
268
+ content: 'Task with empty labels',
269
+ labels: [],
270
+ projectId: '6cfCcrrCFg2xP94Q',
271
+ },
272
+ ],
273
+ }, mockTodoistApi);
274
+ expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
275
+ content: 'Task with empty labels',
276
+ labels: [],
277
+ projectId: '6cfCcrrCFg2xP94Q',
278
+ sectionId: undefined,
279
+ parentId: undefined,
280
+ });
281
+ });
282
+ it('should add task without labels field', async () => {
283
+ const mockApiResponse = createMockTask({
284
+ id: '8485093757',
285
+ content: 'Task without labels',
286
+ url: 'https://todoist.com/showTask?id=8485093757',
287
+ addedAt: '2025-08-13T22:09:56.123456Z',
288
+ });
289
+ mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
290
+ await addTasks.execute({
291
+ tasks: [
292
+ {
293
+ content: 'Task without labels',
294
+ projectId: '6cfCcrrCFg2xP94Q',
295
+ },
296
+ ],
297
+ }, mockTodoistApi);
298
+ expect(mockTodoistApi.addTask).toHaveBeenCalledWith({
299
+ content: 'Task without labels',
300
+ labels: undefined,
301
+ projectId: '6cfCcrrCFg2xP94Q',
302
+ sectionId: undefined,
303
+ parentId: undefined,
304
+ });
305
+ });
306
+ it('should add multiple tasks with different label configurations', async () => {
307
+ const mockApiResponse1 = createMockTask({
308
+ id: '8485093758',
309
+ content: 'Task with labels',
310
+ labels: ['personal'],
311
+ });
312
+ const mockApiResponse2 = createMockTask({
313
+ id: '8485093759',
314
+ content: 'Task without labels',
315
+ });
316
+ const mockApiResponse3 = createMockTask({
317
+ id: '8485093760',
318
+ content: 'Task with multiple labels',
319
+ labels: ['work', 'urgent', 'review'],
320
+ });
321
+ mockTodoistApi.addTask
322
+ .mockResolvedValueOnce(mockApiResponse1)
323
+ .mockResolvedValueOnce(mockApiResponse2)
324
+ .mockResolvedValueOnce(mockApiResponse3);
325
+ await addTasks.execute({
326
+ tasks: [
327
+ {
328
+ content: 'Task with labels',
329
+ labels: ['personal'],
330
+ projectId: '6cfCcrrCFg2xP94Q',
331
+ },
332
+ {
333
+ content: 'Task without labels',
334
+ projectId: '6cfCcrrCFg2xP94Q',
335
+ },
336
+ {
337
+ content: 'Task with multiple labels',
338
+ labels: ['work', 'urgent', 'review'],
339
+ projectId: '6cfCcrrCFg2xP94Q',
340
+ },
341
+ ],
342
+ }, mockTodoistApi);
343
+ expect(mockTodoistApi.addTask).toHaveBeenCalledTimes(3);
344
+ expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(1, expect.objectContaining({
345
+ labels: ['personal'],
346
+ }));
347
+ expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(2, expect.objectContaining({
348
+ labels: undefined,
349
+ }));
350
+ expect(mockTodoistApi.addTask).toHaveBeenNthCalledWith(3, expect.objectContaining({
351
+ labels: ['work', 'urgent', 'review'],
352
+ }));
353
+ });
224
354
  });
225
355
  describe('error handling', () => {
226
356
  it('should throw error for invalid duration format', async () => {
@@ -339,6 +339,82 @@ describe(`${UPDATE_TASKS} tool`, () => {
339
339
  expect(structuredContent.tasks).toHaveLength(1);
340
340
  });
341
341
  });
342
+ describe('updating labels', () => {
343
+ it('should update task labels', async () => {
344
+ const mockApiResponse = createMockTask({
345
+ id: '8485093750',
346
+ content: 'Task with updated labels',
347
+ labels: ['work', 'important'],
348
+ url: 'https://todoist.com/showTask?id=8485093750',
349
+ addedAt: '2025-08-13T22:09:56.123456Z',
350
+ });
351
+ mockTodoistApi.updateTask.mockResolvedValue(mockApiResponse);
352
+ const result = await updateTasks.execute({
353
+ tasks: [
354
+ {
355
+ id: '8485093750',
356
+ labels: ['work', 'important'],
357
+ },
358
+ ],
359
+ }, mockTodoistApi);
360
+ expect(mockTodoistApi.updateTask).toHaveBeenCalledWith('8485093750', {
361
+ labels: ['work', 'important'],
362
+ });
363
+ // Verify structured content includes updated labels
364
+ const structuredContent = extractStructuredContent(result);
365
+ expect(structuredContent.tasks).toHaveLength(1);
366
+ expect(structuredContent.tasks[0]).toEqual(expect.objectContaining({
367
+ labels: ['work', 'important'],
368
+ }));
369
+ });
370
+ it('should clear task labels with empty array', async () => {
371
+ const mockApiResponse = createMockTask({
372
+ id: '8485093751',
373
+ content: 'Task with cleared labels',
374
+ labels: [],
375
+ url: 'https://todoist.com/showTask?id=8485093751',
376
+ addedAt: '2025-08-13T22:09:56.123456Z',
377
+ });
378
+ mockTodoistApi.updateTask.mockResolvedValue(mockApiResponse);
379
+ await updateTasks.execute({
380
+ tasks: [
381
+ {
382
+ id: '8485093751',
383
+ labels: [],
384
+ },
385
+ ],
386
+ }, mockTodoistApi);
387
+ expect(mockTodoistApi.updateTask).toHaveBeenCalledWith('8485093751', {
388
+ labels: [],
389
+ });
390
+ });
391
+ it('should update task with labels along with other fields', async () => {
392
+ const mockApiResponse = createMockTask({
393
+ id: '8485093752',
394
+ content: 'Updated content',
395
+ labels: ['personal', 'todo'],
396
+ priority: 3,
397
+ url: 'https://todoist.com/showTask?id=8485093752',
398
+ addedAt: '2025-08-13T22:09:56.123456Z',
399
+ });
400
+ mockTodoistApi.updateTask.mockResolvedValue(mockApiResponse);
401
+ await updateTasks.execute({
402
+ tasks: [
403
+ {
404
+ id: '8485093752',
405
+ content: 'Updated content',
406
+ labels: ['personal', 'todo'],
407
+ priority: 'p2',
408
+ },
409
+ ],
410
+ }, mockTodoistApi);
411
+ expect(mockTodoistApi.updateTask).toHaveBeenCalledWith('8485093752', {
412
+ content: 'Updated content',
413
+ labels: ['personal', 'todo'],
414
+ priority: 3,
415
+ });
416
+ });
417
+ });
342
418
  describe('error handling', () => {
343
419
  it('should throw error for invalid duration format', async () => {
344
420
  await expect(updateTasks.execute({
@@ -10,6 +10,7 @@ declare const addTasks: {
10
10
  priority: z.ZodOptional<z.ZodEnum<["p1", "p2", "p3", "p4"]>>;
11
11
  dueString: z.ZodOptional<z.ZodString>;
12
12
  duration: z.ZodOptional<z.ZodString>;
13
+ labels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
13
14
  projectId: z.ZodOptional<z.ZodString>;
14
15
  sectionId: z.ZodOptional<z.ZodString>;
15
16
  parentId: z.ZodOptional<z.ZodString>;
@@ -20,6 +21,7 @@ declare const addTasks: {
20
21
  projectId?: string | undefined;
21
22
  parentId?: string | undefined;
22
23
  sectionId?: string | undefined;
24
+ labels?: string[] | undefined;
23
25
  duration?: string | undefined;
24
26
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
25
27
  dueString?: string | undefined;
@@ -30,6 +32,7 @@ declare const addTasks: {
30
32
  projectId?: string | undefined;
31
33
  parentId?: string | undefined;
32
34
  sectionId?: string | undefined;
35
+ labels?: string[] | undefined;
33
36
  duration?: string | undefined;
34
37
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
35
38
  dueString?: string | undefined;
@@ -43,6 +46,7 @@ declare const addTasks: {
43
46
  projectId?: string | undefined;
44
47
  parentId?: string | undefined;
45
48
  sectionId?: string | undefined;
49
+ labels?: string[] | undefined;
46
50
  duration?: string | undefined;
47
51
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
48
52
  dueString?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"add-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/add-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAClF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA0CvB,QAAA,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuB4B,CAAA;AA+H1C,OAAO,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"add-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/add-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAClF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2CvB,QAAA,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuB4B,CAAA;AAgI1C,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -15,6 +15,7 @@ const TaskSchema = z.object({
15
15
  .string()
16
16
  .optional()
17
17
  .describe('The duration of the task. Use format: "2h" (hours), "90m" (minutes), "2h30m" (combined), or "1.5h" (decimal hours). Max 24h.'),
18
+ labels: z.array(z.string()).optional().describe('The labels to attach to the task.'),
18
19
  projectId: z.string().optional().describe('The project ID to add this task to.'),
19
20
  sectionId: z.string().optional().describe('The section ID to add this task to.'),
20
21
  parentId: z.string().optional().describe('The parent task ID (for subtasks).'),
@@ -48,8 +49,8 @@ const addTasks = {
48
49
  },
49
50
  };
50
51
  async function processTask(task, client) {
51
- const { duration: durationStr, projectId, sectionId, parentId, responsibleUser, priority, ...otherTaskArgs } = task;
52
- let taskArgs = { ...otherTaskArgs, projectId, sectionId, parentId };
52
+ const { duration: durationStr, projectId, sectionId, parentId, responsibleUser, priority, labels, ...otherTaskArgs } = task;
53
+ let taskArgs = { ...otherTaskArgs, projectId, sectionId, parentId, labels };
53
54
  // Handle priority conversion if provided
54
55
  if (priority) {
55
56
  taskArgs.priority = convertPriorityToNumber(priority);
@@ -15,6 +15,7 @@ declare const updateTasks: {
15
15
  dueString: z.ZodOptional<z.ZodString>;
16
16
  duration: z.ZodOptional<z.ZodString>;
17
17
  responsibleUser: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
+ labels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
18
19
  }, "strip", z.ZodTypeAny, {
19
20
  id: string;
20
21
  content?: string | undefined;
@@ -22,6 +23,7 @@ declare const updateTasks: {
22
23
  projectId?: string | undefined;
23
24
  parentId?: string | undefined;
24
25
  sectionId?: string | undefined;
26
+ labels?: string[] | undefined;
25
27
  duration?: string | undefined;
26
28
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
27
29
  dueString?: string | undefined;
@@ -34,6 +36,7 @@ declare const updateTasks: {
34
36
  projectId?: string | undefined;
35
37
  parentId?: string | undefined;
36
38
  sectionId?: string | undefined;
39
+ labels?: string[] | undefined;
37
40
  duration?: string | undefined;
38
41
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
39
42
  dueString?: string | undefined;
@@ -49,6 +52,7 @@ declare const updateTasks: {
49
52
  projectId?: string | undefined;
50
53
  parentId?: string | undefined;
51
54
  sectionId?: string | undefined;
55
+ labels?: string[] | undefined;
52
56
  duration?: string | undefined;
53
57
  priority?: "p1" | "p2" | "p3" | "p4" | undefined;
54
58
  dueString?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"update-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/update-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAgDvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8GyB,CAAA;AAqC1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"update-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/update-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAoDvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHyB,CAAA;AAqC1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -29,6 +29,10 @@ const TasksUpdateSchema = z.object({
29
29
  .nullable()
30
30
  .optional()
31
31
  .describe('Change task assignment. Use null to unassign. Can be user ID, name, or email. User must be a project collaborator.'),
32
+ labels: z
33
+ .array(z.string())
34
+ .optional()
35
+ .describe('The new labels for the task. Replaces all existing labels.'),
32
36
  });
33
37
  const ArgsSchema = {
34
38
  tasks: z.array(TasksUpdateSchema).min(1).describe('The tasks to update.'),
@@ -43,8 +47,11 @@ const updateTasks = {
43
47
  if (!hasUpdatesToMake(task)) {
44
48
  return undefined;
45
49
  }
46
- const { id, projectId, sectionId, parentId, duration: durationStr, responsibleUser, priority, ...otherUpdateArgs } = task;
47
- let updateArgs = { ...otherUpdateArgs };
50
+ const { id, projectId, sectionId, parentId, duration: durationStr, responsibleUser, priority, labels, ...otherUpdateArgs } = task;
51
+ let updateArgs = {
52
+ ...otherUpdateArgs,
53
+ ...(labels !== undefined && { labels }),
54
+ };
48
55
  // Handle priority conversion if provided
49
56
  if (priority) {
50
57
  updateArgs.priority = convertPriorityToNumber(priority);
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@doist/todoist-ai",
3
- "version": "4.5.1",
3
+ "version": "4.6.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
+ "mcpName": "net.todoist/mcp",
7
8
  "bin": {
8
9
  "todoist-ai": "dist/main.js"
9
10
  },
@@ -44,7 +45,7 @@
44
45
  "prepare": "husky"
45
46
  },
46
47
  "dependencies": {
47
- "@doist/todoist-api-typescript": "5.4.0",
48
+ "@doist/todoist-api-typescript": "5.5.1",
48
49
  "@modelcontextprotocol/sdk": "^1.11.1",
49
50
  "date-fns": "^4.1.0",
50
51
  "dotenv": "^16.5.0",
@@ -64,7 +65,7 @@
64
65
  "morgan": "^1.10.0",
65
66
  "nodemon": "^3.1.10",
66
67
  "rimraf": "^6.0.1",
67
- "ts-jest": "29.4.2",
68
+ "ts-jest": "29.4.4",
68
69
  "typescript": "^5.8.3"
69
70
  },
70
71
  "lint-staged": {