@doist/todoist-ai 2.2.2 → 4.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.
- package/README.md +6 -14
- package/dist/index.d.ts +619 -250
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -29
- package/dist/main.js +2 -1
- package/dist/mcp-helpers.d.ts +25 -3
- package/dist/mcp-helpers.d.ts.map +1 -1
- package/dist/mcp-helpers.js +37 -19
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +44 -28
- package/dist/tools/__tests__/add-comments.test.d.ts +2 -0
- package/dist/tools/__tests__/add-comments.test.d.ts.map +1 -0
- package/dist/tools/__tests__/add-comments.test.js +241 -0
- package/dist/tools/__tests__/add-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/add-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/add-projects.test.js +152 -0
- package/dist/tools/__tests__/add-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/add-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/add-sections.test.js +181 -0
- package/dist/tools/__tests__/add-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/add-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-add-multiple.test.js → add-tasks.test.js} +89 -79
- package/dist/tools/__tests__/complete-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/complete-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/complete-tasks.test.js +206 -0
- package/dist/tools/__tests__/delete-object.test.d.ts +2 -0
- package/dist/tools/__tests__/delete-object.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{delete-one.test.js → delete-object.test.js} +42 -22
- package/dist/tools/__tests__/find-comments.test.d.ts +2 -0
- package/dist/tools/__tests__/find-comments.test.d.ts.map +1 -0
- package/dist/tools/__tests__/find-comments.test.js +242 -0
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-list-completed.test.js → find-completed-tasks.test.js} +13 -36
- package/dist/tools/__tests__/find-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/find-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{projects-list.test.js → find-projects.test.js} +55 -39
- package/dist/tools/__tests__/find-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/find-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{sections-search.test.js → find-sections.test.js} +64 -50
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts +2 -0
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-list-by-date.test.js → find-tasks-by-date.test.js} +96 -14
- package/dist/tools/__tests__/find-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/find-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/find-tasks.test.js +334 -0
- package/dist/tools/__tests__/get-overview.test.d.ts +2 -0
- package/dist/tools/__tests__/get-overview.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{overview.test.js → get-overview.test.js} +77 -13
- package/dist/tools/__tests__/update-comments.test.d.ts +2 -0
- package/dist/tools/__tests__/update-comments.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-comments.test.js +296 -0
- package/dist/tools/__tests__/update-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/update-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-projects.test.js +205 -0
- package/dist/tools/__tests__/update-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/update-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-sections.test.js +156 -0
- package/dist/tools/__tests__/update-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/update-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-tasks.test.js +645 -0
- package/dist/tools/add-comments.d.ts +51 -0
- package/dist/tools/add-comments.d.ts.map +1 -0
- package/dist/tools/add-comments.js +79 -0
- package/dist/tools/add-projects.d.ts +50 -0
- package/dist/tools/add-projects.d.ts.map +1 -0
- package/dist/tools/add-projects.js +59 -0
- package/dist/tools/add-sections.d.ts +46 -0
- package/dist/tools/add-sections.d.ts.map +1 -0
- package/dist/tools/add-sections.js +61 -0
- package/dist/tools/add-tasks.d.ts +82 -0
- package/dist/tools/add-tasks.d.ts.map +1 -0
- package/dist/tools/add-tasks.js +96 -0
- package/dist/tools/complete-tasks.d.ts +40 -0
- package/dist/tools/complete-tasks.d.ts.map +1 -0
- package/dist/tools/complete-tasks.js +68 -0
- package/dist/tools/delete-object.d.ts +38 -0
- package/dist/tools/delete-object.d.ts.map +1 -0
- package/dist/tools/delete-object.js +79 -0
- package/dist/tools/find-comments.d.ts +46 -0
- package/dist/tools/find-comments.d.ts.map +1 -0
- package/dist/tools/find-comments.js +143 -0
- package/dist/tools/find-completed-tasks.d.ts +74 -0
- package/dist/tools/find-completed-tasks.d.ts.map +1 -0
- package/dist/tools/find-completed-tasks.js +112 -0
- package/dist/tools/find-projects.d.ts +53 -0
- package/dist/tools/find-projects.d.ts.map +1 -0
- package/dist/tools/find-projects.js +101 -0
- package/dist/tools/find-sections.d.ts +42 -0
- package/dist/tools/find-sections.d.ts.map +1 -0
- package/dist/tools/find-sections.js +96 -0
- package/dist/tools/find-tasks-by-date.d.ts +59 -0
- package/dist/tools/find-tasks-by-date.d.ts.map +1 -0
- package/dist/tools/find-tasks-by-date.js +121 -0
- package/dist/tools/find-tasks.d.ts +65 -0
- package/dist/tools/find-tasks.d.ts.map +1 -0
- package/dist/tools/find-tasks.js +182 -0
- package/dist/tools/get-overview.d.ts +67 -0
- package/dist/tools/get-overview.d.ts.map +1 -0
- package/dist/tools/{overview.js → get-overview.js} +66 -19
- package/dist/tools/update-comments.d.ts +50 -0
- package/dist/tools/update-comments.d.ts.map +1 -0
- package/dist/tools/update-comments.js +82 -0
- package/dist/tools/update-projects.d.ts +59 -0
- package/dist/tools/update-projects.d.ts.map +1 -0
- package/dist/tools/update-projects.js +84 -0
- package/dist/tools/update-sections.d.ts +47 -0
- package/dist/tools/update-sections.d.ts.map +1 -0
- package/dist/tools/update-sections.js +70 -0
- package/dist/tools/update-tasks.d.ts +94 -0
- package/dist/tools/update-tasks.d.ts.map +1 -0
- package/dist/tools/update-tasks.js +120 -0
- package/dist/utils/constants.d.ts +39 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +41 -0
- package/dist/utils/response-builders.d.ts +88 -0
- package/dist/utils/response-builders.d.ts.map +1 -0
- package/dist/utils/response-builders.js +202 -0
- package/dist/{tools → utils}/test-helpers.d.ts +16 -0
- package/dist/utils/test-helpers.d.ts.map +1 -0
- package/dist/{tools → utils}/test-helpers.js +51 -0
- package/dist/utils/tool-names.d.ts +28 -0
- package/dist/utils/tool-names.d.ts.map +1 -0
- package/dist/utils/tool-names.js +31 -0
- package/package.json +1 -1
- package/dist/tools/__tests__/delete-one.test.d.ts +0 -2
- package/dist/tools/__tests__/delete-one.test.d.ts.map +0 -1
- package/dist/tools/__tests__/overview.test.d.ts +0 -2
- package/dist/tools/__tests__/overview.test.d.ts.map +0 -1
- package/dist/tools/__tests__/projects-list.test.d.ts +0 -2
- package/dist/tools/__tests__/projects-list.test.d.ts.map +0 -1
- package/dist/tools/__tests__/projects-manage.test.d.ts +0 -2
- package/dist/tools/__tests__/projects-manage.test.d.ts.map +0 -1
- package/dist/tools/__tests__/projects-manage.test.js +0 -106
- package/dist/tools/__tests__/sections-manage.test.d.ts +0 -2
- package/dist/tools/__tests__/sections-manage.test.d.ts.map +0 -1
- package/dist/tools/__tests__/sections-manage.test.js +0 -138
- package/dist/tools/__tests__/sections-search.test.d.ts +0 -2
- package/dist/tools/__tests__/sections-search.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-add-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-add-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-complete-multiple.test.js +0 -146
- package/dist/tools/__tests__/tasks-list-by-date.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-by-date.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-completed.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-completed.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-for-container.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-for-container.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-for-container.test.js +0 -232
- package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-organize-multiple.test.js +0 -245
- package/dist/tools/__tests__/tasks-search.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-search.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-search.test.js +0 -106
- package/dist/tools/__tests__/tasks-update-one.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-update-one.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-update-one.test.js +0 -251
- package/dist/tools/delete-one.d.ts +0 -17
- package/dist/tools/delete-one.d.ts.map +0 -1
- package/dist/tools/delete-one.js +0 -25
- package/dist/tools/overview.d.ts +0 -14
- package/dist/tools/overview.d.ts.map +0 -1
- package/dist/tools/projects-list.d.ts +0 -29
- package/dist/tools/projects-list.d.ts.map +0 -1
- package/dist/tools/projects-list.js +0 -39
- package/dist/tools/projects-manage.d.ts +0 -24
- package/dist/tools/projects-manage.d.ts.map +0 -1
- package/dist/tools/projects-manage.js +0 -26
- package/dist/tools/sections-manage.d.ts +0 -23
- package/dist/tools/sections-manage.d.ts.map +0 -1
- package/dist/tools/sections-manage.js +0 -37
- package/dist/tools/sections-search.d.ts +0 -18
- package/dist/tools/sections-search.d.ts.map +0 -1
- package/dist/tools/sections-search.js +0 -27
- package/dist/tools/tasks-add-multiple.d.ts +0 -55
- package/dist/tools/tasks-add-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-add-multiple.js +0 -52
- package/dist/tools/tasks-complete-multiple.d.ts +0 -16
- package/dist/tools/tasks-complete-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-complete-multiple.js +0 -23
- package/dist/tools/tasks-list-by-date.d.ts +0 -34
- package/dist/tools/tasks-list-by-date.d.ts.map +0 -1
- package/dist/tools/tasks-list-by-date.js +0 -53
- package/dist/tools/tasks-list-completed.d.ts +0 -44
- package/dist/tools/tasks-list-completed.d.ts.map +0 -1
- package/dist/tools/tasks-list-completed.js +0 -49
- package/dist/tools/tasks-list-for-container.d.ts +0 -34
- package/dist/tools/tasks-list-for-container.d.ts.map +0 -1
- package/dist/tools/tasks-list-for-container.js +0 -48
- package/dist/tools/tasks-organize-multiple.d.ts +0 -37
- package/dist/tools/tasks-organize-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-organize-multiple.js +0 -34
- package/dist/tools/tasks-search.d.ts +0 -32
- package/dist/tools/tasks-search.d.ts.map +0 -1
- package/dist/tools/tasks-search.js +0 -30
- package/dist/tools/tasks-update-one.d.ts +0 -29
- package/dist/tools/tasks-update-one.d.ts.map +0 -1
- package/dist/tools/tasks-update-one.js +0 -63
- package/dist/tools/test-helpers.d.ts.map +0 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,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,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAG3D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmBV,CAAA;AAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAA;AAE9B,OAAO,EAEH,QAAQ,EACR,aAAa,EACb,WAAW,EACX,SAAS,EACT,eAAe,EACf,kBAAkB,EAElB,WAAW,EACX,cAAc,EACd,YAAY,EAEZ,WAAW,EACX,cAAc,EACd,YAAY,EAEZ,WAAW,EACX,YAAY,GACf,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,33 +1,49 @@
|
|
|
1
1
|
import { getMcpServer } from './mcp-server.js';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
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 { addProjects } from './tools/add-projects.js';
|
|
11
|
+
import { findProjects } from './tools/find-projects.js';
|
|
12
|
+
import { updateProjects } from './tools/update-projects.js';
|
|
13
|
+
// Section management tools
|
|
14
|
+
import { addSections } from './tools/add-sections.js';
|
|
15
|
+
import { findSections } from './tools/find-sections.js';
|
|
16
|
+
import { updateSections } from './tools/update-sections.js';
|
|
17
|
+
// General tools
|
|
18
|
+
import { deleteObject } from './tools/delete-object.js';
|
|
19
|
+
import { getOverview } from './tools/get-overview.js';
|
|
16
20
|
const tools = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
// Task management tools
|
|
22
|
+
addTasks,
|
|
23
|
+
completeTasks,
|
|
24
|
+
updateTasks,
|
|
25
|
+
findTasks,
|
|
26
|
+
findTasksByDate,
|
|
27
|
+
findCompletedTasks,
|
|
28
|
+
// Project management tools
|
|
29
|
+
addProjects,
|
|
30
|
+
updateProjects,
|
|
31
|
+
findProjects,
|
|
32
|
+
// Section management tools
|
|
33
|
+
addSections,
|
|
34
|
+
updateSections,
|
|
35
|
+
findSections,
|
|
36
|
+
// General tools
|
|
37
|
+
getOverview,
|
|
38
|
+
deleteObject,
|
|
31
39
|
};
|
|
32
40
|
export { tools, getMcpServer };
|
|
33
|
-
export {
|
|
41
|
+
export {
|
|
42
|
+
// Task management tools
|
|
43
|
+
addTasks, completeTasks, updateTasks, findTasks, findTasksByDate, findCompletedTasks,
|
|
44
|
+
// Project management tools
|
|
45
|
+
addProjects, updateProjects, findProjects,
|
|
46
|
+
// Section management tools
|
|
47
|
+
addSections, updateSections, findSections,
|
|
48
|
+
// General tools
|
|
49
|
+
getOverview, deleteObject, };
|
package/dist/main.js
CHANGED
|
@@ -3,11 +3,12 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
3
3
|
import dotenv from 'dotenv';
|
|
4
4
|
import { getMcpServer } from './mcp-server.js';
|
|
5
5
|
function main() {
|
|
6
|
+
const baseUrl = process.env.TODOIST_BASE_URL;
|
|
6
7
|
const todoistApiKey = process.env.TODOIST_API_KEY;
|
|
7
8
|
if (!todoistApiKey) {
|
|
8
9
|
throw new Error('TODOIST_API_KEY is not set');
|
|
9
10
|
}
|
|
10
|
-
const server = getMcpServer({ todoistApiKey });
|
|
11
|
+
const server = getMcpServer({ todoistApiKey, baseUrl });
|
|
11
12
|
const transport = new StdioServerTransport();
|
|
12
13
|
server
|
|
13
14
|
.connect(transport)
|
package/dist/mcp-helpers.d.ts
CHANGED
|
@@ -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
|
-
|
|
6
|
-
|
|
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,
|
|
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;
|
|
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"}
|
package/dist/mcp-helpers.js
CHANGED
|
@@ -1,25 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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
|
|
18
|
-
return typeof data === 'string' ? textContent(data) : jsonContent(data);
|
|
19
|
-
}
|
|
20
|
-
function errorContent(error) {
|
|
38
|
+
function getErrorOutput(error) {
|
|
21
39
|
return {
|
|
22
|
-
|
|
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
|
|
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
|
|
63
|
+
return getErrorOutput(message);
|
|
46
64
|
}
|
|
47
65
|
};
|
|
48
66
|
server.tool(tool.name, tool.description, tool.parameters, cb);
|
|
49
67
|
}
|
|
50
|
-
export { registerTool,
|
|
68
|
+
export { registerTool, getToolOutput };
|
package/dist/mcp-server.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAkCnE;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,aAyC5F;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
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
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
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 { addProjects } from './tools/add-projects.js';
|
|
13
|
+
import { findProjects } from './tools/find-projects.js';
|
|
14
|
+
import { updateProjects } from './tools/update-projects.js';
|
|
15
|
+
// Section management tools
|
|
16
|
+
import { addSections } from './tools/add-sections.js';
|
|
17
|
+
import { findSections } from './tools/find-sections.js';
|
|
18
|
+
import { updateSections } from './tools/update-sections.js';
|
|
19
|
+
// Comment management tools
|
|
20
|
+
import { addComments } from './tools/add-comments.js';
|
|
21
|
+
import { findComments } from './tools/find-comments.js';
|
|
22
|
+
import { updateComments } from './tools/update-comments.js';
|
|
23
|
+
// General tools
|
|
24
|
+
import { deleteObject } from './tools/delete-object.js';
|
|
25
|
+
import { getOverview } from './tools/get-overview.js';
|
|
18
26
|
const instructions = `
|
|
19
27
|
Tools to help you manage your todoist tasks.
|
|
20
28
|
`;
|
|
@@ -32,20 +40,28 @@ function getMcpServer({ todoistApiKey, baseUrl }) {
|
|
|
32
40
|
instructions,
|
|
33
41
|
});
|
|
34
42
|
const todoist = new TodoistApi(todoistApiKey, baseUrl);
|
|
35
|
-
|
|
36
|
-
registerTool(
|
|
37
|
-
registerTool(
|
|
38
|
-
registerTool(
|
|
39
|
-
registerTool(
|
|
40
|
-
registerTool(
|
|
41
|
-
registerTool(
|
|
42
|
-
|
|
43
|
-
registerTool(
|
|
44
|
-
registerTool(
|
|
45
|
-
registerTool(
|
|
46
|
-
|
|
47
|
-
registerTool(
|
|
48
|
-
registerTool(
|
|
43
|
+
// Task management tools
|
|
44
|
+
registerTool(addTasks, server, todoist);
|
|
45
|
+
registerTool(completeTasks, server, todoist);
|
|
46
|
+
registerTool(updateTasks, server, todoist);
|
|
47
|
+
registerTool(findTasks, server, todoist);
|
|
48
|
+
registerTool(findTasksByDate, server, todoist);
|
|
49
|
+
registerTool(findCompletedTasks, server, todoist);
|
|
50
|
+
// Project management tools
|
|
51
|
+
registerTool(addProjects, server, todoist);
|
|
52
|
+
registerTool(updateProjects, server, todoist);
|
|
53
|
+
registerTool(findProjects, server, todoist);
|
|
54
|
+
// Section management tools
|
|
55
|
+
registerTool(addSections, server, todoist);
|
|
56
|
+
registerTool(updateSections, server, todoist);
|
|
57
|
+
registerTool(findSections, server, todoist);
|
|
58
|
+
// Comment management tools
|
|
59
|
+
registerTool(addComments, server, todoist);
|
|
60
|
+
registerTool(findComments, server, todoist);
|
|
61
|
+
registerTool(updateComments, server, todoist);
|
|
62
|
+
// General tools
|
|
63
|
+
registerTool(getOverview, server, todoist);
|
|
64
|
+
registerTool(deleteObject, server, todoist);
|
|
49
65
|
return server;
|
|
50
66
|
}
|
|
51
67
|
export { getMcpServer };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-comments.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-comments.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { extractStructuredContent, extractTextContent } from '../../utils/test-helpers.js';
|
|
3
|
+
import { ToolNames } from '../../utils/tool-names.js';
|
|
4
|
+
import { addComments } from '../add-comments.js';
|
|
5
|
+
// Mock the Todoist API
|
|
6
|
+
const mockTodoistApi = {
|
|
7
|
+
addComment: jest.fn(),
|
|
8
|
+
};
|
|
9
|
+
const { ADD_COMMENTS } = ToolNames;
|
|
10
|
+
const createMockComment = (overrides = {}) => ({
|
|
11
|
+
id: '12345',
|
|
12
|
+
content: 'Test comment content',
|
|
13
|
+
postedAt: '2024-01-01T12:00:00Z',
|
|
14
|
+
postedUid: 'user123',
|
|
15
|
+
taskId: 'task123',
|
|
16
|
+
projectId: undefined,
|
|
17
|
+
fileAttachment: null,
|
|
18
|
+
uidsToNotify: null,
|
|
19
|
+
reactions: null,
|
|
20
|
+
isDeleted: false,
|
|
21
|
+
...overrides,
|
|
22
|
+
});
|
|
23
|
+
describe(`${ADD_COMMENTS} tool`, () => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
jest.clearAllMocks();
|
|
26
|
+
});
|
|
27
|
+
describe('adding comments to tasks', () => {
|
|
28
|
+
it('should add comment to task', async () => {
|
|
29
|
+
const mockComment = createMockComment({
|
|
30
|
+
id: '98765',
|
|
31
|
+
content: 'This is a task comment',
|
|
32
|
+
taskId: 'task456',
|
|
33
|
+
});
|
|
34
|
+
mockTodoistApi.addComment.mockResolvedValue(mockComment);
|
|
35
|
+
const result = await addComments.execute({ comments: [{ taskId: 'task456', content: 'This is a task comment' }] }, mockTodoistApi);
|
|
36
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
37
|
+
content: 'This is a task comment',
|
|
38
|
+
taskId: 'task456',
|
|
39
|
+
});
|
|
40
|
+
// Verify result is a concise summary
|
|
41
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
42
|
+
// Verify structured content
|
|
43
|
+
const structuredContent = extractStructuredContent(result);
|
|
44
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
45
|
+
comments: [
|
|
46
|
+
expect.objectContaining({
|
|
47
|
+
id: '98765',
|
|
48
|
+
content: 'This is a task comment',
|
|
49
|
+
taskId: 'task456',
|
|
50
|
+
}),
|
|
51
|
+
],
|
|
52
|
+
totalCount: 1,
|
|
53
|
+
addedCommentIds: ['98765'],
|
|
54
|
+
}));
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe('adding comments to projects', () => {
|
|
58
|
+
it('should add comment to project', async () => {
|
|
59
|
+
const mockComment = createMockComment({
|
|
60
|
+
id: '98767',
|
|
61
|
+
content: 'This is a project comment',
|
|
62
|
+
taskId: undefined,
|
|
63
|
+
projectId: 'project789',
|
|
64
|
+
});
|
|
65
|
+
mockTodoistApi.addComment.mockResolvedValue(mockComment);
|
|
66
|
+
const result = await addComments.execute({ comments: [{ projectId: 'project789', content: 'This is a project comment' }] }, mockTodoistApi);
|
|
67
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
68
|
+
content: 'This is a project comment',
|
|
69
|
+
projectId: 'project789',
|
|
70
|
+
});
|
|
71
|
+
// Verify result is a concise summary
|
|
72
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
73
|
+
// Verify structured content
|
|
74
|
+
const structuredContent = extractStructuredContent(result);
|
|
75
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
76
|
+
comments: [
|
|
77
|
+
expect.objectContaining({
|
|
78
|
+
id: '98767',
|
|
79
|
+
content: 'This is a project comment',
|
|
80
|
+
taskId: undefined,
|
|
81
|
+
projectId: 'project789',
|
|
82
|
+
}),
|
|
83
|
+
],
|
|
84
|
+
totalCount: 1,
|
|
85
|
+
addedCommentIds: ['98767'],
|
|
86
|
+
}));
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe('bulk operations', () => {
|
|
90
|
+
it('should add multiple comments to different entities (task + project)', async () => {
|
|
91
|
+
const mockTaskComment = createMockComment({
|
|
92
|
+
id: '11111',
|
|
93
|
+
content: 'Task comment',
|
|
94
|
+
taskId: 'task123',
|
|
95
|
+
projectId: undefined,
|
|
96
|
+
});
|
|
97
|
+
const mockProjectComment = createMockComment({
|
|
98
|
+
id: '22222',
|
|
99
|
+
content: 'Project comment',
|
|
100
|
+
taskId: undefined,
|
|
101
|
+
projectId: 'project456',
|
|
102
|
+
});
|
|
103
|
+
mockTodoistApi.addComment
|
|
104
|
+
.mockResolvedValueOnce(mockTaskComment)
|
|
105
|
+
.mockResolvedValueOnce(mockProjectComment);
|
|
106
|
+
const result = await addComments.execute({
|
|
107
|
+
comments: [
|
|
108
|
+
{ taskId: 'task123', content: 'Task comment' },
|
|
109
|
+
{ projectId: 'project456', content: 'Project comment' },
|
|
110
|
+
],
|
|
111
|
+
}, mockTodoistApi);
|
|
112
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledTimes(2);
|
|
113
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
114
|
+
content: 'Task comment',
|
|
115
|
+
taskId: 'task123',
|
|
116
|
+
});
|
|
117
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
118
|
+
content: 'Project comment',
|
|
119
|
+
projectId: 'project456',
|
|
120
|
+
});
|
|
121
|
+
// Verify result is a concise summary
|
|
122
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
123
|
+
const structuredContent = extractStructuredContent(result);
|
|
124
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
125
|
+
comments: [
|
|
126
|
+
expect.objectContaining({
|
|
127
|
+
id: '11111',
|
|
128
|
+
content: 'Task comment',
|
|
129
|
+
taskId: 'task123',
|
|
130
|
+
}),
|
|
131
|
+
expect.objectContaining({
|
|
132
|
+
id: '22222',
|
|
133
|
+
content: 'Project comment',
|
|
134
|
+
projectId: 'project456',
|
|
135
|
+
}),
|
|
136
|
+
],
|
|
137
|
+
totalCount: 2,
|
|
138
|
+
addedCommentIds: ['11111', '22222'],
|
|
139
|
+
}));
|
|
140
|
+
});
|
|
141
|
+
it('should add multiple comments to different tasks', async () => {
|
|
142
|
+
const mockComment1 = createMockComment({
|
|
143
|
+
id: '33333',
|
|
144
|
+
content: 'First task comment',
|
|
145
|
+
taskId: 'task111',
|
|
146
|
+
});
|
|
147
|
+
const mockComment2 = createMockComment({
|
|
148
|
+
id: '44444',
|
|
149
|
+
content: 'Second task comment',
|
|
150
|
+
taskId: 'task222',
|
|
151
|
+
});
|
|
152
|
+
mockTodoistApi.addComment
|
|
153
|
+
.mockResolvedValueOnce(mockComment1)
|
|
154
|
+
.mockResolvedValueOnce(mockComment2);
|
|
155
|
+
const result = await addComments.execute({
|
|
156
|
+
comments: [
|
|
157
|
+
{ taskId: 'task111', content: 'First task comment' },
|
|
158
|
+
{ taskId: 'task222', content: 'Second task comment' },
|
|
159
|
+
],
|
|
160
|
+
}, mockTodoistApi);
|
|
161
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledTimes(2);
|
|
162
|
+
// Verify result is a concise summary
|
|
163
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
164
|
+
const structuredContent = extractStructuredContent(result);
|
|
165
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
166
|
+
comments: expect.arrayContaining([
|
|
167
|
+
expect.objectContaining({
|
|
168
|
+
id: '33333',
|
|
169
|
+
content: 'First task comment',
|
|
170
|
+
taskId: 'task111',
|
|
171
|
+
}),
|
|
172
|
+
expect.objectContaining({
|
|
173
|
+
id: '44444',
|
|
174
|
+
content: 'Second task comment',
|
|
175
|
+
taskId: 'task222',
|
|
176
|
+
}),
|
|
177
|
+
]),
|
|
178
|
+
totalCount: 2,
|
|
179
|
+
addedCommentIds: ['33333', '44444'],
|
|
180
|
+
}));
|
|
181
|
+
});
|
|
182
|
+
it('should add multiple comments to the same task', async () => {
|
|
183
|
+
const mockComment1 = createMockComment({
|
|
184
|
+
id: '55555',
|
|
185
|
+
content: 'First comment on same task',
|
|
186
|
+
taskId: 'task999',
|
|
187
|
+
});
|
|
188
|
+
const mockComment2 = createMockComment({
|
|
189
|
+
id: '66666',
|
|
190
|
+
content: 'Second comment on same task',
|
|
191
|
+
taskId: 'task999',
|
|
192
|
+
});
|
|
193
|
+
mockTodoistApi.addComment
|
|
194
|
+
.mockResolvedValueOnce(mockComment1)
|
|
195
|
+
.mockResolvedValueOnce(mockComment2);
|
|
196
|
+
const result = await addComments.execute({
|
|
197
|
+
comments: [
|
|
198
|
+
{ taskId: 'task999', content: 'First comment on same task' },
|
|
199
|
+
{ taskId: 'task999', content: 'Second comment on same task' },
|
|
200
|
+
],
|
|
201
|
+
}, mockTodoistApi);
|
|
202
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledTimes(2);
|
|
203
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
204
|
+
content: 'First comment on same task',
|
|
205
|
+
taskId: 'task999',
|
|
206
|
+
});
|
|
207
|
+
expect(mockTodoistApi.addComment).toHaveBeenCalledWith({
|
|
208
|
+
content: 'Second comment on same task',
|
|
209
|
+
taskId: 'task999',
|
|
210
|
+
});
|
|
211
|
+
// Verify result is a concise summary
|
|
212
|
+
expect(extractTextContent(result)).toMatchSnapshot();
|
|
213
|
+
const structuredContent = extractStructuredContent(result);
|
|
214
|
+
expect(structuredContent).toEqual(expect.objectContaining({
|
|
215
|
+
comments: expect.arrayContaining([
|
|
216
|
+
expect.objectContaining({
|
|
217
|
+
id: '55555',
|
|
218
|
+
content: 'First comment on same task',
|
|
219
|
+
taskId: 'task999',
|
|
220
|
+
}),
|
|
221
|
+
expect.objectContaining({
|
|
222
|
+
id: '66666',
|
|
223
|
+
content: 'Second comment on same task',
|
|
224
|
+
taskId: 'task999',
|
|
225
|
+
}),
|
|
226
|
+
]),
|
|
227
|
+
totalCount: 2,
|
|
228
|
+
addedCommentIds: ['55555', '66666'],
|
|
229
|
+
}));
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
describe('validation', () => {
|
|
233
|
+
it('should throw error when neither taskId nor projectId provided', async () => {
|
|
234
|
+
await expect(addComments.execute({ comments: [{ content: 'Test comment' }] }, mockTodoistApi)).rejects.toThrow('Comment 1: Either taskId or projectId must be provided.');
|
|
235
|
+
});
|
|
236
|
+
it('should throw error when both taskId and projectId provided', async () => {
|
|
237
|
+
const comment = { taskId: 'task123', projectId: 'project456', content: 'Test comment' };
|
|
238
|
+
await expect(addComments.execute({ comments: [comment] }, mockTodoistApi)).rejects.toThrow('Comment 1: Cannot provide both taskId and projectId. Choose one.');
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-projects.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/add-projects.test.ts"],"names":[],"mappings":""}
|