@taazkareem/clickup-mcp-server 0.6.5 → 0.6.6
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 +2 -2
- package/build/server.js +3 -6
- package/build/services/clickup/base.js +156 -45
- package/build/services/clickup/bulk.js +10 -22
- package/build/services/clickup/tag.js +51 -2
- package/build/services/clickup/task/task-core.js +76 -11
- package/build/services/clickup/task/task-search.js +378 -25
- package/build/services/clickup/workspace.js +14 -12
- package/build/tools/tag.js +102 -43
- package/build/tools/task/attachments.js +43 -21
- package/build/tools/task/bulk-operations.js +36 -16
- package/build/tools/task/handlers.js +253 -136
- package/build/tools/task/main.js +9 -33
- package/build/tools/task/single-operations.js +72 -43
- package/build/tools/task/utilities.js +59 -12
- package/build/tools/task/workspace-operations.js +15 -8
- package/build/utils/date-utils.js +7 -4
- package/build/utils/resolver-utils.js +102 -29
- package/package.json +1 -1
package/build/tools/tag.js
CHANGED
|
@@ -13,8 +13,11 @@ import { clickUpServices } from '../services/shared.js';
|
|
|
13
13
|
import { Logger } from '../logger.js';
|
|
14
14
|
import { sponsorService } from '../utils/sponsor-service.js';
|
|
15
15
|
import { processColorCommand } from '../utils/color-processor.js';
|
|
16
|
+
import { validateTaskIdentification } from './task/utilities.js';
|
|
16
17
|
// Create a logger specific to tag tools
|
|
17
18
|
const logger = new Logger('TagTools');
|
|
19
|
+
// Use shared services instance
|
|
20
|
+
const { task: taskService } = clickUpServices;
|
|
18
21
|
//=============================================================================
|
|
19
22
|
// TOOL DEFINITIONS
|
|
20
23
|
//=============================================================================
|
|
@@ -26,11 +29,15 @@ export const getSpaceTagsTool = {
|
|
|
26
29
|
description: `Purpose: Get all tags available in a ClickUp space.
|
|
27
30
|
|
|
28
31
|
Valid Usage:
|
|
29
|
-
1. Provide spaceId (preferred)
|
|
30
|
-
2. Provide spaceName
|
|
32
|
+
1. Provide spaceId (preferred if available)
|
|
33
|
+
2. Provide spaceName (will be resolved to a space ID)
|
|
31
34
|
|
|
32
35
|
Requirements:
|
|
33
|
-
-
|
|
36
|
+
- EITHER spaceId OR spaceName is REQUIRED
|
|
37
|
+
|
|
38
|
+
Notes:
|
|
39
|
+
- Tags are defined at the space level in ClickUp
|
|
40
|
+
- You need to know the available tags before adding them to tasks`,
|
|
34
41
|
inputSchema: {
|
|
35
42
|
type: "object",
|
|
36
43
|
properties: {
|
|
@@ -53,15 +60,18 @@ export const createSpaceTagTool = {
|
|
|
53
60
|
description: `Purpose: Create a new tag in a ClickUp space.
|
|
54
61
|
|
|
55
62
|
Valid Usage:
|
|
56
|
-
1. Provide spaceId
|
|
57
|
-
2. Provide spaceName
|
|
63
|
+
1. Provide spaceId (preferred if available)
|
|
64
|
+
2. Provide spaceName (will be resolved to a space ID)
|
|
58
65
|
|
|
59
66
|
Requirements:
|
|
60
67
|
- tagName: REQUIRED
|
|
61
|
-
-
|
|
68
|
+
- EITHER spaceId OR spaceName: REQUIRED
|
|
62
69
|
|
|
63
70
|
Notes:
|
|
64
|
-
-
|
|
71
|
+
- New tag will be available for all tasks in the space
|
|
72
|
+
- You can specify background and foreground colors in HEX format (e.g., #FF0000)
|
|
73
|
+
- You can also provide a color command (e.g., "blue tag") to automatically generate colors
|
|
74
|
+
- After creating a tag, you can add it to tasks using add_tag_to_task`,
|
|
65
75
|
inputSchema: {
|
|
66
76
|
type: "object",
|
|
67
77
|
properties: {
|
|
@@ -194,17 +204,18 @@ export const addTagToTaskTool = {
|
|
|
194
204
|
|
|
195
205
|
Valid Usage:
|
|
196
206
|
1. Provide taskId (preferred if available)
|
|
197
|
-
2. Provide taskName
|
|
207
|
+
2. Provide taskName (optionally with listName for disambiguation)
|
|
198
208
|
|
|
199
209
|
Requirements:
|
|
200
210
|
- tagName: REQUIRED
|
|
201
|
-
- EITHER taskId OR
|
|
211
|
+
- EITHER taskId OR customTaskId OR taskName: REQUIRED
|
|
202
212
|
- The tag MUST exist in the space containing the task before calling this tool
|
|
203
213
|
|
|
204
214
|
Warning:
|
|
205
215
|
- The operation will fail if the tag does not exist in the space
|
|
206
216
|
- Always use get_space_tags first to verify the tag exists
|
|
207
217
|
- If the tag doesn't exist, create it using create_space_tag before adding it to the task
|
|
218
|
+
- If multiple tasks have the same name, provide listName to disambiguate
|
|
208
219
|
|
|
209
220
|
Notes:
|
|
210
221
|
- Use get_space_tags to see available tags
|
|
@@ -222,11 +233,11 @@ Notes:
|
|
|
222
233
|
},
|
|
223
234
|
taskName: {
|
|
224
235
|
type: "string",
|
|
225
|
-
description: "Name of the task to add tag to.
|
|
236
|
+
description: "Name of the task to add tag to. Will search across all lists unless listName is provided."
|
|
226
237
|
},
|
|
227
238
|
listName: {
|
|
228
239
|
type: "string",
|
|
229
|
-
description: "Name of the list containing the task.
|
|
240
|
+
description: "Optional: Name of the list containing the task. Use to disambiguate when multiple tasks have the same name."
|
|
230
241
|
},
|
|
231
242
|
tagName: {
|
|
232
243
|
type: "string",
|
|
@@ -245,15 +256,16 @@ export const removeTagFromTaskTool = {
|
|
|
245
256
|
|
|
246
257
|
Valid Usage:
|
|
247
258
|
1. Provide taskId (preferred if available)
|
|
248
|
-
2. Provide taskName
|
|
259
|
+
2. Provide taskName (optionally with listName for disambiguation)
|
|
249
260
|
|
|
250
261
|
Requirements:
|
|
251
262
|
- tagName: REQUIRED
|
|
252
|
-
- EITHER taskId OR
|
|
263
|
+
- EITHER taskId OR customTaskId OR taskName: REQUIRED
|
|
253
264
|
|
|
254
265
|
Notes:
|
|
255
266
|
- This only removes the association between the tag and task
|
|
256
|
-
- The tag will still exist in the space
|
|
267
|
+
- The tag will still exist in the space
|
|
268
|
+
- If multiple tasks have the same name, provide listName to disambiguate`,
|
|
257
269
|
inputSchema: {
|
|
258
270
|
type: "object",
|
|
259
271
|
properties: {
|
|
@@ -267,11 +279,11 @@ Notes:
|
|
|
267
279
|
},
|
|
268
280
|
taskName: {
|
|
269
281
|
type: "string",
|
|
270
|
-
description: "Name of the task to remove tag from.
|
|
282
|
+
description: "Name of the task to remove tag from. Will search across all lists unless listName is provided."
|
|
271
283
|
},
|
|
272
284
|
listName: {
|
|
273
285
|
type: "string",
|
|
274
|
-
description: "Name of the list containing the task.
|
|
286
|
+
description: "Optional: Name of the list containing the task. Use to disambiguate when multiple tasks have the same name."
|
|
275
287
|
},
|
|
276
288
|
tagName: {
|
|
277
289
|
type: "string",
|
|
@@ -334,10 +346,18 @@ export const handleDeleteSpaceTag = createHandlerWrapper(deleteSpaceTag, () => (
|
|
|
334
346
|
/**
|
|
335
347
|
* Wrapper for addTagToTask handler
|
|
336
348
|
*/
|
|
337
|
-
export const handleAddTagToTask = createHandlerWrapper(addTagToTask, () =>
|
|
338
|
-
success
|
|
339
|
-
|
|
340
|
-
|
|
349
|
+
export const handleAddTagToTask = createHandlerWrapper(addTagToTask, (result) => {
|
|
350
|
+
if (!result.success) {
|
|
351
|
+
return {
|
|
352
|
+
success: false,
|
|
353
|
+
error: result.error
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
success: true,
|
|
358
|
+
message: "Tag added to task successfully"
|
|
359
|
+
};
|
|
360
|
+
});
|
|
341
361
|
/**
|
|
342
362
|
* Wrapper for removeTagFromTask handler
|
|
343
363
|
*/
|
|
@@ -666,28 +686,42 @@ export async function deleteSpaceTag(params) {
|
|
|
666
686
|
*/
|
|
667
687
|
async function resolveTaskId(params) {
|
|
668
688
|
const { taskId, customTaskId, taskName, listName } = params;
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
689
|
+
try {
|
|
690
|
+
// First validate task identification with global lookup enabled
|
|
691
|
+
const validationResult = validateTaskIdentification({ taskId, customTaskId, taskName, listName }, { useGlobalLookup: true });
|
|
692
|
+
if (!validationResult.isValid) {
|
|
693
|
+
return {
|
|
694
|
+
success: false,
|
|
695
|
+
error: { message: validationResult.errorMessage }
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
const result = await taskService.findTasks({
|
|
699
|
+
taskId,
|
|
700
|
+
customTaskId,
|
|
701
|
+
taskName,
|
|
702
|
+
listName,
|
|
703
|
+
allowMultipleMatches: false,
|
|
704
|
+
useSmartDisambiguation: true,
|
|
705
|
+
includeFullDetails: false
|
|
706
|
+
});
|
|
707
|
+
if (!result || Array.isArray(result)) {
|
|
708
|
+
return {
|
|
709
|
+
success: false,
|
|
710
|
+
error: { message: 'Task not found with the provided identification' }
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
return { success: true, taskId: result.id };
|
|
676
714
|
}
|
|
677
|
-
|
|
678
|
-
if (taskName && listName) {
|
|
679
|
-
// Implementation would go here
|
|
715
|
+
catch (error) {
|
|
680
716
|
return {
|
|
681
717
|
success: false,
|
|
682
|
-
error: {
|
|
718
|
+
error: {
|
|
719
|
+
message: error.message || 'Failed to resolve task ID',
|
|
720
|
+
code: error.code,
|
|
721
|
+
details: error.data
|
|
722
|
+
}
|
|
683
723
|
};
|
|
684
724
|
}
|
|
685
|
-
return {
|
|
686
|
-
success: false,
|
|
687
|
-
error: {
|
|
688
|
-
message: 'Task identifier is required (taskId, customTaskId, or taskName+listName)'
|
|
689
|
-
}
|
|
690
|
-
};
|
|
691
725
|
}
|
|
692
726
|
/**
|
|
693
727
|
* Add a tag to a task
|
|
@@ -705,12 +739,12 @@ export async function addTagToTask(params) {
|
|
|
705
739
|
}
|
|
706
740
|
};
|
|
707
741
|
}
|
|
708
|
-
if (!taskId && !customTaskId && !
|
|
709
|
-
logger.error('addTagToTask called without
|
|
742
|
+
if (!taskId && !customTaskId && !taskName) {
|
|
743
|
+
logger.error('addTagToTask called without task identifier');
|
|
710
744
|
return {
|
|
711
745
|
success: false,
|
|
712
746
|
error: {
|
|
713
|
-
message: 'Either taskId, customTaskId, or
|
|
747
|
+
message: 'Either taskId, customTaskId, or taskName is required'
|
|
714
748
|
}
|
|
715
749
|
};
|
|
716
750
|
}
|
|
@@ -728,6 +762,31 @@ export async function addTagToTask(params) {
|
|
|
728
762
|
const result = await clickUpServices.tag.addTagToTask(taskIdResult.taskId, tagName);
|
|
729
763
|
if (!result.success) {
|
|
730
764
|
logger.error('Failed to add tag to task', result.error);
|
|
765
|
+
// Provide more specific error messages based on error code
|
|
766
|
+
if (result.error?.code === 'TAG_NOT_FOUND') {
|
|
767
|
+
return {
|
|
768
|
+
success: false,
|
|
769
|
+
error: {
|
|
770
|
+
message: `The tag "${tagName}" does not exist in the space. Please create it first using create_space_tag.`
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
else if (result.error?.code === 'SPACE_NOT_FOUND') {
|
|
775
|
+
return {
|
|
776
|
+
success: false,
|
|
777
|
+
error: {
|
|
778
|
+
message: 'Could not determine which space the task belongs to.'
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
else if (result.error?.code === 'TAG_VERIFICATION_FAILED') {
|
|
783
|
+
return {
|
|
784
|
+
success: false,
|
|
785
|
+
error: {
|
|
786
|
+
message: 'The tag addition could not be verified. Please check if the tag was added manually.'
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
}
|
|
731
790
|
return {
|
|
732
791
|
success: false,
|
|
733
792
|
error: result.error || {
|
|
@@ -768,12 +827,12 @@ export async function removeTagFromTask(params) {
|
|
|
768
827
|
}
|
|
769
828
|
};
|
|
770
829
|
}
|
|
771
|
-
if (!taskId && !customTaskId && !
|
|
772
|
-
logger.error('removeTagFromTask called without
|
|
830
|
+
if (!taskId && !customTaskId && !taskName) {
|
|
831
|
+
logger.error('removeTagFromTask called without task identifier');
|
|
773
832
|
return {
|
|
774
833
|
success: false,
|
|
775
834
|
error: {
|
|
776
|
-
message: 'Either taskId, customTaskId, or
|
|
835
|
+
message: 'Either taskId, customTaskId, or taskName is required'
|
|
777
836
|
}
|
|
778
837
|
};
|
|
779
838
|
}
|
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
import { clickUpServices } from '../../services/shared.js';
|
|
11
11
|
import { validateTaskIdentification } from './utilities.js';
|
|
12
12
|
import { sponsorService } from '../../utils/sponsor-service.js';
|
|
13
|
+
import { Logger } from '../../logger.js';
|
|
13
14
|
// Use shared services instance
|
|
14
15
|
const { task: taskService } = clickUpServices;
|
|
16
|
+
// Create a logger instance for attachments
|
|
17
|
+
const logger = new Logger('TaskAttachments');
|
|
15
18
|
// Session storage for chunked uploads (in-memory for demonstration)
|
|
16
19
|
const chunkSessions = new Map();
|
|
17
20
|
// Clean up expired sessions periodically
|
|
@@ -21,7 +24,7 @@ setInterval(() => {
|
|
|
21
24
|
for (const [token, session] of chunkSessions.entries()) {
|
|
22
25
|
if (now - session.timestamp > expired) {
|
|
23
26
|
chunkSessions.delete(token);
|
|
24
|
-
|
|
27
|
+
logger.debug(`Cleaned up expired upload session: ${token}`);
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
}, 3600 * 1000); // Check every hour
|
|
@@ -33,23 +36,39 @@ export const attachTaskFileTool = {
|
|
|
33
36
|
description: `Purpose: Attaches a file to a ClickUp task.
|
|
34
37
|
|
|
35
38
|
Valid Usage:
|
|
36
|
-
1. Use taskId (preferred) - works with both regular and custom IDs
|
|
37
|
-
2. Use taskName
|
|
39
|
+
1. Use taskId alone (preferred) - works with both regular and custom IDs
|
|
40
|
+
2. Use taskName alone (will search across all lists)
|
|
41
|
+
3. Use taskName + listName (for faster, targeted search)
|
|
38
42
|
|
|
39
|
-
File
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
File Source Options:
|
|
44
|
+
1. Upload from base64: Provide file_data + file_name
|
|
45
|
+
2. Upload from URL: Provide file_url starting with http:// or https://
|
|
46
|
+
3. Upload from local file: Provide file_url as absolute path (starting with / or drive letter)
|
|
47
|
+
4. For large files: Use chunk_* parameters for advanced chunked uploading
|
|
44
48
|
|
|
45
49
|
Requirements:
|
|
46
|
-
-
|
|
47
|
-
-
|
|
50
|
+
- EITHER taskId OR taskName: REQUIRED
|
|
51
|
+
- listName: Optional, but recommended when using taskName
|
|
52
|
+
- File Source: ONE of the following is REQUIRED:
|
|
53
|
+
- file_data + file_name
|
|
54
|
+
- file_url (web URL or local path)
|
|
55
|
+
- chunk_session (for continuing chunked upload)
|
|
48
56
|
|
|
49
57
|
Notes:
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
58
|
+
- The tool automatically searches for tasks using smart name matching
|
|
59
|
+
- When only taskName is provided, it searches across all lists
|
|
60
|
+
- Adding listName narrows the search to a specific list for better performance
|
|
61
|
+
- The system automatically selects the best upload method based on file size and source:
|
|
62
|
+
- Base64 method: Limited to 10MB due to encoding overhead
|
|
63
|
+
- URL method: Works for files hosted online
|
|
64
|
+
- Local file method: Works with absolute paths only
|
|
65
|
+
- Large files: Automatically uses chunked uploading
|
|
66
|
+
|
|
67
|
+
Warning:
|
|
68
|
+
- Using taskName without listName may match multiple tasks
|
|
69
|
+
- If multiple matches are found, the operation will fail with a disambiguation error
|
|
70
|
+
- For local files, relative paths are not supported
|
|
71
|
+
- Base64 uploads over 10MB will automatically switch to chunked upload mode`,
|
|
53
72
|
inputSchema: {
|
|
54
73
|
type: "object",
|
|
55
74
|
properties: {
|
|
@@ -106,9 +125,12 @@ Notes:
|
|
|
106
125
|
*/
|
|
107
126
|
async function attachTaskFileHandler(params) {
|
|
108
127
|
// Extract common parameters
|
|
109
|
-
const { taskId, taskName, listName, file_name, file_data, file_url, auth_header, chunk_total, chunk_size, chunk_index, session_id } = params;
|
|
128
|
+
const { taskId, taskName, listName, customTaskId, file_name, file_data, file_url, auth_header, chunk_total, chunk_size, chunk_index, session_id } = params;
|
|
110
129
|
// Validate task identification
|
|
111
|
-
validateTaskIdentification(
|
|
130
|
+
const validationResult = validateTaskIdentification({ taskId, taskName, listName, customTaskId }, { useGlobalLookup: true });
|
|
131
|
+
if (!validationResult.isValid) {
|
|
132
|
+
throw new Error(validationResult.errorMessage);
|
|
133
|
+
}
|
|
112
134
|
// Validate file source - either file_data or file_url must be provided
|
|
113
135
|
if (!file_data && !file_url && !session_id) {
|
|
114
136
|
throw new Error("Either file_data, file_url, or session_id must be provided");
|
|
@@ -134,13 +156,13 @@ async function attachTaskFileHandler(params) {
|
|
|
134
156
|
// CASE 2: URL-based upload or local file path
|
|
135
157
|
if (file_url) {
|
|
136
158
|
// Check if it's a local file path
|
|
137
|
-
|
|
159
|
+
logger.debug(`Checking if path is local: ${file_url}`);
|
|
138
160
|
if (file_url.startsWith('/') || /^[A-Za-z]:\\/.test(file_url)) {
|
|
139
|
-
|
|
161
|
+
logger.debug(`Detected as local path, proceeding to handle: ${file_url}`);
|
|
140
162
|
return await handleLocalFileUpload(resolvedTaskId, file_url, file_name);
|
|
141
163
|
}
|
|
142
164
|
else if (file_url.startsWith('http://') || file_url.startsWith('https://')) {
|
|
143
|
-
|
|
165
|
+
logger.debug(`Detected as URL, proceeding with URL upload: ${file_url}`);
|
|
144
166
|
return await handleUrlUpload(resolvedTaskId, file_url, file_name, auth_header);
|
|
145
167
|
}
|
|
146
168
|
else {
|
|
@@ -167,7 +189,7 @@ async function attachTaskFileHandler(params) {
|
|
|
167
189
|
throw new Error("Invalid parameters: Unable to determine upload method");
|
|
168
190
|
}
|
|
169
191
|
catch (error) {
|
|
170
|
-
|
|
192
|
+
logger.error(`Error attaching file to task:`, error);
|
|
171
193
|
throw error;
|
|
172
194
|
}
|
|
173
195
|
}
|
|
@@ -315,7 +337,7 @@ async function handleLocalFileUpload(taskId, filePath, fileName) {
|
|
|
315
337
|
// Import fs and path modules
|
|
316
338
|
const fs = await import('fs');
|
|
317
339
|
const path = await import('path');
|
|
318
|
-
|
|
340
|
+
logger.debug(`Processing absolute file path: ${filePath}`);
|
|
319
341
|
// Normalize the path to prevent directory traversal attacks
|
|
320
342
|
const normalizedPath = path.normalize(filePath);
|
|
321
343
|
// Check if file exists
|
|
@@ -332,7 +354,7 @@ async function handleLocalFileUpload(taskId, filePath, fileName) {
|
|
|
332
354
|
// Read file
|
|
333
355
|
const fileBuffer = fs.readFileSync(normalizedPath);
|
|
334
356
|
const fileSize = fileBuffer.length;
|
|
335
|
-
|
|
357
|
+
logger.debug(`Successfully read file: ${extractedFileName} (${fileSize} bytes)`);
|
|
336
358
|
// Choose upload method based on file size
|
|
337
359
|
if (fileSize > 10 * 1024 * 1024) {
|
|
338
360
|
// For large files, start chunked upload process
|
|
@@ -81,11 +81,13 @@ Valid Usage:
|
|
|
81
81
|
|
|
82
82
|
Requirements:
|
|
83
83
|
- tasks: REQUIRED (array of tasks, each with at least a name)
|
|
84
|
-
-
|
|
84
|
+
- EITHER listId OR listName: REQUIRED
|
|
85
|
+
- All tasks will be created in the specified list
|
|
85
86
|
|
|
86
87
|
Notes:
|
|
87
|
-
- Configure batch
|
|
88
|
-
-
|
|
88
|
+
- Configure batch size and concurrency via options for performance
|
|
89
|
+
- Each task should have a name with emoji prefix
|
|
90
|
+
- Custom fields can be set for each task using the custom_fields property (array of {id, value} objects)`,
|
|
89
91
|
inputSchema: {
|
|
90
92
|
type: "object",
|
|
91
93
|
properties: {
|
|
@@ -168,16 +170,22 @@ export const updateBulkTasksTool = {
|
|
|
168
170
|
description: `Purpose: Update multiple tasks efficiently in a single operation.
|
|
169
171
|
|
|
170
172
|
Valid Usage:
|
|
171
|
-
1.
|
|
172
|
-
2.
|
|
173
|
+
1. For each task, provide taskId (preferred)
|
|
174
|
+
2. For each task, provide taskName + listName
|
|
173
175
|
|
|
174
176
|
Requirements:
|
|
175
177
|
- tasks: REQUIRED (array of tasks to update)
|
|
176
|
-
-
|
|
178
|
+
- For each task entry, EITHER taskId OR (taskName + listName) is REQUIRED
|
|
179
|
+
- At least one update field per task (name, description, status, priority, dueDate)
|
|
177
180
|
|
|
178
181
|
Notes:
|
|
179
182
|
- Only specified fields will be updated for each task
|
|
180
|
-
- Configure batch
|
|
183
|
+
- Configure batch size and concurrency via options for performance
|
|
184
|
+
- Each task can have different fields to update
|
|
185
|
+
- Custom fields can be updated using the custom_fields property (array of {id, value} objects)
|
|
186
|
+
|
|
187
|
+
Warning:
|
|
188
|
+
- Using taskName without listName will fail as tasks may have identical names across lists`,
|
|
181
189
|
inputSchema: {
|
|
182
190
|
type: "object",
|
|
183
191
|
properties: {
|
|
@@ -261,14 +269,21 @@ export const moveBulkTasksTool = {
|
|
|
261
269
|
description: `Purpose: Move multiple tasks to a different list efficiently.
|
|
262
270
|
|
|
263
271
|
Valid Usage:
|
|
264
|
-
1.
|
|
272
|
+
1. For each task, provide taskId + target list (preferred)
|
|
273
|
+
2. For each task, provide taskName + listName + target list
|
|
265
274
|
|
|
266
275
|
Requirements:
|
|
267
|
-
- tasks: REQUIRED (array of
|
|
268
|
-
-
|
|
276
|
+
- tasks: REQUIRED (array of tasks to move)
|
|
277
|
+
- EITHER targetListId OR targetListName: REQUIRED
|
|
278
|
+
- For each task entry, EITHER taskId OR (taskName + listName) is REQUIRED
|
|
279
|
+
|
|
280
|
+
Notes:
|
|
281
|
+
- Configure batch size and concurrency via options for performance
|
|
282
|
+
- All tasks will be moved to the same destination list
|
|
269
283
|
|
|
270
284
|
Warning:
|
|
271
|
-
- Task statuses may reset if destination list has different status options
|
|
285
|
+
- Task statuses may reset if destination list has different status options
|
|
286
|
+
- Using taskName without listName will fail as tasks may have identical names across lists`,
|
|
272
287
|
inputSchema: {
|
|
273
288
|
type: "object",
|
|
274
289
|
properties: {
|
|
@@ -318,15 +333,20 @@ export const deleteBulkTasksTool = {
|
|
|
318
333
|
description: `Purpose: PERMANENTLY DELETE multiple tasks at once.
|
|
319
334
|
|
|
320
335
|
Valid Usage:
|
|
321
|
-
1.
|
|
322
|
-
2.
|
|
336
|
+
1. For each task, provide taskId (preferred and safest)
|
|
337
|
+
2. For each task, provide taskName + listName
|
|
323
338
|
|
|
324
339
|
Requirements:
|
|
325
|
-
- tasks: REQUIRED (array of
|
|
340
|
+
- tasks: REQUIRED (array of tasks to delete)
|
|
341
|
+
- For each task entry, EITHER taskId OR (taskName + listName) is REQUIRED
|
|
342
|
+
|
|
343
|
+
Notes:
|
|
344
|
+
- Configure batch size and concurrency via options for performance
|
|
326
345
|
|
|
327
346
|
Warning:
|
|
328
|
-
- This action CANNOT be undone
|
|
329
|
-
-
|
|
347
|
+
- This action CANNOT be undone for any of the tasks
|
|
348
|
+
- Using taskName without listName is dangerous as names may not be unique
|
|
349
|
+
- Always provide listName when using taskName for safer targeting`,
|
|
330
350
|
inputSchema: {
|
|
331
351
|
type: "object",
|
|
332
352
|
properties: {
|