Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { findProjectTool } from "./tools/projects";
import { getCurrentUserTool } from "./tools/users";
import { findWorkspacesTool } from "./tools/workspaces";
import { createTagTool, getTagsTool } from "./tools/tags";
import { listTasksTool } from "./tools/tasks";
import { createTaskTool, listTasksTool } from "./tools/tasks";
import { z } from "zod";
import { argv } from "process";

Expand Down Expand Up @@ -96,6 +96,13 @@ export default function createStatelessServer({
listTasksTool.parameters,
listTasksTool.handler
);

server.tool(
createTaskTool.name,
createTaskTool.description,
createTaskTool.parameters,
createTaskTool.handler
);
return server.server;
}

Expand Down
66 changes: 66 additions & 0 deletions src/tools/tasks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,73 @@
import { api } from "../config/api";
import { fetchAllPages } from "../config/pagination";
import { z } from "zod";
import { McpResponse, McpToolConfig } from "../types";

export const createTaskTool: McpToolConfig = {
name: "create-task",
description:
"Create a new task (activity) within a project. The created task can be associated with time entries.",
parameters: {
workspaceId: z
.string()
.describe("The ID of the workspace that contains the project"),
projectId: z
.string()
.describe("The ID of the project to create the task in"),
name: z.string().describe("The name of the task to create"),
assigneeIds: z
.array(z.string())
.optional()
.describe("Optional array of user IDs to assign to the task"),
status: z
.enum(["ACTIVE", "DONE"])
.optional()
.describe("Optional status of the task (defaults to ACTIVE)"),
},
handler: async ({
workspaceId,
projectId,
name,
assigneeIds,
status,
}: {
workspaceId: string;
projectId: string;
name: string;
assigneeIds?: string[];
status?: "ACTIVE" | "DONE";
}): Promise<McpResponse> => {
if (!workspaceId || typeof workspaceId !== "string") {
throw new Error("Workspace ID required to create a task");
}
if (!projectId || typeof projectId !== "string") {
throw new Error("Project ID required to create a task");
}
if (!name || typeof name !== "string") {
throw new Error("Task name required to create a task");
}

const response = await api.post(
`workspaces/${workspaceId}/projects/${projectId}/tasks`,
{
name,
...(assigneeIds ? { assigneeIds } : {}),
...(status ? { status } : {}),
}
);

const task = response.data;
return {
content: [
{
type: "text",
text: `Task created successfully. ID: ${task.id} Name: ${task.name} Status: ${task.status}`,
},
],
};
},
};

export const listTasksTool: McpToolConfig = {
name: "list-tasks",
description: "List tasks (activities) within a project. Tasks can be associated with time entries.",
Expand Down