@doist/todoist-ai 2.2.1 → 3.0.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 (168) hide show
  1. package/README.md +11 -3
  2. package/dist/index.d.ts +496 -255
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +41 -29
  5. package/dist/mcp-helpers.d.ts +25 -3
  6. package/dist/mcp-helpers.d.ts.map +1 -1
  7. package/dist/mcp-helpers.js +37 -19
  8. package/dist/mcp-server.d.ts.map +1 -1
  9. package/dist/mcp-server.js +32 -28
  10. package/dist/tools/__tests__/add-tasks.test.d.ts +2 -0
  11. package/dist/tools/__tests__/add-tasks.test.d.ts.map +1 -0
  12. package/dist/tools/__tests__/{tasks-add-multiple.test.js → add-tasks.test.js} +85 -81
  13. package/dist/tools/__tests__/complete-tasks.test.d.ts +2 -0
  14. package/dist/tools/__tests__/complete-tasks.test.d.ts.map +1 -0
  15. package/dist/tools/__tests__/complete-tasks.test.js +206 -0
  16. package/dist/tools/__tests__/delete-object.test.d.ts +2 -0
  17. package/dist/tools/__tests__/delete-object.test.d.ts.map +1 -0
  18. package/dist/tools/__tests__/{delete-one.test.js → delete-object.test.js} +42 -22
  19. package/dist/tools/__tests__/find-completed-tasks.test.d.ts +2 -0
  20. package/dist/tools/__tests__/find-completed-tasks.test.d.ts.map +1 -0
  21. package/dist/tools/__tests__/{tasks-list-completed.test.js → find-completed-tasks.test.js} +13 -36
  22. package/dist/tools/__tests__/find-projects.test.d.ts +2 -0
  23. package/dist/tools/__tests__/find-projects.test.d.ts.map +1 -0
  24. package/dist/tools/__tests__/{projects-list.test.js → find-projects.test.js} +55 -39
  25. package/dist/tools/__tests__/find-sections.test.d.ts +2 -0
  26. package/dist/tools/__tests__/find-sections.test.d.ts.map +1 -0
  27. package/dist/tools/__tests__/{sections-search.test.js → find-sections.test.js} +64 -50
  28. package/dist/tools/__tests__/find-tasks-by-date.test.d.ts +2 -0
  29. package/dist/tools/__tests__/find-tasks-by-date.test.d.ts.map +1 -0
  30. package/dist/tools/__tests__/{tasks-list-by-date.test.js → find-tasks-by-date.test.js} +96 -14
  31. package/dist/tools/__tests__/find-tasks.test.d.ts +2 -0
  32. package/dist/tools/__tests__/find-tasks.test.d.ts.map +1 -0
  33. package/dist/tools/__tests__/find-tasks.test.js +334 -0
  34. package/dist/tools/__tests__/get-overview.test.d.ts +2 -0
  35. package/dist/tools/__tests__/get-overview.test.d.ts.map +1 -0
  36. package/dist/tools/__tests__/{overview.test.js → get-overview.test.js} +77 -13
  37. package/dist/tools/__tests__/manage-projects.test.d.ts +2 -0
  38. package/dist/tools/__tests__/manage-projects.test.d.ts.map +1 -0
  39. package/dist/tools/__tests__/{projects-manage.test.js → manage-projects.test.js} +33 -30
  40. package/dist/tools/__tests__/manage-sections.test.d.ts +2 -0
  41. package/dist/tools/__tests__/manage-sections.test.d.ts.map +1 -0
  42. package/dist/tools/__tests__/manage-sections.test.js +162 -0
  43. package/dist/tools/__tests__/update-tasks.test.d.ts +2 -0
  44. package/dist/tools/__tests__/update-tasks.test.d.ts.map +1 -0
  45. package/dist/tools/__tests__/update-tasks.test.js +645 -0
  46. package/dist/tools/{tasks-add-multiple.d.ts → add-tasks.d.ts} +36 -16
  47. package/dist/tools/add-tasks.d.ts.map +1 -0
  48. package/dist/tools/{tasks-add-multiple.js → add-tasks.js} +39 -4
  49. package/dist/tools/complete-tasks.d.ts +40 -0
  50. package/dist/tools/complete-tasks.d.ts.map +1 -0
  51. package/dist/tools/complete-tasks.js +68 -0
  52. package/dist/tools/delete-object.d.ts +38 -0
  53. package/dist/tools/delete-object.d.ts.map +1 -0
  54. package/dist/tools/delete-object.js +69 -0
  55. package/dist/tools/find-completed-tasks.d.ts +74 -0
  56. package/dist/tools/find-completed-tasks.d.ts.map +1 -0
  57. package/dist/tools/find-completed-tasks.js +112 -0
  58. package/dist/tools/find-projects.d.ts +53 -0
  59. package/dist/tools/find-projects.d.ts.map +1 -0
  60. package/dist/tools/find-projects.js +101 -0
  61. package/dist/tools/find-sections.d.ts +42 -0
  62. package/dist/tools/find-sections.d.ts.map +1 -0
  63. package/dist/tools/find-sections.js +96 -0
  64. package/dist/tools/find-tasks-by-date.d.ts +59 -0
  65. package/dist/tools/find-tasks-by-date.d.ts.map +1 -0
  66. package/dist/tools/find-tasks-by-date.js +121 -0
  67. package/dist/tools/find-tasks.d.ts +65 -0
  68. package/dist/tools/find-tasks.d.ts.map +1 -0
  69. package/dist/tools/find-tasks.js +182 -0
  70. package/dist/tools/get-overview.d.ts +67 -0
  71. package/dist/tools/get-overview.d.ts.map +1 -0
  72. package/dist/tools/{overview.js → get-overview.js} +66 -19
  73. package/dist/tools/manage-projects.d.ts +35 -0
  74. package/dist/tools/manage-projects.d.ts.map +1 -0
  75. package/dist/tools/manage-projects.js +63 -0
  76. package/dist/tools/manage-sections.d.ts +38 -0
  77. package/dist/tools/manage-sections.d.ts.map +1 -0
  78. package/dist/tools/manage-sections.js +78 -0
  79. package/dist/tools/update-tasks.d.ts +94 -0
  80. package/dist/tools/update-tasks.d.ts.map +1 -0
  81. package/dist/tools/update-tasks.js +120 -0
  82. package/dist/utils/constants.d.ts +35 -0
  83. package/dist/utils/constants.d.ts.map +1 -0
  84. package/dist/utils/constants.js +37 -0
  85. package/dist/utils/response-builders.d.ts +88 -0
  86. package/dist/utils/response-builders.d.ts.map +1 -0
  87. package/dist/utils/response-builders.js +202 -0
  88. package/dist/{tools → utils}/test-helpers.d.ts +16 -0
  89. package/dist/utils/test-helpers.d.ts.map +1 -0
  90. package/dist/{tools → utils}/test-helpers.js +51 -0
  91. package/dist/utils/tool-names.d.ts +23 -0
  92. package/dist/utils/tool-names.d.ts.map +1 -0
  93. package/dist/utils/tool-names.js +25 -0
  94. package/package.json +2 -2
  95. package/dist/tools/__tests__/delete-one.test.d.ts +0 -2
  96. package/dist/tools/__tests__/delete-one.test.d.ts.map +0 -1
  97. package/dist/tools/__tests__/overview.test.d.ts +0 -2
  98. package/dist/tools/__tests__/overview.test.d.ts.map +0 -1
  99. package/dist/tools/__tests__/projects-list.test.d.ts +0 -2
  100. package/dist/tools/__tests__/projects-list.test.d.ts.map +0 -1
  101. package/dist/tools/__tests__/projects-manage.test.d.ts +0 -2
  102. package/dist/tools/__tests__/projects-manage.test.d.ts.map +0 -1
  103. package/dist/tools/__tests__/sections-manage.test.d.ts +0 -2
  104. package/dist/tools/__tests__/sections-manage.test.d.ts.map +0 -1
  105. package/dist/tools/__tests__/sections-manage.test.js +0 -138
  106. package/dist/tools/__tests__/sections-search.test.d.ts +0 -2
  107. package/dist/tools/__tests__/sections-search.test.d.ts.map +0 -1
  108. package/dist/tools/__tests__/tasks-add-multiple.test.d.ts +0 -2
  109. package/dist/tools/__tests__/tasks-add-multiple.test.d.ts.map +0 -1
  110. package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts +0 -2
  111. package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts.map +0 -1
  112. package/dist/tools/__tests__/tasks-complete-multiple.test.js +0 -146
  113. package/dist/tools/__tests__/tasks-list-by-date.test.d.ts +0 -2
  114. package/dist/tools/__tests__/tasks-list-by-date.test.d.ts.map +0 -1
  115. package/dist/tools/__tests__/tasks-list-completed.test.d.ts +0 -2
  116. package/dist/tools/__tests__/tasks-list-completed.test.d.ts.map +0 -1
  117. package/dist/tools/__tests__/tasks-list-for-container.test.d.ts +0 -2
  118. package/dist/tools/__tests__/tasks-list-for-container.test.d.ts.map +0 -1
  119. package/dist/tools/__tests__/tasks-list-for-container.test.js +0 -232
  120. package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts +0 -2
  121. package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts.map +0 -1
  122. package/dist/tools/__tests__/tasks-organize-multiple.test.js +0 -245
  123. package/dist/tools/__tests__/tasks-search.test.d.ts +0 -2
  124. package/dist/tools/__tests__/tasks-search.test.d.ts.map +0 -1
  125. package/dist/tools/__tests__/tasks-search.test.js +0 -106
  126. package/dist/tools/__tests__/tasks-update-one.test.d.ts +0 -2
  127. package/dist/tools/__tests__/tasks-update-one.test.d.ts.map +0 -1
  128. package/dist/tools/__tests__/tasks-update-one.test.js +0 -251
  129. package/dist/tools/delete-one.d.ts +0 -17
  130. package/dist/tools/delete-one.d.ts.map +0 -1
  131. package/dist/tools/delete-one.js +0 -25
  132. package/dist/tools/overview.d.ts +0 -14
  133. package/dist/tools/overview.d.ts.map +0 -1
  134. package/dist/tools/projects-list.d.ts +0 -29
  135. package/dist/tools/projects-list.d.ts.map +0 -1
  136. package/dist/tools/projects-list.js +0 -39
  137. package/dist/tools/projects-manage.d.ts +0 -24
  138. package/dist/tools/projects-manage.d.ts.map +0 -1
  139. package/dist/tools/projects-manage.js +0 -26
  140. package/dist/tools/sections-manage.d.ts +0 -23
  141. package/dist/tools/sections-manage.d.ts.map +0 -1
  142. package/dist/tools/sections-manage.js +0 -37
  143. package/dist/tools/sections-search.d.ts +0 -18
  144. package/dist/tools/sections-search.d.ts.map +0 -1
  145. package/dist/tools/sections-search.js +0 -27
  146. package/dist/tools/tasks-add-multiple.d.ts.map +0 -1
  147. package/dist/tools/tasks-complete-multiple.d.ts +0 -16
  148. package/dist/tools/tasks-complete-multiple.d.ts.map +0 -1
  149. package/dist/tools/tasks-complete-multiple.js +0 -23
  150. package/dist/tools/tasks-list-by-date.d.ts +0 -34
  151. package/dist/tools/tasks-list-by-date.d.ts.map +0 -1
  152. package/dist/tools/tasks-list-by-date.js +0 -53
  153. package/dist/tools/tasks-list-completed.d.ts +0 -44
  154. package/dist/tools/tasks-list-completed.d.ts.map +0 -1
  155. package/dist/tools/tasks-list-completed.js +0 -49
  156. package/dist/tools/tasks-list-for-container.d.ts +0 -34
  157. package/dist/tools/tasks-list-for-container.d.ts.map +0 -1
  158. package/dist/tools/tasks-list-for-container.js +0 -48
  159. package/dist/tools/tasks-organize-multiple.d.ts +0 -37
  160. package/dist/tools/tasks-organize-multiple.d.ts.map +0 -1
  161. package/dist/tools/tasks-organize-multiple.js +0 -34
  162. package/dist/tools/tasks-search.d.ts +0 -32
  163. package/dist/tools/tasks-search.d.ts.map +0 -1
  164. package/dist/tools/tasks-search.js +0 -30
  165. package/dist/tools/tasks-update-one.d.ts +0 -29
  166. package/dist/tools/tasks-update-one.d.ts.map +0 -1
  167. package/dist/tools/tasks-update-one.js +0 -63
  168. package/dist/tools/test-helpers.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE5D,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAeV,CAAA;AAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAA;AAE9B,OAAO,EACH,YAAY,EACZ,cAAc,EACd,SAAS,EACT,cAAc,EACd,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,QAAQ,GACX,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAG9C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGrD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBV,CAAA;AAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAA;AAE9B,OAAO,EAEH,QAAQ,EACR,aAAa,EACb,WAAW,EACX,SAAS,EACT,eAAe,EACf,kBAAkB,EAElB,YAAY,EACZ,cAAc,EAEd,YAAY,EACZ,cAAc,EAEd,WAAW,EACX,YAAY,GACf,CAAA"}
package/dist/index.js CHANGED
@@ -1,33 +1,45 @@
1
1
  import { getMcpServer } from './mcp-server.js';
2
- import { deleteOne } from './tools/delete-one.js';
3
- import { projectsList } from './tools/projects-list.js';
4
- import { projectsManage } from './tools/projects-manage.js';
5
- import { sectionsManage } from './tools/sections-manage.js';
6
- import { sectionsSearch } from './tools/sections-search.js';
7
- import { overview } from './tools/overview.js';
8
- import { tasksAddMultiple } from './tools/tasks-add-multiple.js';
9
- import { tasksCompleteMultiple } from './tools/tasks-complete-multiple.js';
10
- import { tasksListByDate } from './tools/tasks-list-by-date.js';
11
- import { tasksListCompleted } from './tools/tasks-list-completed.js';
12
- import { tasksListForContainer } from './tools/tasks-list-for-container.js';
13
- import { tasksOrganizeMultiple } from './tools/tasks-organize-multiple.js';
14
- import { tasksSearch } from './tools/tasks-search.js';
15
- import { tasksUpdateOne } from './tools/tasks-update-one.js';
2
+ // Task management tools
3
+ import { addTasks } from './tools/add-tasks.js';
4
+ import { completeTasks } from './tools/complete-tasks.js';
5
+ import { findCompletedTasks } from './tools/find-completed-tasks.js';
6
+ import { findTasksByDate } from './tools/find-tasks-by-date.js';
7
+ import { findTasks } from './tools/find-tasks.js';
8
+ import { updateTasks } from './tools/update-tasks.js';
9
+ // Project management tools
10
+ import { findProjects } from './tools/find-projects.js';
11
+ import { manageProjects } from './tools/manage-projects.js';
12
+ // Section management tools
13
+ import { findSections } from './tools/find-sections.js';
14
+ import { manageSections } from './tools/manage-sections.js';
15
+ // General tools
16
+ import { deleteObject } from './tools/delete-object.js';
17
+ import { getOverview } from './tools/get-overview.js';
16
18
  const tools = {
17
- projectsList,
18
- projectsManage,
19
- deleteOne,
20
- sectionsSearch,
21
- sectionsManage,
22
- tasksListByDate,
23
- tasksListCompleted,
24
- tasksListForContainer,
25
- tasksCompleteMultiple,
26
- tasksSearch,
27
- tasksAddMultiple,
28
- tasksUpdateOne,
29
- tasksOrganizeMultiple,
30
- overview,
19
+ // Task management tools
20
+ addTasks,
21
+ completeTasks,
22
+ updateTasks,
23
+ findTasks,
24
+ findTasksByDate,
25
+ findCompletedTasks,
26
+ // Project management tools
27
+ findProjects,
28
+ manageProjects,
29
+ // Section management tools
30
+ findSections,
31
+ manageSections,
32
+ // General tools
33
+ getOverview,
34
+ deleteObject,
31
35
  };
32
36
  export { tools, getMcpServer };
33
- export { projectsList, projectsManage, deleteOne, sectionsSearch, sectionsManage, tasksListByDate, tasksListForContainer, tasksListCompleted, tasksCompleteMultiple, tasksSearch, tasksAddMultiple, tasksUpdateOne, tasksOrganizeMultiple, overview, };
37
+ export {
38
+ // Task management tools
39
+ addTasks, completeTasks, updateTasks, findTasks, findTasksByDate, findCompletedTasks,
40
+ // Project management tools
41
+ findProjects, manageProjects,
42
+ // Section management tools
43
+ findSections, manageSections,
44
+ // General tools
45
+ getOverview, deleteObject, };
@@ -2,12 +2,34 @@ import type { TodoistApi } from '@doist/todoist-api-typescript';
2
2
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import type { z } from 'zod';
4
4
  import type { TodoistTool } from './todoist-tool.js';
5
- declare function errorContent(error: string): {
6
- isError: boolean;
5
+ /**
6
+ * Get the output payload for a tool, in the correct format expected by MCP client apps.
7
+ *
8
+ * @param textContent - The text content to return.
9
+ * @param structuredContent - The structured content to return.
10
+ * @returns The output payload.
11
+ * @see USE_STRUCTURED_CONTENT - Wether to use the structured content feature of the MCP protocol.
12
+ */
13
+ declare function getToolOutput<StructuredContent extends Record<string, unknown>>({ textContent, structuredContent, }: {
14
+ textContent: string;
15
+ structuredContent: StructuredContent;
16
+ }): {
7
17
  content: {
8
18
  type: "text";
9
19
  text: string;
10
20
  }[];
21
+ structuredContent: StructuredContent;
22
+ } | {
23
+ content: ({
24
+ type: "text";
25
+ text: string;
26
+ mimeType?: undefined;
27
+ } | {
28
+ type: "text";
29
+ mimeType: string;
30
+ text: string;
31
+ })[];
32
+ structuredContent?: undefined;
11
33
  };
12
34
  /**
13
35
  * Register a Todoist tool in an MCP server.
@@ -16,5 +38,5 @@ declare function errorContent(error: string): {
16
38
  * @param client - The Todoist API client to use to execute the tool.
17
39
  */
18
40
  declare function registerTool<Params extends z.ZodRawShape>(tool: TodoistTool<Params>, server: McpServer, client: TodoistApi): void;
19
- export { registerTool, errorContent };
41
+ export { registerTool, getToolOutput };
20
42
  //# sourceMappingURL=mcp-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-helpers.d.ts","sourceRoot":"","sources":["../src/mcp-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,yCAAyC,CAAA;AACtF,OAAO,KAAK,EAAc,CAAC,EAAE,MAAM,KAAK,CAAA;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAwBpD,iBAAS,YAAY,CAAC,KAAK,EAAE,MAAM;;;;;;EAKlC;AAED;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,MAAM,SAAS,CAAC,CAAC,WAAW,EAC9C,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EACzB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,QAqBrB;AAED,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"mcp-helpers.d.ts","sourceRoot":"","sources":["../src/mcp-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,yCAAyC,CAAA;AACtF,OAAO,KAAK,EAAc,CAAC,EAAE,MAAM,KAAK,CAAA;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAkBpD;;;;;;;GAOG;AACH,iBAAS,aAAa,CAAC,iBAAiB,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACtE,WAAW,EACX,iBAAiB,GACpB,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAA;CAAE;;;;;;;;;;;;;;;;;EAe/D;AASD;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,MAAM,SAAS,CAAC,CAAC,WAAW,EAC9C,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EACzB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,QAqBrB;AAED,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAA"}
@@ -1,25 +1,43 @@
1
- function textContent(text) {
2
- return {
3
- content: [{ type: 'text', text }],
4
- };
5
- }
6
- function jsonContent(data) {
1
+ /**
2
+ * Wether to return the structured content directly, vs. in the `content` part of the output.
3
+ *
4
+ * The `structuredContent` part of the output is relatively new in the spec, and it's not yet
5
+ * supported by all clients. This flag controls wether we return the structured content using this
6
+ * new feature of the MCP protocol or not.
7
+ *
8
+ * If `false`, the `structuredContent` will be returned as stringified JSON in one of the `content`
9
+ * parts.
10
+ *
11
+ * Eventually we should be able to remove this, and change the code to always work with the
12
+ * structured content returned directly, once most or all MCP clients support it.
13
+ */
14
+ const USE_STRUCTURED_CONTENT = process.env.USE_STRUCTURED_CONTENT === 'true' || process.env.NODE_ENV === 'test';
15
+ /**
16
+ * Get the output payload for a tool, in the correct format expected by MCP client apps.
17
+ *
18
+ * @param textContent - The text content to return.
19
+ * @param structuredContent - The structured content to return.
20
+ * @returns The output payload.
21
+ * @see USE_STRUCTURED_CONTENT - Wether to use the structured content feature of the MCP protocol.
22
+ */
23
+ function getToolOutput({ textContent, structuredContent, }) {
24
+ if (USE_STRUCTURED_CONTENT) {
25
+ return {
26
+ content: [{ type: 'text', text: textContent }],
27
+ structuredContent,
28
+ };
29
+ }
30
+ const json = JSON.stringify(structuredContent);
7
31
  return {
8
32
  content: [
9
- {
10
- type: 'text',
11
- mimeType: 'application/json',
12
- text: JSON.stringify(data, null, 2),
13
- },
33
+ { type: 'text', text: textContent },
34
+ { type: 'text', mimeType: 'application/json', text: json },
14
35
  ],
15
36
  };
16
37
  }
17
- function textOrJsonContent(data) {
18
- return typeof data === 'string' ? textContent(data) : jsonContent(data);
19
- }
20
- function errorContent(error) {
38
+ function getErrorOutput(error) {
21
39
  return {
22
- ...textContent(error),
40
+ content: [{ type: 'text', text: error }],
23
41
  isError: true,
24
42
  };
25
43
  }
@@ -34,7 +52,7 @@ function registerTool(tool, server, client) {
34
52
  const cb = async (args, _context) => {
35
53
  try {
36
54
  const result = await tool.execute(args, client);
37
- return textOrJsonContent(result);
55
+ return result;
38
56
  }
39
57
  catch (error) {
40
58
  console.error(`Error executing tool ${tool.name}:`, {
@@ -42,9 +60,9 @@ function registerTool(tool, server, client) {
42
60
  error,
43
61
  });
44
62
  const message = error instanceof Error ? error.message : 'An unknown error occurred';
45
- return errorContent(message);
63
+ return getErrorOutput(message);
46
64
  }
47
65
  };
48
66
  server.tool(tool.name, tool.description, tool.parameters, cb);
49
67
  }
50
- export { registerTool, errorContent };
68
+ export { registerTool, getToolOutput };
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAwBnE;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,aA6B5F;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AA2BnE;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,aAkC5F;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -1,20 +1,22 @@
1
1
  import { TodoistApi } from '@doist/todoist-api-typescript';
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { registerTool } from './mcp-helpers.js';
4
- import { deleteOne } from './tools/delete-one.js';
5
- import { projectsList } from './tools/projects-list.js';
6
- import { projectsManage } from './tools/projects-manage.js';
7
- import { sectionsManage } from './tools/sections-manage.js';
8
- import { sectionsSearch } from './tools/sections-search.js';
9
- import { overview } from './tools/overview.js';
10
- import { tasksAddMultiple } from './tools/tasks-add-multiple.js';
11
- import { tasksCompleteMultiple } from './tools/tasks-complete-multiple.js';
12
- import { tasksListByDate } from './tools/tasks-list-by-date.js';
13
- import { tasksListCompleted } from './tools/tasks-list-completed.js';
14
- import { tasksListForContainer } from './tools/tasks-list-for-container.js';
15
- import { tasksOrganizeMultiple } from './tools/tasks-organize-multiple.js';
16
- import { tasksSearch } from './tools/tasks-search.js';
17
- import { tasksUpdateOne } from './tools/tasks-update-one.js';
4
+ // Task management tools
5
+ import { addTasks } from './tools/add-tasks.js';
6
+ import { completeTasks } from './tools/complete-tasks.js';
7
+ import { findCompletedTasks } from './tools/find-completed-tasks.js';
8
+ import { findTasksByDate } from './tools/find-tasks-by-date.js';
9
+ import { findTasks } from './tools/find-tasks.js';
10
+ import { updateTasks } from './tools/update-tasks.js';
11
+ // Project management tools
12
+ import { findProjects } from './tools/find-projects.js';
13
+ import { manageProjects } from './tools/manage-projects.js';
14
+ // Section management tools
15
+ import { findSections } from './tools/find-sections.js';
16
+ import { manageSections } from './tools/manage-sections.js';
17
+ // General tools
18
+ import { deleteObject } from './tools/delete-object.js';
19
+ import { getOverview } from './tools/get-overview.js';
18
20
  const instructions = `
19
21
  Tools to help you manage your todoist tasks.
20
22
  `;
@@ -32,20 +34,22 @@ function getMcpServer({ todoistApiKey, baseUrl }) {
32
34
  instructions,
33
35
  });
34
36
  const todoist = new TodoistApi(todoistApiKey, baseUrl);
35
- registerTool(tasksListCompleted, server, todoist);
36
- registerTool(tasksListByDate, server, todoist);
37
- registerTool(tasksSearch, server, todoist);
38
- registerTool(projectsList, server, todoist);
39
- registerTool(tasksAddMultiple, server, todoist);
40
- registerTool(tasksUpdateOne, server, todoist);
41
- registerTool(deleteOne, server, todoist);
42
- registerTool(tasksCompleteMultiple, server, todoist);
43
- registerTool(projectsManage, server, todoist);
44
- registerTool(sectionsManage, server, todoist);
45
- registerTool(tasksOrganizeMultiple, server, todoist);
46
- registerTool(sectionsSearch, server, todoist);
47
- registerTool(overview, server, todoist);
48
- registerTool(tasksListForContainer, server, todoist);
37
+ // Task management tools
38
+ registerTool(addTasks, server, todoist);
39
+ registerTool(completeTasks, server, todoist);
40
+ registerTool(updateTasks, server, todoist);
41
+ registerTool(findTasks, server, todoist);
42
+ registerTool(findTasksByDate, server, todoist);
43
+ registerTool(findCompletedTasks, server, todoist);
44
+ // Project management tools
45
+ registerTool(findProjects, server, todoist);
46
+ registerTool(manageProjects, server, todoist);
47
+ // Section management tools
48
+ registerTool(findSections, server, todoist);
49
+ registerTool(manageSections, server, todoist);
50
+ // General tools
51
+ registerTool(getOverview, server, todoist);
52
+ registerTool(deleteObject, server, todoist);
49
53
  return server;
50
54
  }
51
55
  export { getMcpServer };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=add-tasks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-tasks.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-tasks.test.ts"],"names":[],"mappings":""}
@@ -1,11 +1,13 @@
1
1
  import { jest } from '@jest/globals';
2
- import { tasksAddMultiple } from '../tasks-add-multiple.js';
3
- import { createMockTask } from '../test-helpers.js';
2
+ import { TODAY, createMockTask, extractStructuredContent, extractTextContent, } from '../../utils/test-helpers.js';
3
+ import { ToolNames } from '../../utils/tool-names.js';
4
+ import { addTasks } from '../add-tasks.js';
4
5
  // Mock the Todoist API
5
6
  const mockTodoistApi = {
6
7
  addTask: jest.fn(),
7
8
  };
8
- describe('tasks-add-multiple tool', () => {
9
+ const { ADD_TASKS, GET_OVERVIEW } = ToolNames;
10
+ describe(`${ADD_TASKS} tool`, () => {
9
11
  beforeEach(() => {
10
12
  jest.clearAllMocks();
11
13
  });
@@ -38,7 +40,7 @@ describe('tasks-add-multiple tool', () => {
38
40
  mockTodoistApi.addTask
39
41
  .mockResolvedValueOnce(mockApiResponse1)
40
42
  .mockResolvedValueOnce(mockApiResponse2);
41
- const result = await tasksAddMultiple.execute({
43
+ const result = await addTasks.execute({
42
44
  projectId: '6cfCcrrCFg2xP94Q',
43
45
  tasks: [
44
46
  { content: 'First task content' },
@@ -67,23 +69,18 @@ describe('tasks-add-multiple tool', () => {
67
69
  sectionId: undefined,
68
70
  parentId: undefined,
69
71
  });
70
- // Verify result is properly mapped
71
- expect(result).toEqual([
72
- expect.objectContaining({
73
- id: '8485093748',
74
- content: 'First task content',
75
- description: '',
76
- labels: [],
77
- }),
78
- expect.objectContaining({
79
- id: '8485093749',
80
- content: 'Second task content',
81
- description: 'Task description',
82
- dueDate: '2025-08-15',
83
- priority: 2,
84
- labels: ['work', 'urgent'],
85
- }),
86
- ]);
72
+ // Verify result is a concise summary
73
+ expect(extractTextContent(result)).toMatchSnapshot();
74
+ // Verify structured content
75
+ const structuredContent = extractStructuredContent(result);
76
+ expect(structuredContent.tasks).toHaveLength(2);
77
+ expect(structuredContent).toEqual(expect.objectContaining({
78
+ totalCount: 2,
79
+ tasks: expect.arrayContaining([
80
+ expect.objectContaining({ id: '8485093748' }),
81
+ expect.objectContaining({ id: '8485093749' }),
82
+ ]),
83
+ }));
87
84
  });
88
85
  it('should handle tasks with section and parent IDs', async () => {
89
86
  const mockApiResponse = createMockTask({
@@ -97,7 +94,7 @@ describe('tasks-add-multiple tool', () => {
97
94
  addedAt: '2025-08-13T22:09:58.123456Z',
98
95
  });
99
96
  mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
100
- const result = await tasksAddMultiple.execute({
97
+ const result = await addTasks.execute({
101
98
  projectId: '6cfCcrrCFg2xP94Q',
102
99
  sectionId: 'section-123',
103
100
  parentId: 'parent-task-456',
@@ -117,17 +114,14 @@ describe('tasks-add-multiple tool', () => {
117
114
  sectionId: 'section-123',
118
115
  parentId: 'parent-task-456',
119
116
  });
120
- expect(result).toEqual([
121
- expect.objectContaining({
122
- id: '8485093750',
123
- content: 'Subtask content',
124
- description: 'Subtask description',
125
- priority: 3,
126
- sectionId: 'section-123',
127
- parentId: 'parent-task-456',
128
- labels: [],
129
- }),
130
- ]);
117
+ // Verify result is a concise summary
118
+ expect(extractTextContent(result)).toMatchSnapshot();
119
+ // Verify structured content
120
+ const structuredContent = extractStructuredContent(result);
121
+ expect(structuredContent).toEqual(expect.objectContaining({
122
+ totalCount: 1,
123
+ tasks: expect.arrayContaining([expect.objectContaining({ id: '8485093750' })]),
124
+ }));
131
125
  });
132
126
  it('should add tasks with duration', async () => {
133
127
  const mockApiResponse1 = createMockTask({
@@ -147,17 +141,11 @@ describe('tasks-add-multiple tool', () => {
147
141
  mockTodoistApi.addTask
148
142
  .mockResolvedValueOnce(mockApiResponse1)
149
143
  .mockResolvedValueOnce(mockApiResponse2);
150
- const result = await tasksAddMultiple.execute({
144
+ const result = await addTasks.execute({
151
145
  projectId: '6cfCcrrCFg2xP94Q',
152
146
  tasks: [
153
- {
154
- content: 'Task with 2 hour duration',
155
- duration: '2h',
156
- },
157
- {
158
- content: 'Task with 45 minute duration',
159
- duration: '45m',
160
- },
147
+ { content: 'Task with 2 hour duration', duration: '2h' },
148
+ { content: 'Task with 45 minute duration', duration: '45m' },
161
149
  ],
162
150
  }, mockTodoistApi);
163
151
  // Verify API was called with parsed duration
@@ -177,19 +165,18 @@ describe('tasks-add-multiple tool', () => {
177
165
  duration: 45,
178
166
  durationUnit: 'minute',
179
167
  });
180
- // Verify result includes formatted duration
181
- expect(result).toEqual([
182
- expect.objectContaining({
183
- id: '8485093752',
184
- content: 'Task with 2 hour duration',
185
- duration: '2h',
186
- }),
187
- expect.objectContaining({
188
- id: '8485093753',
189
- content: 'Task with 45 minute duration',
190
- duration: '45m',
191
- }),
192
- ]);
168
+ // Verify result is a concise summary
169
+ expect(extractTextContent(result)).toMatchSnapshot();
170
+ // Verify structured content
171
+ const structuredContent = extractStructuredContent(result);
172
+ expect(structuredContent.tasks).toHaveLength(2);
173
+ expect(structuredContent).toEqual(expect.objectContaining({
174
+ totalCount: 2,
175
+ tasks: expect.arrayContaining([
176
+ expect.objectContaining({ id: '8485093752' }),
177
+ expect.objectContaining({ id: '8485093753' }),
178
+ ]),
179
+ }));
193
180
  });
194
181
  it('should handle various duration formats', async () => {
195
182
  const mockApiResponse = createMockTask({
@@ -209,14 +196,7 @@ describe('tasks-add-multiple tool', () => {
209
196
  ];
210
197
  for (const testCase of testCases) {
211
198
  mockTodoistApi.addTask.mockClear();
212
- await tasksAddMultiple.execute({
213
- tasks: [
214
- {
215
- content: 'Test task',
216
- duration: testCase.input,
217
- },
218
- ],
219
- }, mockTodoistApi);
199
+ await addTasks.execute({ tasks: [{ content: 'Test task', duration: testCase.input }] }, mockTodoistApi);
220
200
  expect(mockTodoistApi.addTask).toHaveBeenCalledWith(expect.objectContaining({
221
201
  duration: testCase.expectedMinutes,
222
202
  durationUnit: 'minute',
@@ -226,29 +206,15 @@ describe('tasks-add-multiple tool', () => {
226
206
  });
227
207
  describe('error handling', () => {
228
208
  it('should throw error for invalid duration format', async () => {
229
- await expect(tasksAddMultiple.execute({
230
- tasks: [
231
- {
232
- content: 'Task with invalid duration',
233
- duration: 'invalid',
234
- },
235
- ],
236
- }, mockTodoistApi)).rejects.toThrow('Task "Task with invalid duration": Invalid duration format "invalid"');
209
+ await expect(addTasks.execute({ tasks: [{ content: 'Task with invalid duration', duration: 'invalid' }] }, mockTodoistApi)).rejects.toThrow('Task "Task with invalid duration": Invalid duration format "invalid"');
237
210
  });
238
211
  it('should throw error for duration exceeding 24 hours', async () => {
239
- await expect(tasksAddMultiple.execute({
240
- tasks: [
241
- {
242
- content: 'Task with too long duration',
243
- duration: '25h',
244
- },
245
- ],
246
- }, mockTodoistApi)).rejects.toThrow('Task "Task with too long duration": Invalid duration format "25h": Duration cannot exceed 24 hours (1440 minutes)');
212
+ await expect(addTasks.execute({ tasks: [{ content: 'Task with too long duration', duration: '25h' }] }, mockTodoistApi)).rejects.toThrow('Task "Task with too long duration": Invalid duration format "25h": Duration cannot exceed 24 hours (1440 minutes)');
247
213
  });
248
214
  it('should propagate API errors', async () => {
249
215
  const apiError = new Error('API Error: Task content is required');
250
216
  mockTodoistApi.addTask.mockRejectedValue(apiError);
251
- await expect(tasksAddMultiple.execute({ tasks: [{ content: '' }] }, mockTodoistApi)).rejects.toThrow(apiError.message);
217
+ await expect(addTasks.execute({ tasks: [{ content: '' }] }, mockTodoistApi)).rejects.toThrow(apiError.message);
252
218
  });
253
219
  it('should handle partial failures when adding multiple tasks', async () => {
254
220
  const mockApiResponse = createMockTask({
@@ -261,7 +227,7 @@ describe('tasks-add-multiple tool', () => {
261
227
  mockTodoistApi.addTask
262
228
  .mockResolvedValueOnce(mockApiResponse)
263
229
  .mockRejectedValueOnce(apiError);
264
- await expect(tasksAddMultiple.execute({
230
+ await expect(addTasks.execute({
265
231
  tasks: [
266
232
  { content: 'First task content' },
267
233
  { content: 'Second task content' },
@@ -271,4 +237,42 @@ describe('tasks-add-multiple tool', () => {
271
237
  expect(mockTodoistApi.addTask).toHaveBeenCalledTimes(2);
272
238
  });
273
239
  });
240
+ describe('next steps logic', () => {
241
+ it('should suggest find-tasks-by-date for today when hasToday is true', async () => {
242
+ const mockApiResponse = createMockTask({
243
+ id: '8485093755',
244
+ content: 'Task due today',
245
+ url: 'https://todoist.com/showTask?id=8485093755',
246
+ addedAt: '2025-08-13T22:09:56.123456Z',
247
+ due: {
248
+ date: TODAY,
249
+ isRecurring: false,
250
+ lang: 'en',
251
+ string: 'today',
252
+ timezone: null,
253
+ },
254
+ });
255
+ mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
256
+ const result = await addTasks.execute({ tasks: [{ content: 'Task due today', dueString: 'today' }] }, mockTodoistApi);
257
+ const textContent = extractTextContent(result);
258
+ expect(textContent).toMatchSnapshot();
259
+ expect(textContent).toContain(`Use ${GET_OVERVIEW} to see your updated project organization`);
260
+ });
261
+ it('should suggest overview tool when no hasToday context', async () => {
262
+ const mockApiResponse = createMockTask({
263
+ id: '8485093756',
264
+ content: 'Regular task',
265
+ url: 'https://todoist.com/showTask?id=8485093756',
266
+ addedAt: '2025-08-13T22:09:56.123456Z',
267
+ });
268
+ mockTodoistApi.addTask.mockResolvedValue(mockApiResponse);
269
+ const result = await addTasks.execute({
270
+ projectId: '6cfCcrrCFg2xP94Q',
271
+ tasks: [{ content: 'Regular task' }],
272
+ }, mockTodoistApi);
273
+ const textContent = extractTextContent(result);
274
+ expect(textContent).toMatchSnapshot();
275
+ expect(textContent).toContain(`Use ${GET_OVERVIEW} to see your updated project organization`);
276
+ });
277
+ });
274
278
  });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=complete-tasks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complete-tasks.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/complete-tasks.test.ts"],"names":[],"mappings":""}