@doist/todoist-ai 0.1.0

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 (119) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +93 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +1 -0
  6. package/dist/main.d.ts +2 -0
  7. package/dist/main.d.ts.map +1 -0
  8. package/dist/main.js +23 -0
  9. package/dist/mcp-helpers.d.ts +13 -0
  10. package/dist/mcp-helpers.d.ts.map +1 -0
  11. package/dist/mcp-helpers.js +52 -0
  12. package/dist/mcp-server.d.ts +11 -0
  13. package/dist/mcp-server.d.ts.map +1 -0
  14. package/dist/mcp-server.js +66 -0
  15. package/dist/todoist-tool.d.ts +35 -0
  16. package/dist/todoist-tool.d.ts.map +1 -0
  17. package/dist/todoist-tool.js +1 -0
  18. package/dist/tools/account-overview.d.ts +9 -0
  19. package/dist/tools/account-overview.d.ts.map +1 -0
  20. package/dist/tools/account-overview.js +94 -0
  21. package/dist/tools/index.d.ts +23 -0
  22. package/dist/tools/index.d.ts.map +1 -0
  23. package/dist/tools/index.js +22 -0
  24. package/dist/tools/project-overview.d.ts +14 -0
  25. package/dist/tools/project-overview.d.ts.map +1 -0
  26. package/dist/tools/project-overview.js +107 -0
  27. package/dist/tools/projects-add-one.d.ts +22 -0
  28. package/dist/tools/projects-add-one.d.ts.map +1 -0
  29. package/dist/tools/projects-add-one.js +15 -0
  30. package/dist/tools/projects-delete-one.d.ts +15 -0
  31. package/dist/tools/projects-delete-one.d.ts.map +1 -0
  32. package/dist/tools/projects-delete-one.js +14 -0
  33. package/dist/tools/projects-list.d.ts +18 -0
  34. package/dist/tools/projects-list.d.ts.map +1 -0
  35. package/dist/tools/projects-list.js +30 -0
  36. package/dist/tools/projects-search.d.ts +29 -0
  37. package/dist/tools/projects-search.d.ts.map +1 -0
  38. package/dist/tools/projects-search.js +39 -0
  39. package/dist/tools/projects-update-one.d.ts +15 -0
  40. package/dist/tools/projects-update-one.d.ts.map +1 -0
  41. package/dist/tools/projects-update-one.js +16 -0
  42. package/dist/tools/sections-add-one.d.ts +15 -0
  43. package/dist/tools/sections-add-one.d.ts.map +1 -0
  44. package/dist/tools/sections-add-one.js +21 -0
  45. package/dist/tools/sections-delete-one.d.ts +15 -0
  46. package/dist/tools/sections-delete-one.d.ts.map +1 -0
  47. package/dist/tools/sections-delete-one.js +14 -0
  48. package/dist/tools/sections-search.d.ts +18 -0
  49. package/dist/tools/sections-search.d.ts.map +1 -0
  50. package/dist/tools/sections-search.js +30 -0
  51. package/dist/tools/sections-update-one.d.ts +15 -0
  52. package/dist/tools/sections-update-one.d.ts.map +1 -0
  53. package/dist/tools/sections-update-one.js +16 -0
  54. package/dist/tools/shared.d.ts +55 -0
  55. package/dist/tools/shared.d.ts.map +1 -0
  56. package/dist/tools/shared.js +71 -0
  57. package/dist/tools/subtasks-list-for-parent-task.d.ts +31 -0
  58. package/dist/tools/subtasks-list-for-parent-task.d.ts.map +1 -0
  59. package/dist/tools/subtasks-list-for-parent-task.js +37 -0
  60. package/dist/tools/tasks-add-multiple.d.ts +50 -0
  61. package/dist/tools/tasks-add-multiple.d.ts.map +1 -0
  62. package/dist/tools/tasks-add-multiple.js +47 -0
  63. package/dist/tools/tasks-by-date-range.d.ts +33 -0
  64. package/dist/tools/tasks-by-date-range.d.ts.map +1 -0
  65. package/dist/tools/tasks-by-date-range.js +47 -0
  66. package/dist/tools/tasks-by-project.d.ts +31 -0
  67. package/dist/tools/tasks-by-project.d.ts.map +1 -0
  68. package/dist/tools/tasks-by-project.js +37 -0
  69. package/dist/tools/tasks-complete-multiple.d.ts +16 -0
  70. package/dist/tools/tasks-complete-multiple.d.ts.map +1 -0
  71. package/dist/tools/tasks-complete-multiple.js +26 -0
  72. package/dist/tools/tasks-delete-one.d.ts +15 -0
  73. package/dist/tools/tasks-delete-one.d.ts.map +1 -0
  74. package/dist/tools/tasks-delete-one.js +14 -0
  75. package/dist/tools/tasks-list-for-section.d.ts +31 -0
  76. package/dist/tools/tasks-list-for-section.d.ts.map +1 -0
  77. package/dist/tools/tasks-list-for-section.js +37 -0
  78. package/dist/tools/tasks-list-overdue.d.ts +29 -0
  79. package/dist/tools/tasks-list-overdue.d.ts.map +1 -0
  80. package/dist/tools/tasks-list-overdue.js +29 -0
  81. package/dist/tools/tasks-organize-multiple.d.ts +37 -0
  82. package/dist/tools/tasks-organize-multiple.d.ts.map +1 -0
  83. package/dist/tools/tasks-organize-multiple.js +40 -0
  84. package/dist/tools/tasks-search.d.ts +31 -0
  85. package/dist/tools/tasks-search.d.ts.map +1 -0
  86. package/dist/tools/tasks-search.js +30 -0
  87. package/dist/tools/tasks-update-one.d.ts +27 -0
  88. package/dist/tools/tasks-update-one.d.ts.map +1 -0
  89. package/dist/tools/tasks-update-one.js +42 -0
  90. package/package.json +60 -0
  91. package/src/index.ts +1 -0
  92. package/src/main.ts +26 -0
  93. package/src/mcp-helpers.ts +76 -0
  94. package/src/mcp-server.ts +79 -0
  95. package/src/todoist-tool.ts +42 -0
  96. package/src/tools/account-overview.ts +130 -0
  97. package/src/tools/index.ts +26 -0
  98. package/src/tools/project-overview.ts +130 -0
  99. package/src/tools/projects-add-one.ts +19 -0
  100. package/src/tools/projects-delete-one.ts +18 -0
  101. package/src/tools/projects-list.ts +36 -0
  102. package/src/tools/projects-search.ts +49 -0
  103. package/src/tools/projects-update-one.ts +20 -0
  104. package/src/tools/sections-add-one.ts +25 -0
  105. package/src/tools/sections-delete-one.ts +18 -0
  106. package/src/tools/sections-search.ts +39 -0
  107. package/src/tools/sections-update-one.ts +20 -0
  108. package/src/tools/shared.ts +94 -0
  109. package/src/tools/subtasks-list-for-parent-task.ts +43 -0
  110. package/src/tools/tasks-add-multiple.ts +53 -0
  111. package/src/tools/tasks-by-date-range.ts +58 -0
  112. package/src/tools/tasks-by-project.ts +43 -0
  113. package/src/tools/tasks-complete-multiple.ts +29 -0
  114. package/src/tools/tasks-delete-one.ts +18 -0
  115. package/src/tools/tasks-list-for-section.ts +43 -0
  116. package/src/tools/tasks-list-overdue.ts +35 -0
  117. package/src/tools/tasks-organize-multiple.ts +45 -0
  118. package/src/tools/tasks-search.ts +36 -0
  119. package/src/tools/tasks-update-one.ts +48 -0
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const ArgsSchema = {
5
+ limit: z
6
+ .number()
7
+ .int()
8
+ .min(1)
9
+ .max(100)
10
+ .default(50)
11
+ .describe("The maximum number of projects to return."),
12
+ cursor: z
13
+ .string()
14
+ .optional()
15
+ .describe(
16
+ "The cursor to get the next page of projects (cursor is obtained from the previous call to this tool, with the same parameters).",
17
+ ),
18
+ };
19
+
20
+ const projectsList = {
21
+ name: "projects-list",
22
+ description: "List all projects for the user.",
23
+ parameters: ArgsSchema,
24
+ async execute(args, client) {
25
+ const { results, nextCursor } = await client.getProjects({
26
+ limit: args.limit,
27
+ cursor: args.cursor ?? null,
28
+ });
29
+ return {
30
+ projects: results,
31
+ nextCursor,
32
+ };
33
+ },
34
+ } satisfies TodoistTool<typeof ArgsSchema>;
35
+
36
+ export { projectsList };
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+ import { mapProject } from "./shared.js";
4
+
5
+ const ArgsSchema = {
6
+ search: z
7
+ .string()
8
+ .optional()
9
+ .describe(
10
+ "Search for a project by name (partial and case insensitive match). If omitted, all projects are returned.",
11
+ ),
12
+ limit: z
13
+ .number()
14
+ .int()
15
+ .min(1)
16
+ .max(100)
17
+ .default(50)
18
+ .describe("The maximum number of projects to return."),
19
+ cursor: z
20
+ .string()
21
+ .optional()
22
+ .describe(
23
+ "The cursor to get the next page of projects (cursor is obtained from the previous call to this tool, with the same parameters).",
24
+ ),
25
+ };
26
+
27
+ const projectsSearch = {
28
+ name: "projects-search",
29
+ description: "Search for projects by name or other criteria.",
30
+ parameters: ArgsSchema,
31
+ async execute(args, client) {
32
+ const { results, nextCursor } = await client.getProjects({
33
+ limit: args.limit,
34
+ cursor: args.cursor ?? null,
35
+ });
36
+ const searchLower = args.search ? args.search.toLowerCase() : undefined;
37
+ const filtered = searchLower
38
+ ? results.filter((project) =>
39
+ project.name.toLowerCase().includes(searchLower),
40
+ )
41
+ : results;
42
+ return {
43
+ projects: filtered.map(mapProject),
44
+ nextCursor,
45
+ };
46
+ },
47
+ } satisfies TodoistTool<typeof ArgsSchema>;
48
+
49
+ export { projectsSearch };
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const ArgsSchema = {
5
+ id: z.string().min(1).describe("The ID of the project to update."),
6
+ name: z.string().min(1).describe("The new name for the project."),
7
+ };
8
+
9
+ const projectsUpdateOne = {
10
+ name: "projects-update-one",
11
+ description: "Update a project's name by its ID.",
12
+ parameters: ArgsSchema,
13
+ async execute(args, client) {
14
+ const { id, name } = args;
15
+ const project = await client.updateProject(id, { name });
16
+ return project;
17
+ },
18
+ } satisfies TodoistTool<typeof ArgsSchema>;
19
+
20
+ export { projectsUpdateOne };
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const ArgsSchema = {
5
+ name: z.string().min(1).describe("The name of the section to add."),
6
+ projectId: z
7
+ .string()
8
+ .min(1)
9
+ .describe("The ID of the project to add the section to."),
10
+ };
11
+
12
+ const sectionsAddOne = {
13
+ name: "sections-add-one",
14
+ description: "Add a new section to a project.",
15
+ parameters: ArgsSchema,
16
+ async execute(args, client) {
17
+ const section = await client.addSection({
18
+ name: args.name,
19
+ projectId: args.projectId,
20
+ });
21
+ return section;
22
+ },
23
+ } satisfies TodoistTool<typeof ArgsSchema>;
24
+
25
+ export { sectionsAddOne };
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const ArgsSchema = {
5
+ id: z.string().min(1).describe("The ID of the section to delete."),
6
+ };
7
+
8
+ const sectionsDeleteOne = {
9
+ name: "sections-delete-one",
10
+ description: "Delete a section by its ID.",
11
+ parameters: ArgsSchema,
12
+ async execute(args, client) {
13
+ await client.deleteSection(args.id);
14
+ return { success: true };
15
+ },
16
+ } satisfies TodoistTool<typeof ArgsSchema>;
17
+
18
+ export { sectionsDeleteOne };
@@ -0,0 +1,39 @@
1
+ import type { Section } from "@doist/todoist-api-typescript";
2
+ import { z } from "zod";
3
+ import type { TodoistTool } from "../todoist-tool.js";
4
+
5
+ const ArgsSchema = {
6
+ projectId: z
7
+ .string()
8
+ .min(1)
9
+ .describe("The ID of the project to search sections in."),
10
+ search: z
11
+ .string()
12
+ .optional()
13
+ .describe(
14
+ "Search for a section by name (partial and case insensitive match). If omitted, all sections in the project are returned.",
15
+ ),
16
+ };
17
+
18
+ const sectionsSearch = {
19
+ name: "sections-search",
20
+ description: "Search for sections by name or other criteria in a project.",
21
+ parameters: ArgsSchema,
22
+ async execute(args, client) {
23
+ const { results } = await client.getSections({
24
+ projectId: args.projectId,
25
+ });
26
+ const searchLower = args.search ? args.search.toLowerCase() : undefined;
27
+ const filtered = searchLower
28
+ ? results.filter((section: Section) =>
29
+ section.name.toLowerCase().includes(searchLower),
30
+ )
31
+ : results;
32
+ return filtered.map((section: Section) => ({
33
+ id: section.id,
34
+ name: section.name,
35
+ }));
36
+ },
37
+ } satisfies TodoistTool<typeof ArgsSchema>;
38
+
39
+ export { sectionsSearch };
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const ArgsSchema = {
5
+ id: z.string().min(1).describe("The ID of the section to update."),
6
+ name: z.string().min(1).describe("The new name for the section."),
7
+ };
8
+
9
+ const sectionsUpdateOne = {
10
+ name: "sections-update-one",
11
+ description: "Update a section's name by its ID.",
12
+ parameters: ArgsSchema,
13
+ async execute(args, client) {
14
+ const { id, name } = args;
15
+ const section = await client.updateSection(id, { name });
16
+ return section;
17
+ },
18
+ } satisfies TodoistTool<typeof ArgsSchema>;
19
+
20
+ export { sectionsUpdateOne };
@@ -0,0 +1,94 @@
1
+ import {
2
+ type Project,
3
+ type Task,
4
+ type TodoistApi,
5
+ getSanitizedContent,
6
+ } from "@doist/todoist-api-typescript";
7
+ import z from "zod";
8
+
9
+ /**
10
+ * Map a single Todoist task to a more structured format, for LLM consumption.
11
+ * @param task - The task to map.
12
+ * @returns The mapped task.
13
+ */
14
+ function mapTask(task: Task) {
15
+ return {
16
+ id: task.id,
17
+ content: getSanitizedContent(task.content),
18
+ description: getSanitizedContent(task.description),
19
+ dueDate: task.due?.date,
20
+ recurring:
21
+ task.due?.isRecurring && task.due.string ? task.due.string : false,
22
+ priority: task.priority,
23
+ projectId: task.projectId,
24
+ sectionId: task.sectionId,
25
+ parentId: task.parentId,
26
+ labels: task.labels,
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Map a single Todoist project to a more structured format, for LLM consumption.
32
+ * @param project - The project to map.
33
+ * @returns The mapped project.
34
+ */
35
+ function mapProject(project: Project) {
36
+ return {
37
+ id: project.id,
38
+ name: project.name,
39
+ color: project.color,
40
+ isFavorite: project.isFavorite,
41
+ isShared: project.isShared,
42
+ parentId: project.parentId ?? null,
43
+ inboxProject: project.isInboxProject ?? false,
44
+ viewStyle: project.viewStyle,
45
+ };
46
+ }
47
+
48
+ const ErrorSchema = z.object({
49
+ httpStatusCode: z.number(),
50
+ responseData: z.object({
51
+ error: z.string(),
52
+ errorCode: z.number(),
53
+ errorTag: z.string(),
54
+ }),
55
+ });
56
+
57
+ async function getTasksByFilter({
58
+ client,
59
+ query,
60
+ limit,
61
+ cursor,
62
+ }: {
63
+ client: TodoistApi;
64
+ query: string;
65
+ limit: number | undefined;
66
+ cursor: string | undefined;
67
+ }) {
68
+ try {
69
+ const { results, nextCursor } = await client.getTasksByFilter({
70
+ query,
71
+ cursor,
72
+ limit,
73
+ });
74
+
75
+ return {
76
+ tasks: results.map(mapTask),
77
+ nextCursor,
78
+ };
79
+ } catch (error) {
80
+ const parsedError = ErrorSchema.safeParse(error);
81
+ if (!parsedError.success) {
82
+ throw error;
83
+ }
84
+ const { responseData } = parsedError.data;
85
+ if (responseData.errorTag === "INVALID_SEARCH_QUERY") {
86
+ throw new Error(`Invalid filter query: ${query}`);
87
+ }
88
+ throw new Error(
89
+ `${responseData.error} (tag: ${responseData.errorTag}, code: ${responseData.errorCode})`,
90
+ );
91
+ }
92
+ }
93
+
94
+ export { getTasksByFilter, mapTask, mapProject };
@@ -0,0 +1,43 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+ import { mapTask } from "./shared.js";
4
+
5
+ const ArgsSchema = {
6
+ parentId: z
7
+ .string()
8
+ .min(1)
9
+ .describe("The ID of the parent task to get subtasks for."),
10
+ limit: z
11
+ .number()
12
+ .int()
13
+ .min(1)
14
+ .max(50)
15
+ .default(10)
16
+ .describe("The maximum number of subtasks to return."),
17
+ cursor: z
18
+ .string()
19
+ .optional()
20
+ .describe(
21
+ "The cursor to get the next page of subtasks (from previous call).",
22
+ ),
23
+ };
24
+
25
+ const subtasksListForParentTask = {
26
+ name: "subtasks-list-for-parent-task",
27
+ description: "List subtasks for a given parent task.",
28
+ parameters: ArgsSchema,
29
+ async execute(args, client) {
30
+ const { parentId, limit, cursor } = args;
31
+ const { results, nextCursor } = await client.getTasks({
32
+ parentId,
33
+ limit,
34
+ cursor: cursor ?? null,
35
+ });
36
+ return {
37
+ tasks: results.map(mapTask),
38
+ nextCursor,
39
+ };
40
+ },
41
+ } satisfies TodoistTool<typeof ArgsSchema>;
42
+
43
+ export { subtasksListForParentTask };
@@ -0,0 +1,53 @@
1
+ import type { Task } from "@doist/todoist-api-typescript";
2
+ import { z } from "zod";
3
+ import type { TodoistTool } from "../todoist-tool.js";
4
+ import { mapTask } from "./shared.js";
5
+
6
+ const TaskSchema = z.object({
7
+ content: z.string().min(1).describe("The content of the task to create."),
8
+ description: z.string().optional().describe("The description of the task."),
9
+ priority: z
10
+ .number()
11
+ .int()
12
+ .min(1)
13
+ .max(4)
14
+ .optional()
15
+ .describe("The priority of the task (1-4)."),
16
+ dueString: z
17
+ .string()
18
+ .optional()
19
+ .describe("The due date for the task, in natural language."),
20
+ });
21
+
22
+ const ArgsSchema = {
23
+ projectId: z
24
+ .string()
25
+ .optional()
26
+ .describe("The project ID to add the tasks to."),
27
+ sectionId: z
28
+ .string()
29
+ .optional()
30
+ .describe("The section ID to add the tasks to."),
31
+ parentId: z
32
+ .string()
33
+ .optional()
34
+ .describe("The parent task ID (for subtasks)."),
35
+ tasks: z.array(TaskSchema).min(1).describe("The array of tasks to add."),
36
+ };
37
+
38
+ const tasksAddMultiple = {
39
+ name: "tasks-add-multiple",
40
+ description: "Add one or more tasks to a project, section, or parent.",
41
+ parameters: ArgsSchema,
42
+ async execute(args, client) {
43
+ const { projectId, sectionId, parentId, tasks } = args;
44
+ const newTasks: Task[] = [];
45
+ for (const task of tasks) {
46
+ const taskArgs = { ...task, projectId, sectionId, parentId };
47
+ newTasks.push(await client.addTask(taskArgs));
48
+ }
49
+ return newTasks.map(mapTask);
50
+ },
51
+ } satisfies TodoistTool<typeof ArgsSchema>;
52
+
53
+ export { tasksAddMultiple };
@@ -0,0 +1,58 @@
1
+ import { addDays, formatISO } from "date-fns";
2
+ import { z } from "zod";
3
+ import type { TodoistTool } from "../todoist-tool.js";
4
+ import { getTasksByFilter } from "./shared.js";
5
+
6
+ const ArgsSchema = {
7
+ startDate: z
8
+ .string()
9
+ .regex(/^(\d{4}-\d{2}-\d{2}|today)$/)
10
+ .describe(
11
+ "The start date to get the tasks for. Format: YYYY-MM-DD or 'today'.",
12
+ ),
13
+ daysCount: z
14
+ .number()
15
+ .int()
16
+ .min(1)
17
+ .max(30)
18
+ .default(1)
19
+ .describe(
20
+ "The number of days to get the tasks for, starting from the start date.",
21
+ ),
22
+ limit: z
23
+ .number()
24
+ .int()
25
+ .min(1)
26
+ .max(50)
27
+ .default(10)
28
+ .describe("The maximum number of tasks to return."),
29
+ cursor: z
30
+ .string()
31
+ .optional()
32
+ .describe(
33
+ "The cursor to get the next page of tasks (cursor is obtained from the previous call to this tool, with the same parameters).",
34
+ ),
35
+ };
36
+
37
+ const tasksListByDate = {
38
+ name: "tasks-list-by-date",
39
+ description: "Get tasks by date range.",
40
+ parameters: ArgsSchema,
41
+ async execute(args, client) {
42
+ const startDate =
43
+ args.startDate === "today"
44
+ ? formatISO(new Date(), { representation: "date" })
45
+ : args.startDate;
46
+ const endDate = addDays(startDate, args.daysCount + 1);
47
+ const endDateStr = formatISO(endDate, { representation: "date" });
48
+ const query = `(due after: ${startDate} | due: ${startDate}) & due before: ${endDateStr}`;
49
+ return await getTasksByFilter({
50
+ client,
51
+ query,
52
+ cursor: args.cursor,
53
+ limit: args.limit,
54
+ });
55
+ },
56
+ } satisfies TodoistTool<typeof ArgsSchema>;
57
+
58
+ export { tasksListByDate };
@@ -0,0 +1,43 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+ import { mapTask } from "./shared.js";
4
+
5
+ const ArgsSchema = {
6
+ projectId: z
7
+ .string()
8
+ .min(1)
9
+ .describe("The ID of the project to get tasks for."),
10
+ limit: z
11
+ .number()
12
+ .int()
13
+ .min(1)
14
+ .max(50)
15
+ .default(10)
16
+ .describe("The maximum number of tasks to return."),
17
+ cursor: z
18
+ .string()
19
+ .optional()
20
+ .describe(
21
+ "The cursor to get the next page of tasks (cursor is obtained from the previous call to this tool, with the same parameters).",
22
+ ),
23
+ };
24
+
25
+ const tasksListForProject = {
26
+ name: "tasks-list-for-project",
27
+ description: "Get tasks by project ID.",
28
+ parameters: ArgsSchema,
29
+ async execute(args, client) {
30
+ const { projectId, limit, cursor } = args;
31
+ const { results, nextCursor } = await client.getTasks({
32
+ projectId,
33
+ limit,
34
+ cursor: cursor ?? null,
35
+ });
36
+ return {
37
+ tasks: results.map(mapTask),
38
+ nextCursor,
39
+ };
40
+ },
41
+ } satisfies TodoistTool<typeof ArgsSchema>;
42
+
43
+ export { tasksListForProject };
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const ArgsSchema = {
5
+ ids: z
6
+ .array(z.string().min(1))
7
+ .min(1)
8
+ .describe("The IDs of the tasks to complete."),
9
+ };
10
+
11
+ const tasksCompleteMultiple = {
12
+ name: "tasks-complete-multiple",
13
+ description: "Complete one or more tasks by their IDs.",
14
+ parameters: ArgsSchema,
15
+ async execute(args, client) {
16
+ const completed: string[] = [];
17
+ for (const id of args.ids) {
18
+ try {
19
+ await client.closeTask(id);
20
+ completed.push(id);
21
+ } catch {
22
+ // Ignore errors for individual tasks, continue with others
23
+ }
24
+ }
25
+ return { success: true, completed };
26
+ },
27
+ } satisfies TodoistTool<typeof ArgsSchema>;
28
+
29
+ export { tasksCompleteMultiple };
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const ArgsSchema = {
5
+ id: z.string().min(1).describe("The ID of the task to delete."),
6
+ };
7
+
8
+ const tasksDeleteOne = {
9
+ name: "tasks-delete-one",
10
+ description: "Delete a task by its ID.",
11
+ parameters: ArgsSchema,
12
+ async execute(args, client) {
13
+ await client.deleteTask(args.id);
14
+ return { success: true };
15
+ },
16
+ } satisfies TodoistTool<typeof ArgsSchema>;
17
+
18
+ export { tasksDeleteOne };
@@ -0,0 +1,43 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+ import { mapTask } from "./shared.js";
4
+
5
+ const ArgsSchema = {
6
+ sectionId: z
7
+ .string()
8
+ .min(1)
9
+ .describe("The ID of the section to get tasks for."),
10
+ limit: z
11
+ .number()
12
+ .int()
13
+ .min(1)
14
+ .max(50)
15
+ .default(10)
16
+ .describe("The maximum number of tasks to return."),
17
+ cursor: z
18
+ .string()
19
+ .optional()
20
+ .describe(
21
+ "The cursor to get the next page of tasks (from previous call).",
22
+ ),
23
+ };
24
+
25
+ const tasksListForSection = {
26
+ name: "tasks-list-for-section",
27
+ description: "List tasks for a given section.",
28
+ parameters: ArgsSchema,
29
+ async execute(args, client) {
30
+ const { sectionId, limit, cursor } = args;
31
+ const { results, nextCursor } = await client.getTasks({
32
+ sectionId,
33
+ limit,
34
+ cursor: cursor ?? null,
35
+ });
36
+ return {
37
+ tasks: results.map(mapTask),
38
+ nextCursor,
39
+ };
40
+ },
41
+ } satisfies TodoistTool<typeof ArgsSchema>;
42
+
43
+ export { tasksListForSection };
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+ import { getTasksByFilter } from "./shared.js";
4
+
5
+ const ArgsSchema = {
6
+ limit: z
7
+ .number()
8
+ .int()
9
+ .min(1)
10
+ .max(50)
11
+ .default(10)
12
+ .describe("The maximum number of overdue tasks to return."),
13
+ cursor: z
14
+ .string()
15
+ .optional()
16
+ .describe(
17
+ "The cursor to get the next page of overdue tasks (cursor is obtained from the previous call to this tool, with the same parameters).",
18
+ ),
19
+ };
20
+
21
+ const tasksListOverdue = {
22
+ name: "tasks-list-overdue",
23
+ description: "Get overdue tasks.",
24
+ parameters: ArgsSchema,
25
+ async execute(args, client) {
26
+ return await getTasksByFilter({
27
+ client,
28
+ query: "overdue",
29
+ cursor: args.cursor,
30
+ limit: args.limit,
31
+ });
32
+ },
33
+ } satisfies TodoistTool<typeof ArgsSchema>;
34
+
35
+ export { tasksListOverdue };
@@ -0,0 +1,45 @@
1
+ import { z } from "zod";
2
+ import type { TodoistTool } from "../todoist-tool.js";
3
+
4
+ const TaskUpdateSchema = z.object({
5
+ id: z.string().min(1).describe("The ID of the task to update."),
6
+ projectId: z
7
+ .string()
8
+ .optional()
9
+ .describe("The new project ID for the task."),
10
+ sectionId: z
11
+ .string()
12
+ .optional()
13
+ .describe("The new section ID for the task."),
14
+ parentId: z
15
+ .string()
16
+ .optional()
17
+ .describe("The new parent task ID (for subtasks)."),
18
+ order: z
19
+ .number()
20
+ .optional()
21
+ .describe("The new order of the task within its parent/section."),
22
+ });
23
+
24
+ const ArgsSchema = {
25
+ tasks: z
26
+ .array(TaskUpdateSchema)
27
+ .min(1)
28
+ .describe("Array of task updates to apply."),
29
+ };
30
+
31
+ const tasksOrganizeMultiple = {
32
+ name: "tasks-organize-multiple",
33
+ description: "Organize multiple tasks (move, reorder, etc.) in bulk.",
34
+ parameters: ArgsSchema,
35
+ async execute(args, client) {
36
+ const results = [];
37
+ for (const update of args.tasks) {
38
+ const { id, ...updateArgs } = update;
39
+ results.push(await client.updateTask(id, updateArgs));
40
+ }
41
+ return results;
42
+ },
43
+ } satisfies TodoistTool<typeof ArgsSchema>;
44
+
45
+ export { tasksOrganizeMultiple };