@taazkareem/clickup-mcp-server 0.2.3 → 0.2.4

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
@@ -12,7 +12,9 @@ Directions for use with Cursor Composer Agent:
12
12
  2. Go to Features in settings
13
13
  3. Add under MCP Servers:
14
14
  ```bash
15
- npx -y @taazkareem/clickup-mcp-server --env CLICKUP_API_KEY=your_api_key_here --env TEAM_ID=your_team_id_here
15
+ npx -y @taazkareem/clickup-mcp-server \
16
+ --env CLICKUP_API_KEY=your_api_key_here \
17
+ --env CLICKUP_TEAM_ID=your_team_id_here
16
18
  ```
17
19
  4. Replace the credentials and click Save
18
20
  5. Use Natural Language to interact with your ClickUp Workspace!
@@ -31,7 +33,7 @@ npx -y @taazkareem/clickup-mcp-server --env CLICKUP_API_KEY=your_api_key_here --
31
33
  - List and folder management in spaces
32
34
  - Smart caching to reduce API calls
33
35
  - Name/ID-based item lookup
34
- - Optimized task organization
36
+
35
37
 
36
38
  - 🔄 **Smart Integration**
37
39
  - Case-insensitive name lookups
@@ -47,61 +49,30 @@ npx -y @taazkareem/clickup-mcp-server --env CLICKUP_API_KEY=your_api_key_here --
47
49
 
48
50
  ## Available Tools
49
51
 
50
- ### Workspace Tools
51
- **get_workspace_hierarchy**
52
- Returns complete workspace structure (spaces, folders, lists). No parameters required.
53
-
54
- ### Task Tools
55
- **get_tasks** `(listId|listName)`
56
- Get tasks from list with optional filters (archived, page, order_by, reverse, subtasks, statuses, include_closed, assignees, due_date_gt/lt, custom_fields).
57
-
58
- **get_task** `(taskId|taskName, ?listName)`
59
- Get detailed task info including attachments and custom fields.
60
-
61
- **create_task** `(listId|listName, taskName)`
62
- Create task with optional description (markdown), status, priority (1-4), dueDate.
63
-
64
- **create_bulk_tasks** `(listId|listName, tasks[])`
65
- Bulk create tasks with automatic rate limiting. Each task: name (required), description, status, priority, dueDate (optional).
66
-
67
- **update_task** `(taskId|taskName, ?listName)`
68
- Update task name, description, status, priority (1-4), dueDate.
69
-
70
- **delete_task** `(taskId|taskName, ?listName)`
71
- Permanently delete a task.
72
-
73
- **move_task** `(taskId|taskName, destinationListId|destinationListName, ?sourceListName)`
74
- Move task to different list, preserving task data.
75
-
76
- **duplicate_task** `(taskId|taskName, destinationListId|destinationListName, ?sourceListName)`
77
- Create copy of task in specified list.
78
-
79
- ### List & Folder Tools
80
- **create_list** `(spaceId|spaceName, listName)`
81
- Create list with optional content, dueDate, priority (1-4), assignee.
82
-
83
- **create_folder** `(spaceId|spaceName, folderName, ?overrideStatuses)`
84
- Create folder in space.
85
-
86
- **create_list_in_folder** `(folderId|folderName, listName)`
87
- Create list in folder with optional content and status.
52
+ | Tool | Description | Required Parameters |
53
+ |------|-------------|-------------------|
54
+ | [get_workspace_hierarchy](docs/tools.md#workspace-organization) | Get complete workspace structure | None |
55
+ | [get_tasks](docs/tools.md#task-management) | Retrieve tasks from a list | `listId` or `listName` |
56
+ | [get_task](docs/tools.md#task-management) | Get single task details | `taskId` or `taskName` |
57
+ | [create_task](docs/tools.md#task-management) | Create a new task | `listId`, `taskName` |
58
+ | [create_bulk_tasks](docs/tools.md#task-management) | Create multiple tasks | `listId`, `tasks[]` |
59
+ | [update_task](docs/tools.md#task-management) | Modify task properties | `taskId` or `taskName` |
60
+ | [delete_task](docs/tools.md#task-management) | Remove a task | `taskId` or `taskName` |
61
+ | [move_task](docs/tools.md#task-management) | Move task to another list | `taskId`, `destinationListId` |
62
+ | [duplicate_task](docs/tools.md#task-management) | Copy task to another list | `taskId`, `destinationListId` |
63
+ | [create_list](docs/tools.md#list-management) | Create a new list | `spaceId`, `listName` |
64
+ | [create_folder](docs/tools.md#folder-management) | Create a new folder | `spaceId`, `folderName` |
65
+ | [create_list_in_folder](docs/tools.md#list-management) | Create list in folder | `folderId`, `listName` |
66
+
67
+ See [full documentation](docs/tools.md) for optional parameters and advanced usage.
88
68
 
89
69
  ## Available Prompts
90
70
 
91
- 1. **summarize_tasks**
92
- - Basic task summary by status
93
- - Lists tasks with their current states
94
- - Shows task relationships within lists
95
-
96
- 2. **analyze_priorities**
97
- - Reviews current task priorities
98
- - Suggests priority adjustments
99
- - Recommends task sequencing
100
-
101
- 3. **generate_description**
102
- - Interactive prompt for creating task descriptions
103
- - Helps structure task information
104
- - Includes objectives, criteria, and dependencies
71
+ | Prompt | Purpose | Features |
72
+ |--------|---------|----------|
73
+ | [summarize_tasks](docs/tools.md#prompts) | Generate task overview | Status summary, relationships, current states |
74
+ | [analyze_priorities](docs/tools.md#prompts) | Review task priorities | Priority review, adjustments, sequencing |
75
+ | [generate_description](docs/tools.md#prompts) | Create task descriptions | Structure, objectives, dependencies |
105
76
 
106
77
  ## Error Handling
107
78
 
@@ -115,12 +86,9 @@ The server provides clear error messages for:
115
86
 
116
87
  ## Support the Developer
117
88
 
118
- If you find this project useful, please consider supporting the developer:
119
- Talib Kareem (taazkareem@icloud.com)
120
-
121
- [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-Support-orange)](https://www.buymeacoffee.com/taazkareem)
89
+ If you find this project useful, please consider supporting
122
90
 
123
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle; margin-right: 4px;"><path d="M4 18h12l4-4h-12z" /><path d="M8 14l-4-4h12l4 4" /><path d="M16 10l4-4h-12l-4 4" /></svg><span style="vertical-align: middle;">**Solana Wallet:** `GjtRksihd7SWQw7hJSCDMcTxPHbgpNs7xPW3nFubNjVM`</span>
91
+ [![Sponsor TaazKareem](https://img.shields.io/badge/Sponsor-TaazKareem-orange?logo=github)](https://github.com/sponsors/TaazKareem)
124
92
 
125
93
  ## Contributing
126
94
 
package/build/config.js CHANGED
@@ -1,4 +1,3 @@
1
- // Parse command line arguments for --env flags
2
1
  const args = process.argv.slice(2);
3
2
  const envArgs = {};
4
3
  for (let i = 0; i < args.length; i++) {
@@ -6,16 +5,15 @@ for (let i = 0; i < args.length; i++) {
6
5
  const [key, value] = args[i + 1].split('=');
7
6
  if (key === 'CLICKUP_API_KEY')
8
7
  envArgs.clickupApiKey = value;
9
- if (key === 'TEAM_ID')
10
- envArgs.teamId = value;
11
- i++; // Skip the next argument since we used it
8
+ if (key === 'CLICKUP_TEAM_ID')
9
+ envArgs.clickupTeamId = value;
10
+ i++;
12
11
  }
13
12
  }
14
13
  const configuration = {
15
- clickupApiKey: envArgs.clickupApiKey || '',
16
- teamId: envArgs.teamId || '',
14
+ clickupApiKey: envArgs.clickupApiKey || process.env.CLICKUP_API_KEY || '',
15
+ clickupTeamId: envArgs.clickupTeamId || process.env.CLICKUP_TEAM_ID || '',
17
16
  };
18
- // Check for missing environment variables
19
17
  const missingEnvVars = Object.entries(configuration)
20
18
  .filter(([_, value]) => !value)
21
19
  .map(([key]) => key);
package/build/index.js CHANGED
@@ -25,7 +25,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema
25
25
  import { ClickUpService } from "./services/clickup.js";
26
26
  import config from "./config.js";
27
27
  // Initialize ClickUp service
28
- const clickup = ClickUpService.initialize(config.clickupApiKey, config.teamId);
28
+ const clickup = ClickUpService.initialize(config.clickupApiKey, config.clickupTeamId);
29
29
  /**
30
30
  * Create an MCP server with capabilities for tools and prompts.
31
31
  * Resources have been removed as they are being replaced with direct tool calls.
@@ -48,7 +48,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
48
48
  tools: [
49
49
  {
50
50
  name: "get_workspace_hierarchy",
51
- description: "Get the complete hierarchy of spaces, folders, and lists in the workspace. -First check chat history for space, folder, and list names or IDs. If not found, use this tool to get necessary information.",
51
+ description: "Get the complete hierarchy of spaces, folders, and lists in the workspace. Important: If looking up information, first check chat history for space, folder, and list names or ID matches. If not found, use this tool to get necessary information.",
52
52
  inputSchema: {
53
53
  type: "object",
54
54
  properties: {},
@@ -366,7 +366,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
366
366
  },
367
367
  {
368
368
  name: "get_tasks",
369
- description: "Get tasks from a ClickUp list with optional filters. Supports direct name-based lookup for lists - no need to know the list ID. If the list doesn't exist, you can create it using create_list or create_list_in_folder.",
369
+ description: "Get tasks from a ClickUp list with optional filters. Supports direct name-based lookup for lists - no need to know the list ID. If the list doesn't exist, you can create it using create_list or create_list_in_folder. ",
370
370
  inputSchema: {
371
371
  type: "object",
372
372
  properties: {
@@ -852,7 +852,7 @@ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
852
852
  try {
853
853
  switch (request.params.name) {
854
854
  case "summarize_tasks": {
855
- const spaces = await clickup.getSpaces(config.teamId);
855
+ const spaces = await clickup.getSpaces(config.clickupTeamId);
856
856
  const tasks = [];
857
857
  // Gather all tasks
858
858
  for (const space of spaces) {
@@ -893,7 +893,7 @@ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
893
893
  };
894
894
  }
895
895
  case "analyze_priorities": {
896
- const spaces = await clickup.getSpaces(config.teamId);
896
+ const spaces = await clickup.getSpaces(config.clickupTeamId);
897
897
  const tasks = [];
898
898
  for (const space of spaces) {
899
899
  const lists = await clickup.getLists(space.id);
@@ -6,10 +6,10 @@ import axios from 'axios';
6
6
  export class ClickUpService {
7
7
  client;
8
8
  static instance;
9
- teamId;
9
+ clickupTeamId;
10
10
  rateLimitRemaining = 100; // Default to lowest tier limit
11
11
  rateLimitReset = 0;
12
- constructor(apiKey, teamId) {
12
+ constructor(apiKey, clickupTeamId) {
13
13
  this.client = axios.create({
14
14
  baseURL: 'https://api.clickup.com/api/v2',
15
15
  headers: {
@@ -35,7 +35,7 @@ export class ClickUpService {
35
35
  }
36
36
  throw error;
37
37
  });
38
- this.teamId = teamId;
38
+ this.clickupTeamId = clickupTeamId;
39
39
  }
40
40
  /**
41
41
  * Checks if we're close to hitting rate limits and waits if necessary.
@@ -73,13 +73,13 @@ export class ClickUpService {
73
73
  /**
74
74
  * Initializes the ClickUpService singleton instance.
75
75
  * @param apiKey - The ClickUp API key for authentication
76
- * @param teamId - The team/workspace ID to operate on
76
+ * @param clickupTeamId - The team/workspace ID to operate on
77
77
  * @returns The singleton instance of ClickUpService
78
78
  * @throws Error if initialization fails
79
79
  */
80
- static initialize(apiKey, teamId) {
80
+ static initialize(apiKey, clickupTeamId) {
81
81
  if (!ClickUpService.instance) {
82
- ClickUpService.instance = new ClickUpService(apiKey, teamId);
82
+ ClickUpService.instance = new ClickUpService(apiKey, clickupTeamId);
83
83
  }
84
84
  return ClickUpService.instance;
85
85
  }
@@ -244,13 +244,13 @@ export class ClickUpService {
244
244
  }
245
245
  /**
246
246
  * Gets all lists in the workspace.
247
- * @param teamId - ID of the team/workspace
247
+ * @param clickupTeamId - ID of the team/workspace
248
248
  * @returns Promise resolving to array of ClickUpList objects
249
249
  * @throws Error if the API request fails
250
250
  */
251
- async getAllLists(teamId) {
251
+ async getAllLists(clickupTeamId) {
252
252
  return this.makeRequest(async () => {
253
- const response = await this.client.get(`/team/${teamId}/list`);
253
+ const response = await this.client.get(`/team/${clickupTeamId}/list`);
254
254
  return response.data.lists;
255
255
  });
256
256
  }
@@ -267,9 +267,9 @@ export class ClickUpService {
267
267
  });
268
268
  }
269
269
  // Spaces
270
- async getSpaces(teamId) {
270
+ async getSpaces(clickupTeamId) {
271
271
  return this.makeRequest(async () => {
272
- const response = await this.client.get(`/team/${teamId}/space`);
272
+ const response = await this.client.get(`/team/${clickupTeamId}/space`);
273
273
  return response.data.spaces;
274
274
  });
275
275
  }
@@ -279,8 +279,8 @@ export class ClickUpService {
279
279
  return response.data;
280
280
  });
281
281
  }
282
- async findSpaceByName(teamId, spaceName) {
283
- const spaces = await this.getSpaces(teamId);
282
+ async findSpaceByName(clickupTeamId, spaceName) {
283
+ const spaces = await this.getSpaces(clickupTeamId);
284
284
  return spaces.find(space => space.name.toLowerCase() === spaceName.toLowerCase()) || null;
285
285
  }
286
286
  /**
@@ -448,7 +448,7 @@ export class ClickUpService {
448
448
  }
449
449
  async findListByNameGlobally(listName) {
450
450
  // First try the direct lists
451
- const lists = await this.getAllLists(this.teamId);
451
+ const lists = await this.getAllLists(this.clickupTeamId);
452
452
  const directList = lists.find(list => list.name.toLowerCase() === listName.toLowerCase());
453
453
  if (directList)
454
454
  return directList;
@@ -477,9 +477,9 @@ export class ClickUpService {
477
477
  * @throws Error if API requests fail
478
478
  */
479
479
  async getWorkspaceHierarchy() {
480
- const spaces = await this.getSpaces(this.teamId);
480
+ const spaces = await this.getSpaces(this.clickupTeamId);
481
481
  const root = {
482
- id: this.teamId,
482
+ id: this.clickupTeamId,
483
483
  name: 'Workspace',
484
484
  type: 'workspace',
485
485
  children: []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taazkareem/clickup-mcp-server",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "ClickUp MCP Server - Integrate ClickUp tasks with AI through Model Context Protocol",
5
5
  "type": "module",
6
6
  "main": "build/index.js",