mcp-clickup
Version:
A Model Context Protocol server for the ClickUp API.
195 lines (188 loc) • 5.2 kB
JavaScript
// 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);
});