@taazkareem/clickup-mcp-server
Version:
ClickUp MCP Server - Integrate ClickUp tasks with AI through Model Context Protocol
105 lines (104 loc) • 4.37 kB
JavaScript
/**
* SPDX-FileCopyrightText: © 2025 Talib Kareem <taazkareem@icloud.com>
* SPDX-License-Identifier: MIT
*
* ClickUp Task Service - Comments Module
*
* Handles comment operations for ClickUp tasks, including:
* - Retrieving comments for a task
* - Creating comments on a task
*/
import { TaskServiceAttachments } from './task-attachments.js';
/**
* Comments functionality for the TaskService
*/
export class TaskServiceComments extends TaskServiceAttachments {
/**
* Get all comments for a task
*
* @param taskId ID of the task to get comments for
* @param start Optional pagination start
* @param startId Optional comment ID to start from
* @returns Array of task comments
*/
async getTaskComments(taskId, start, startId) {
this.logOperation('getTaskComments', { taskId, start, startId });
try {
// Build query parameters for pagination
const queryParams = new URLSearchParams();
if (start !== undefined) {
queryParams.append('start', start.toString());
}
if (startId) {
queryParams.append('start_id', startId);
}
const queryString = queryParams.toString() ? `?${queryParams.toString()}` : '';
const response = await this.client.get(`/task/${taskId}/comment${queryString}`);
return response.data.comments || [];
}
catch (error) {
throw this.handleError(error, 'Failed to get task comments');
}
}
/**
* Create a comment on a task
*
* @param taskId ID of the task to comment on
* @param commentText Text content of the comment
* @param notifyAll Whether to notify all assignees
* @param assignee Optional user ID to assign the comment to
* @returns The created comment
*/
async createTaskComment(taskId, commentText, notifyAll = false, assignee) {
this.logOperation('createTaskComment', { taskId, commentText, notifyAll, assignee });
try {
const payload = {
comment_text: commentText,
notify_all: notifyAll
};
if (assignee) {
payload.assignee = assignee;
}
// Make the request directly without using makeRequest for better error handling
const response = await this.client.post(`/task/${taskId}/comment`, payload);
// Handle different response formats from ClickUp API
if (response.data) {
if (response.data.comment) {
// Standard format: { comment: ClickUpComment }
return response.data.comment;
}
else if (response.data.id && (response.data.comment_text || response.data.comment)) {
// Direct format: the comment object itself
return response.data;
}
else {
// Fallback: construct a minimal valid comment object
return {
id: response.data.id || `custom-${Date.now()}`,
comment: response.data.comment || commentText,
comment_text: response.data.comment_text || commentText,
user: response.data.user || { id: 0, username: 'Unknown', email: '', color: '' },
date: response.data.date || new Date().toISOString(),
resolved: false
};
}
}
throw new Error('Invalid response from ClickUp API');
}
catch (error) {
// Check if comment might have been created despite error
if (error.response?.status === 200 || error.response?.status === 201) {
// Try to construct a comment object from what we know
return {
id: `fallback-${Date.now()}`,
comment: commentText,
comment_text: commentText,
user: { id: 0, username: 'Unknown', email: '', color: '' },
date: new Date().toISOString(),
resolved: false
};
}
throw this.handleError(error, 'Failed to create task comment');
}
}
}