@doist/todoist-ai 4.13.4 → 4.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ import { addTasks } from './tools/add-tasks.js';
6
6
  import { completeTasks } from './tools/complete-tasks.js';
7
7
  import { deleteObject } from './tools/delete-object.js';
8
8
  import { fetch } from './tools/fetch.js';
9
+ import { findActivity } from './tools/find-activity.js';
9
10
  import { findComments } from './tools/find-comments.js';
10
11
  import { findCompletedTasks } from './tools/find-completed-tasks.js';
11
12
  import { findProjectCollaborators } from './tools/find-project-collaborators.js';
@@ -1091,6 +1092,72 @@ declare const tools: {
1091
1092
  structuredContent?: undefined;
1092
1093
  }>;
1093
1094
  };
1095
+ findActivity: {
1096
+ name: "find-activity";
1097
+ description: string;
1098
+ parameters: {
1099
+ objectType: import("zod").ZodOptional<import("zod").ZodEnum<["task", "project", "comment"]>>;
1100
+ objectId: import("zod").ZodOptional<import("zod").ZodString>;
1101
+ eventType: import("zod").ZodOptional<import("zod").ZodEnum<["added", "updated", "deleted", "completed", "uncompleted", "archived", "unarchived", "shared", "left"]>>;
1102
+ projectId: import("zod").ZodOptional<import("zod").ZodString>;
1103
+ taskId: import("zod").ZodOptional<import("zod").ZodString>;
1104
+ initiatorId: import("zod").ZodOptional<import("zod").ZodString>;
1105
+ limit: import("zod").ZodDefault<import("zod").ZodNumber>;
1106
+ cursor: import("zod").ZodOptional<import("zod").ZodString>;
1107
+ };
1108
+ execute(args: {
1109
+ limit: number;
1110
+ taskId?: string | undefined;
1111
+ projectId?: string | undefined;
1112
+ objectType?: "task" | "comment" | "project" | undefined;
1113
+ objectId?: string | undefined;
1114
+ eventType?: "added" | "updated" | "completed" | "deleted" | "uncompleted" | "archived" | "unarchived" | "shared" | "left" | undefined;
1115
+ initiatorId?: string | undefined;
1116
+ cursor?: string | undefined;
1117
+ }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
1118
+ content: {
1119
+ type: "text";
1120
+ text: string;
1121
+ }[];
1122
+ structuredContent: {
1123
+ events: {
1124
+ id: string | null;
1125
+ objectType: string;
1126
+ objectId: string;
1127
+ eventType: string;
1128
+ eventDate: string;
1129
+ parentProjectId: string | null;
1130
+ parentItemId: string | null;
1131
+ initiatorId: string | null;
1132
+ extraData: Record<string, any> | null;
1133
+ }[];
1134
+ nextCursor: string | null;
1135
+ totalCount: number;
1136
+ hasMore: boolean;
1137
+ appliedFilters: {
1138
+ limit: number;
1139
+ taskId?: string | undefined;
1140
+ projectId?: string | undefined;
1141
+ objectType?: "task" | "comment" | "project" | undefined;
1142
+ objectId?: string | undefined;
1143
+ eventType?: "added" | "updated" | "completed" | "deleted" | "uncompleted" | "archived" | "unarchived" | "shared" | "left" | undefined;
1144
+ initiatorId?: string | undefined;
1145
+ cursor?: string | undefined;
1146
+ };
1147
+ };
1148
+ } | {
1149
+ content: ({
1150
+ type: "text";
1151
+ text: string;
1152
+ mimeType?: undefined;
1153
+ } | {
1154
+ type: "text";
1155
+ mimeType: string;
1156
+ text: string;
1157
+ })[];
1158
+ structuredContent?: undefined;
1159
+ }>;
1160
+ };
1094
1161
  getOverview: {
1095
1162
  name: "get-overview";
1096
1163
  description: string;
@@ -1312,5 +1379,5 @@ declare const tools: {
1312
1379
  };
1313
1380
  };
1314
1381
  export { tools, getMcpServer };
1315
- export { addTasks, completeTasks, updateTasks, findTasks, findTasksByDate, findCompletedTasks, addProjects, updateProjects, findProjects, addSections, updateSections, findSections, addComments, updateComments, findComments, getOverview, deleteObject, userInfo, findProjectCollaborators, manageAssignments, search, fetch, };
1382
+ export { addTasks, completeTasks, updateTasks, findTasks, findTasksByDate, findCompletedTasks, addProjects, updateProjects, findProjects, addSections, updateSections, findSections, addComments, updateComments, findComments, findActivity, getOverview, deleteObject, userInfo, findProjectCollaborators, manageAssignments, search, fetch, };
1316
1383
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -11,6 +11,8 @@ import { completeTasks } from './tools/complete-tasks.js';
11
11
  // General tools
12
12
  import { deleteObject } from './tools/delete-object.js';
13
13
  import { fetch } from './tools/fetch.js';
14
+ // Activity and audit tools
15
+ import { findActivity } from './tools/find-activity.js';
14
16
  import { findComments } from './tools/find-comments.js';
15
17
  import { findCompletedTasks } from './tools/find-completed-tasks.js';
16
18
  // Assignment and collaboration tools
@@ -47,6 +49,8 @@ const tools = {
47
49
  addComments,
48
50
  updateComments,
49
51
  findComments,
52
+ // Activity and audit tools
53
+ findActivity,
50
54
  // General tools
51
55
  getOverview,
52
56
  deleteObject,
@@ -68,6 +72,8 @@ addProjects, updateProjects, findProjects,
68
72
  addSections, updateSections, findSections,
69
73
  // Comment management tools
70
74
  addComments, updateComments, findComments,
75
+ // Activity and audit tools
76
+ findActivity,
71
77
  // General tools
72
78
  getOverview, deleteObject, userInfo,
73
79
  // Assignment and collaboration tools
@@ -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;AA0FnE;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,aAkD5F;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;AA+FnE;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,aAqD5F;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -8,6 +8,7 @@ import { addTasks } from './tools/add-tasks.js';
8
8
  import { completeTasks } from './tools/complete-tasks.js';
9
9
  import { deleteObject } from './tools/delete-object.js';
10
10
  import { fetch } from './tools/fetch.js';
11
+ import { findActivity } from './tools/find-activity.js';
11
12
  import { findComments } from './tools/find-comments.js';
12
13
  import { findCompletedTasks } from './tools/find-completed-tasks.js';
13
14
  import { findProjectCollaborators } from './tools/find-project-collaborators.js';
@@ -43,7 +44,7 @@ You have access to comprehensive Todoist management tools for personal productiv
43
44
  - **complete-tasks**: Mark tasks as done using task IDs
44
45
  - **find-tasks**: Search by text, project/section/parent container, responsible user, or labels. Requires at least one search parameter
45
46
  - **find-tasks-by-date**: Get tasks by date range (startDate: YYYY-MM-DD or 'today' which includes overdue tasks) or specific day counts
46
- - **find-completed-tasks**: View completed tasks by completion date or original due date
47
+ - **find-completed-tasks**: View completed tasks by completion date or original due date (returns all collaborators unless filtered)
47
48
 
48
49
  **Project & Organization:**
49
50
  - **add-projects/update-projects/find-projects**: Manage project lifecycle with names, favorites, and view styles (list/board/calendar)
@@ -55,6 +56,9 @@ You have access to comprehensive Todoist management tools for personal productiv
55
56
  - **find-project-collaborators**: Find team members by name or email for assignments
56
57
  - **manage-assignments**: Bulk assign/unassign/reassign up to 50 tasks with atomic operations and dry-run validation
57
58
 
59
+ **Activity & Audit:**
60
+ - **find-activity**: Retrieve recent activity logs to monitor and audit changes. Shows events from all users by default; use initiatorId to filter by specific user. Filter by object type (task/project/comment), event type (added/updated/deleted/completed/uncompleted/archived/unarchived/shared/left), and specific objects (objectId, projectId, taskId). Useful for tracking who did what and when. Note: Date-based filtering is not supported.
61
+
58
62
  **General Operations:**
59
63
  - **delete-object**: Remove projects, sections, tasks, or comments by type and ID
60
64
  - **user-info**: Get user details including timezone, goals, and plan information
@@ -84,6 +88,7 @@ You have access to comprehensive Todoist management tools for personal productiv
84
88
  - **Task Search**: find-tasks with multiple filters → update-tasks or complete-tasks based on results
85
89
  - **Project Organization**: add-projects → add-sections → add-tasks with projectId and sectionId
86
90
  - **Progress Reviews**: find-completed-tasks with date ranges → get-overview for project summaries
91
+ - **Activity Auditing**: find-activity with event/object filters to track changes, monitor team activity, or investigate specific actions
87
92
 
88
93
  Always provide clear, actionable task titles and descriptions. Use the overview tools to give users context about their workload and project status.
89
94
  `;
@@ -120,6 +125,8 @@ function getMcpServer({ todoistApiKey, baseUrl }) {
120
125
  registerTool(addComments, server, todoist);
121
126
  registerTool(findComments, server, todoist);
122
127
  registerTool(updateComments, server, todoist);
128
+ // Activity and audit tools
129
+ registerTool(findActivity, server, todoist);
123
130
  // General tools
124
131
  registerTool(getOverview, server, todoist);
125
132
  registerTool(deleteObject, server, todoist);
@@ -1,4 +1,4 @@
1
- import type { MoveTaskArgs, PersonalProject, Task, TodoistApi, WorkspaceProject } from '@doist/todoist-api-typescript';
1
+ import type { ActivityEvent, MoveTaskArgs, PersonalProject, Task, TodoistApi, WorkspaceProject } from '@doist/todoist-api-typescript';
2
2
  export { appendToQuery, buildResponsibleUserQueryFilter, filterTasksByResponsibleUser, RESPONSIBLE_USER_FILTERING, type ResponsibleUserFiltering, resolveResponsibleUser, } from './filter-helpers.js';
3
3
  export type Project = PersonalProject | WorkspaceProject;
4
4
  export declare function isPersonalProject(project: Project): project is PersonalProject;
@@ -50,6 +50,22 @@ declare function mapProject(project: Project): {
50
50
  inboxProject: boolean;
51
51
  viewStyle: string;
52
52
  };
53
+ /**
54
+ * Map a single Todoist activity event to a more structured format, for LLM consumption.
55
+ * @param event - The activity event to map.
56
+ * @returns The mapped activity event.
57
+ */
58
+ declare function mapActivityEvent(event: ActivityEvent): {
59
+ id: string | null;
60
+ objectType: string;
61
+ objectId: string;
62
+ eventType: string;
63
+ eventDate: string;
64
+ parentProjectId: string | null;
65
+ parentItemId: string | null;
66
+ initiatorId: string | null;
67
+ extraData: Record<string, any> | null;
68
+ };
53
69
  declare function getTasksByFilter({ client, query, limit, cursor, }: {
54
70
  client: TodoistApi;
55
71
  query: string;
@@ -82,5 +98,5 @@ declare function getTasksByFilter({ client, query, limit, cursor, }: {
82
98
  * @returns The URL string
83
99
  */
84
100
  declare function buildTodoistUrl(type: 'task' | 'project', id: string): string;
85
- export { buildTodoistUrl, getTasksByFilter, mapProject, mapTask };
101
+ export { buildTodoistUrl, getTasksByFilter, mapActivityEvent, mapProject, mapTask };
86
102
  //# sourceMappingURL=tool-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-helpers.d.ts","sourceRoot":"","sources":["../src/tool-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,YAAY,EACZ,eAAe,EACf,IAAI,EACJ,UAAU,EACV,gBAAgB,EACnB,MAAM,+BAA+B,CAAA;AAKtC,OAAO,EACH,aAAa,EACb,+BAA+B,EAC/B,4BAA4B,EAC5B,0BAA0B,EAC1B,KAAK,wBAAwB,EAC7B,sBAAsB,GACzB,MAAM,qBAAqB,CAAA;AAE5B,MAAM,MAAM,OAAO,GAAG,eAAe,GAAG,gBAAgB,CAAA;AAExD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,eAAe,CAE9E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB,CAEhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAC9B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAClB,YAAY,CAsBd;AAED;;;;GAIG;AACH,iBAAS,OAAO,CAAC,IAAI,EAAE,IAAI;;;;;;;;;;;;;;;;EAkB1B;AAED;;;;GAIG;AACH,iBAAS,UAAU,CAAC,OAAO,EAAE,OAAO;;;;;;;;;EAWnC;AAWD,iBAAe,gBAAgB,CAAC,EAC5B,MAAM,EACN,KAAK,EACL,KAAK,EACL,MAAM,GACT,EAAE;IACC,MAAM,EAAE,UAAU,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B;;;;;;;;;;;;;;;;;;;GAkBA;AAED;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAAE,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"tool-helpers.d.ts","sourceRoot":"","sources":["../src/tool-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,aAAa,EACb,YAAY,EACZ,eAAe,EACf,IAAI,EACJ,UAAU,EACV,gBAAgB,EACnB,MAAM,+BAA+B,CAAA;AAKtC,OAAO,EACH,aAAa,EACb,+BAA+B,EAC/B,4BAA4B,EAC5B,0BAA0B,EAC1B,KAAK,wBAAwB,EAC7B,sBAAsB,GACzB,MAAM,qBAAqB,CAAA;AAE5B,MAAM,MAAM,OAAO,GAAG,eAAe,GAAG,gBAAgB,CAAA;AAExD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,eAAe,CAE9E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB,CAEhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAC9B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAClB,YAAY,CAsBd;AAED;;;;GAIG;AACH,iBAAS,OAAO,CAAC,IAAI,EAAE,IAAI;;;;;;;;;;;;;;;;EAkB1B;AAED;;;;GAIG;AACH,iBAAS,UAAU,CAAC,OAAO,EAAE,OAAO;;;;;;;;;EAWnC;AAED;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,KAAK,EAAE,aAAa;;;;;;;;;;EAY7C;AAWD,iBAAe,gBAAgB,CAAC,EAC5B,MAAM,EACN,KAAK,EACL,KAAK,EACL,MAAM,GACT,EAAE;IACC,MAAM,EAAE,UAAU,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B;;;;;;;;;;;;;;;;;;;GAkBA;AAED;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,OAAO,EAAE,CAAA"}
@@ -77,6 +77,24 @@ function mapProject(project) {
77
77
  viewStyle: project.viewStyle,
78
78
  };
79
79
  }
80
+ /**
81
+ * Map a single Todoist activity event to a more structured format, for LLM consumption.
82
+ * @param event - The activity event to map.
83
+ * @returns The mapped activity event.
84
+ */
85
+ function mapActivityEvent(event) {
86
+ return {
87
+ id: event.id,
88
+ objectType: event.objectType,
89
+ objectId: event.objectId,
90
+ eventType: event.eventType,
91
+ eventDate: event.eventDate,
92
+ parentProjectId: event.parentProjectId,
93
+ parentItemId: event.parentItemId,
94
+ initiatorId: event.initiatorId,
95
+ extraData: event.extraData,
96
+ };
97
+ }
80
98
  const ErrorSchema = z.object({
81
99
  httpStatusCode: z.number(),
82
100
  responseData: z.object({
@@ -112,4 +130,4 @@ async function getTasksByFilter({ client, query, limit, cursor, }) {
112
130
  function buildTodoistUrl(type, id) {
113
131
  return `https://app.todoist.com/app/${type}/${id}`;
114
132
  }
115
- export { buildTodoistUrl, getTasksByFilter, mapProject, mapTask };
133
+ export { buildTodoistUrl, getTasksByFilter, mapActivityEvent, mapProject, mapTask };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=find-activity.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-activity.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/find-activity.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,229 @@
1
+ import { jest } from '@jest/globals';
2
+ import { extractTextContent } from '../../utils/test-helpers.js';
3
+ import { ToolNames } from '../../utils/tool-names.js';
4
+ import { findActivity } from '../find-activity.js';
5
+ // Mock the Todoist API
6
+ const mockTodoistApi = {
7
+ getActivityLogs: jest.fn(),
8
+ };
9
+ const { FIND_ACTIVITY } = ToolNames;
10
+ /**
11
+ * Helper to create a mock activity event
12
+ */
13
+ function createMockActivityEvent(overrides = {}) {
14
+ return {
15
+ id: 'event-123',
16
+ objectType: 'task',
17
+ objectId: 'task-456',
18
+ eventType: 'added',
19
+ eventDate: '2024-10-23T10:30:00Z',
20
+ parentProjectId: 'project-789',
21
+ parentItemId: null,
22
+ initiatorId: 'user-001',
23
+ extraData: null,
24
+ ...overrides,
25
+ };
26
+ }
27
+ describe(`${FIND_ACTIVITY} tool`, () => {
28
+ beforeEach(() => {
29
+ jest.clearAllMocks();
30
+ });
31
+ describe('basic functionality', () => {
32
+ it('should retrieve activity events with default parameters', async () => {
33
+ const mockEvents = [
34
+ createMockActivityEvent({
35
+ id: 'event-1',
36
+ eventType: 'added',
37
+ eventDate: '2024-10-23T10:00:00Z',
38
+ }),
39
+ createMockActivityEvent({
40
+ id: 'event-2',
41
+ eventType: 'completed',
42
+ eventDate: '2024-10-23T11:00:00Z',
43
+ }),
44
+ ];
45
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
46
+ results: mockEvents,
47
+ nextCursor: null,
48
+ });
49
+ const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
50
+ expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
51
+ limit: 20,
52
+ cursor: null,
53
+ });
54
+ expect(extractTextContent(result)).toMatchSnapshot();
55
+ });
56
+ it('should handle empty results', async () => {
57
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
58
+ results: [],
59
+ nextCursor: null,
60
+ });
61
+ const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
62
+ expect(extractTextContent(result)).toMatchSnapshot();
63
+ });
64
+ it('should handle pagination with cursor', async () => {
65
+ const mockEvents = Array.from({ length: 20 }, (_, i) => createMockActivityEvent({
66
+ id: `event-${i}`,
67
+ objectId: `task-${i}`,
68
+ }));
69
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
70
+ results: mockEvents,
71
+ nextCursor: 'next-page-cursor',
72
+ });
73
+ const result = await findActivity.execute({ limit: 20, cursor: 'current-cursor' }, mockTodoistApi);
74
+ expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
75
+ limit: 20,
76
+ cursor: 'current-cursor',
77
+ });
78
+ expect(extractTextContent(result)).toContain('Pass cursor');
79
+ expect(extractTextContent(result)).toContain('next-page-cursor');
80
+ });
81
+ });
82
+ describe('filtering', () => {
83
+ it.each([
84
+ ['task', 'added'],
85
+ ['project', 'updated'],
86
+ ['comment', 'deleted'],
87
+ ])('should filter by object type: %s', async (objectType, eventType) => {
88
+ const mockEvents = [
89
+ createMockActivityEvent({
90
+ objectType: objectType,
91
+ eventType: eventType,
92
+ }),
93
+ ];
94
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
95
+ results: mockEvents,
96
+ nextCursor: null,
97
+ });
98
+ const result = await findActivity.execute({ objectType: objectType, limit: 20 }, mockTodoistApi);
99
+ expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
100
+ objectType,
101
+ limit: 20,
102
+ cursor: null,
103
+ });
104
+ expect(extractTextContent(result)).toContain(objectType);
105
+ });
106
+ it.each([
107
+ ['added', 'task-1'],
108
+ ['completed', 'task-2'],
109
+ ['updated', 'task-3'],
110
+ ['deleted', 'task-4'],
111
+ ])('should filter by event type: %s', async (eventType, objectId) => {
112
+ const mockEvents = [
113
+ createMockActivityEvent({
114
+ eventType: eventType,
115
+ objectId,
116
+ }),
117
+ ];
118
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
119
+ results: mockEvents,
120
+ nextCursor: null,
121
+ });
122
+ const result = await findActivity.execute({
123
+ eventType: eventType,
124
+ limit: 20,
125
+ }, mockTodoistApi);
126
+ expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
127
+ eventType,
128
+ limit: 20,
129
+ cursor: null,
130
+ });
131
+ expect(extractTextContent(result)).toContain(eventType);
132
+ });
133
+ it.each([
134
+ ['objectId', 'task-123', { objectId: 'task-123' }],
135
+ ['projectId', 'project-abc', { parentProjectId: 'project-abc' }],
136
+ ['taskId', 'parent-task-789', { parentItemId: 'parent-task-789' }],
137
+ ['initiatorId', 'user-alice', { initiatorId: 'user-alice' }],
138
+ ])('should filter by %s', async (filterName, filterId, expectedApiCall) => {
139
+ const mockEvents = [createMockActivityEvent()];
140
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
141
+ results: mockEvents,
142
+ nextCursor: null,
143
+ });
144
+ const args = { limit: 20 };
145
+ args[filterName] = filterId;
146
+ await findActivity.execute(args, mockTodoistApi);
147
+ expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
148
+ ...expectedApiCall,
149
+ limit: 20,
150
+ cursor: null,
151
+ });
152
+ });
153
+ it('should support multiple filters simultaneously', async () => {
154
+ const mockEvents = [
155
+ createMockActivityEvent({
156
+ objectType: 'task',
157
+ eventType: 'completed',
158
+ parentProjectId: 'project-work',
159
+ initiatorId: 'user-bob',
160
+ }),
161
+ ];
162
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
163
+ results: mockEvents,
164
+ nextCursor: null,
165
+ });
166
+ const result = await findActivity.execute({
167
+ objectType: 'task',
168
+ eventType: 'completed',
169
+ projectId: 'project-work',
170
+ initiatorId: 'user-bob',
171
+ limit: 50,
172
+ }, mockTodoistApi);
173
+ expect(mockTodoistApi.getActivityLogs).toHaveBeenCalledWith({
174
+ objectType: 'task',
175
+ eventType: 'completed',
176
+ parentProjectId: 'project-work',
177
+ initiatorId: 'user-bob',
178
+ limit: 50,
179
+ cursor: null,
180
+ });
181
+ expect(extractTextContent(result)).toMatchSnapshot();
182
+ });
183
+ });
184
+ describe('content extraction', () => {
185
+ it('should extract task content from extraData', async () => {
186
+ const mockEvents = [
187
+ createMockActivityEvent({
188
+ eventType: 'added',
189
+ extraData: { content: 'Buy groceries' },
190
+ }),
191
+ ];
192
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
193
+ results: mockEvents,
194
+ nextCursor: null,
195
+ });
196
+ const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
197
+ expect(extractTextContent(result)).toContain('Buy groceries');
198
+ });
199
+ it('should handle system-generated events with no initiator', async () => {
200
+ const mockEvents = [
201
+ createMockActivityEvent({
202
+ initiatorId: null,
203
+ eventType: 'completed',
204
+ }),
205
+ ];
206
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
207
+ results: mockEvents,
208
+ nextCursor: null,
209
+ });
210
+ const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
211
+ expect(extractTextContent(result)).toContain('system');
212
+ });
213
+ it('should truncate long content', async () => {
214
+ const longContent = 'A'.repeat(100);
215
+ const mockEvents = [
216
+ createMockActivityEvent({
217
+ extraData: { content: longContent },
218
+ }),
219
+ ];
220
+ mockTodoistApi.getActivityLogs.mockResolvedValue({
221
+ results: mockEvents,
222
+ nextCursor: null,
223
+ });
224
+ const result = await findActivity.execute({ limit: 20 }, mockTodoistApi);
225
+ expect(extractTextContent(result)).toContain('...');
226
+ expect(extractTextContent(result)).not.toContain(longContent);
227
+ });
228
+ });
229
+ });
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ declare const findActivity: {
3
+ name: "find-activity";
4
+ description: string;
5
+ parameters: {
6
+ objectType: z.ZodOptional<z.ZodEnum<["task", "project", "comment"]>>;
7
+ objectId: z.ZodOptional<z.ZodString>;
8
+ eventType: z.ZodOptional<z.ZodEnum<["added", "updated", "deleted", "completed", "uncompleted", "archived", "unarchived", "shared", "left"]>>;
9
+ projectId: z.ZodOptional<z.ZodString>;
10
+ taskId: z.ZodOptional<z.ZodString>;
11
+ initiatorId: z.ZodOptional<z.ZodString>;
12
+ limit: z.ZodDefault<z.ZodNumber>;
13
+ cursor: z.ZodOptional<z.ZodString>;
14
+ };
15
+ execute(args: {
16
+ limit: number;
17
+ taskId?: string | undefined;
18
+ projectId?: string | undefined;
19
+ objectType?: "task" | "comment" | "project" | undefined;
20
+ objectId?: string | undefined;
21
+ eventType?: "added" | "updated" | "completed" | "deleted" | "uncompleted" | "archived" | "unarchived" | "shared" | "left" | undefined;
22
+ initiatorId?: string | undefined;
23
+ cursor?: string | undefined;
24
+ }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
25
+ content: {
26
+ type: "text";
27
+ text: string;
28
+ }[];
29
+ structuredContent: {
30
+ events: {
31
+ id: string | null;
32
+ objectType: string;
33
+ objectId: string;
34
+ eventType: string;
35
+ eventDate: string;
36
+ parentProjectId: string | null;
37
+ parentItemId: string | null;
38
+ initiatorId: string | null;
39
+ extraData: Record<string, any> | null;
40
+ }[];
41
+ nextCursor: string | null;
42
+ totalCount: number;
43
+ hasMore: boolean;
44
+ appliedFilters: {
45
+ limit: number;
46
+ taskId?: string | undefined;
47
+ projectId?: string | undefined;
48
+ objectType?: "task" | "comment" | "project" | undefined;
49
+ objectId?: string | undefined;
50
+ eventType?: "added" | "updated" | "completed" | "deleted" | "uncompleted" | "archived" | "unarchived" | "shared" | "left" | undefined;
51
+ initiatorId?: string | undefined;
52
+ cursor?: string | undefined;
53
+ };
54
+ };
55
+ } | {
56
+ content: ({
57
+ type: "text";
58
+ text: string;
59
+ mimeType?: undefined;
60
+ } | {
61
+ type: "text";
62
+ mimeType: string;
63
+ text: string;
64
+ })[];
65
+ structuredContent?: undefined;
66
+ }>;
67
+ };
68
+ export { findActivity };
69
+ //# sourceMappingURL=find-activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-activity.d.ts","sourceRoot":"","sources":["../../src/tools/find-activity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAwDvB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6CwB,CAAA;AA+J1C,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -0,0 +1,221 @@
1
+ import { z } from 'zod';
2
+ import { getToolOutput } from '../mcp-helpers.js';
3
+ import { mapActivityEvent } from '../tool-helpers.js';
4
+ import { ApiLimits } from '../utils/constants.js';
5
+ import { summarizeList } from '../utils/response-builders.js';
6
+ import { ToolNames } from '../utils/tool-names.js';
7
+ const { FIND_TASKS, USER_INFO } = ToolNames;
8
+ const ArgsSchema = {
9
+ objectType: z
10
+ .enum(['task', 'project', 'comment'])
11
+ .optional()
12
+ .describe('Type of object to filter by.'),
13
+ objectId: z
14
+ .string()
15
+ .optional()
16
+ .describe('Filter by specific object ID (task, project, or comment).'),
17
+ eventType: z
18
+ .enum([
19
+ 'added',
20
+ 'updated',
21
+ 'deleted',
22
+ 'completed',
23
+ 'uncompleted',
24
+ 'archived',
25
+ 'unarchived',
26
+ 'shared',
27
+ 'left',
28
+ ])
29
+ .optional()
30
+ .describe('Type of event to filter by.'),
31
+ projectId: z.string().optional().describe('Filter events by parent project ID.'),
32
+ taskId: z.string().optional().describe('Filter events by parent task ID (for subtask events).'),
33
+ initiatorId: z.string().optional().describe('Filter by the user ID who initiated the event.'),
34
+ limit: z
35
+ .number()
36
+ .int()
37
+ .min(1)
38
+ .max(ApiLimits.ACTIVITY_MAX)
39
+ .default(ApiLimits.ACTIVITY_DEFAULT)
40
+ .describe('Maximum number of activity events to return.'),
41
+ cursor: z
42
+ .string()
43
+ .optional()
44
+ .describe('Pagination cursor for retrieving the next page of results.'),
45
+ };
46
+ const findActivity = {
47
+ name: ToolNames.FIND_ACTIVITY,
48
+ description: 'Retrieve recent activity logs to monitor and audit changes in Todoist. Shows events from all users by default (use initiatorId to filter by specific user). Track task completions, updates, deletions, project changes, and more with flexible filtering. Note: Date-based filtering is not supported by the Todoist API.',
49
+ parameters: ArgsSchema,
50
+ async execute(args, client) {
51
+ const { objectType, objectId, eventType, projectId, taskId, initiatorId, limit, cursor } = args;
52
+ // Build API arguments
53
+ const apiArgs = {
54
+ limit,
55
+ cursor: cursor ?? null,
56
+ };
57
+ // Add optional filters
58
+ if (objectType)
59
+ apiArgs.objectType = objectType;
60
+ if (objectId)
61
+ apiArgs.objectId = objectId;
62
+ if (eventType)
63
+ apiArgs.eventType = eventType;
64
+ if (projectId)
65
+ apiArgs.parentProjectId = projectId;
66
+ if (taskId)
67
+ apiArgs.parentItemId = taskId;
68
+ if (initiatorId)
69
+ apiArgs.initiatorId = initiatorId;
70
+ // Fetch activity logs from API
71
+ const { results, nextCursor } = await client.getActivityLogs(apiArgs);
72
+ const events = results.map(mapActivityEvent);
73
+ // Generate text content
74
+ const textContent = generateTextContent({
75
+ events,
76
+ args,
77
+ nextCursor,
78
+ });
79
+ return getToolOutput({
80
+ textContent,
81
+ structuredContent: {
82
+ events,
83
+ nextCursor,
84
+ totalCount: events.length,
85
+ hasMore: Boolean(nextCursor),
86
+ appliedFilters: args,
87
+ },
88
+ });
89
+ },
90
+ };
91
+ function generateTextContent({ events, args, nextCursor, }) {
92
+ // Generate subject description
93
+ let subject = 'Activity events';
94
+ // Build subject based on filters
95
+ const subjectParts = [];
96
+ if (args.eventType) {
97
+ subjectParts.push(`${args.eventType}`);
98
+ }
99
+ if (args.objectType) {
100
+ const objectLabel = args.objectType === 'task' ? 'tasks' : `${args.objectType}s`;
101
+ subjectParts.push(objectLabel);
102
+ }
103
+ if (subjectParts.length > 0) {
104
+ subject = `Activity: ${subjectParts.join(' ')}`;
105
+ }
106
+ // Generate filter hints
107
+ const filterHints = [];
108
+ if (args.objectId) {
109
+ filterHints.push(`object ID: ${args.objectId}`);
110
+ }
111
+ if (args.projectId) {
112
+ filterHints.push(`project: ${args.projectId}`);
113
+ }
114
+ if (args.taskId) {
115
+ filterHints.push(`task: ${args.taskId}`);
116
+ }
117
+ if (args.initiatorId) {
118
+ filterHints.push(`initiator: ${args.initiatorId}`);
119
+ }
120
+ // Generate helpful suggestions for empty results
121
+ const zeroReasonHints = [];
122
+ if (events.length === 0) {
123
+ zeroReasonHints.push('No activity events match the specified filters');
124
+ zeroReasonHints.push('Note: Activity logs only show recent events');
125
+ if (args.eventType) {
126
+ zeroReasonHints.push(`Try removing the eventType filter (${args.eventType})`);
127
+ }
128
+ if (args.objectType) {
129
+ zeroReasonHints.push(`Try removing the objectType filter (${args.objectType})`);
130
+ }
131
+ if (args.objectId || args.projectId || args.taskId) {
132
+ zeroReasonHints.push('Verify the object ID is correct');
133
+ }
134
+ }
135
+ // Generate contextual next steps
136
+ const nextSteps = [];
137
+ if (events.length > 0) {
138
+ // Suggest related tools based on what was found
139
+ const hasTaskEvents = events.some((e) => e.objectType === 'task' || e.objectType === 'item');
140
+ const hasCompletions = events.some((e) => e.eventType === 'completed');
141
+ if (hasTaskEvents) {
142
+ nextSteps.push(`Use ${FIND_TASKS} to view current task details`);
143
+ }
144
+ if (hasCompletions) {
145
+ nextSteps.push('Review completed tasks to track productivity');
146
+ }
147
+ if (args.initiatorId) {
148
+ nextSteps.push(`Use ${USER_INFO} to get details about the user`);
149
+ }
150
+ // Suggest narrowing down if too many results
151
+ if (events.length >= args.limit && !nextCursor) {
152
+ nextSteps.push('Add more specific filters to narrow down results');
153
+ }
154
+ }
155
+ return summarizeList({
156
+ subject,
157
+ count: events.length,
158
+ limit: args.limit,
159
+ nextCursor: nextCursor ?? undefined,
160
+ filterHints,
161
+ previewLines: previewActivityEvents(events, Math.min(events.length, args.limit)),
162
+ zeroReasonHints,
163
+ nextSteps,
164
+ });
165
+ }
166
+ /**
167
+ * Formats activity events into readable preview lines
168
+ */
169
+ function previewActivityEvents(events, limit = 10) {
170
+ const previewEvents = events.slice(0, limit);
171
+ const lines = previewEvents.map(formatActivityEventPreview).join('\n');
172
+ // If we're showing fewer events than the total, add an indicator
173
+ if (events.length > limit) {
174
+ const remaining = events.length - limit;
175
+ return `${lines}\n ... and ${remaining} more event${remaining === 1 ? '' : 's'}`;
176
+ }
177
+ return lines;
178
+ }
179
+ /**
180
+ * Formats a single activity event into a readable preview line
181
+ */
182
+ function formatActivityEventPreview(event) {
183
+ const date = formatEventDate(event.eventDate);
184
+ const eventLabel = `${event.eventType} ${event.objectType}`;
185
+ // Extract useful content from extraData if available
186
+ let contentInfo = '';
187
+ if (event.extraData) {
188
+ const content = event.extraData.content || event.extraData.name || event.extraData.last_content;
189
+ if (content && typeof content === 'string') {
190
+ // Truncate long content
191
+ const truncated = content.length > 50 ? `${content.substring(0, 47)}...` : content;
192
+ contentInfo = ` • "${truncated}"`;
193
+ }
194
+ }
195
+ const objectId = event.objectId ? ` • id=${event.objectId}` : '';
196
+ const initiator = event.initiatorId ? ` • by=${event.initiatorId}` : ' • system';
197
+ const projectInfo = event.parentProjectId ? ` • project=${event.parentProjectId}` : '';
198
+ return ` [${date}] ${eventLabel}${contentInfo}${objectId}${initiator}${projectInfo}`;
199
+ }
200
+ /**
201
+ * Formats an ISO date string to a more readable format
202
+ */
203
+ function formatEventDate(isoDate) {
204
+ try {
205
+ const date = new Date(isoDate);
206
+ // Format as: Oct 23, 14:30 (in UTC for deterministic snapshots)
207
+ const month = date.toLocaleDateString('en-US', { month: 'short', timeZone: 'UTC' });
208
+ const day = date.toLocaleDateString('en-US', { day: 'numeric', timeZone: 'UTC' });
209
+ const time = date.toLocaleTimeString('en-US', {
210
+ hour: '2-digit',
211
+ minute: '2-digit',
212
+ hour12: false,
213
+ timeZone: 'UTC',
214
+ });
215
+ return `${month} ${day}, ${time}`;
216
+ }
217
+ catch {
218
+ return isoDate;
219
+ }
220
+ }
221
+ export { findActivity };
@@ -1 +1 @@
1
- {"version":3,"file":"find-completed-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-completed-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAsDvB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkEkB,CAAA;AA2E1C,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"find-completed-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-completed-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAwDvB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmEkB,CAAA;AA2E1C,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -29,7 +29,7 @@ const ArgsSchema = {
29
29
  responsibleUser: z
30
30
  .string()
31
31
  .optional()
32
- .describe('Find tasks assigned to this user. Can be a user ID, name, or email address.'),
32
+ .describe('Find tasks assigned to this user. Can be a user ID, name, or email address. Defaults to all collaborators when omitted.'),
33
33
  limit: z
34
34
  .number()
35
35
  .int()
@@ -45,7 +45,7 @@ const ArgsSchema = {
45
45
  };
46
46
  const findCompletedTasks = {
47
47
  name: ToolNames.FIND_COMPLETED_TASKS,
48
- description: 'Get completed tasks.',
48
+ description: 'Get completed tasks (includes all collaborators by default—use responsibleUser to narrow).',
49
49
  parameters: ArgsSchema,
50
50
  async execute(args, client) {
51
51
  const { getBy, labels, labelsOperator, since, until, responsibleUser, ...rest } = args;
@@ -23,6 +23,10 @@ export declare const ApiLimits: {
23
23
  readonly COMMENTS_DEFAULT: 10;
24
24
  /** Maximum limit for comment search and list operations */
25
25
  readonly COMMENTS_MAX: 10;
26
+ /** Default limit for activity log listings */
27
+ readonly ACTIVITY_DEFAULT: 20;
28
+ /** Maximum limit for activity log search and list operations */
29
+ readonly ACTIVITY_MAX: 100;
26
30
  };
27
31
  export declare const DisplayLimits: {
28
32
  /** Maximum number of failures to show in detailed error messages */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,eAAO,MAAM,SAAS;IAClB,sCAAsC;;IAEtC,wDAAwD;;IAExD,wCAAwC;;IAExC,wCAAwC;;IAExC,yCAAyC;;IAEzC,yCAAyC;;IAEzC,qDAAqD;;IAErD,yCAAyC;;IAEzC,2DAA2D;;CAErD,CAAA;AAGV,eAAO,MAAM,aAAa;IACtB,oEAAoE;;IAEpE,gDAAgD;;CAE1C,CAAA;AAGV,eAAO,MAAM,cAAc;IACvB,oDAAoD;;IAEpD,mCAAmC;;CAE7B,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,eAAO,MAAM,SAAS;IAClB,sCAAsC;;IAEtC,wDAAwD;;IAExD,wCAAwC;;IAExC,wCAAwC;;IAExC,yCAAyC;;IAEzC,yCAAyC;;IAEzC,qDAAqD;;IAErD,yCAAyC;;IAEzC,2DAA2D;;IAE3D,8CAA8C;;IAE9C,gEAAgE;;CAE1D,CAAA;AAGV,eAAO,MAAM,aAAa;IACtB,oEAAoE;;IAEpE,gDAAgD;;CAE1C,CAAA;AAGV,eAAO,MAAM,cAAc;IACvB,oDAAoD;;IAEpD,mCAAmC;;CAE7B,CAAA"}
@@ -24,6 +24,10 @@ export const ApiLimits = {
24
24
  COMMENTS_DEFAULT: 10,
25
25
  /** Maximum limit for comment search and list operations */
26
26
  COMMENTS_MAX: 10,
27
+ /** Default limit for activity log listings */
28
+ ACTIVITY_DEFAULT: 20,
29
+ /** Maximum limit for activity log search and list operations */
30
+ ACTIVITY_MAX: 100,
27
31
  };
28
32
  // UI Display Limits
29
33
  export const DisplayLimits = {
@@ -23,6 +23,7 @@ export declare const ToolNames: {
23
23
  readonly FIND_COMMENTS: "find-comments";
24
24
  readonly FIND_PROJECT_COLLABORATORS: "find-project-collaborators";
25
25
  readonly MANAGE_ASSIGNMENTS: "manage-assignments";
26
+ readonly FIND_ACTIVITY: "find-activity";
26
27
  readonly GET_OVERVIEW: "get-overview";
27
28
  readonly DELETE_OBJECT: "delete-object";
28
29
  readonly USER_INFO: "user-info";
@@ -1 +1 @@
1
- {"version":3,"file":"tool-names.d.ts","sourceRoot":"","sources":["../../src/utils/tool-names.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;CAoCZ,CAAA;AAGV,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"tool-names.d.ts","sourceRoot":"","sources":["../../src/utils/tool-names.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;CAuCZ,CAAA;AAGV,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAA"}
@@ -28,6 +28,8 @@ export const ToolNames = {
28
28
  // Assignment and collaboration tools
29
29
  FIND_PROJECT_COLLABORATORS: 'find-project-collaborators',
30
30
  MANAGE_ASSIGNMENTS: 'manage-assignments',
31
+ // Activity and audit tools
32
+ FIND_ACTIVITY: 'find-activity',
31
33
  // General tools
32
34
  GET_OVERVIEW: 'get-overview',
33
35
  DELETE_OBJECT: 'delete-object',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/todoist-ai",
3
- "version": "4.13.4",
3
+ "version": "4.14.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -45,9 +45,9 @@
45
45
  "prepare": "husky"
46
46
  },
47
47
  "dependencies": {
48
- "@doist/todoist-api-typescript": "5.7.0",
49
48
  "@modelcontextprotocol/sdk": "^1.11.1",
50
49
  "date-fns": "^4.1.0",
50
+ "@doist/todoist-api-typescript": "5.7.1",
51
51
  "dotenv": "^17.0.0",
52
52
  "zod": "^3.25.7"
53
53
  },