Skip to main content
Glama
custom-field.tools.ts7 kB
import { Tool } from "@modelcontextprotocol/sdk/types.js"; import { GetCustomFieldsParams, ClickUpCustomField, SetTaskCustomFieldValueParams, RemoveTaskCustomFieldValueParams, } from "../types.js"; import { ClickUpService } from "../services/clickup.service.js"; import { logger } from "../logger.js"; // Tool Definitions export const getCustomFieldsTool: Tool = { name: "clickup_get_custom_fields", description: "Retrieves all accessible Custom Fields for a given List.", inputSchema: { type: "object", properties: { list_id: { type: "string", description: "The ID of the List to get Custom Fields from.", }, }, required: ["list_id"], }, outputSchema: { type: "object", properties: { fields: { type: "array", items: { type: "object", properties: { id: { type: "string" }, name: { type: "string" }, type: { type: "string" } } } } }, description: "An object containing an array of custom field objects in the 'fields' property.", }, }; export const setTaskCustomFieldValueTool: Tool = { name: "clickup_set_task_custom_field_value", description: "Sets the value of a Custom Field on a specific task.", inputSchema: { type: "object", properties: { task_id: { type: "string", description: "The ID of the task to update.", }, field_id: { type: "string", description: "The ID of the Custom Field to set.", }, value: { type: "string", description: 'The value to set for the Custom Field, provided as a string. Convert numbers, booleans, and array elements to their string representations. For arrays (e.g., for label fields), provide a JSON string array like \'["label1", "label2"]\'. For date fields, if \'value_options.time\' is true, provide a Unix timestamp in milliseconds as a string (e.g., "1672531200000"). If \'value_options.time\' is false or not provided for a date field, provide a date string like "YYYY-MM-DD". Consult the custom field\'s type to format the string appropriately.', }, value_options: { type: "object", description: 'Optional: Additional options for setting the value. For date custom fields, use { "time": true } to set a timestamp including time, or { "time": false } for a date-only value. Other custom field types might not use these options.', properties: { time: { type: "boolean", description: "For date custom fields: true to include time in the date value, false for date-only.", }, }, additionalProperties: false, }, }, required: ["task_id", "field_id", "value"], }, outputSchema: { type: "object", properties: { success: { type: "boolean" } }, description: "An object indicating whether the custom field value was set successfully.", }, }; export const removeTaskCustomFieldValueTool: Tool = { name: "clickup_remove_task_custom_field_value", description: "Removes the value of a Custom Field from a specific task.", inputSchema: { type: "object", properties: { task_id: { type: "string", description: "The ID of the task to update.", }, field_id: { type: "string", description: "The ID of the Custom Field to clear.", }, }, required: ["task_id", "field_id"], }, outputSchema: { type: "object", properties: { success: { type: "boolean" } }, description: "An object indicating whether the custom field value was removed successfully.", }, }; // Handler Functions export async function handleGetCustomFields( clickUpService: ClickUpService, args: Record<string, unknown>, ) { const params = args as unknown as GetCustomFieldsParams; if (!params.list_id || typeof params.list_id !== "string") { throw new Error("List ID is required."); } logger.info( `Handling tool call: ${getCustomFieldsTool.name} for list_id: ${params.list_id}`, ); try { const customFields: ClickUpCustomField[] = await clickUpService.customFieldService.getCustomFields(params.list_id); return { content: [ { type: "text", text: JSON.stringify(customFields, null, 2), }, ], structuredContent: { fields: customFields }, }; } catch (error) { logger.error(`Error in ${getCustomFieldsTool.name}:`, error); throw error instanceof Error ? error : new Error("Failed to get custom fields"); } } export async function handleSetTaskCustomFieldValue( clickUpService: ClickUpService, args: Record<string, unknown>, ) { const params = args as unknown as SetTaskCustomFieldValueParams; if (!params.task_id || typeof params.task_id !== "string") { throw new Error("Task ID is required."); } if (!params.field_id || typeof params.field_id !== "string") { throw new Error("Field ID is required."); } if (params.value === undefined) { // Explicitly check for undefined as null/false/0 might be valid values throw new Error("Value is required to set a custom field."); } logger.info( `Handling tool call: ${setTaskCustomFieldValueTool.name} for task_id: ${params.task_id}, field_id: ${params.field_id}`, ); try { await clickUpService.customFieldService.setTaskCustomFieldValue(params); return { content: [ { type: "text", text: `Successfully set custom field ${params.field_id} for task ${params.task_id}.`, }, ], structuredContent: { success: true }, }; } catch (error) { logger.error(`Error in ${setTaskCustomFieldValueTool.name}:`, error); throw error instanceof Error ? error : new Error("Failed to set task custom field value"); } } export async function handleRemoveTaskCustomFieldValue( clickUpService: ClickUpService, args: Record<string, unknown>, ) { const params = args as unknown as RemoveTaskCustomFieldValueParams; if (!params.task_id || typeof params.task_id !== "string") { throw new Error("Task ID is required."); } if (!params.field_id || typeof params.field_id !== "string") { throw new Error("Field ID is required."); } logger.info( `Handling tool call: ${removeTaskCustomFieldValueTool.name} for task_id: ${params.task_id}, field_id: ${params.field_id}`, ); try { await clickUpService.customFieldService.removeTaskCustomFieldValue(params); return { content: [ { type: "text", text: `Successfully removed custom field ${params.field_id} for task ${params.task_id}.`, }, ], structuredContent: { success: true }, }; } catch (error) { logger.error(`Error in ${removeTaskCustomFieldValueTool.name}:`, error); throw error instanceof Error ? error : new Error("Failed to remove task custom field value"); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nazruden/clickup-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server