@taazkareem/clickup-mcp-server 0.7.1 → 0.7.2
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
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
A Model Context Protocol (MCP) server for integrating ClickUp tasks with AI applications. This server allows AI agents to interact with ClickUp tasks, spaces, lists, and folders through a standardized protocol.
|
|
8
8
|
|
|
9
|
-
> 🚀 **Status Update:** v0.7.
|
|
9
|
+
> 🚀 **Status Update:** v0.7.2 now available with complete Time Tracking support and Document Management features.
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
@@ -61,13 +61,13 @@ Please disable tools you don't need if you are having issues with the number of
|
|
|
61
61
|
|
|
62
62
|
## Features
|
|
63
63
|
|
|
64
|
-
| 📝 Task Management
|
|
65
|
-
|
|
|
66
|
-
| • Create, update, and delete tasks
|
|
67
|
-
| ⏱️**Time Tracking**
|
|
68
|
-
| • View time entries for tasks
|
|
69
|
-
|
|
|
70
|
-
| •
|
|
64
|
+
| 📝 Task Management | 🏷️ Tag Management |
|
|
65
|
+
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
66
|
+
| • Create, update, and delete tasks`<br>`• Move and duplicate tasks anywhere `<br>`• Support for single and bulk operations `<br>`• Set start/due dates with natural language `<br>`• Create and manage subtasks `<br>`• Add comments and attachments | • Create, update, and delete space tags`<br>`• Add and remove tags from tasks `<br>`• Use natural language color commands `<br>`• Automatic contrasting foreground colors `<br>`• View all space tags `<br>`• Tag-based task organization across workspace |
|
|
67
|
+
| ⏱️**Time Tracking** | 🌳**Workspace Organization** |
|
|
68
|
+
| • View time entries for tasks`<br>`• Start/stop time tracking on tasks `<br>`• Add manual time entries `<br>`• Delete time entries `<br>`• View currently running timer `<br>`• Track billable and non-billable time | • Navigate spaces, folders, and lists`<br>`• Create and manage folders `<br>`• Organize lists within spaces `<br>`• Create lists in folders `<br>`• View workspace hierarchy `<br>`• Efficient path navigation |
|
|
69
|
+
| 📄**Document Management** | ⚡**Integration Features** |
|
|
70
|
+
| • Document Listing through all workspace`<br>` • Document Page listing `<br>` • Document Page Details `<br>` • Document Creation `<br>` • Document page update (append & prepend) | • Global name or ID-based lookups`<br>`• Case-insensitive matching `<br>`• Markdown formatting support `<br>`• Built-in rate limiting `<br>`• Error handling and validation `<br>`• Comprehensive API coverage |
|
|
71
71
|
|
|
72
72
|
## Available Tools
|
|
73
73
|
|
package/build/server.js
CHANGED
|
@@ -51,6 +51,34 @@ function getCachedTaskContext(taskName) {
|
|
|
51
51
|
//=============================================================================
|
|
52
52
|
// SHARED UTILITY FUNCTIONS
|
|
53
53
|
//=============================================================================
|
|
54
|
+
/**
|
|
55
|
+
* Parse time estimate string into minutes
|
|
56
|
+
* Supports formats like "2h 30m", "150m", "2.5h"
|
|
57
|
+
*/
|
|
58
|
+
function parseTimeEstimate(timeEstimate) {
|
|
59
|
+
// If it's already a number, return it directly
|
|
60
|
+
if (typeof timeEstimate === 'number') {
|
|
61
|
+
return timeEstimate;
|
|
62
|
+
}
|
|
63
|
+
if (!timeEstimate || typeof timeEstimate !== 'string')
|
|
64
|
+
return 0;
|
|
65
|
+
// If it's just a number as string, parse it
|
|
66
|
+
if (/^\d+$/.test(timeEstimate)) {
|
|
67
|
+
return parseInt(timeEstimate, 10);
|
|
68
|
+
}
|
|
69
|
+
let totalMinutes = 0;
|
|
70
|
+
// Extract hours
|
|
71
|
+
const hoursMatch = timeEstimate.match(/(\d+\.?\d*)h/);
|
|
72
|
+
if (hoursMatch) {
|
|
73
|
+
totalMinutes += parseFloat(hoursMatch[1]) * 60;
|
|
74
|
+
}
|
|
75
|
+
// Extract minutes
|
|
76
|
+
const minutesMatch = timeEstimate.match(/(\d+)m/);
|
|
77
|
+
if (minutesMatch) {
|
|
78
|
+
totalMinutes += parseInt(minutesMatch[1], 10);
|
|
79
|
+
}
|
|
80
|
+
return Math.round(totalMinutes); // Return minutes
|
|
81
|
+
}
|
|
54
82
|
/**
|
|
55
83
|
* Build task update data from parameters
|
|
56
84
|
*/
|
|
@@ -75,6 +103,15 @@ function buildUpdateData(params) {
|
|
|
75
103
|
updateData.start_date = parseDueDate(params.startDate);
|
|
76
104
|
updateData.start_date_time = true;
|
|
77
105
|
}
|
|
106
|
+
// Handle time estimate if provided - convert from string to minutes
|
|
107
|
+
if (params.time_estimate !== undefined) {
|
|
108
|
+
// Log the time estimate for debugging
|
|
109
|
+
console.log(`Original time_estimate: ${params.time_estimate}, typeof: ${typeof params.time_estimate}`);
|
|
110
|
+
// Parse and convert to number in minutes
|
|
111
|
+
const minutes = parseTimeEstimate(params.time_estimate);
|
|
112
|
+
console.log(`Converted time_estimate: ${minutes}`);
|
|
113
|
+
updateData.time_estimate = minutes;
|
|
114
|
+
}
|
|
78
115
|
// Handle custom fields if provided
|
|
79
116
|
if (params.custom_fields !== undefined) {
|
|
80
117
|
updateData.custom_fields = params.custom_fields;
|
|
@@ -174,6 +174,10 @@ export const updateTaskTool = {
|
|
|
174
174
|
type: "string",
|
|
175
175
|
description: "New start date. Supports both Unix timestamps (in milliseconds) and natural language expressions."
|
|
176
176
|
},
|
|
177
|
+
time_estimate: {
|
|
178
|
+
type: "string",
|
|
179
|
+
description: "Time estimate for the task. For best compatibility with the ClickUp API, use a numeric value in minutes (e.g., '150' for 2h 30m)"
|
|
180
|
+
},
|
|
177
181
|
custom_fields: {
|
|
178
182
|
type: "array",
|
|
179
183
|
items: {
|
|
@@ -112,14 +112,6 @@ export function validateListIdentification(listId, listName) {
|
|
|
112
112
|
* Ensures at least one update field is provided
|
|
113
113
|
*/
|
|
114
114
|
export function validateTaskUpdateData(updateData) {
|
|
115
|
-
// Check if there are any valid update fields present
|
|
116
|
-
const hasUpdates = Object.keys(updateData).some(key => {
|
|
117
|
-
return ['name', 'description', 'markdown_description', 'status', 'priority',
|
|
118
|
-
'dueDate', 'startDate', 'custom_fields'].includes(key);
|
|
119
|
-
});
|
|
120
|
-
if (!hasUpdates) {
|
|
121
|
-
throw new Error("At least one field to update must be provided");
|
|
122
|
-
}
|
|
123
115
|
// Validate custom_fields if provided
|
|
124
116
|
if (updateData.custom_fields) {
|
|
125
117
|
if (!Array.isArray(updateData.custom_fields)) {
|
|
@@ -131,6 +123,10 @@ export function validateTaskUpdateData(updateData) {
|
|
|
131
123
|
}
|
|
132
124
|
}
|
|
133
125
|
}
|
|
126
|
+
// Ensure there's at least one field to update
|
|
127
|
+
if (Object.keys(updateData).length === 0) {
|
|
128
|
+
throw new Error("At least one field to update must be provided");
|
|
129
|
+
}
|
|
134
130
|
}
|
|
135
131
|
/**
|
|
136
132
|
* Validate bulk task array and task identification
|
package/package.json
CHANGED