@taazkareem/clickup-mcp-server 0.8.4 → 0.9.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/LICENSE +9 -17
- package/README.md +33 -38
- package/build/enhanced_server.js +262 -0
- package/build/index.js +9 -3
- package/build/license.js +172 -0
- package/build/middleware/auth.js +211 -0
- package/build/routes/auth.js +306 -0
- package/build/schemas/member.js +13 -0
- package/build/server.js +15 -1
- package/build/server.log +15 -0
- package/build/services/auth/oauth2.js +236 -0
- package/build/services/auth/session.js +337 -0
- package/build/services/clickup/adapter.js +281 -0
- package/build/services/clickup/factory.js +339 -0
- package/build/services/clickup/task/task-attachments.js +20 -12
- package/build/services/clickup/task/task-comments.js +19 -9
- package/build/services/clickup/task/task-core.js +68 -4
- package/build/services/clickup/task/task-custom-fields.js +23 -13
- package/build/services/clickup/task/task-search.js +79 -71
- package/build/services/clickup/task/task-service.js +88 -9
- package/build/services/clickup/task/task-tags.js +25 -13
- package/build/sse_server.js +4 -4
- package/build/tools/documents.js +11 -4
- package/build/tools/health.js +23 -0
- package/build/tools/member.js +2 -4
- package/build/tools/task/bulk-operations.js +5 -5
- package/build/tools/task/handlers.js +62 -12
- package/build/tools/task/single-operations.js +9 -9
- package/build/tools/task/time-tracking.js +61 -170
- package/build/tools/task/utilities.js +56 -22
- package/build/utils/date-utils.js +341 -141
- package/build/utils/schema-compatibility.js +222 -0
- package/build/utils/universal-schema-compatibility.js +171 -0
- package/build/virtual-sdk/generator.js +53 -0
- package/build/virtual-sdk/registry.js +45 -0
- package/package.json +2 -2
|
@@ -7,12 +7,20 @@
|
|
|
7
7
|
* Handles tag operations for ClickUp tasks, including:
|
|
8
8
|
* - Adding tags to a task
|
|
9
9
|
* - Removing tags from a task
|
|
10
|
+
*
|
|
11
|
+
* REFACTORED: Now uses composition instead of inheritance.
|
|
12
|
+
* Only depends on TaskServiceCore for getTask() and base functionality.
|
|
10
13
|
*/
|
|
11
|
-
import { TaskServiceComments } from './task-comments.js';
|
|
12
14
|
/**
|
|
13
15
|
* Tags functionality for the TaskService
|
|
16
|
+
*
|
|
17
|
+
* This service handles all tag-related operations for ClickUp tasks.
|
|
18
|
+
* It uses composition to access core functionality instead of inheritance.
|
|
14
19
|
*/
|
|
15
|
-
export class TaskServiceTags
|
|
20
|
+
export class TaskServiceTags {
|
|
21
|
+
constructor(core) {
|
|
22
|
+
this.core = core;
|
|
23
|
+
}
|
|
16
24
|
/**
|
|
17
25
|
* Add a tag to a task
|
|
18
26
|
*
|
|
@@ -21,16 +29,18 @@ export class TaskServiceTags extends TaskServiceComments {
|
|
|
21
29
|
* @returns Success response
|
|
22
30
|
*/
|
|
23
31
|
async addTagToTask(taskId, tagName) {
|
|
24
|
-
this.logOperation('addTagToTask', { taskId, tagName });
|
|
32
|
+
this.core.logOperation('addTagToTask', { taskId, tagName });
|
|
25
33
|
try {
|
|
26
34
|
const payload = {
|
|
27
35
|
tag_name: tagName,
|
|
28
36
|
};
|
|
29
|
-
await this.
|
|
37
|
+
await this.core.makeRequest(async () => {
|
|
38
|
+
return await this.core.client.post(`/task/${taskId}/tag/${encodeURIComponent(tagName)}`, payload);
|
|
39
|
+
});
|
|
30
40
|
return true;
|
|
31
41
|
}
|
|
32
42
|
catch (error) {
|
|
33
|
-
throw this.handleError(error, `Failed to add tag "${tagName}" to task`);
|
|
43
|
+
throw this.core.handleError(error, `Failed to add tag "${tagName}" to task`);
|
|
34
44
|
}
|
|
35
45
|
}
|
|
36
46
|
/**
|
|
@@ -41,13 +51,15 @@ export class TaskServiceTags extends TaskServiceComments {
|
|
|
41
51
|
* @returns Success response
|
|
42
52
|
*/
|
|
43
53
|
async removeTagFromTask(taskId, tagName) {
|
|
44
|
-
this.logOperation('removeTagFromTask', { taskId, tagName });
|
|
54
|
+
this.core.logOperation('removeTagFromTask', { taskId, tagName });
|
|
45
55
|
try {
|
|
46
|
-
await this.
|
|
56
|
+
await this.core.makeRequest(async () => {
|
|
57
|
+
return await this.core.client.delete(`/task/${taskId}/tag/${encodeURIComponent(tagName)}`);
|
|
58
|
+
});
|
|
47
59
|
return true;
|
|
48
60
|
}
|
|
49
61
|
catch (error) {
|
|
50
|
-
throw this.handleError(error, `Failed to remove tag "${tagName}" from task`);
|
|
62
|
+
throw this.core.handleError(error, `Failed to remove tag "${tagName}" from task`);
|
|
51
63
|
}
|
|
52
64
|
}
|
|
53
65
|
/**
|
|
@@ -57,14 +69,14 @@ export class TaskServiceTags extends TaskServiceComments {
|
|
|
57
69
|
* @returns Array of task tags
|
|
58
70
|
*/
|
|
59
71
|
async getTaskTags(taskId) {
|
|
60
|
-
this.logOperation('getTaskTags', { taskId });
|
|
72
|
+
this.core.logOperation('getTaskTags', { taskId });
|
|
61
73
|
try {
|
|
62
74
|
// We need to fetch the full task to get its tags
|
|
63
|
-
const task = await this.getTask(taskId);
|
|
75
|
+
const task = await this.core.getTask(taskId);
|
|
64
76
|
return task.tags || [];
|
|
65
77
|
}
|
|
66
78
|
catch (error) {
|
|
67
|
-
throw this.handleError(error, 'Failed to get task tags');
|
|
79
|
+
throw this.core.handleError(error, 'Failed to get task tags');
|
|
68
80
|
}
|
|
69
81
|
}
|
|
70
82
|
/**
|
|
@@ -75,7 +87,7 @@ export class TaskServiceTags extends TaskServiceComments {
|
|
|
75
87
|
* @returns Success response
|
|
76
88
|
*/
|
|
77
89
|
async updateTaskTags(taskId, tagNames) {
|
|
78
|
-
this.logOperation('updateTaskTags', { taskId, tagNames });
|
|
90
|
+
this.core.logOperation('updateTaskTags', { taskId, tagNames });
|
|
79
91
|
try {
|
|
80
92
|
// First get existing tags
|
|
81
93
|
const existingTags = await this.getTaskTags(taskId);
|
|
@@ -95,7 +107,7 @@ export class TaskServiceTags extends TaskServiceComments {
|
|
|
95
107
|
return true;
|
|
96
108
|
}
|
|
97
109
|
catch (error) {
|
|
98
|
-
throw this.handleError(error, 'Failed to update task tags');
|
|
110
|
+
throw this.core.handleError(error, 'Failed to update task tags');
|
|
99
111
|
}
|
|
100
112
|
}
|
|
101
113
|
}
|
package/build/sse_server.js
CHANGED
|
@@ -244,11 +244,11 @@ export function startSSEServer() {
|
|
|
244
244
|
}
|
|
245
245
|
catch (error) {
|
|
246
246
|
logger.error('Failed to start HTTPS server', {
|
|
247
|
-
error: error.
|
|
248
|
-
sslKeyPath:
|
|
249
|
-
sslCertPath:
|
|
247
|
+
error: 'An error occurred while starting HTTPS server.',
|
|
248
|
+
sslKeyPath: 'REDACTED',
|
|
249
|
+
sslCertPath: 'REDACTED'
|
|
250
250
|
});
|
|
251
|
-
console.log(`❌ Failed to start HTTPS server
|
|
251
|
+
console.log(`❌ Failed to start HTTPS server. Please check the server configuration and logs for details.`);
|
|
252
252
|
return null;
|
|
253
253
|
}
|
|
254
254
|
}
|
package/build/tools/documents.js
CHANGED
|
@@ -19,7 +19,14 @@ const { document: documentService } = clickUpServices;
|
|
|
19
19
|
*/
|
|
20
20
|
export const createDocumentTool = {
|
|
21
21
|
name: "create_document",
|
|
22
|
-
description: `Creates a document in a ClickUp space, folder, or list. Requires name, parent info, visibility and create_page flag
|
|
22
|
+
description: `Creates a document in a ClickUp space, folder, or list. Requires name, parent info, visibility and create_page flag.
|
|
23
|
+
|
|
24
|
+
Example usage:
|
|
25
|
+
- For list: parent: {"id": "901407953112", "type": 6}
|
|
26
|
+
- For space: parent: {"id": "90141392755", "type": 4}
|
|
27
|
+
- For folder: parent: {"id": "90144231850", "type": 5}
|
|
28
|
+
|
|
29
|
+
Note: Document creation permissions may vary by ClickUp plan and parent container type.`,
|
|
23
30
|
inputSchema: {
|
|
24
31
|
type: "object",
|
|
25
32
|
properties: {
|
|
@@ -32,16 +39,16 @@ export const createDocumentTool = {
|
|
|
32
39
|
properties: {
|
|
33
40
|
id: {
|
|
34
41
|
type: "string",
|
|
35
|
-
description: "ID of the parent container (space, folder, or list)"
|
|
42
|
+
description: "ID of the parent container (space, folder, or list). Use actual ID from workspace hierarchy."
|
|
36
43
|
},
|
|
37
44
|
type: {
|
|
38
45
|
type: "number",
|
|
39
46
|
enum: [4, 5, 6, 7, 12],
|
|
40
|
-
description: "Type of the parent container
|
|
47
|
+
description: "Type of the parent container: 4=space, 5=folder, 6=list, 7=everything, 12=workspace. Most commonly use 6 for lists."
|
|
41
48
|
}
|
|
42
49
|
},
|
|
43
50
|
required: ["id", "type"],
|
|
44
|
-
description: "Parent container
|
|
51
|
+
description: "Parent container object with id and type properties. Example: {\"id\": \"901407953112\", \"type\": 6}"
|
|
45
52
|
},
|
|
46
53
|
visibility: {
|
|
47
54
|
type: "string",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple health‑check tool – returns a tiny JSON payload confirming the server is alive.
|
|
3
|
+
*/
|
|
4
|
+
export const healthCheckTool = {
|
|
5
|
+
name: "health_check",
|
|
6
|
+
description: "Returns a simple health status for the MCP server.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {},
|
|
10
|
+
additionalProperties: false,
|
|
11
|
+
},
|
|
12
|
+
outputSchema: {
|
|
13
|
+
type: "object",
|
|
14
|
+
properties: {
|
|
15
|
+
status: { type: "string" },
|
|
16
|
+
},
|
|
17
|
+
required: ["status"],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
/** Handler invoked by CallTool when the client requests "health_check" */
|
|
21
|
+
export async function handleHealthCheck() {
|
|
22
|
+
return { status: "ok" };
|
|
23
|
+
}
|
package/build/tools/member.js
CHANGED
|
@@ -97,12 +97,10 @@ export async function handleResolveAssignees(parameters) {
|
|
|
97
97
|
m.name?.toLowerCase() === input.toLowerCase());
|
|
98
98
|
return found ? found.id : null;
|
|
99
99
|
});
|
|
100
|
-
|
|
101
|
-
return { userIds: resolved };
|
|
100
|
+
return sponsorService.createResponse({ userIds: resolved }, true);
|
|
102
101
|
}
|
|
103
102
|
catch (error) {
|
|
104
103
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
105
|
-
|
|
106
|
-
return { error: `Failed to resolve assignees: ${errorMessage}` };
|
|
104
|
+
return sponsorService.createErrorResponse(`Failed to resolve assignees: ${errorMessage}`);
|
|
107
105
|
}
|
|
108
106
|
}
|
|
@@ -50,7 +50,7 @@ const bulkOptionsSchema = {
|
|
|
50
50
|
const taskIdentifierSchema = {
|
|
51
51
|
taskId: {
|
|
52
52
|
type: "string",
|
|
53
|
-
description: "Task ID (preferred).
|
|
53
|
+
description: "Task ID (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
54
54
|
},
|
|
55
55
|
taskName: {
|
|
56
56
|
type: "string",
|
|
@@ -62,7 +62,7 @@ const taskIdentifierSchema = {
|
|
|
62
62
|
},
|
|
63
63
|
customTaskId: {
|
|
64
64
|
type: "string",
|
|
65
|
-
description: "Custom task ID (e.g., 'DEV-1234').
|
|
65
|
+
description: "Custom task ID (e.g., 'DEV-1234'). This parameter is now optional since taskId automatically handles custom IDs. Use only for explicit custom ID lookup or backward compatibility."
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
68
|
//=============================================================================
|
|
@@ -175,7 +175,7 @@ export const updateBulkTasksTool = {
|
|
|
175
175
|
properties: {
|
|
176
176
|
taskId: {
|
|
177
177
|
type: "string",
|
|
178
|
-
description: "Task ID (preferred).
|
|
178
|
+
description: "Task ID (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
179
179
|
},
|
|
180
180
|
taskName: {
|
|
181
181
|
type: "string",
|
|
@@ -267,7 +267,7 @@ export const moveBulkTasksTool = {
|
|
|
267
267
|
properties: {
|
|
268
268
|
taskId: {
|
|
269
269
|
type: "string",
|
|
270
|
-
description: "Task ID (preferred).
|
|
270
|
+
description: "Task ID (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
271
271
|
},
|
|
272
272
|
taskName: {
|
|
273
273
|
type: "string",
|
|
@@ -314,7 +314,7 @@ export const deleteBulkTasksTool = {
|
|
|
314
314
|
properties: {
|
|
315
315
|
taskId: {
|
|
316
316
|
type: "string",
|
|
317
|
-
description: "Task ID (preferred).
|
|
317
|
+
description: "Task ID (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
318
318
|
},
|
|
319
319
|
taskName: {
|
|
320
320
|
type: "string",
|
|
@@ -110,10 +110,15 @@ async function resolveAssignees(assignees) {
|
|
|
110
110
|
if (toResolve.length > 0) {
|
|
111
111
|
try {
|
|
112
112
|
const result = await handleResolveAssignees({ assignees: toResolve });
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
// The result is wrapped by sponsorService.createResponse, so we need to parse the JSON
|
|
114
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
115
|
+
const dataText = result.content[0].text;
|
|
116
|
+
const parsedData = JSON.parse(dataText);
|
|
117
|
+
if (parsedData.userIds && Array.isArray(parsedData.userIds)) {
|
|
118
|
+
for (const userId of parsedData.userIds) {
|
|
119
|
+
if (userId !== null && typeof userId === 'number') {
|
|
120
|
+
resolved.push(userId);
|
|
121
|
+
}
|
|
117
122
|
}
|
|
118
123
|
}
|
|
119
124
|
}
|
|
@@ -143,12 +148,28 @@ async function buildUpdateData(params) {
|
|
|
143
148
|
updateData.priority = toTaskPriority(params.priority);
|
|
144
149
|
}
|
|
145
150
|
if (params.dueDate !== undefined) {
|
|
146
|
-
|
|
147
|
-
|
|
151
|
+
const parsedDueDate = parseDueDate(params.dueDate);
|
|
152
|
+
if (parsedDueDate !== undefined) {
|
|
153
|
+
updateData.due_date = parsedDueDate;
|
|
154
|
+
updateData.due_date_time = true;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// Clear the due date by setting it to null
|
|
158
|
+
updateData.due_date = null;
|
|
159
|
+
updateData.due_date_time = false;
|
|
160
|
+
}
|
|
148
161
|
}
|
|
149
162
|
if (params.startDate !== undefined) {
|
|
150
|
-
|
|
151
|
-
|
|
163
|
+
const parsedStartDate = parseDueDate(params.startDate);
|
|
164
|
+
if (parsedStartDate !== undefined) {
|
|
165
|
+
updateData.start_date = parsedStartDate;
|
|
166
|
+
updateData.start_date_time = true;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Clear the start date by setting it to null
|
|
170
|
+
updateData.start_date = null;
|
|
171
|
+
updateData.start_date_time = false;
|
|
172
|
+
}
|
|
152
173
|
}
|
|
153
174
|
// Handle time estimate if provided - convert from string to minutes
|
|
154
175
|
if (params.time_estimate !== undefined) {
|
|
@@ -165,7 +186,21 @@ async function buildUpdateData(params) {
|
|
|
165
186
|
}
|
|
166
187
|
// Handle assignees if provided - resolve emails/usernames to user IDs
|
|
167
188
|
if (params.assignees !== undefined) {
|
|
168
|
-
|
|
189
|
+
// Parse assignees if it's a string (from MCP serialization)
|
|
190
|
+
let assigneesArray = params.assignees;
|
|
191
|
+
if (typeof params.assignees === 'string') {
|
|
192
|
+
try {
|
|
193
|
+
assigneesArray = JSON.parse(params.assignees);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
console.warn('Failed to parse assignees string:', params.assignees, error);
|
|
197
|
+
assigneesArray = [];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const resolvedAssignees = await resolveAssignees(assigneesArray);
|
|
201
|
+
// Store the resolved assignees for processing in the updateTask method
|
|
202
|
+
// The actual add/rem logic will be handled there based on current vs new assignees
|
|
203
|
+
updateData.assignees = resolvedAssignees;
|
|
169
204
|
}
|
|
170
205
|
return updateData;
|
|
171
206
|
}
|
|
@@ -181,7 +216,7 @@ async function findTask(params) {
|
|
|
181
216
|
throw new Error(validationResult.errorMessage);
|
|
182
217
|
}
|
|
183
218
|
try {
|
|
184
|
-
// Direct path for taskId - most efficient
|
|
219
|
+
// Direct path for taskId - most efficient (now includes automatic custom ID detection)
|
|
185
220
|
if (taskId) {
|
|
186
221
|
const task = await taskService.getTask(taskId);
|
|
187
222
|
// Add subtasks if requested
|
|
@@ -191,7 +226,8 @@ async function findTask(params) {
|
|
|
191
226
|
}
|
|
192
227
|
return { task };
|
|
193
228
|
}
|
|
194
|
-
// Direct path for customTaskId -
|
|
229
|
+
// Direct path for customTaskId - for explicit custom ID requests
|
|
230
|
+
// Note: This is now mainly for backward compatibility since getTask() handles custom IDs automatically
|
|
195
231
|
if (customTaskId) {
|
|
196
232
|
const task = await taskService.getTaskByCustomId(customTaskId);
|
|
197
233
|
// Add subtasks if requested
|
|
@@ -429,7 +465,21 @@ export async function createTaskHandler(params) {
|
|
|
429
465
|
const priority = toTaskPriority(params.priority);
|
|
430
466
|
const listId = await getListId(params.listId, params.listName);
|
|
431
467
|
// Resolve assignees if provided
|
|
432
|
-
|
|
468
|
+
let resolvedAssignees = undefined;
|
|
469
|
+
if (assignees) {
|
|
470
|
+
// Parse assignees if it's a string (from MCP serialization)
|
|
471
|
+
let assigneesArray = assignees;
|
|
472
|
+
if (typeof assignees === 'string') {
|
|
473
|
+
try {
|
|
474
|
+
assigneesArray = JSON.parse(assignees);
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
console.warn('Failed to parse assignees string in createTask:', assignees, error);
|
|
478
|
+
assigneesArray = [];
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
resolvedAssignees = await resolveAssignees(assigneesArray);
|
|
482
|
+
}
|
|
433
483
|
const taskData = {
|
|
434
484
|
name,
|
|
435
485
|
description,
|
|
@@ -144,7 +144,7 @@ export const updateTaskTool = {
|
|
|
144
144
|
properties: {
|
|
145
145
|
taskId: {
|
|
146
146
|
type: "string",
|
|
147
|
-
description: "ID of task to update (preferred).
|
|
147
|
+
description: "ID of task to update (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
148
148
|
},
|
|
149
149
|
taskName: {
|
|
150
150
|
type: "string",
|
|
@@ -229,7 +229,7 @@ export const moveTaskTool = {
|
|
|
229
229
|
properties: {
|
|
230
230
|
taskId: {
|
|
231
231
|
type: "string",
|
|
232
|
-
description: "ID of the task to move (preferred).
|
|
232
|
+
description: "ID of the task to move (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
233
233
|
},
|
|
234
234
|
taskName: {
|
|
235
235
|
type: "string",
|
|
@@ -262,7 +262,7 @@ export const duplicateTaskTool = {
|
|
|
262
262
|
properties: {
|
|
263
263
|
taskId: {
|
|
264
264
|
type: "string",
|
|
265
|
-
description: "ID of task to duplicate (preferred).
|
|
265
|
+
description: "ID of task to duplicate (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
266
266
|
},
|
|
267
267
|
taskName: {
|
|
268
268
|
type: "string",
|
|
@@ -289,13 +289,13 @@ export const duplicateTaskTool = {
|
|
|
289
289
|
*/
|
|
290
290
|
export const getTaskTool = {
|
|
291
291
|
name: "get_task",
|
|
292
|
-
description: `Gets task details by taskId (
|
|
292
|
+
description: `Gets task details by taskId (automatically handles both regular and custom IDs) or taskName. For taskName search, provide listName for faster lookup. Set subtasks=true to include all subtask details.`,
|
|
293
293
|
inputSchema: {
|
|
294
294
|
type: "object",
|
|
295
295
|
properties: {
|
|
296
296
|
taskId: {
|
|
297
297
|
type: "string",
|
|
298
|
-
description: "ID of task to retrieve (preferred).
|
|
298
|
+
description: "ID of task to retrieve (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456'). Simply provide any task ID format here."
|
|
299
299
|
},
|
|
300
300
|
taskName: {
|
|
301
301
|
type: "string",
|
|
@@ -307,7 +307,7 @@ export const getTaskTool = {
|
|
|
307
307
|
},
|
|
308
308
|
customTaskId: {
|
|
309
309
|
type: "string",
|
|
310
|
-
description: "Custom task ID (e.g., 'DEV-1234').
|
|
310
|
+
description: "Custom task ID (e.g., 'DEV-1234'). This parameter is now optional since taskId automatically handles custom IDs. Use only for explicit custom ID lookup or backward compatibility."
|
|
311
311
|
},
|
|
312
312
|
subtasks: {
|
|
313
313
|
type: "boolean",
|
|
@@ -385,7 +385,7 @@ export const getTaskCommentsTool = {
|
|
|
385
385
|
properties: {
|
|
386
386
|
taskId: {
|
|
387
387
|
type: "string",
|
|
388
|
-
description: "ID of task to retrieve comments for (preferred).
|
|
388
|
+
description: "ID of task to retrieve comments for (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
389
389
|
},
|
|
390
390
|
taskName: {
|
|
391
391
|
type: "string",
|
|
@@ -417,7 +417,7 @@ export const createTaskCommentTool = {
|
|
|
417
417
|
properties: {
|
|
418
418
|
taskId: {
|
|
419
419
|
type: "string",
|
|
420
|
-
description: "ID of task to comment on (preferred).
|
|
420
|
+
description: "ID of task to comment on (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
421
421
|
},
|
|
422
422
|
taskName: {
|
|
423
423
|
type: "string",
|
|
@@ -454,7 +454,7 @@ export const deleteTaskTool = {
|
|
|
454
454
|
properties: {
|
|
455
455
|
taskId: {
|
|
456
456
|
type: "string",
|
|
457
|
-
description: "ID of task to delete (preferred).
|
|
457
|
+
description: "ID of task to delete (preferred). Automatically detects and handles both regular task IDs (9 characters) and custom IDs (like 'DEV-1234', 'PROJ-456')."
|
|
458
458
|
},
|
|
459
459
|
taskName: {
|
|
460
460
|
type: "string",
|