@taazkareem/clickup-mcp-server 0.6.8 → 0.6.9
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 +1 -1
- package/build/mcp-tools.js +64 -0
- package/build/server-state.js +93 -0
- package/build/server.js +1 -1
- package/build/server.log +76 -0
- package/build/services/clickup/task/handlers.js +1 -0
- package/build/services/clickup/task.js +976 -0
- package/build/services/clickup/tools/tag.js +149 -0
- package/build/tools/bulk-tasks.js +36 -0
- package/build/tools/debug.js +76 -0
- package/build/tools/logs.js +55 -0
- package/build/tools/task.js +1554 -0
- package/build/utils/params-utils.js +39 -0
- package/build/utils/sponsor-analytics.js +100 -0
- package/build/utils/sponsor-utils.js +57 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
A Model Context Protocol (MCP) server for integrating ClickUp tasks with AI applications. This server allows AI agents to interact with ClickUp tasks, spaces, lists, and folders through a standardized protocol.
|
|
8
8
|
|
|
9
|
-
> 🚧 **Status Update:** Rolling out v0.6.
|
|
9
|
+
> 🚧 **Status Update:** Rolling out v0.6.9 will add Global Task Lookup with smart disambiguation, Start Date Support for tasks with natural language expressions, Complete Tag Support including natural language tag color commands, Subtasks Support, Custom ID Support, and Logging Fixes
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Logger } from "./logger.js";
|
|
2
|
+
// Create a logger instance
|
|
3
|
+
const logger = new Logger('MCPTools');
|
|
4
|
+
/**
|
|
5
|
+
* Register a handler for a tool that may receive JSON string parameters
|
|
6
|
+
* This wrapper ensures that array and object parameters are properly parsed
|
|
7
|
+
*
|
|
8
|
+
* @param server MCP Server instance
|
|
9
|
+
* @param name Tool name
|
|
10
|
+
* @param handler Handler function
|
|
11
|
+
*/
|
|
12
|
+
export function registerToolHandler(server, name, handler) {
|
|
13
|
+
// Create a wrapper handler that pre-processes parameters
|
|
14
|
+
const wrappedHandler = async (params) => {
|
|
15
|
+
logger.debug(`Processing parameters for tool ${name}`, { params });
|
|
16
|
+
try {
|
|
17
|
+
// Process the parameters before passing them to the actual handler
|
|
18
|
+
const processedParams = {};
|
|
19
|
+
// Process each parameter - try to parse strings that might be JSON
|
|
20
|
+
for (const [key, value] of Object.entries(params)) {
|
|
21
|
+
if (typeof value === 'string') {
|
|
22
|
+
try {
|
|
23
|
+
// Check if this might be a JSON array or object
|
|
24
|
+
if ((value.startsWith('[') && value.endsWith(']')) ||
|
|
25
|
+
(value.startsWith('{') && value.endsWith('}'))) {
|
|
26
|
+
try {
|
|
27
|
+
processedParams[key] = JSON.parse(value);
|
|
28
|
+
logger.debug(`Parsed JSON parameter: ${key}`, { original: value, parsed: processedParams[key] });
|
|
29
|
+
}
|
|
30
|
+
catch (parseError) {
|
|
31
|
+
// If parsing fails, use the original string
|
|
32
|
+
processedParams[key] = value;
|
|
33
|
+
logger.debug(`Failed to parse JSON for parameter: ${key}, using original`, { error: parseError.message });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
processedParams[key] = value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
// If there's any error, use the original value
|
|
42
|
+
processedParams[key] = value;
|
|
43
|
+
logger.debug(`Error processing parameter: ${key}`, { error: error.message });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Non-string values are used as-is
|
|
48
|
+
processedParams[key] = value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
logger.debug(`Processed parameters for tool ${name}`, { processedParams });
|
|
52
|
+
// Call the original handler with processed parameters
|
|
53
|
+
return handler(processedParams);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
logger.error(`Error in wrapped handler for tool ${name}:`, { error: error.stack || error.message });
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
// Use setRequestHandler to register the wrapped handler
|
|
61
|
+
logger.info(`Registering wrapped handler for tool: ${name}`);
|
|
62
|
+
// Override the tool's handler in the CallTool switch statement
|
|
63
|
+
// The server.ts file will use the switch case to call this handler
|
|
64
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server State Management Module
|
|
3
|
+
*
|
|
4
|
+
* This module provides shared state management for the MCP server,
|
|
5
|
+
* particularly for controlling shutdown behavior and tracking busy states.
|
|
6
|
+
*/
|
|
7
|
+
// State variables
|
|
8
|
+
let serverBusyState = false; // Tracks if server is doing critical work
|
|
9
|
+
let gracePeriodActive = false; // Tracks if we're in post-initialization grace period
|
|
10
|
+
let gracePeriodTimer = null;
|
|
11
|
+
export const GRACE_PERIOD_MS = 10000; // 10 second grace period after startup
|
|
12
|
+
/**
|
|
13
|
+
* Logging helper that avoids circular dependency
|
|
14
|
+
*/
|
|
15
|
+
function safeLog(level, message, data) {
|
|
16
|
+
// Use console as a fallback to avoid circular dependency with logger
|
|
17
|
+
const timestamp = new Date().toISOString();
|
|
18
|
+
if (level === 'error') {
|
|
19
|
+
console.error(`[${timestamp}] ${level.toUpperCase()}: ${message}`, data || '');
|
|
20
|
+
}
|
|
21
|
+
else if (level === 'debug' && process.env.DEBUG) {
|
|
22
|
+
console.debug(`[${timestamp}] ${level.toUpperCase()}: ${message}`, data || '');
|
|
23
|
+
}
|
|
24
|
+
else if (level !== 'debug') {
|
|
25
|
+
console.log(`[${timestamp}] ${level.toUpperCase()}: ${message}`, data || '');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Set the server as busy doing critical work that shouldn't be interrupted
|
|
30
|
+
* @param busy Whether the server is currently busy with critical operations
|
|
31
|
+
*/
|
|
32
|
+
export function setServerBusy(busy) {
|
|
33
|
+
serverBusyState = busy;
|
|
34
|
+
safeLog('debug', `Server busy state set to: ${busy}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Start grace period after initialization to prevent immediate shutdown
|
|
38
|
+
*/
|
|
39
|
+
export function startGracePeriod() {
|
|
40
|
+
gracePeriodActive = true;
|
|
41
|
+
safeLog('debug', `Starting ${GRACE_PERIOD_MS}ms grace period to prevent premature shutdown`);
|
|
42
|
+
if (gracePeriodTimer) {
|
|
43
|
+
clearTimeout(gracePeriodTimer);
|
|
44
|
+
}
|
|
45
|
+
gracePeriodTimer = setTimeout(() => {
|
|
46
|
+
gracePeriodActive = false;
|
|
47
|
+
safeLog('debug', 'Grace period ended, server will now respond to shutdown signals');
|
|
48
|
+
gracePeriodTimer = null;
|
|
49
|
+
}, GRACE_PERIOD_MS);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Cancel the grace period if needed
|
|
53
|
+
*/
|
|
54
|
+
export function cancelGracePeriod() {
|
|
55
|
+
if (gracePeriodTimer) {
|
|
56
|
+
clearTimeout(gracePeriodTimer);
|
|
57
|
+
gracePeriodTimer = null;
|
|
58
|
+
}
|
|
59
|
+
gracePeriodActive = false;
|
|
60
|
+
safeLog('debug', 'Grace period canceled, server will now respond to shutdown signals');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if the server should ignore shutdown signals
|
|
64
|
+
* @returns true if shutdown signals should be ignored
|
|
65
|
+
*/
|
|
66
|
+
export function shouldIgnoreShutdown() {
|
|
67
|
+
// Ignore shutdown if explicitly configured via environment variable
|
|
68
|
+
if (process.env.FORCE_KEEP_ALIVE === 'true') {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
// Ignore shutdown during the grace period after startup
|
|
72
|
+
if (gracePeriodActive) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
// Ignore shutdown if the server is doing critical work
|
|
76
|
+
if (serverBusyState) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
// Otherwise, allow normal shutdown
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if grace period is currently active
|
|
84
|
+
*/
|
|
85
|
+
export function isGracePeriodActive() {
|
|
86
|
+
return gracePeriodActive;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Check if server is currently in busy state
|
|
90
|
+
*/
|
|
91
|
+
export function isServerBusy() {
|
|
92
|
+
return serverBusyState;
|
|
93
|
+
}
|
package/build/server.js
CHANGED
package/build/server.log
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Logging initialized to /Volumes/Code/Projects/MCP/clickup-mcp-server/build/server.log
|
|
2
|
+
[2025-04-03T23:48:48.480Z] [PID:89934] INFO: [SponsorService] SponsorService initialized
|
|
3
|
+
{
|
|
4
|
+
"enabled": true
|
|
5
|
+
}
|
|
6
|
+
[2025-04-03T23:48:48.526Z] [PID:89934] INFO: [SharedServices] Creating shared ClickUp services singleton
|
|
7
|
+
[2025-04-03T23:48:48.526Z] [PID:89934] INFO: [ClickUpServices] Starting ClickUp services initialization
|
|
8
|
+
{
|
|
9
|
+
"teamId": "9014370478",
|
|
10
|
+
"baseUrl": "https://api.clickup.com/api/v2"
|
|
11
|
+
}
|
|
12
|
+
[2025-04-03T23:48:48.526Z] [PID:89934] INFO: [ClickUpServices] Initializing ClickUp Workspace service
|
|
13
|
+
[2025-04-03T23:48:48.528Z] [PID:89934] DEBUG: [ClickUp:WorkspaceService] Initialized WorkspaceService (teamId="9014370478" baseUrl="https://api.clickup.com/api/v2")
|
|
14
|
+
[2025-04-03T23:48:48.528Z] [PID:89934] INFO: [ClickUpServices] Initializing ClickUp Task service
|
|
15
|
+
[2025-04-03T23:48:48.528Z] [PID:89934] DEBUG: [ClickUp:TaskService] Initialized TaskService (teamId="9014370478" baseUrl="https://api.clickup.com/api/v2")
|
|
16
|
+
[2025-04-03T23:48:48.528Z] [PID:89934] INFO: [ClickUp:TaskService] Operation: constructor
|
|
17
|
+
{
|
|
18
|
+
"usingSharedWorkspaceService": true
|
|
19
|
+
}
|
|
20
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] DEBUG: [ClickUp:ListService] Initialized ListService (teamId="9014370478" baseUrl="https://api.clickup.com/api/v2")
|
|
21
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] INFO: [ClickUp:TaskService] Operation: constructor
|
|
22
|
+
{
|
|
23
|
+
"initialized": true
|
|
24
|
+
}
|
|
25
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] INFO: [ClickUp:TaskService] Operation: constructor
|
|
26
|
+
{
|
|
27
|
+
"initialized": true
|
|
28
|
+
}
|
|
29
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] INFO: [ClickUpServices] Initializing ClickUp List service
|
|
30
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] DEBUG: [ClickUp:ListService] Initialized ListService (teamId="9014370478" baseUrl="https://api.clickup.com/api/v2")
|
|
31
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] INFO: [ClickUpServices] Initializing ClickUp Folder service
|
|
32
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] DEBUG: [ClickUp:FolderService] Initialized FolderService (teamId="9014370478" baseUrl="https://api.clickup.com/api/v2")
|
|
33
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] INFO: [ClickUpServices] Initializing ClickUp Tag service
|
|
34
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] DEBUG: [ClickUp:ClickUpTagService] Initialized ClickUpTagService (teamId="9014370478" baseUrl="https://api.clickup.com/api/v2")
|
|
35
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] INFO: [ClickUpServices] All ClickUp services initialized successfully
|
|
36
|
+
{
|
|
37
|
+
"services": [
|
|
38
|
+
"workspace",
|
|
39
|
+
"task",
|
|
40
|
+
"list",
|
|
41
|
+
"folder",
|
|
42
|
+
"tag"
|
|
43
|
+
],
|
|
44
|
+
"baseUrl": "https://api.clickup.com/api/v2"
|
|
45
|
+
}
|
|
46
|
+
[2025-04-03T23:48:48.529Z] [PID:89934] INFO: [SharedServices] Services initialization complete
|
|
47
|
+
{
|
|
48
|
+
"services": "workspace, task, list, folder, tag",
|
|
49
|
+
"teamId": "9014370478"
|
|
50
|
+
}
|
|
51
|
+
[2025-04-03T23:48:48.530Z] [PID:89934] INFO: [BulkService] BulkService initialized
|
|
52
|
+
[2025-04-03T23:48:48.530Z] [PID:89934] INFO: [BulkService] BulkService initialized
|
|
53
|
+
[2025-04-03T23:48:48.531Z] [PID:89934] INFO: Starting ClickUp MCP Server...
|
|
54
|
+
[2025-04-03T23:48:48.531Z] [PID:89934] INFO: Server environment
|
|
55
|
+
{
|
|
56
|
+
"pid": 89934,
|
|
57
|
+
"node": "v23.5.0",
|
|
58
|
+
"os": "darwin",
|
|
59
|
+
"arch": "x64"
|
|
60
|
+
}
|
|
61
|
+
[2025-04-03T23:48:48.531Z] [PID:89934] INFO: Configuring server request handlers
|
|
62
|
+
[2025-04-03T23:48:48.531Z] [PID:89934] INFO: [Server] Registering server request handlers
|
|
63
|
+
[2025-04-03T23:48:48.531Z] [PID:89934] INFO: [Server] Registering tool handlers
|
|
64
|
+
{
|
|
65
|
+
"toolCount": 31,
|
|
66
|
+
"categories": [
|
|
67
|
+
"workspace",
|
|
68
|
+
"task",
|
|
69
|
+
"list",
|
|
70
|
+
"folder",
|
|
71
|
+
"tag"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
[2025-04-03T23:48:48.532Z] [PID:89934] INFO: Connecting to MCP stdio transport
|
|
75
|
+
[2025-04-03T23:48:48.532Z] [PID:89934] INFO: Server startup complete - ready to handle requests
|
|
76
|
+
[2025-04-03T23:48:49.141Z] [PID:89934] DEBUG: [Server] Received ListTools request
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|