@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.
Files changed (57) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +295 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +184 -0
  6. package/dist/clickup-text.d.ts +83 -0
  7. package/dist/clickup-text.d.ts.map +1 -0
  8. package/dist/clickup-text.js +563 -0
  9. package/dist/index.d.ts +5 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +135 -0
  12. package/dist/resources/space-resources.d.ts +6 -0
  13. package/dist/resources/space-resources.d.ts.map +1 -0
  14. package/dist/resources/space-resources.js +95 -0
  15. package/dist/shared/config.d.ts +11 -0
  16. package/dist/shared/config.d.ts.map +1 -0
  17. package/dist/shared/config.js +61 -0
  18. package/dist/shared/data-uri.d.ts +14 -0
  19. package/dist/shared/data-uri.d.ts.map +1 -0
  20. package/dist/shared/data-uri.js +34 -0
  21. package/dist/shared/image-processing.d.ts +13 -0
  22. package/dist/shared/image-processing.d.ts.map +1 -0
  23. package/dist/shared/image-processing.js +199 -0
  24. package/dist/shared/types.d.ts +21 -0
  25. package/dist/shared/types.d.ts.map +1 -0
  26. package/dist/shared/types.js +2 -0
  27. package/dist/shared/utils.d.ts +71 -0
  28. package/dist/shared/utils.d.ts.map +1 -0
  29. package/dist/shared/utils.js +508 -0
  30. package/dist/test-utils.d.ts +23 -0
  31. package/dist/test-utils.d.ts.map +1 -0
  32. package/dist/test-utils.js +44 -0
  33. package/dist/tools/admin-tools.d.ts +3 -0
  34. package/dist/tools/admin-tools.d.ts.map +1 -0
  35. package/dist/tools/admin-tools.js +288 -0
  36. package/dist/tools/doc-tools.d.ts +4 -0
  37. package/dist/tools/doc-tools.d.ts.map +1 -0
  38. package/dist/tools/doc-tools.js +436 -0
  39. package/dist/tools/list-tools.d.ts +4 -0
  40. package/dist/tools/list-tools.d.ts.map +1 -0
  41. package/dist/tools/list-tools.js +175 -0
  42. package/dist/tools/search-tools.d.ts +3 -0
  43. package/dist/tools/search-tools.d.ts.map +1 -0
  44. package/dist/tools/search-tools.js +161 -0
  45. package/dist/tools/space-tools.d.ts +3 -0
  46. package/dist/tools/space-tools.d.ts.map +1 -0
  47. package/dist/tools/space-tools.js +128 -0
  48. package/dist/tools/task-tools.d.ts +8 -0
  49. package/dist/tools/task-tools.d.ts.map +1 -0
  50. package/dist/tools/task-tools.js +329 -0
  51. package/dist/tools/task-write-tools.d.ts +3 -0
  52. package/dist/tools/task-write-tools.d.ts.map +1 -0
  53. package/dist/tools/task-write-tools.js +567 -0
  54. package/dist/tools/time-tools.d.ts +4 -0
  55. package/dist/tools/time-tools.d.ts.map +1 -0
  56. package/dist/tools/time-tools.js +338 -0
  57. package/package.json +74 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Marco Pfeiffer
4
+ Copyright (c) 2026 MW Pripanggalih
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,295 @@
1
+ # ClickUp MCP by MW Pripanggalih
2
+
3
+ Model Context Protocol (MCP) server for working with ClickUp workspaces from AI assistants. It supports rich task context, project search, task creation and updates, comments, documents, time tracking, and non-destructive workspace administration tools for Spaces, Folders, and Lists.
4
+
5
+ This project is maintained as an independent ClickUp MCP distribution by MW Pripanggalih. It uses ClickUp API keys and is designed for local automation, coding assistants, and personal/team workflows that need direct ClickUp API access.
6
+
7
+ ## What You Can Do
8
+
9
+ Turn natural language into powerful ClickUp actions:
10
+
11
+ **Agentic Coding & Development:**
12
+ - *"Look at CU-abc123, can you find the relevant code?"*
13
+ - *"Can you build the dashboard like described in https://app.clickup.com/t/12a23b45c?"*
14
+ - *"Check task CU-xyz789 and fix the bugs mentioned in the comments"*
15
+ - *"Implement the API endpoints described in the integration task"*
16
+
17
+ **Time Tracking & Productivity:**
18
+ - *"Book 2 hours for the client meeting on the XYZ project"*
19
+ - *"How much time did I spend on development tasks this week?"*
20
+ - *"Log 30 minutes for code review on the authentication feature"*
21
+
22
+ **Smart Search & Discovery:**
23
+ - *"What task did I mention the CSV import in?"*
24
+ - *"Find all tasks related to the payment gateway integration"*
25
+ - *"Show me tasks where users reported login issues"*
26
+
27
+ **Daily Workflow Management:**
28
+ - *"What do I need to do today?"*
29
+ - *"Create a task for fixing the dashboard bug in the frontend list"*
30
+ - *"Update the API documentation task to 'in review' status"*
31
+ - *"What tasks are blocking the mobile app release?"*
32
+
33
+ **Rich Context & Collaboration:**
34
+ - *"Show me all comments on the user authentication task"*
35
+ - *"What's the latest update on the database migration?"*
36
+ - *"Add a comment to the design task about the new wireframes"*
37
+
38
+ **Document Management:**
39
+ - *"Find documents about hiring in the Product space"*
40
+ - *"Search for API documentation across all spaces"*
41
+ - *"Read the API documentation in the development space"*
42
+ - *"Create a new requirements document for the mobile app project"*
43
+ - *"Update the meeting notes with today's decisions"*
44
+ - *"What documents are in the product strategy space?"*
45
+
46
+ **Workspace Administration (write mode):**
47
+ - *"Create a new Space for the client migration project"*
48
+ - *"Add a Folder called Roadmap to the Product space"*
49
+ - *"Create a folderless List called Intake in the Operations space"*
50
+ - *"Rename the Sprint Planning List to Delivery Planning"*
51
+
52
+ ## Key Features
53
+
54
+ ### 🔍 **Intelligent Search**
55
+ - Fuzzy matching across task names, descriptions, and comments
56
+ - Multi-language search support for international teams
57
+ - Filter by assignees, projects, status, and metadata
58
+
59
+ ### 💬 **Complete Context**
60
+ - Full comment histories and team discussions
61
+ - Task descriptions with embedded images
62
+ - List descriptions and project guidelines
63
+ - Document content with page navigation
64
+ - Access to complete task history and decisions
65
+
66
+ ### ⏱️ **Time Tracking**
67
+ - Log time entries with descriptions
68
+ - View historical time logs and entries
69
+ - Query time entries by task or date range
70
+
71
+ ### 📋 **Task & Document Management**
72
+ - Create and update tasks with markdown descriptions
73
+ - Create, read, and update documents and pages
74
+ - Add comments and collaborate with team members
75
+ - Manage priorities, due dates, assignees, and tags
76
+ - Handle time estimates and custom field values
77
+
78
+ ### 🧭 **Workspace Administration**
79
+ - Create and update Spaces, Folders, and Lists using official ClickUp API v2 endpoints
80
+ - Create either folderless Lists in Spaces or Lists inside Folders
81
+ - Keep destructive delete operations out of the default tool set
82
+ - Treat List `status` as List color only, not task workflow status
83
+
84
+ ### 🔒 **Safety Features**
85
+ - **Append-Only Descriptions**: Description fields are never overwritten - new content is safely appended with timestamps
86
+ - **Normal Field Updates**: Status, priority, assignees, tags, and dates can be updated normally (easily revertible through ClickUp's history)
87
+
88
+ ## Installation
89
+
90
+ ### Prerequisites
91
+
92
+ For all installation methods, you'll need:
93
+ - Your `CLICKUP_API_KEY` (Profile Icon > Settings > Apps > API Token ~ usually starts with pk_)
94
+ - Your `CLICKUP_TEAM_ID` (The 7–10 digit number in the URL when you are in the settings)
95
+
96
+ ### Option 1: MCPB Bundle (Recommended for Claude Desktop)
97
+
98
+ Download the pre-built bundle from the [releases page](https://github.com/pripanggalih/clickup-mcp/releases). This method requires no Node.js installation.
99
+
100
+ You'll get a configuration screen where you are prompted to enter your API key and team ID.
101
+
102
+ ### Option 2: NPX Installation
103
+
104
+ This method automatically updates to the latest version and is preferred for users who want the newest features.
105
+
106
+ **For Claude Desktop, Windsurf, Cursor and others:**
107
+
108
+ Add the following to your MCP configuration file:
109
+
110
+ ```json
111
+ {
112
+ "mcpServers": {
113
+ "clickup": {
114
+ "command": "npx",
115
+ "args": [
116
+ "@pripanggalih/clickup-mcp@latest"
117
+ ],
118
+ "env": {
119
+ "CLICKUP_API_KEY": "your_api_key",
120
+ "CLICKUP_TEAM_ID": "your_team_id"
121
+ }
122
+ }
123
+ }
124
+ }
125
+ ```
126
+
127
+ Replace `your_api_key` and `your_team_id` with your actual ClickUp credentials.
128
+
129
+ **Where to add this configuration:**
130
+ - **Claude Desktop**: Settings > Developer > Edit Config
131
+ - **Windsurf**: Add to your MCP configuration file
132
+ - **Cursor**: Configure through the MCP settings panel
133
+
134
+ ### Option 3: Coding Tools Integration
135
+
136
+ **Claude Code (CLI):**
137
+ ```bash
138
+ claude mcp add --scope user clickup \
139
+ --env CLICKUP_API_KEY=YOUR_KEY \
140
+ --env CLICKUP_TEAM_ID=YOUR_ID \
141
+ --env CLICKUP_MCP_MODE=read-minimal \
142
+ --env MAX_IMAGES=16 \
143
+ --env MAX_RESPONSE_SIZE_MB=4 \
144
+ -- npx -y @pripanggalih/clickup-mcp
145
+ ```
146
+
147
+ > Claude Code can handle a lot of images, thus the recommended increased limits.
148
+
149
+ > Note the `CLICKUP_MCP_MODE=read-minimal`. This is my usage recommendation, but feel free to use one of the other modes.
150
+
151
+ **OpenAI Codex:**
152
+ Add these lines to your `~/.codex/config.toml` file:
153
+ ```toml
154
+ [mcp_servers.clickup]
155
+ command = "npx"
156
+ args = ["-y", "@pripanggalih/clickup-mcp@latest"]
157
+ env = { "CLICKUP_API_KEY" = "YOUR_KEY", "CLICKUP_TEAM_ID" = "YOUR_ID", "CLICKUP_MCP_MODE" = "read-minimal" }
158
+ ```
159
+
160
+ > Codex seems to not be able to handle images from MCP's. See [this issue](https://github.com/openai/codex/issues/3741) for more details.
161
+
162
+ > Note the `CLICKUP_MCP_MODE=read-minimal`. This is my usage recommendation, but feel free to use one of the other modes.
163
+
164
+ ## MCP Modes & Available Tools
165
+
166
+ The ClickUp MCP supports three operational modes to balance functionality, security, and performance:
167
+
168
+ - **🚀 `read-minimal`**: Perfect for AI coding assistants and context gathering
169
+ - **📖 `read`**: Full read-only access for project exploration and workflow understanding
170
+ - **✏️ `write`** (Default): Complete functionality for task management and productivity workflows
171
+
172
+ | Tool | read-minimal | read | write | Description |
173
+ |------------------------|:------------:|:----:|:-----:|-----------------------------------------------------------------------------------------|
174
+ | `getTaskById` | ✅ | ✅ | ✅ | Get complete task details including comments, images, and metadata |
175
+ | `addComment` | ❌ | ❌ | ✅ | Add comments to tasks for collaboration |
176
+ | `updateTask` | ❌ | ❌ | ✅ | Update tasks (status, priority, assignees, etc.) with **SAFE APPEND-ONLY** descriptions |
177
+ | `createTask` | ❌ | ❌ | ✅ | Create new tasks with full markdown support |
178
+ | `searchTasks` | ✅ | ✅ | ✅ | Find tasks by content, keywords, assignees, or project context |
179
+ | `searchSpaces` | ❌ | ✅ | ✅ | Browse workspace structure, project organization, and documents |
180
+ | `getListInfo` | ❌ | ✅ | ✅ | Get list details and available statuses for task creation |
181
+ | `updateListInfo` | ❌ | ❌ | ✅ | **SAFE APPEND-ONLY** updates to list descriptions (preserves existing content) |
182
+ | `createSpace` | ❌ | ❌ | ✅ | Create a new Space in the configured Workspace |
183
+ | `updateSpace` | ❌ | ❌ | ✅ | Update Space name, color, privacy, assignee, admin, and feature settings |
184
+ | `createFolder` | ❌ | ❌ | ✅ | Create a Folder inside a Space |
185
+ | `updateFolder` | ❌ | ❌ | ✅ | Rename an existing Folder |
186
+ | `createList` | ❌ | ❌ | ✅ | Create a folderless List in a Space or a List inside a Folder |
187
+ | `updateList` | ❌ | ❌ | ✅ | Update List fields; `status_color` maps to ClickUp's List color, not task status |
188
+ | `getTimeEntries` | ❌ | ✅ | ✅ | View time entries and analyze time spent across projects |
189
+ | `createTimeEntry` | ❌ | ❌ | ✅ | Log time entries for task tracking |
190
+ | `readDocument` | ❌ | ✅ | ✅ | Get document details, page structure, and content with navigation |
191
+ | `searchDocuments` | ❌ | ✅ | ✅ | Search documents by name and space with fuzzy matching and space filtering |
192
+ | `updateDocumentPage` | ❌ | ❌ | ✅ | Update existing page content or name with replace/append modes |
193
+ | `createDocumentOrPage` | ❌ | ❌ | ✅ | Create new documents with first page, or add pages/sub-pages to existing documents |
194
+
195
+ ### Setting the Mode
196
+
197
+ Add the mode to your MCP configuration:
198
+
199
+ ```json
200
+ {
201
+ "mcpServers": {
202
+ "clickup": {
203
+ "command": "npx",
204
+ "args": ["-y", "@pripanggalih/clickup-mcp@latest"],
205
+ "env": {
206
+ "CLICKUP_API_KEY": "your_api_key",
207
+ "CLICKUP_TEAM_ID": "your_team_id",
208
+ "CLICKUP_MCP_MODE": "read"
209
+ }
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ ## Configuration
216
+
217
+ This MCP server can be configured using environment variables:
218
+
219
+ - `CLICKUP_API_KEY`: (Required) Your ClickUp API key.
220
+ - `CLICKUP_TEAM_ID`: (Required) Your ClickUp Team ID (formerly Workspace ID).
221
+ - `CLICKUP_MCP_MODE`: (Optional) Controls which tools are available. Options: `read-minimal`, `read`, `write` (default).
222
+ - `MAX_IMAGES`: (Optional) The maximum number of images to return for a task in `getTaskById`. Defaults to 4.
223
+ - `MAX_RESPONSE_SIZE_MB`: (Optional) The maximum response size in megabytes for `getTaskById`. Uses intelligent size budgeting to fit the most important images within the limit. Defaults to 1.
224
+ - `CLICKUP_PRIMARY_LANGUAGE`: (Optional) A hint for the primary language used in your ClickUp tasks (e.g., "de" for German, "en" for English). This helps the `searchTask` tool provide more tailored guidance in its description for multilingual searches.
225
+ - `LANG`: (Optional) If `CLICKUP_PRIMARY_LANGUAGE` is not set, the MCP will check this standard environment variable (e.g., "en_US.UTF-8", "de_DE") as a fallback to infer the primary language.
226
+
227
+ ### Language-Aware Search Guidance
228
+
229
+ The `searchTask` tool's description will dynamically adjust based on the detected primary language:
230
+ - If `CLICKUP_PRIMARY_LANGUAGE` or `LANG` suggests a known primary language (e.g., German), the tool's description will specifically recommend providing search terms in both English and that detected language (e.g., German) for optimal results.
231
+ - If no primary language is detected, a more general recommendation for multilingual workspaces will be provided.
232
+
233
+ This feature aims to improve search effectiveness when the language of user queries (often English) differs from the language of the tasks in ClickUp, without making the MCP itself perform translations. The responsibility for providing bilingual search terms still lies with the agent calling the MCP, but the MCP offers more specific advice if it has a language hint.
234
+
235
+ ## Markdown Formatting Support
236
+
237
+ Task descriptions and list documentation support full markdown formatting:
238
+
239
+ ### Examples
240
+
241
+ **Task Creation with Markdown:**
242
+ ```
243
+ Create a task called "API Integration" with description:
244
+ # API Integration Requirements
245
+
246
+ ## Authentication
247
+ - Implement OAuth 2.0 flow
248
+ - Add JWT token validation
249
+ - **Priority**: High security standards
250
+
251
+ ## Endpoints
252
+ 1. `/api/users` - User management
253
+ 2. `/api/data` - Data retrieval
254
+ 3. `/api/webhook` - Event notifications
255
+
256
+ ## Testing
257
+ - [ ] Unit tests for auth flow
258
+ - [ ] Integration tests
259
+ - [ ] Load testing with 1000+ concurrent users
260
+
261
+ > **Note**: This replaces the legacy REST implementation
262
+
263
+ See related task: https://app.clickup.com/t/abc123
264
+ ```
265
+
266
+ **Append-Only Updates (Safe):**
267
+ When updating task descriptions, content is safely appended:
268
+ ```markdown
269
+ [Existing task description content]
270
+
271
+ ---
272
+ **Edit (2024-01-15):** Added new acceptance criteria based on client feedback:
273
+ - Must support mobile responsive design
274
+ - Performance requirement: < 2s load time
275
+ ```
276
+
277
+ This ensures no existing content is ever lost while maintaining a clear audit trail.
278
+
279
+ ## Performance & Limitations
280
+
281
+ **Optimized for AI Workflows:**
282
+ - **Smart Image Processing**: Intelligent size budgeting prioritizes the most recent images while respecting both count (`MAX_IMAGES`, default: 4) and total response size limits (`MAX_RESPONSE_SIZE_MB`, default: 1MB)
283
+ - **Search Scope**: Searches within the most recent 1000-3000 tasks to prevent running into rate limits (exact number varies by endpoint)
284
+ - **Search Results**: Returns up to 50 most relevant matches to prevent flooding the agent with too many results
285
+
286
+ **Current Scope:**
287
+ - Focused on task-level operations rather than bulk workspace management
288
+ - Optimized for conversational AI workflows rather than data migration
289
+ - Designed for productivity enhancement, not administrative operations
290
+
291
+ These limitations ensure reliable performance while covering the most common use cases for both development context and productivity management.
292
+
293
+ ## License
294
+
295
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ require("dotenv/config"); // Load .env file
5
+ const index_1 = require("./index");
6
+ async function main() {
7
+ // Wait for server initialization to complete
8
+ const server = await index_1.serverPromise;
9
+ const args = process.argv.slice(2);
10
+ // Special command to show instructions
11
+ if (args.length === 1 && args[0] === 'instructions') {
12
+ console.log("Server Instructions:");
13
+ console.log(server.server._instructions || "No instructions configured");
14
+ process.exit(0);
15
+ }
16
+ // Special commands for testing resources
17
+ if (args.length === 1 && args[0] === 'resources') {
18
+ console.log("Listing available resources...");
19
+ try {
20
+ // @ts-ignore - Accessing private property for testing purposes
21
+ const resourceTemplates = server._registeredResourceTemplates;
22
+ if (resourceTemplates && Object.keys(resourceTemplates).length > 0) {
23
+ for (const [name, template] of Object.entries(resourceTemplates)) {
24
+ console.log(`Resource template: ${name}`);
25
+ // @ts-ignore - Access template properties
26
+ const uriTemplate = template.resourceTemplate.uriTemplate;
27
+ console.log(` URI Template: ${uriTemplate}`);
28
+ // Test the list callback if available
29
+ // @ts-ignore - Access template properties
30
+ if (template.resourceTemplate._callbacks.list) {
31
+ try {
32
+ // @ts-ignore - Call list callback
33
+ const result = await template.resourceTemplate._callbacks.list();
34
+ console.log(` Resources found: ${result.resources.length}`);
35
+ result.resources.slice(0, 3).forEach((res, idx) => {
36
+ console.log(` ${idx + 1}. ${res.name} (${res.uri})`);
37
+ });
38
+ if (result.resources.length > 3) {
39
+ console.log(` ... and ${result.resources.length - 3} more`);
40
+ }
41
+ }
42
+ catch (error) {
43
+ console.log(` Error listing resources: ${error instanceof Error ? error.message : 'Unknown error'}`);
44
+ }
45
+ }
46
+ console.log("");
47
+ }
48
+ }
49
+ else {
50
+ console.log("No resource templates registered.");
51
+ }
52
+ }
53
+ catch (error) {
54
+ console.error("Error accessing resources:", error instanceof Error ? error.message : 'Unknown error');
55
+ }
56
+ process.exit(0);
57
+ }
58
+ // Special command to read a specific resource
59
+ if (args.length === 2 && args[0] === 'resource') {
60
+ const resourceUri = args[1];
61
+ console.log(`Reading resource: ${resourceUri}`);
62
+ try {
63
+ // @ts-ignore - Accessing private property for testing purposes
64
+ const resourceTemplates = server._registeredResourceTemplates;
65
+ // Find matching template and call read callback
66
+ for (const [name, template] of Object.entries(resourceTemplates)) {
67
+ try {
68
+ // @ts-ignore - Access template properties
69
+ const result = await template.readCallback(new URL(resourceUri), {}, {});
70
+ console.dir(result, { depth: null });
71
+ process.exit(0);
72
+ }
73
+ catch (error) {
74
+ // Continue to next template if this one doesn't match
75
+ continue;
76
+ }
77
+ }
78
+ console.error("No matching resource template found for URI:", resourceUri);
79
+ process.exit(1);
80
+ }
81
+ catch (error) {
82
+ console.error("Error reading resource:", error instanceof Error ? error.message : 'Unknown error');
83
+ process.exit(1);
84
+ }
85
+ }
86
+ if (args.length < 1) {
87
+ console.error("Usage: npm run cli <tool-name> [param1=value1 param2=value2 ...]");
88
+ console.error(" npm run cli instructions");
89
+ console.error(" npm run cli resources");
90
+ console.error(" npm run cli resource <uri>");
91
+ console.error("\nAvailable tools:");
92
+ // @ts-ignore - Accessing private property for testing purposes
93
+ const tools = server._registeredTools;
94
+ if (tools) {
95
+ for (const [name, tool] of Object.entries(tools)) {
96
+ console.error(` - ${name}: ${tool.description}`);
97
+ if (tool.inputSchema && tool.inputSchema._def && typeof tool.inputSchema._def.shape === 'function') {
98
+ console.error(" Parameters:");
99
+ const shape = tool.inputSchema._def.shape();
100
+ for (const [paramName, schema] of Object.entries(shape)) {
101
+ // @ts-ignore - Accessing schema description
102
+ const description = schema.description || "No description";
103
+ console.error(` - ${paramName}: ${description}`);
104
+ }
105
+ }
106
+ else {
107
+ console.error(" Parameters: None");
108
+ }
109
+ console.error("");
110
+ }
111
+ }
112
+ process.exit(1);
113
+ }
114
+ const toolName = args[0];
115
+ const params = {};
116
+ // Parse parameters
117
+ for (let i = 1; i < args.length; i++) {
118
+ const arg = args[i];
119
+ const match = arg.match(/^([^=]+)=(.*)$/);
120
+ if (match) {
121
+ const [, key, value] = match;
122
+ // Try to parse as JSON if it looks like a JSON value
123
+ try {
124
+ if (value.startsWith('{') || value.startsWith('[') ||
125
+ value === 'true' || value === 'false' ||
126
+ (value.startsWith('"') && value.endsWith('"')) ||
127
+ (!isNaN(Number(value)) && !key.includes('id') && !value.startsWith('"'))) {
128
+ params[key] = JSON.parse(value);
129
+ }
130
+ else {
131
+ params[key] = value;
132
+ }
133
+ }
134
+ catch (e) {
135
+ params[key] = value;
136
+ }
137
+ }
138
+ }
139
+ try {
140
+ // @ts-ignore - Accessing private property for testing purposes
141
+ const tools = server._registeredTools;
142
+ if (!tools || !tools[toolName]) {
143
+ console.error(`Unknown tool: ${toolName}`);
144
+ process.exit(1);
145
+ }
146
+ const tool = tools[toolName];
147
+ // Validate parameters using the tool's schema, if it exists
148
+ if (tool.inputSchema) {
149
+ try {
150
+ tool.inputSchema.parse(params);
151
+ }
152
+ catch (error) {
153
+ const validationError = error;
154
+ console.error("Parameter validation error:", validationError.message);
155
+ process.exit(1);
156
+ }
157
+ }
158
+ else if (Object.keys(params).length > 0) {
159
+ // If there's no schema, but parameters were provided, it's an error
160
+ console.error(`Error: Tool '${toolName}' does not accept any parameters, but parameters were provided.`);
161
+ process.exit(1);
162
+ }
163
+ // Mock environment variables for testing if they're not set
164
+ if (!process.env.CLICKUP_API_KEY || !process.env.CLICKUP_TEAM_ID) {
165
+ console.warn("Warning: Using mock API credentials. This will not return real data.");
166
+ process.env.CLICKUP_API_KEY = process.env.CLICKUP_API_KEY || 'test_api_key';
167
+ process.env.CLICKUP_TEAM_ID = process.env.CLICKUP_TEAM_ID || 'test_team_id';
168
+ }
169
+ // Call the tool's callback function
170
+ const result = await tool.callback(params);
171
+ console.dir(result.content);
172
+ process.exit(0);
173
+ }
174
+ catch (error) {
175
+ if (error instanceof Error) {
176
+ console.error("Error:", error.message);
177
+ }
178
+ else {
179
+ console.error("Unknown error occurred");
180
+ }
181
+ process.exit(1);
182
+ }
183
+ }
184
+ main().catch(console.error);
@@ -0,0 +1,83 @@
1
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types";
2
+ import { ImageMetadataBlock } from "./shared/types";
3
+ /**
4
+ * Represents a ClickUp text item which can be plain text or an image
5
+ */
6
+ export interface ClickUpTextItem {
7
+ text?: string;
8
+ type?: string;
9
+ image?: {
10
+ id?: string;
11
+ name?: string;
12
+ title?: string;
13
+ type?: string;
14
+ extension?: string;
15
+ thumbnail_large?: string;
16
+ thumbnail_medium?: string;
17
+ thumbnail_small?: string;
18
+ url: string;
19
+ uploaded?: boolean;
20
+ };
21
+ attributes?: any;
22
+ }
23
+ /**
24
+ * Represents a ClickUp attachment
25
+ */
26
+ export interface ClickUpAttachment {
27
+ thumbnail_large?: string;
28
+ thumbnail_medium?: string;
29
+ thumbnail_small?: string;
30
+ url: string;
31
+ [key: string]: any;
32
+ }
33
+ /**
34
+ * Process an array of ClickUp text items into a structured content format
35
+ * that includes both text and images in their original sequence
36
+ *
37
+ * @param textItems Array of text items from ClickUp API
38
+ * @returns Promise resolving to an array of content blocks (text and images)
39
+ */
40
+ export declare function convertClickUpTextItemsToToolCallResult(textItems: ClickUpTextItem[]): Promise<(CallToolResult["content"][number] | ImageMetadataBlock)[]>;
41
+ /**
42
+ * Splits markdown text at image references and converts them to image blocks
43
+ * @param markdownText The markdown text to process
44
+ * @param attachments Array of attachments from the Clickup API
45
+ * @returns Array of content blocks (text and images)
46
+ */
47
+ export declare function convertMarkdownToToolCallResult(markdownText: string, attachments: ClickUpAttachment[] | null | undefined): (CallToolResult["content"][number] | ImageMetadataBlock)[];
48
+ /**
49
+ * Represents a ClickUp comment block with formatting
50
+ */
51
+ export interface ClickUpCommentBlock {
52
+ text?: string;
53
+ type?: string;
54
+ attributes?: {
55
+ bold?: boolean;
56
+ italic?: boolean;
57
+ code?: boolean;
58
+ link?: string;
59
+ 'code-block'?: {
60
+ 'code-block': string;
61
+ };
62
+ header?: number;
63
+ blockquote?: {};
64
+ 'blockquote-size'?: 'large';
65
+ list?: {
66
+ list: 'bullet' | 'ordered' | 'unchecked' | 'checked';
67
+ };
68
+ indent?: number;
69
+ 'block-id'?: string;
70
+ };
71
+ list?: {
72
+ list: 'bullet' | 'ordered' | 'unchecked' | 'checked';
73
+ };
74
+ }
75
+ /**
76
+ * Convert markdown text to ClickUp comment blocks format using remark
77
+ * Supports: headers, bold, italic, code, links, lists, blockquotes, code blocks
78
+ *
79
+ * @param markdown The markdown text to convert
80
+ * @returns Array of ClickUp comment blocks
81
+ */
82
+ export declare function convertMarkdownToClickUpBlocks(markdown: string): ClickUpCommentBlock[];
83
+ //# sourceMappingURL=clickup-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickup-text.d.ts","sourceRoot":"","sources":["../src/clickup-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAOpD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QACN,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AA4BD;;;;;;GAMG;AACH,wBAAsB,uCAAuC,CAC3D,SAAS,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAsNrE;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GAClD,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAAG,kBAAkB,CAAC,EAAE,CA0I5D;AA8BD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE;YACb,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,EAAE,CAAC;QAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,IAAI,CAAC,EAAE;YACL,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;SACtD,CAAC;QACF,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;KACtD,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAoBtF"}