@taazkareem/clickup-mcp-server 0.6.2 → 0.6.4

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 (41) hide show
  1. package/README.md +6 -6
  2. package/build/logger.js +26 -1
  3. package/build/server.js +1 -1
  4. package/build/services/clickup/base.js +22 -1
  5. package/build/services/clickup/bulk.js +111 -69
  6. package/build/services/clickup/index.js +2 -2
  7. package/build/services/clickup/task/index.js +32 -0
  8. package/build/services/clickup/task/task-attachments.js +97 -0
  9. package/build/services/clickup/task/task-comments.js +104 -0
  10. package/build/services/clickup/task/task-core.js +439 -0
  11. package/build/services/clickup/task/task-custom-fields.js +97 -0
  12. package/build/services/clickup/task/task-search.js +462 -0
  13. package/build/services/clickup/task/task-service.js +25 -0
  14. package/build/services/clickup/task/task-tags.js +101 -0
  15. package/build/services/clickup/workspace.js +81 -36
  16. package/build/tools/folder.js +1 -1
  17. package/build/tools/list.js +2 -4
  18. package/build/tools/task/attachments.js +49 -20
  19. package/build/tools/task/attachments.types.js +9 -0
  20. package/build/tools/task/bulk-operations.js +102 -18
  21. package/build/tools/task/handlers.js +216 -53
  22. package/build/tools/task/index.js +1 -1
  23. package/build/tools/task/main.js +161 -32
  24. package/build/tools/task/single-operations.js +82 -17
  25. package/build/tools/task/utilities.js +47 -75
  26. package/build/tools/utils.js +2 -2
  27. package/build/utils/date-utils.js +149 -30
  28. package/build/utils/resolver-utils.js +33 -40
  29. package/build/utils/sponsor-service.js +1 -1
  30. package/package.json +1 -1
  31. package/build/mcp-tools.js +0 -64
  32. package/build/server-state.js +0 -93
  33. package/build/server.log +0 -0
  34. package/build/services/clickup/task.js +0 -701
  35. package/build/tools/bulk-tasks.js +0 -36
  36. package/build/tools/debug.js +0 -76
  37. package/build/tools/logs.js +0 -55
  38. package/build/tools/task.js +0 -1554
  39. package/build/utils/params-utils.js +0 -39
  40. package/build/utils/sponsor-analytics.js +0 -100
  41. package/build/utils/sponsor-utils.js +0 -57
@@ -11,7 +11,7 @@ import { toTaskPriority } from '../../services/clickup/types.js';
11
11
  import { clickUpServices } from '../../services/shared.js';
12
12
  import { BulkService } from '../../services/clickup/bulk.js';
13
13
  import { parseDueDate } from '../utils.js';
14
- import { validateTaskIdentification, validateListIdentification, validateTaskUpdateData, validateBulkTasks, parseBulkOptions, resolveTaskIdWithValidation, resolveListIdWithValidation } from './utilities.js';
14
+ import { validateTaskIdentification, validateListIdentification, validateTaskUpdateData, validateBulkTasks, parseBulkOptions, resolveListIdWithValidation } from './utilities.js';
15
15
  // Use shared services instance
16
16
  const { task: taskService, list: listService } = clickUpServices;
17
17
  // Create a bulk service instance that uses the task service
@@ -32,18 +32,49 @@ function buildUpdateData(params) {
32
32
  updateData.markdown_description = params.markdown_description;
33
33
  if (params.status !== undefined)
34
34
  updateData.status = params.status;
35
+ // Skip toTaskPriority conversion since we're handling priority in the main handler
35
36
  if (params.priority !== undefined)
36
- updateData.priority = toTaskPriority(params.priority);
37
- if (params.dueDate !== undefined)
37
+ updateData.priority = params.priority;
38
+ if (params.dueDate !== undefined) {
38
39
  updateData.due_date = parseDueDate(params.dueDate);
40
+ updateData.due_date_time = true;
41
+ }
42
+ if (params.startDate !== undefined) {
43
+ updateData.start_date = parseDueDate(params.startDate);
44
+ updateData.start_date_time = true;
45
+ }
46
+ // Handle custom fields if provided
47
+ if (params.custom_fields !== undefined) {
48
+ updateData.custom_fields = params.custom_fields;
49
+ }
39
50
  return updateData;
40
51
  }
41
52
  /**
42
- * Process a task identification validation, returning the task ID
53
+ * Resolves a task ID from various input formats
54
+ * Smart disambiguation is used for task name lookups
55
+ *
56
+ * @param taskId Direct task ID
57
+ * @param taskName Task name to search for
58
+ * @param listName List name for context
59
+ * @param customTaskId Custom task ID (prefixed format)
60
+ * @returns Resolved task ID
43
61
  */
44
- async function getTaskId(taskId, taskName, listName, customTaskId) {
45
- validateTaskIdentification(taskId, taskName, listName, customTaskId);
46
- return await resolveTaskIdWithValidation(taskId, taskName, listName, customTaskId);
62
+ export async function getTaskId(taskId, taskName, listName, customTaskId) {
63
+ validateTaskIdentification(taskId, taskName, listName, customTaskId, true);
64
+ const result = await taskService.findTasks({
65
+ taskId,
66
+ customTaskId,
67
+ taskName,
68
+ listName,
69
+ allowMultipleMatches: false,
70
+ useSmartDisambiguation: true,
71
+ includeFullDetails: false,
72
+ includeListContext: false
73
+ });
74
+ if (result && !Array.isArray(result)) {
75
+ return result.id;
76
+ }
77
+ throw new Error("Task not found");
47
78
  }
48
79
  /**
49
80
  * Process a list identification validation, returning the list ID
@@ -72,11 +103,12 @@ function buildTaskFilters(params) {
72
103
  }
73
104
  /**
74
105
  * Map tasks for bulk operations, resolving task IDs
106
+ * Uses smart disambiguation for tasks without list context
75
107
  */
76
108
  async function mapTaskIds(tasks) {
77
109
  return Promise.all(tasks.map(async (task) => {
78
110
  validateTaskIdentification(task.taskId, task.taskName, task.listName, task.customTaskId);
79
- return await resolveTaskIdWithValidation(task.taskId, task.taskName, task.listName, task.customTaskId);
111
+ return await getTaskId(task.taskId, task.taskName, task.listName, task.customTaskId);
80
112
  }));
81
113
  }
82
114
  //=============================================================================
@@ -86,30 +118,46 @@ async function mapTaskIds(tasks) {
86
118
  * Handler for creating a task
87
119
  */
88
120
  export async function createTaskHandler(params) {
89
- const { name, description, markdown_description, status, dueDate, parent, tags } = params;
121
+ const { name, description, markdown_description, status, dueDate, startDate, parent, tags, custom_fields, check_required_custom_fields } = params;
90
122
  if (!name)
91
123
  throw new Error("Task name is required");
92
124
  // Use our helper function to validate and convert priority
93
125
  const priority = toTaskPriority(params.priority);
94
126
  const listId = await getListId(params.listId, params.listName);
95
- return await taskService.createTask(listId, {
127
+ const taskData = {
96
128
  name,
97
129
  description,
98
130
  markdown_description,
99
131
  status,
100
132
  priority,
101
- due_date: dueDate ? parseDueDate(dueDate) : undefined,
102
133
  parent,
103
- tags
104
- });
134
+ tags,
135
+ custom_fields,
136
+ check_required_custom_fields
137
+ };
138
+ // Add due date if specified
139
+ if (dueDate) {
140
+ taskData.due_date = parseDueDate(dueDate);
141
+ taskData.due_date_time = true;
142
+ }
143
+ // Add start date if specified
144
+ if (startDate) {
145
+ taskData.start_date = parseDueDate(startDate);
146
+ taskData.start_date_time = true;
147
+ }
148
+ return await taskService.createTask(listId, taskData);
105
149
  }
106
150
  /**
107
151
  * Handler for updating a task
108
152
  */
109
153
  export async function updateTaskHandler(params) {
154
+ console.log('Update Task Handler - Raw params:', JSON.stringify(params));
155
+ console.log('Update Task Handler - Priority type:', typeof params.priority, 'Value:', params.priority);
110
156
  validateTaskUpdateData(params);
111
157
  const taskId = await getTaskId(params.taskId, params.taskName, params.listName);
112
- return await taskService.updateTask(taskId, buildUpdateData(params));
158
+ const updateData = buildUpdateData(params);
159
+ console.log('Update Task Handler - Update data:', JSON.stringify(updateData));
160
+ return await taskService.updateTask(taskId, updateData);
113
161
  }
114
162
  /**
115
163
  * Handler for moving a task
@@ -134,15 +182,107 @@ export async function duplicateTaskHandler(params) {
134
182
  * Handler for getting a task
135
183
  */
136
184
  export async function getTaskHandler(params) {
137
- // resolveTaskIdWithValidation now auto-detects whether taskId is a regular ID or custom ID
138
- const taskId = await getTaskId(params.taskId, params.taskName, params.listName, params.customTaskId);
139
- // If subtasks parameter is provided and true, use the getTaskWithSubtasks method
140
- if (params.subtasks) {
141
- const task = await taskService.getTask(taskId);
142
- const subtasks = await taskService.getSubtasks(taskId);
143
- return { ...task, subtasks };
185
+ try {
186
+ // Direct path for taskId - most efficient
187
+ if (params.taskId) {
188
+ const task = await taskService.getTask(params.taskId);
189
+ // Add subtasks if requested
190
+ if (params.subtasks) {
191
+ const subtasks = await taskService.getSubtasks(task.id);
192
+ return { ...task, subtasks };
193
+ }
194
+ return task;
195
+ }
196
+ // Direct path for customTaskId - also efficient
197
+ if (params.customTaskId) {
198
+ const task = await taskService.getTaskByCustomId(params.customTaskId);
199
+ // Add subtasks if requested
200
+ if (params.subtasks) {
201
+ const subtasks = await taskService.getSubtasks(task.id);
202
+ return { ...task, subtasks };
203
+ }
204
+ return task;
205
+ }
206
+ // Special optimized path for taskName + listName combination
207
+ if (params.taskName && params.listName) {
208
+ // First, get the list ID
209
+ const listId = await getListId(null, params.listName);
210
+ if (!listId) {
211
+ throw new Error(`List "${params.listName}" not found`);
212
+ }
213
+ // Use the ClickUp API to get filtered tasks
214
+ // Need to get all tasks and filter on client side
215
+ // This is more efficient than the original approach because it's a dedicated path
216
+ // that skips the global lookup framework entirely
217
+ const allTasks = await taskService.getTasks(listId);
218
+ // Find the matching task
219
+ // Extract this to avoid dependency on internal isNameMatch implementation
220
+ const matchingTask = findTaskByName(allTasks, params.taskName);
221
+ if (!matchingTask) {
222
+ throw new Error(`Task "${params.taskName}" not found in list "${params.listName}"`);
223
+ }
224
+ // Add subtasks if requested
225
+ if (params.subtasks) {
226
+ const subtasks = await taskService.getSubtasks(matchingTask.id);
227
+ return { ...matchingTask, subtasks };
228
+ }
229
+ return matchingTask;
230
+ }
231
+ // Fallback to the original global lookup for all other cases
232
+ const result = await taskService.findTasks({
233
+ taskName: params.taskName,
234
+ allowMultipleMatches: true,
235
+ useSmartDisambiguation: false,
236
+ includeFullDetails: true,
237
+ includeListContext: true
238
+ });
239
+ // Handle the response based on the result type
240
+ if (Array.isArray(result)) {
241
+ // If multiple tasks matched, format them with task count
242
+ return {
243
+ matches: result,
244
+ count: result.length
245
+ };
246
+ }
247
+ else if (result) {
248
+ // Single task found, check if we need to include subtasks
249
+ if (params.subtasks) {
250
+ const subtasks = await taskService.getSubtasks(result.id);
251
+ return { ...result, subtasks };
252
+ }
253
+ // Return the single task
254
+ return result;
255
+ }
256
+ else {
257
+ throw new Error("Task not found");
258
+ }
259
+ }
260
+ catch (error) {
261
+ // Enhance error message for non-existent tasks
262
+ if (params.taskName && error.message.includes('not found')) {
263
+ throw new Error(`Task "${params.taskName}" not found. Please check the task name and try again.`);
264
+ }
265
+ // Pass along other formatted errors
266
+ throw error;
144
267
  }
145
- return await taskService.getTask(taskId);
268
+ }
269
+ /**
270
+ * Helper function to find a task by name in an array of tasks
271
+ */
272
+ function findTaskByName(tasks, name) {
273
+ if (!tasks || !Array.isArray(tasks) || !name)
274
+ return null;
275
+ // Try exact match first
276
+ let match = tasks.find(task => task.name === name);
277
+ if (match)
278
+ return match;
279
+ // Try case-insensitive match
280
+ match = tasks.find(task => task.name.toLowerCase() === name.toLowerCase());
281
+ if (match)
282
+ return match;
283
+ // Try fuzzy match - looking for name as substring
284
+ match = tasks.find(task => task.name.toLowerCase().includes(name.toLowerCase()));
285
+ return match || null;
146
286
  }
147
287
  /**
148
288
  * Handler for getting tasks
@@ -212,7 +352,8 @@ export async function getWorkspaceTasksHandler(taskService, params) {
212
352
  if (!hasFilter) {
213
353
  throw new Error('At least one filter parameter is required (tags, list_ids, folder_ids, space_ids, statuses, assignees, or date filters)');
214
354
  }
215
- // Create filter object from parameters
355
+ // For workspace tasks, we'll continue to use the direct getWorkspaceTasks method
356
+ // since it supports specific workspace-wide filters that aren't part of the unified findTasks
216
357
  const filters = {
217
358
  tags: params.tags,
218
359
  list_ids: params.list_ids,
@@ -251,54 +392,76 @@ export async function getWorkspaceTasksHandler(taskService, params) {
251
392
  * Handler for creating multiple tasks
252
393
  */
253
394
  export async function createBulkTasksHandler(params) {
254
- validateBulkTasks(params.tasks);
255
- const listId = await getListId(params.listId, params.listName);
256
- // Process tasks - prepare data for each task
257
- const tasks = params.tasks.map(task => {
258
- const processedTask = { ...task };
395
+ const { tasks, listId, listName, options } = params;
396
+ // Validate tasks array
397
+ validateBulkTasks(tasks, 'create');
398
+ // Validate and resolve list ID
399
+ const targetListId = await resolveListIdWithValidation(listId, listName);
400
+ // Format tasks for creation
401
+ const formattedTasks = tasks.map(task => {
402
+ const taskData = {
403
+ name: task.name,
404
+ description: task.description,
405
+ markdown_description: task.markdown_description,
406
+ status: task.status,
407
+ priority: toTaskPriority(task.priority),
408
+ tags: task.tags,
409
+ custom_fields: task.custom_fields
410
+ };
411
+ // Add due date if specified
259
412
  if (task.dueDate) {
260
- processedTask.due_date = parseDueDate(task.dueDate);
261
- delete processedTask.dueDate;
413
+ taskData.due_date = parseDueDate(task.dueDate);
414
+ taskData.due_date_time = true;
415
+ }
416
+ // Add start date if specified
417
+ if (task.startDate) {
418
+ taskData.start_date = parseDueDate(task.startDate);
419
+ taskData.start_date_time = true;
262
420
  }
263
- return processedTask;
421
+ return taskData;
264
422
  });
265
- const result = await bulkService.createTasks(listId, tasks, parseBulkOptions(params.options));
266
- return result.successful;
423
+ // Parse bulk options
424
+ const bulkOptions = parseBulkOptions(options);
425
+ // Create tasks - pass arguments in correct order: listId, tasks, options
426
+ return await bulkService.createTasks(targetListId, formattedTasks, bulkOptions);
267
427
  }
268
428
  /**
269
429
  * Handler for updating multiple tasks
270
430
  */
271
431
  export async function updateBulkTasksHandler(params) {
272
- validateBulkTasks(params.tasks);
273
- const updates = await Promise.all(params.tasks.map(async (task) => {
274
- validateTaskUpdateData(task);
275
- const taskId = await getTaskId(task.taskId, task.taskName, task.listName);
276
- return { id: taskId, data: buildUpdateData(task) };
277
- }));
278
- const result = await bulkService.updateTasks(updates, parseBulkOptions(params.options));
279
- return result.successful;
432
+ const { tasks, options } = params;
433
+ // Validate tasks array
434
+ validateBulkTasks(tasks, 'update');
435
+ // Parse bulk options
436
+ const bulkOptions = parseBulkOptions(options);
437
+ // Update tasks
438
+ return await bulkService.updateTasks(tasks, bulkOptions);
280
439
  }
281
440
  /**
282
441
  * Handler for moving multiple tasks
283
442
  */
284
443
  export async function moveBulkTasksHandler(params) {
285
- validateBulkTasks(params.tasks);
286
- if (!params.targetListId && !params.targetListName) {
287
- throw new Error("Either targetListId or targetListName must be provided");
288
- }
289
- const targetListId = await getListId(params.targetListId, params.targetListName);
290
- const taskIds = await mapTaskIds(params.tasks);
291
- const result = await bulkService.moveTasks(taskIds, targetListId, parseBulkOptions(params.options));
292
- return result.successful;
444
+ const { tasks, targetListId, targetListName, options } = params;
445
+ // Validate tasks array
446
+ validateBulkTasks(tasks, 'move');
447
+ // Validate and resolve target list ID
448
+ const resolvedTargetListId = await resolveListIdWithValidation(targetListId, targetListName);
449
+ // Parse bulk options
450
+ const bulkOptions = parseBulkOptions(options);
451
+ // Move tasks
452
+ return await bulkService.moveTasks(tasks, resolvedTargetListId, bulkOptions);
293
453
  }
294
454
  /**
295
455
  * Handler for deleting multiple tasks
296
456
  */
297
457
  export async function deleteBulkTasksHandler(params) {
298
- validateBulkTasks(params.tasks);
299
- const taskIds = await mapTaskIds(params.tasks);
300
- await bulkService.deleteTasks(taskIds, parseBulkOptions(params.options));
301
- return taskIds.map(() => true);
458
+ const { tasks, options } = params;
459
+ // Validate tasks array
460
+ validateBulkTasks(tasks, 'delete');
461
+ // Parse bulk options
462
+ const bulkOptions = parseBulkOptions(options);
463
+ // Delete tasks
464
+ return await bulkService.deleteTasks(tasks, bulkOptions);
302
465
  }
303
466
  /**
304
467
  * Handler for deleting a task
@@ -25,4 +25,4 @@ createBulkTasksHandler, updateBulkTasksHandler, moveBulkTasksHandler, deleteBulk
25
25
  // Team task operation handlers
26
26
  getWorkspaceTasksHandler } from './handlers.js';
27
27
  // Re-export utilities
28
- export { formatTaskData, validateTaskIdentification, validateListIdentification, validateTaskUpdateData, validateBulkTasks, parseBulkOptions, resolveTaskIdWithValidation, resolveListIdWithValidation } from './utilities.js';
28
+ export { formatTaskData, validateTaskIdentification, validateListIdentification, validateTaskUpdateData, validateBulkTasks, parseBulkOptions, resolveListIdWithValidation } from './utilities.js';
@@ -43,7 +43,42 @@ export const handleGetTasks = createHandlerWrapper(getTasksHandler, (tasks) => (
43
43
  tasks,
44
44
  count: tasks.length
45
45
  }));
46
- export const handleUpdateTask = createHandlerWrapper(updateTaskHandler);
46
+ export const handleUpdateTask = async (parameters) => {
47
+ try {
48
+ // Special handling for priority parameter
49
+ if (parameters.priority !== undefined) {
50
+ // Ensure priority is converted to a number if it's a valid value
51
+ if (parameters.priority === null) {
52
+ // null is valid for clearing priority
53
+ }
54
+ else if (typeof parameters.priority === 'number' && [1, 2, 3, 4].includes(parameters.priority)) {
55
+ // Valid priority number, keep as is
56
+ }
57
+ else if (typeof parameters.priority === 'string') {
58
+ // Try to convert string to number
59
+ const numPriority = parseInt(parameters.priority, 10);
60
+ if (!isNaN(numPriority) && [1, 2, 3, 4].includes(numPriority)) {
61
+ parameters.priority = numPriority;
62
+ }
63
+ else if (parameters.priority === 'null') {
64
+ parameters.priority = null;
65
+ }
66
+ else {
67
+ throw new Error(`Invalid priority value: ${parameters.priority}. Must be 1, 2, 3, 4, or null.`);
68
+ }
69
+ }
70
+ else {
71
+ throw new Error(`Invalid priority value: ${parameters.priority}. Must be 1, 2, 3, 4, or null.`);
72
+ }
73
+ }
74
+ // Proceed with normal handling
75
+ const result = await updateTaskHandler(parameters);
76
+ return sponsorService.createResponse(result, true);
77
+ }
78
+ catch (error) {
79
+ return sponsorService.createErrorResponse(error, parameters);
80
+ }
81
+ };
47
82
  export const handleMoveTask = createHandlerWrapper(moveTaskHandler);
48
83
  export const handleDuplicateTask = createHandlerWrapper(duplicateTaskHandler);
49
84
  export const handleDeleteTask = createHandlerWrapper(deleteTaskHandler, () => ({
@@ -65,22 +100,37 @@ export const handleCreateTaskComment = createHandlerWrapper(createTaskCommentHan
65
100
  //=============================================================================
66
101
  // BULK TASK OPERATIONS - HANDLER IMPLEMENTATIONS
67
102
  //=============================================================================
68
- export const handleCreateBulkTasks = createHandlerWrapper(createBulkTasksHandler, (tasks) => ({
69
- tasks,
70
- count: tasks.length
103
+ export const handleCreateBulkTasks = createHandlerWrapper(createBulkTasksHandler, (result) => ({
104
+ successful: result.successful,
105
+ failed: result.failed,
106
+ count: result.totals.total,
107
+ success_count: result.totals.success,
108
+ failure_count: result.totals.failure,
109
+ errors: result.failed.map(f => f.error)
71
110
  }));
72
- export const handleUpdateBulkTasks = createHandlerWrapper(updateBulkTasksHandler, (tasks) => ({
73
- tasks,
74
- count: tasks.length
111
+ export const handleUpdateBulkTasks = createHandlerWrapper(updateBulkTasksHandler, (result) => ({
112
+ successful: result.successful,
113
+ failed: result.failed,
114
+ count: result.totals.total,
115
+ success_count: result.totals.success,
116
+ failure_count: result.totals.failure,
117
+ errors: result.failed.map(f => f.error)
75
118
  }));
76
- export const handleMoveBulkTasks = createHandlerWrapper(moveBulkTasksHandler, (tasks) => ({
77
- tasks,
78
- count: tasks.length
119
+ export const handleMoveBulkTasks = createHandlerWrapper(moveBulkTasksHandler, (result) => ({
120
+ successful: result.successful,
121
+ failed: result.failed,
122
+ count: result.totals.total,
123
+ success_count: result.totals.success,
124
+ failure_count: result.totals.failure,
125
+ errors: result.failed.map(f => f.error)
79
126
  }));
80
- export const handleDeleteBulkTasks = createHandlerWrapper(deleteBulkTasksHandler, (results) => ({
81
- success: true,
82
- count: results.length,
83
- results
127
+ export const handleDeleteBulkTasks = createHandlerWrapper(deleteBulkTasksHandler, (result) => ({
128
+ successful: result.successful,
129
+ failed: result.failed,
130
+ count: result.totals.total,
131
+ success_count: result.totals.success,
132
+ failure_count: result.totals.failure,
133
+ errors: result.failed.map(f => f.error)
84
134
  }));
85
135
  //=============================================================================
86
136
  // WORKSPACE TASK OPERATIONS - HANDLER IMPLEMENTATIONS
@@ -93,22 +143,101 @@ export const handleGetWorkspaceTasks = createHandlerWrapper(
93
143
  // TOOL DEFINITIONS AND HANDLERS EXPORT
94
144
  //=============================================================================
95
145
  // Tool definitions with their handler mappings
96
- export const taskTools = [
97
- // Single task operations
98
- { definition: createTaskTool, handler: handleCreateTask },
99
- { definition: getTaskTool, handler: handleGetTask },
100
- { definition: getTasksTool, handler: handleGetTasks },
101
- { definition: updateTaskTool, handler: handleUpdateTask },
102
- { definition: moveTaskTool, handler: handleMoveTask },
103
- { definition: duplicateTaskTool, handler: handleDuplicateTask },
104
- { definition: deleteTaskTool, handler: handleDeleteTask },
105
- { definition: getTaskCommentsTool, handler: handleGetTaskComments },
106
- { definition: createTaskCommentTool, handler: handleCreateTaskComment },
107
- // Bulk task operations
108
- { definition: createBulkTasksTool, handler: handleCreateBulkTasks },
109
- { definition: updateBulkTasksTool, handler: handleUpdateBulkTasks },
110
- { definition: moveBulkTasksTool, handler: handleMoveBulkTasks },
111
- { definition: deleteBulkTasksTool, handler: handleDeleteBulkTasks },
112
- // Team task operations
113
- { definition: getWorkspaceTasksTool, handler: handleGetWorkspaceTasks }
146
+ export const tools = [
147
+ {
148
+ definition: createTaskTool,
149
+ handler: createTaskHandler
150
+ },
151
+ {
152
+ definition: updateTaskTool,
153
+ handler: updateTaskHandler
154
+ },
155
+ {
156
+ definition: moveTaskTool,
157
+ handler: moveTaskHandler
158
+ },
159
+ {
160
+ definition: duplicateTaskTool,
161
+ handler: duplicateTaskHandler
162
+ },
163
+ {
164
+ definition: getTaskTool,
165
+ handler: getTaskHandler
166
+ },
167
+ {
168
+ definition: getTasksTool,
169
+ handler: getTasksHandler
170
+ },
171
+ {
172
+ definition: getTaskCommentsTool,
173
+ handler: getTaskCommentsHandler
174
+ },
175
+ {
176
+ definition: createTaskCommentTool,
177
+ handler: createTaskCommentHandler
178
+ },
179
+ {
180
+ definition: deleteTaskTool,
181
+ handler: deleteTaskHandler
182
+ },
183
+ {
184
+ definition: getWorkspaceTasksTool,
185
+ handler: getWorkspaceTasksHandler
186
+ },
187
+ {
188
+ definition: createBulkTasksTool,
189
+ handler: async (params) => {
190
+ const result = await createBulkTasksHandler(params);
191
+ return {
192
+ successful: result.successful,
193
+ failed: result.failed,
194
+ count: result.totals.total,
195
+ success_count: result.totals.success,
196
+ failure_count: result.totals.failure,
197
+ errors: result.failed.map(f => f.error)
198
+ };
199
+ }
200
+ },
201
+ {
202
+ definition: updateBulkTasksTool,
203
+ handler: async (params) => {
204
+ const result = await updateBulkTasksHandler(params);
205
+ return {
206
+ successful: result.successful,
207
+ failed: result.failed,
208
+ count: result.totals.total,
209
+ success_count: result.totals.success,
210
+ failure_count: result.totals.failure,
211
+ errors: result.failed.map(f => f.error)
212
+ };
213
+ }
214
+ },
215
+ {
216
+ definition: moveBulkTasksTool,
217
+ handler: async (params) => {
218
+ const result = await moveBulkTasksHandler(params);
219
+ return {
220
+ successful: result.successful,
221
+ failed: result.failed,
222
+ count: result.totals.total,
223
+ success_count: result.totals.success,
224
+ failure_count: result.totals.failure,
225
+ errors: result.failed.map(f => f.error)
226
+ };
227
+ }
228
+ },
229
+ {
230
+ definition: deleteBulkTasksTool,
231
+ handler: async (params) => {
232
+ const result = await deleteBulkTasksHandler(params);
233
+ return {
234
+ successful: result.successful,
235
+ failed: result.failed,
236
+ count: result.totals.total,
237
+ success_count: result.totals.success,
238
+ failure_count: result.totals.failure,
239
+ errors: result.failed.map(f => f.error)
240
+ };
241
+ }
242
+ }
114
243
  ];