@taazkareem/clickup-mcp-server 0.6.9 → 0.7.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.
@@ -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 = {}));
@@ -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;