UNPKG

mcp-clickup

Version:

A Model Context Protocol server for the ClickUp API.

195 lines (188 loc) 5.2 kB
#!/usr/bin/env node // src/index.ts import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; // src/common/tool.ts import dottenv from "dotenv"; // src/utils/defineTool.ts import { z } from "zod"; var defineTool = (cb) => { const tool = cb(z); const wrappedHandler = async (input, _) => { try { const result = await tool.handler(input); return { content: [ { type: "text", text: JSON.stringify(result, null, 2) } ] }; } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } }; return { ...tool, handler: wrappedHandler }; }; // src/common/clickup.ts var BASE_URL = "https://api.clickup.com/api/v2"; var ClickUpClient = class { headers; workspaceId; constructor(apiToken2, workspaceId2) { this.headers = { Authorization: apiToken2, "Content-Type": "application/json" }; this.workspaceId = workspaceId2; } async request(endpoint, options = {}) { const response = await fetch(`${BASE_URL}${endpoint}`, { ...options, headers: this.headers }); return response.json(); } async authenticate() { return this.request("/user"); } async getTask(taskId) { return this.request( `/task/${taskId}?custom_task_ids=false&team_id=${this.workspaceId}&include_subtasks=true&include_markdown_description=true` ); } async getTaskByCustomId(customId) { return this.request( `/task/${customId}?custom_task_ids=true&team_id=${this.workspaceId}&include_subtasks=true&include_markdown_description=true` ); } async getTasks(taskIds) { const tasksUrl = `/team/${this.workspaceId}/task?include_markdown_description=true&include_subtasks=true&${taskIds.map((id) => `task_ids=${id}`).join("&")}`; return this.request(tasksUrl); } }; var clickup_default = ClickUpClient; // src/common/tool.ts dottenv.config(); var apiToken = process.env.CLICKUP_API_TOKEN; var workspaceId = process.env.CLICKUP_WORKSPACE_ID; if (!apiToken || !workspaceId) { console.error( "Please set CLICKUP_API_TOKEN and CLICKUP_WORKSPACE_ID environment variables" ); process.exit(1); } var clickUpClient = new clickup_default(apiToken, workspaceId); var authenticateTool = defineTool((z2) => ({ name: "clickup_authenticate", description: "Authenticate with ClickUp API using an API token and workspace ID", inputSchema: { type: z2.object({}) }, handler: async (input) => { const response = await clickUpClient.authenticate(); return { content: [{ type: "text", text: JSON.stringify(response) }] }; } })); var getTaskTool = defineTool((z2) => ({ name: "clickup_get_task", description: "Get a task by its ID", inputSchema: { type: z2.object({ task_id: z2.string() }) }, handler: async (input) => { const { task_id } = input; const response = await clickUpClient.getTask(task_id); return { content: [{ type: "text", text: JSON.stringify(response) }] }; } })); var getTaskByCustomIdTool = defineTool((z2) => ({ name: "clickup_get_task_by_custom_id", description: "Get a task by its custom ID", inputSchema: { type: z2.object({ custom_id: z2.string() }) }, handler: async (input) => { const { custom_id } = input; const response = await clickUpClient.getTaskByCustomId(custom_id); return { content: [{ type: "text", text: JSON.stringify(response) }] }; } })); var getTasksTool = defineTool((z2) => ({ name: "clickup_get_tasks", description: "Get multiple tasks by their IDs", inputSchema: { type: z2.object({ task_ids: z2.array(z2.string()) }) }, handler: async (input) => { const { task_ids } = input; const response = await clickUpClient.getTasks(task_ids); return { content: [{ type: "text", text: JSON.stringify(response) }] }; } })); // src/index.ts var tools = [ authenticateTool, getTaskByCustomIdTool, getTasksTool, getTaskTool ]; async function main() { console.error("Starting ClickUp MCP Server..."); const apiToken2 = process.env.CLICKUP_API_TOKEN; const workspaceId2 = process.env.CLICKUP_WORKSPACE_ID; if (!apiToken2 || !workspaceId2) { console.error( "Please set CLICKUP_API_TOKEN and CLICKUP_WORKSPACE_ID environment variables" ); process.exit(1); } const server = new McpServer( { name: "ClickUp MCP Server", version: "1.0.0" }, { capabilities: { tools: {} } } ); tools.forEach((tool) => { server.tool(tool.name, tool.description, tool.inputSchema, tool.handler); }); const transport = new StdioServerTransport(); console.error("Connecting server to transport..."); await server.connect(transport); console.error("ClickUp MCP Server running on stdio"); } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });