@pripanggalih/clickup-mcp 1.6.1
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 +22 -0
- package/README.md +295 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +184 -0
- package/dist/clickup-text.d.ts +83 -0
- package/dist/clickup-text.d.ts.map +1 -0
- package/dist/clickup-text.js +563 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +135 -0
- package/dist/resources/space-resources.d.ts +6 -0
- package/dist/resources/space-resources.d.ts.map +1 -0
- package/dist/resources/space-resources.js +95 -0
- package/dist/shared/config.d.ts +11 -0
- package/dist/shared/config.d.ts.map +1 -0
- package/dist/shared/config.js +61 -0
- package/dist/shared/data-uri.d.ts +14 -0
- package/dist/shared/data-uri.d.ts.map +1 -0
- package/dist/shared/data-uri.js +34 -0
- package/dist/shared/image-processing.d.ts +13 -0
- package/dist/shared/image-processing.d.ts.map +1 -0
- package/dist/shared/image-processing.js +199 -0
- package/dist/shared/types.d.ts +21 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/utils.d.ts +71 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/shared/utils.js +508 -0
- package/dist/test-utils.d.ts +23 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +44 -0
- package/dist/tools/admin-tools.d.ts +3 -0
- package/dist/tools/admin-tools.d.ts.map +1 -0
- package/dist/tools/admin-tools.js +288 -0
- package/dist/tools/doc-tools.d.ts +4 -0
- package/dist/tools/doc-tools.d.ts.map +1 -0
- package/dist/tools/doc-tools.js +436 -0
- package/dist/tools/list-tools.d.ts +4 -0
- package/dist/tools/list-tools.d.ts.map +1 -0
- package/dist/tools/list-tools.js +175 -0
- package/dist/tools/search-tools.d.ts +3 -0
- package/dist/tools/search-tools.d.ts.map +1 -0
- package/dist/tools/search-tools.js +161 -0
- package/dist/tools/space-tools.d.ts +3 -0
- package/dist/tools/space-tools.d.ts.map +1 -0
- package/dist/tools/space-tools.js +128 -0
- package/dist/tools/task-tools.d.ts +8 -0
- package/dist/tools/task-tools.d.ts.map +1 -0
- package/dist/tools/task-tools.js +329 -0
- package/dist/tools/task-write-tools.d.ts +3 -0
- package/dist/tools/task-write-tools.d.ts.map +1 -0
- package/dist/tools/task-write-tools.js +567 -0
- package/dist/tools/time-tools.d.ts +4 -0
- package/dist/tools/time-tools.d.ts.map +1 -0
- package/dist/tools/time-tools.js +338 -0
- package/package.json +74 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerAdminToolsWrite = registerAdminToolsWrite;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const config_1 = require("../shared/config");
|
|
6
|
+
const utils_1 = require("../shared/utils");
|
|
7
|
+
const spaceFeaturesSchema = zod_1.z.record(zod_1.z.any()).optional().describe("Optional ClickUp Space features object passed through to the official API");
|
|
8
|
+
const colorSchema = zod_1.z.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("Optional hex color (for example, #123456)");
|
|
9
|
+
const listDescriptionSchema = zod_1.z.string().optional().describe("Optional list description/content");
|
|
10
|
+
const listStatusColorSchema = colorSchema.describe("Optional List color. ClickUp's List API calls this field `status`; it is not a task workflow status.");
|
|
11
|
+
const listPrioritySchema = zod_1.z.number().int().min(1).max(4).optional().describe("Optional list priority number: 1 urgent, 2 high, 3 normal, 4 low");
|
|
12
|
+
const dateSchema = zod_1.z.string().optional().describe("Optional ISO date string, converted to ClickUp's millisecond timestamp");
|
|
13
|
+
function registerAdminToolsWrite(server) {
|
|
14
|
+
server.tool("createSpace", [
|
|
15
|
+
"Creates a new ClickUp Space in the configured Workspace using the official ClickUp API v2.",
|
|
16
|
+
"Only use when the user explicitly wants a new Space/project container.",
|
|
17
|
+
"The response includes the Space ID and URL; always mention both when referencing the created Space."
|
|
18
|
+
].join("\n"), {
|
|
19
|
+
name: zod_1.z.string().min(1).describe("The name of the Space to create"),
|
|
20
|
+
multiple_assignees: zod_1.z.boolean().optional().describe("Whether tasks in this Space can have multiple assignees"),
|
|
21
|
+
private: zod_1.z.boolean().optional().describe("Whether the Space should be private"),
|
|
22
|
+
admin_can_manage: zod_1.z.boolean().optional().describe("Whether admins can manage the private Space"),
|
|
23
|
+
features: spaceFeaturesSchema,
|
|
24
|
+
}, {
|
|
25
|
+
readOnlyHint: false,
|
|
26
|
+
destructiveHint: false,
|
|
27
|
+
idempotentHint: false,
|
|
28
|
+
openWorldHint: true,
|
|
29
|
+
}, async ({ name, multiple_assignees, private: isPrivate, admin_can_manage, features }) => {
|
|
30
|
+
try {
|
|
31
|
+
const body = removeUndefined({
|
|
32
|
+
name,
|
|
33
|
+
multiple_assignees,
|
|
34
|
+
private: isPrivate,
|
|
35
|
+
admin_can_manage,
|
|
36
|
+
features,
|
|
37
|
+
});
|
|
38
|
+
const createdSpace = await clickUpFetch(`/team/${config_1.CONFIG.teamId}/space`, "POST", body, "creating space");
|
|
39
|
+
return textResult(formatSpaceResponse(createdSpace, "created"));
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error("Error creating space:", error);
|
|
43
|
+
return errorResult("creating space", error);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
server.tool("updateSpace", [
|
|
47
|
+
"Updates an existing ClickUp Space using the official ClickUp API v2.",
|
|
48
|
+
"Use searchSpaces first if you need to confirm the Space ID.",
|
|
49
|
+
"This tool does not manage task workflow statuses."
|
|
50
|
+
].join("\n"), {
|
|
51
|
+
space_id: zod_1.z.string().min(1).describe("The Space ID to update"),
|
|
52
|
+
name: zod_1.z.string().min(1).optional().describe("Optional new Space name"),
|
|
53
|
+
color: colorSchema,
|
|
54
|
+
multiple_assignees: zod_1.z.boolean().optional().describe("Optional multiple-assignee setting"),
|
|
55
|
+
private: zod_1.z.boolean().optional().describe("Optional private setting"),
|
|
56
|
+
admin_can_manage: zod_1.z.boolean().optional().describe("Optional private-Space admin management setting"),
|
|
57
|
+
features: spaceFeaturesSchema,
|
|
58
|
+
}, {
|
|
59
|
+
readOnlyHint: false,
|
|
60
|
+
destructiveHint: false,
|
|
61
|
+
idempotentHint: false,
|
|
62
|
+
openWorldHint: true,
|
|
63
|
+
}, async ({ space_id, name, color, multiple_assignees, private: isPrivate, admin_can_manage, features }) => {
|
|
64
|
+
try {
|
|
65
|
+
const body = removeUndefined({
|
|
66
|
+
name,
|
|
67
|
+
color,
|
|
68
|
+
multiple_assignees,
|
|
69
|
+
private: isPrivate,
|
|
70
|
+
admin_can_manage,
|
|
71
|
+
features,
|
|
72
|
+
});
|
|
73
|
+
if (Object.keys(body).length === 0) {
|
|
74
|
+
return textResult(["No updates provided. Please specify at least one Space field to update."]);
|
|
75
|
+
}
|
|
76
|
+
const updatedSpace = await clickUpFetch(`/space/${space_id}`, "PUT", body, "updating space");
|
|
77
|
+
return textResult(formatSpaceResponse({ ...updatedSpace, id: updatedSpace.id || space_id }, "updated"));
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error("Error updating space:", error);
|
|
81
|
+
return errorResult("updating space", error);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
server.tool("createFolder", [
|
|
85
|
+
"Creates a new Folder inside a ClickUp Space using the official ClickUp API v2.",
|
|
86
|
+
"Use searchSpaces first if you need to confirm the Space ID.",
|
|
87
|
+
"The response includes Folder and Space references with IDs."
|
|
88
|
+
].join("\n"), {
|
|
89
|
+
space_id: zod_1.z.string().min(1).describe("The Space ID where the Folder will be created"),
|
|
90
|
+
name: zod_1.z.string().min(1).describe("The name of the Folder to create"),
|
|
91
|
+
}, {
|
|
92
|
+
readOnlyHint: false,
|
|
93
|
+
destructiveHint: false,
|
|
94
|
+
idempotentHint: false,
|
|
95
|
+
openWorldHint: true,
|
|
96
|
+
}, async ({ space_id, name }) => {
|
|
97
|
+
try {
|
|
98
|
+
const createdFolder = await clickUpFetch(`/space/${space_id}/folder`, "POST", { name }, "creating folder");
|
|
99
|
+
return textResult(formatFolderResponse(createdFolder, "created", space_id));
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
console.error("Error creating folder:", error);
|
|
103
|
+
return errorResult("creating folder", error);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
server.tool("updateFolder", [
|
|
107
|
+
"Renames an existing ClickUp Folder using the official ClickUp API v2.",
|
|
108
|
+
"Use searchSpaces first if you need to confirm the Folder ID.",
|
|
109
|
+
"The response includes the Folder ID and URL."
|
|
110
|
+
].join("\n"), {
|
|
111
|
+
folder_id: zod_1.z.string().min(1).describe("The Folder ID to update"),
|
|
112
|
+
name: zod_1.z.string().min(1).describe("The new Folder name"),
|
|
113
|
+
}, {
|
|
114
|
+
readOnlyHint: false,
|
|
115
|
+
destructiveHint: false,
|
|
116
|
+
idempotentHint: false,
|
|
117
|
+
openWorldHint: true,
|
|
118
|
+
}, async ({ folder_id, name }) => {
|
|
119
|
+
try {
|
|
120
|
+
const updatedFolder = await clickUpFetch(`/folder/${folder_id}`, "PUT", { name }, "updating folder");
|
|
121
|
+
return textResult(formatFolderResponse({ ...updatedFolder, id: updatedFolder.id || folder_id }, "updated"));
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error("Error updating folder:", error);
|
|
125
|
+
return errorResult("updating folder", error);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
server.tool("createList", [
|
|
129
|
+
"Creates a new ClickUp List using the official ClickUp API v2.",
|
|
130
|
+
"Provide exactly one of space_id for a folderless List, or folder_id for a List inside a Folder.",
|
|
131
|
+
"IMPORTANT: status_color maps to the ClickUp List API `status` field, which is the List color, not a task workflow status."
|
|
132
|
+
].join("\n"), {
|
|
133
|
+
space_id: zod_1.z.string().min(1).optional().describe("Create a folderless List in this Space ID. Mutually exclusive with folder_id."),
|
|
134
|
+
folder_id: zod_1.z.string().min(1).optional().describe("Create a List inside this Folder ID. Mutually exclusive with space_id."),
|
|
135
|
+
name: zod_1.z.string().min(1).describe("The name of the List to create"),
|
|
136
|
+
content: listDescriptionSchema,
|
|
137
|
+
status_color: listStatusColorSchema,
|
|
138
|
+
due_date: dateSchema,
|
|
139
|
+
due_date_time: zod_1.z.boolean().optional().describe("Whether due_date includes a specific time"),
|
|
140
|
+
priority: listPrioritySchema,
|
|
141
|
+
assignee: zod_1.z.string().optional().describe("Optional user ID for the List owner/assignee"),
|
|
142
|
+
}, {
|
|
143
|
+
readOnlyHint: false,
|
|
144
|
+
destructiveHint: false,
|
|
145
|
+
idempotentHint: false,
|
|
146
|
+
openWorldHint: true,
|
|
147
|
+
}, async ({ space_id, folder_id, name, content, status_color, due_date, due_date_time, priority, assignee }) => {
|
|
148
|
+
try {
|
|
149
|
+
const targetError = validateListTarget(space_id, folder_id);
|
|
150
|
+
if (targetError) {
|
|
151
|
+
return textResult([targetError]);
|
|
152
|
+
}
|
|
153
|
+
const body = buildListRequestBody({ name, content, status_color, due_date, due_date_time, priority, assignee });
|
|
154
|
+
const endpoint = space_id ? `/space/${space_id}/list` : `/folder/${folder_id}/list`;
|
|
155
|
+
const createdList = await clickUpFetch(endpoint, "POST", body, "creating list");
|
|
156
|
+
return textResult(formatListResponse(createdList, "created", { space_id, folder_id }));
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
console.error("Error creating list:", error);
|
|
160
|
+
return errorResult("creating list", error);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
server.tool("updateList", [
|
|
164
|
+
"Updates ClickUp List fields using the official ClickUp API v2.",
|
|
165
|
+
"Use getListInfo first if you need current List context.",
|
|
166
|
+
"IMPORTANT: status_color maps to the ClickUp List API `status` field, which is the List color, not a task workflow status."
|
|
167
|
+
].join("\n"), {
|
|
168
|
+
list_id: zod_1.z.string().min(1).describe("The List ID to update"),
|
|
169
|
+
name: zod_1.z.string().min(1).optional().describe("Optional new List name"),
|
|
170
|
+
content: listDescriptionSchema,
|
|
171
|
+
status_color: listStatusColorSchema,
|
|
172
|
+
due_date: dateSchema,
|
|
173
|
+
due_date_time: zod_1.z.boolean().optional().describe("Whether due_date includes a specific time"),
|
|
174
|
+
priority: listPrioritySchema,
|
|
175
|
+
assignee: zod_1.z.string().optional().describe("Optional user ID for the List owner/assignee"),
|
|
176
|
+
unset_status: zod_1.z.boolean().optional().describe("Optional official API flag for unsetting the List color/status"),
|
|
177
|
+
}, {
|
|
178
|
+
readOnlyHint: false,
|
|
179
|
+
destructiveHint: false,
|
|
180
|
+
idempotentHint: false,
|
|
181
|
+
openWorldHint: true,
|
|
182
|
+
}, async ({ list_id, name, content, status_color, due_date, due_date_time, priority, assignee, unset_status }) => {
|
|
183
|
+
try {
|
|
184
|
+
const body = buildListRequestBody({ name, content, status_color, due_date, due_date_time, priority, assignee, unset_status });
|
|
185
|
+
if (Object.keys(body).length === 0) {
|
|
186
|
+
return textResult(["No updates provided. Please specify at least one List field to update."]);
|
|
187
|
+
}
|
|
188
|
+
const updatedList = await clickUpFetch(`/list/${list_id}`, "PUT", body, "updating list");
|
|
189
|
+
return textResult(formatListResponse({ ...updatedList, id: updatedList.id || list_id }, "updated"));
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
console.error("Error updating list:", error);
|
|
193
|
+
return errorResult("updating list", error);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
async function clickUpFetch(path, method, body, action) {
|
|
198
|
+
const response = await fetch(`https://api.clickup.com/api/v2${path}`, {
|
|
199
|
+
method,
|
|
200
|
+
headers: {
|
|
201
|
+
Authorization: config_1.CONFIG.apiKey,
|
|
202
|
+
"Content-Type": "application/json",
|
|
203
|
+
},
|
|
204
|
+
body: JSON.stringify(body),
|
|
205
|
+
});
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
const errorData = await response.json().catch(() => ({}));
|
|
208
|
+
throw new Error(`Error ${action}: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`);
|
|
209
|
+
}
|
|
210
|
+
return await response.json();
|
|
211
|
+
}
|
|
212
|
+
function buildListRequestBody(params) {
|
|
213
|
+
const body = removeUndefined({
|
|
214
|
+
name: params.name,
|
|
215
|
+
content: params.content,
|
|
216
|
+
status: params.status_color,
|
|
217
|
+
due_date: params.due_date ? new Date(params.due_date).getTime() : undefined,
|
|
218
|
+
due_date_time: params.due_date_time,
|
|
219
|
+
priority: params.priority,
|
|
220
|
+
assignee: params.assignee,
|
|
221
|
+
unset_status: params.unset_status,
|
|
222
|
+
});
|
|
223
|
+
return body;
|
|
224
|
+
}
|
|
225
|
+
function validateListTarget(spaceId, folderId) {
|
|
226
|
+
if ((spaceId && folderId) || (!spaceId && !folderId)) {
|
|
227
|
+
return "Provide exactly one of space_id or folder_id when creating a List.";
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
function removeUndefined(value) {
|
|
232
|
+
return Object.fromEntries(Object.entries(value).filter(([, entryValue]) => entryValue !== undefined));
|
|
233
|
+
}
|
|
234
|
+
function textResult(lines) {
|
|
235
|
+
return {
|
|
236
|
+
content: [
|
|
237
|
+
{
|
|
238
|
+
type: "text",
|
|
239
|
+
text: lines.join("\n"),
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function errorResult(action, error) {
|
|
245
|
+
return textResult([`Error ${action}: ${error instanceof Error ? error.message : "Unknown error"}`]);
|
|
246
|
+
}
|
|
247
|
+
function formatSpaceResponse(space, action) {
|
|
248
|
+
const spaceId = space.id || "N/A";
|
|
249
|
+
return [
|
|
250
|
+
`Space ${action} successfully!`,
|
|
251
|
+
`space_id: ${spaceId}`,
|
|
252
|
+
`space_url: ${(0, utils_1.generateSpaceUrl)(spaceId)}`,
|
|
253
|
+
`name: ${space.name || "N/A"}`,
|
|
254
|
+
...(space.color ? [`color: ${space.color}`] : []),
|
|
255
|
+
...(space.private !== undefined ? [`private: ${space.private}`] : []),
|
|
256
|
+
];
|
|
257
|
+
}
|
|
258
|
+
function formatFolderResponse(folder, action, spaceId) {
|
|
259
|
+
const folderId = folder.id || "N/A";
|
|
260
|
+
return [
|
|
261
|
+
`Folder ${action} successfully!`,
|
|
262
|
+
`folder_id: ${folderId}`,
|
|
263
|
+
`folder_url: ${(0, utils_1.generateFolderUrl)(folderId)}`,
|
|
264
|
+
`name: ${folder.name || "N/A"}`,
|
|
265
|
+
...(spaceId ? [`space_id: ${spaceId}`, `space_url: ${(0, utils_1.generateSpaceUrl)(spaceId)}`] : []),
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
function formatListResponse(list, action, target) {
|
|
269
|
+
const listId = list.id || "N/A";
|
|
270
|
+
const lines = [
|
|
271
|
+
`List ${action} successfully!`,
|
|
272
|
+
`list_id: ${listId}`,
|
|
273
|
+
`list_url: ${(0, utils_1.generateListUrl)(listId)}`,
|
|
274
|
+
`name: ${list.name || "N/A"}`,
|
|
275
|
+
];
|
|
276
|
+
if (target?.space_id) {
|
|
277
|
+
lines.push(`space_id: ${target.space_id}`);
|
|
278
|
+
lines.push(`space_url: ${(0, utils_1.generateSpaceUrl)(target.space_id)}`);
|
|
279
|
+
}
|
|
280
|
+
if (target?.folder_id) {
|
|
281
|
+
lines.push(`folder_id: ${target.folder_id}`);
|
|
282
|
+
lines.push(`folder_url: ${(0, utils_1.generateFolderUrl)(target.folder_id)}`);
|
|
283
|
+
}
|
|
284
|
+
if (list.status) {
|
|
285
|
+
lines.push(`list_status_color: ${typeof list.status === "string" ? list.status : JSON.stringify(list.status)}`);
|
|
286
|
+
}
|
|
287
|
+
return lines;
|
|
288
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doc-tools.d.ts","sourceRoot":"","sources":["../../src/tools/doc-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoDpE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,QA0J1D;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,QAoS3D"}
|