todoist_comment_get
Retrieve comments for Todoist tasks or projects to track discussions and feedback.
Instructions
Get comments for a task or project in Todoist
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| task_id | No | ID of the task to get comments for (optional) | |
| task_name | No | Name/content of the task to get comments for (optional) | |
| project_id | No | ID of the project to get comments for (optional) |
Implementation Reference
- src/handlers/comment-handlers.ts:83-179 (handler)The core handler function `handleGetComments` that implements the `todoist_comment_get` tool logic. It retrieves comments for a task (by ID or name) or project using the Todoist API, employs caching via SimpleCache, handles task lookup by name, formats output, and uses error handling.export async function handleGetComments( todoistClient: TodoistApi, args: GetCommentsArgs ): Promise<string> { return ErrorHandler.wrapAsync("get comments", async () => { let comments: TodoistComment[] = []; if (args.task_id) { // Get comments for specific task const cacheKey = createCacheKey("comments", { task_id: args.task_id }); const cached = commentCache.get(cacheKey); if (cached) { comments = cached; } else { const result = await todoistClient.getComments({ taskId: args.task_id, }); comments = extractArrayFromResponse<TodoistComment>(result); commentCache.set(cacheKey, comments); } } else if (args.task_name) { // Search for task by name, then get comments const taskResult = await todoistClient.getTasks(); const tasks = extractArrayFromResponse<TodoistTask>(taskResult); const matchingTask = tasks.find((task: TodoistTask) => task.content.toLowerCase().includes(args.task_name!.toLowerCase()) ); if (!matchingTask) { ErrorHandler.handleTaskNotFound(args.task_name!); } const cacheKey = createCacheKey("comments", { task_id: matchingTask!.id, }); const cached = commentCache.get(cacheKey); if (cached) { comments = cached; } else { const result = await todoistClient.getComments({ taskId: matchingTask.id, }); comments = extractArrayFromResponse<TodoistComment>(result); commentCache.set(cacheKey, comments); } } else if (args.project_id) { // Get comments for specific project const cacheKey = createCacheKey("comments", { project_id: args.project_id, }); const cached = commentCache.get(cacheKey); if (cached) { comments = cached; } else { const result = await todoistClient.getComments({ projectId: args.project_id, }); comments = extractArrayFromResponse<TodoistComment>(result); commentCache.set(cacheKey, comments); } } else { // Get all comments (this might not be supported by all Todoist API versions) const cacheKey = createCacheKey("comments", { scope: "all" }); const cached = commentCache.get(cacheKey); if (cached) { comments = cached; } else { // Getting all comments might not be supported, so we return empty comments = []; commentCache.set(cacheKey, comments); } } if (comments.length === 0) { return "No comments found."; } const commentList = comments .map((comment) => { // Use defensive typing for comment properties const commentData = comment as CommentResponse; return `- ${commentData.content}${ commentData.attachment ? `\n Attachment: ${commentData.attachment.fileName} (${commentData.attachment.fileType})` : "" }\n Posted: ${commentData.postedAt || "Unknown"}${ commentData.taskId ? `\n Task ID: ${commentData.taskId}` : "" }${commentData.projectId ? `\n Project ID: ${commentData.projectId}` : ""}`; }) .join("\n\n"); return `Found ${comments.length} comment${comments.length > 1 ? "s" : ""}:\n\n${commentList}`; }); }
- src/tools/comment-tools.ts:47-67 (schema)Tool schema definition for `todoist_comment_get`, including name, description, and inputSchema specifying optional task_id, task_name, or project_id.export const GET_COMMENTS_TOOL: Tool = { name: "todoist_comment_get", description: "Get comments for a task or project in Todoist", inputSchema: { type: "object", properties: { task_id: { type: "string", description: "ID of the task to get comments for (optional)", }, task_name: { type: "string", description: "Name/content of the task to get comments for (optional)", }, project_id: { type: "string", description: "ID of the project to get comments for (optional)", }, }, }, };
- src/index.ts:247-252 (registration)Dispatch registration in main server switch statement: maps tool name to `handleGetComments` handler with argument validation via `isGetCommentsArgs`.case "todoist_comment_get": if (!isGetCommentsArgs(args)) { throw new Error("Invalid arguments for todoist_comment_get"); } result = await handleGetComments(apiClient, args); break;
- src/tools/index.ts:4-69 (registration)Tool registration in ALL_TOOLS array, which includes COMMENT_TOOLS containing `todoist_comment_get`, used for listing available tools in MCP server.import { PROJECT_TOOLS } from "./project-tools.js"; import { COMMENT_TOOLS } from "./comment-tools.js"; import { LABEL_TOOLS } from "./label-tools.js"; import { TEST_TOOLS } from "./test-tools.js"; // Export individual tool categories export { TASK_TOOLS } from "./task-tools.js"; export { SUBTASK_TOOLS } from "./subtask-tools.js"; export { PROJECT_TOOLS } from "./project-tools.js"; export { COMMENT_TOOLS } from "./comment-tools.js"; export { LABEL_TOOLS } from "./label-tools.js"; export { TEST_TOOLS } from "./test-tools.js"; // Export individual tools for backwards compatibility export { CREATE_TASK_TOOL, GET_TASKS_TOOL, UPDATE_TASK_TOOL, DELETE_TASK_TOOL, COMPLETE_TASK_TOOL, BULK_CREATE_TASKS_TOOL, BULK_UPDATE_TASKS_TOOL, BULK_DELETE_TASKS_TOOL, BULK_COMPLETE_TASKS_TOOL, } from "./task-tools.js"; export { CREATE_SUBTASK_TOOL, BULK_CREATE_SUBTASKS_TOOL, CONVERT_TO_SUBTASK_TOOL, PROMOTE_SUBTASK_TOOL, GET_TASK_HIERARCHY_TOOL, } from "./subtask-tools.js"; export { GET_PROJECTS_TOOL, GET_SECTIONS_TOOL, CREATE_PROJECT_TOOL, CREATE_SECTION_TOOL, } from "./project-tools.js"; export { CREATE_COMMENT_TOOL, GET_COMMENTS_TOOL } from "./comment-tools.js"; export { GET_LABELS_TOOL, CREATE_LABEL_TOOL, UPDATE_LABEL_TOOL, DELETE_LABEL_TOOL, GET_LABEL_STATS_TOOL, } from "./label-tools.js"; export { TEST_CONNECTION_TOOL, TEST_ALL_FEATURES_TOOL, TEST_PERFORMANCE_TOOL, } from "./test-tools.js"; // Combined array of all tools in the same order as the original export const ALL_TOOLS = [ ...TASK_TOOLS, ...PROJECT_TOOLS, ...COMMENT_TOOLS, ...LABEL_TOOLS, ...SUBTASK_TOOLS, ...TEST_TOOLS, ];
- src/type-guards.ts:212-221 (schema)Type guard `isGetCommentsArgs` for input validation of `todoist_comment_get` arguments, ensuring task_id, task_name, project_id are optional strings.export function isGetCommentsArgs(args: unknown): args is GetCommentsArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.task_id === undefined || typeof obj.task_id === "string") && (obj.task_name === undefined || typeof obj.task_name === "string") && (obj.project_id === undefined || typeof obj.project_id === "string") ); }