@taazkareem/clickup-mcp-server 0.6.8 → 0.6.10
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 +73 -51
- package/build/config.js +17 -1
- package/build/server.js +65 -6
- package/build/services/clickup/document.js +159 -0
- package/build/services/clickup/index.js +11 -1
- package/build/services/clickup/task/task-core.js +14 -2
- package/build/services/clickup/time.js +244 -0
- package/build/services/clickup/types.js +11 -0
- package/build/services/shared.js +1 -1
- package/build/tools/documents.js +501 -0
- package/build/tools/task/bulk-operations.js +2 -1
- package/build/tools/task/index.js +2 -0
- package/build/tools/task/single-operations.js +2 -1
- package/build/tools/task/time-tracking.js +684 -0
- package/build/utils/sponsor-service.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: © 2025 Talib Kareem <taazkareem@icloud.com>
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* Time tracking service for ClickUp tasks
|
|
6
|
+
*
|
|
7
|
+
* This service provides methods to manage time tracking for ClickUp tasks:
|
|
8
|
+
* - Get time entries for a task
|
|
9
|
+
* - Start time tracking on a task
|
|
10
|
+
* - Stop time tracking on a task
|
|
11
|
+
* - Add a manual time entry
|
|
12
|
+
* - Delete a time entry
|
|
13
|
+
*/
|
|
14
|
+
import { BaseClickUpService, ErrorCode, ClickUpServiceError } from './base.js';
|
|
15
|
+
/**
|
|
16
|
+
* Time tracking service for ClickUp
|
|
17
|
+
*/
|
|
18
|
+
export class TimeTrackingService extends BaseClickUpService {
|
|
19
|
+
/**
|
|
20
|
+
* Get all time entries for a task
|
|
21
|
+
* @param taskId ID of the task
|
|
22
|
+
* @param startDate Optional start date filter (Unix timestamp in milliseconds)
|
|
23
|
+
* @param endDate Optional end date filter (Unix timestamp in milliseconds)
|
|
24
|
+
* @returns List of time entries
|
|
25
|
+
*/
|
|
26
|
+
async getTimeEntries(taskId, startDate, endDate) {
|
|
27
|
+
try {
|
|
28
|
+
this.logOperation('getTimeEntries', { taskId, startDate, endDate });
|
|
29
|
+
// Build query parameters
|
|
30
|
+
let query = {};
|
|
31
|
+
if (startDate)
|
|
32
|
+
query.start_date = startDate;
|
|
33
|
+
if (endDate)
|
|
34
|
+
query.end_date = endDate;
|
|
35
|
+
const path = `/task/${taskId}/time`;
|
|
36
|
+
this.traceRequest('GET', path, query);
|
|
37
|
+
const response = await this.makeRequest(() => this.client.get(path, {
|
|
38
|
+
params: query
|
|
39
|
+
}));
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
data: response.data.data
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error instanceof ClickUpServiceError) {
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
error: {
|
|
50
|
+
message: error.message,
|
|
51
|
+
code: error.code,
|
|
52
|
+
details: error.data
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
success: false,
|
|
58
|
+
error: {
|
|
59
|
+
message: `Failed to get time entries: ${error.message}`,
|
|
60
|
+
code: ErrorCode.UNKNOWN
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Start time tracking on a task
|
|
67
|
+
* @param data Task ID and optional parameters
|
|
68
|
+
* @returns The created time entry
|
|
69
|
+
*/
|
|
70
|
+
async startTimeTracking(data) {
|
|
71
|
+
try {
|
|
72
|
+
this.logOperation('startTimeTracking', { taskId: data.tid });
|
|
73
|
+
const path = `/team/${this.teamId}/time_entries/start`;
|
|
74
|
+
this.traceRequest('POST', path, data);
|
|
75
|
+
const response = await this.makeRequest(() => this.client.post(path, data));
|
|
76
|
+
return {
|
|
77
|
+
success: true,
|
|
78
|
+
data: response.data.data
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error instanceof ClickUpServiceError) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
error: {
|
|
86
|
+
message: error.message,
|
|
87
|
+
code: error.code,
|
|
88
|
+
details: error.data
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
success: false,
|
|
94
|
+
error: {
|
|
95
|
+
message: `Failed to start time tracking: ${error.message}`,
|
|
96
|
+
code: ErrorCode.UNKNOWN
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Stop the currently running time tracker
|
|
103
|
+
* @param data Optional parameters for the stopped time entry
|
|
104
|
+
* @returns The completed time entry
|
|
105
|
+
*/
|
|
106
|
+
async stopTimeTracking(data) {
|
|
107
|
+
try {
|
|
108
|
+
this.logOperation('stopTimeTracking', {});
|
|
109
|
+
const path = `/team/${this.teamId}/time_entries/stop`;
|
|
110
|
+
this.traceRequest('POST', path, data || {});
|
|
111
|
+
const response = await this.makeRequest(() => this.client.post(path, data || {}));
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
data: response.data.data
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (error instanceof ClickUpServiceError) {
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
error: {
|
|
122
|
+
message: error.message,
|
|
123
|
+
code: error.code,
|
|
124
|
+
details: error.data
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
error: {
|
|
131
|
+
message: `Failed to stop time tracking: ${error.message}`,
|
|
132
|
+
code: ErrorCode.UNKNOWN
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Add a manual time entry to a task
|
|
139
|
+
* @param data Time entry data including task ID, start time, and duration
|
|
140
|
+
* @returns The created time entry
|
|
141
|
+
*/
|
|
142
|
+
async addTimeEntry(data) {
|
|
143
|
+
try {
|
|
144
|
+
this.logOperation('addTimeEntry', { taskId: data.tid, duration: data.duration });
|
|
145
|
+
const path = `/team/${this.teamId}/time_entries`;
|
|
146
|
+
this.traceRequest('POST', path, data);
|
|
147
|
+
const response = await this.makeRequest(() => this.client.post(path, data));
|
|
148
|
+
return {
|
|
149
|
+
success: true,
|
|
150
|
+
data: response.data.data
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (error instanceof ClickUpServiceError) {
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
error: {
|
|
158
|
+
message: error.message,
|
|
159
|
+
code: error.code,
|
|
160
|
+
details: error.data
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
error: {
|
|
167
|
+
message: `Failed to add time entry: ${error.message}`,
|
|
168
|
+
code: ErrorCode.UNKNOWN
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Delete a time entry
|
|
175
|
+
* @param timeEntryId ID of the time entry to delete
|
|
176
|
+
* @returns Success response
|
|
177
|
+
*/
|
|
178
|
+
async deleteTimeEntry(timeEntryId) {
|
|
179
|
+
try {
|
|
180
|
+
this.logOperation('deleteTimeEntry', { timeEntryId });
|
|
181
|
+
const path = `/team/${this.teamId}/time_entries/${timeEntryId}`;
|
|
182
|
+
this.traceRequest('DELETE', path);
|
|
183
|
+
await this.makeRequest(() => this.client.delete(path));
|
|
184
|
+
return {
|
|
185
|
+
success: true,
|
|
186
|
+
data: true
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
if (error instanceof ClickUpServiceError) {
|
|
191
|
+
return {
|
|
192
|
+
success: false,
|
|
193
|
+
error: {
|
|
194
|
+
message: error.message,
|
|
195
|
+
code: error.code,
|
|
196
|
+
details: error.data
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
error: {
|
|
203
|
+
message: `Failed to delete time entry: ${error.message}`,
|
|
204
|
+
code: ErrorCode.UNKNOWN
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get currently running time entry for the user
|
|
211
|
+
* @returns The currently running time entry or null if no timer is running
|
|
212
|
+
*/
|
|
213
|
+
async getCurrentTimeEntry() {
|
|
214
|
+
try {
|
|
215
|
+
this.logOperation('getCurrentTimeEntry', {});
|
|
216
|
+
const path = `/team/${this.teamId}/time_entries/current`;
|
|
217
|
+
this.traceRequest('GET', path);
|
|
218
|
+
const response = await this.makeRequest(() => this.client.get(path));
|
|
219
|
+
return {
|
|
220
|
+
success: true,
|
|
221
|
+
data: response.data.data
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
if (error instanceof ClickUpServiceError) {
|
|
226
|
+
return {
|
|
227
|
+
success: false,
|
|
228
|
+
error: {
|
|
229
|
+
message: error.message,
|
|
230
|
+
code: error.code,
|
|
231
|
+
details: error.data
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
success: false,
|
|
237
|
+
error: {
|
|
238
|
+
message: `Failed to get current time entry: ${error.message}`,
|
|
239
|
+
code: ErrorCode.UNKNOWN
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -20,3 +20,14 @@ export function toTaskPriority(value) {
|
|
|
20
20
|
}
|
|
21
21
|
return undefined;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* ClickUp parent container types
|
|
25
|
+
*/
|
|
26
|
+
export var ClickUpParentType;
|
|
27
|
+
(function (ClickUpParentType) {
|
|
28
|
+
ClickUpParentType[ClickUpParentType["Space"] = 4] = "Space";
|
|
29
|
+
ClickUpParentType[ClickUpParentType["Folder"] = 5] = "Folder";
|
|
30
|
+
ClickUpParentType[ClickUpParentType["List"] = 6] = "List";
|
|
31
|
+
ClickUpParentType[ClickUpParentType["All"] = 7] = "All";
|
|
32
|
+
ClickUpParentType[ClickUpParentType["Workspace"] = 12] = "Workspace";
|
|
33
|
+
})(ClickUpParentType || (ClickUpParentType = {}));
|
package/build/services/shared.js
CHANGED
|
@@ -35,4 +35,4 @@ function getClickUpServices() {
|
|
|
35
35
|
// Create a single instance of ClickUp services to be shared
|
|
36
36
|
export const clickUpServices = getClickUpServices();
|
|
37
37
|
// Export individual services for convenience
|
|
38
|
-
export const { list: listService, task: taskService, folder: folderService, workspace: workspaceService } = clickUpServices;
|
|
38
|
+
export const { list: listService, task: taskService, folder: folderService, workspace: workspaceService, timeTracking: timeTrackingService, document: documentService } = clickUpServices;
|