Skip to main content
Glama
create-task.ts7.64 kB
/** * Create Task Tool * Create a new task in a project */ import { z } from 'zod'; import * as projectsApi from '../../api/projects.js'; import { formatError } from '../../utils/errors.js'; import { transformMembers } from '../../utils/member-transform.js'; const memberSchema = z.object({ id: z.string(), type: z.enum(['member', 'group', 'email']), }); const bodySchema = z.object({ mimeType: z.enum(['text/x-markdown', 'text/html']), content: z.string(), }); export const createTaskSchema = z.object({ projectId: z.string().describe('Project ID where the task will be created'), parentPostId: z.string().optional().describe('Parent task ID to create this as a subtask'), isDraft: z.boolean().optional().describe('Set to true to create a draft task (임시 업무) that can be continued in the browser. Default: false'), subject: z.string().describe('Task subject/title'), body: bodySchema.optional().describe('Task body content'), assignees: z.array(memberSchema).optional().describe('List of assignees'), cc: z.array(memberSchema).optional().describe('List of CC recipients'), dueDate: z.string().optional().describe('Due date (ISO 8601 format: YYYY-MM-DDTHH:mm:ssZ)'), milestoneId: z.string().optional().describe('Milestone ID'), tagIds: z.array(z.string()).optional().describe('Array of tag IDs'), priority: z.enum(['highest', 'high', 'normal', 'low', 'lowest', 'none']).optional().describe('Task priority level'), }); export type CreateTaskInput = z.infer<typeof createTaskSchema>; export async function createTaskHandler(args: CreateTaskInput) { try { const isDraft = args.isDraft || false; const apiParams = { projectId: args.projectId, parentPostId: args.parentPostId, subject: args.subject, body: args.body, users: { to: transformMembers(args.assignees), cc: transformMembers(args.cc), }, dueDate: args.dueDate, milestoneId: args.milestoneId, tagIds: args.tagIds, priority: args.priority, }; if (isDraft) { // Create draft task const result = await projectsApi.createDraftTask(apiParams); return { content: [ { type: 'text', text: JSON.stringify({ id: result.id, url: result.url, message: 'Draft task created successfully. Open the URL in your browser to continue editing.', }, null, 2), }, ], }; } else { // Create regular task const result = await projectsApi.createTask(apiParams); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } } catch (error) { return { content: [ { type: 'text', text: `Error: ${formatError(error)}`, }, ], isError: true, }; } } export const createTaskTool = { name: 'create-task', description: `Create a new task (업무) in a Dooray project. Required: projectId, subject. **DRAFT vs REGULAR**: ASK USER which type to create: - **Draft (isDraft: true)**: Returns URL to continue editing in browser. Use for complex tasks or when user wants to review. - **Regular (isDraft: false, default)**: Saves immediately. Use when all info is available. **INTERACTIVE WORKFLOW**: 1. **Templates**: Ask about get-project-template-list. If yes, use get-project-template for defaults. 2. **Content**: Get subject and body. If no template and no body, ask user for details. 3. **Assignees/CC**: Use get-my-member-info, get-project-member-list, or get-project-member-group-list. Format: {id, type: "member|group|email"} 4. **Tags**: Call get-tag-list. **CRITICAL**: Check mandatory tag groups - must select or creation fails (500 error). selectOne=true requires exactly ONE tag from group. **Key Points**: - Priority defaults to "none" - Set parentPostId for subtasks (하위업무) - Extract PROJECT_ID from URLs like "https://nhnent.dooray.com/task/PROJECT_ID" **Examples**: - Draft: {"projectId": "123", "subject": "Bug fix", "isDraft": true} - Regular: {"projectId": "123", "subject": "Deploy", "assignees": [{"id": "user1", "type": "member"}], "tagIds": ["tag1"], "priority": "high"} Returns: Task object (regular) or {id, url, message} (draft).`, inputSchema: { type: 'object', properties: { projectId: { type: 'string', description: 'Project ID where the task will be created', }, parentPostId: { type: 'string', description: 'Parent task ID to create this as a subtask (하위업무). Omit to create a regular task.', }, isDraft: { type: 'boolean', description: 'Set to true to create a draft task (임시 업무) that can be continued in the browser. Returns a URL for further editing. Default: false (creates regular task).', }, subject: { type: 'string', description: 'Task subject/title (required)', }, body: { type: 'object', properties: { mimeType: { type: 'string', enum: ['text/x-markdown', 'text/html'], description: 'Content format', }, content: { type: 'string', description: 'Task body content', }, }, required: ['mimeType', 'content'], description: 'Task body with formatted content. IMPORTANT: If user has not provided body content and no template is selected, ask the user for task details/description before creating the task.', }, assignees: { type: 'array', items: { type: 'object', properties: { id: { type: 'string' }, type: { type: 'string', enum: ['member', 'group', 'email'] }, }, required: ['id', 'type'], }, description: 'List of assignees (담당자). To get assignee options: (1) use get-my-member-info for current user, (2) use get-project-member-list for project members, (3) use get-project-member-group-list for member groups. Each assignee object has {id: string, type: "member"|"group"|"email"}.', }, cc: { type: 'array', items: { type: 'object', properties: { id: { type: 'string' }, type: { type: 'string', enum: ['member', 'group', 'email'] }, }, required: ['id', 'type'], }, description: 'List of CC recipients (참조). To get CC options: (1) use get-my-member-info for current user, (2) use get-project-member-list for project members, (3) use get-project-member-group-list for member groups. Each CC object has {id: string, type: "member"|"group"|"email"}.', }, dueDate: { type: 'string', description: 'Due date in ISO 8601 format (YYYY-MM-DDTHH:mm:ssZ)', }, milestoneId: { type: 'string', description: 'Milestone ID to associate with this task', }, tagIds: { type: 'array', items: { type: 'string' }, description: 'Array of tag IDs to apply to this task. IMPORTANT: Check for mandatory tag groups using get-tag-list tool. Projects may require specific tags from mandatory tag groups.', }, priority: { type: 'string', enum: ['highest', 'high', 'normal', 'low', 'lowest', 'none'], description: 'Task priority level (highest, high, normal, low, lowest, none). Default: "none" if not specified by user.', }, }, required: ['projectId', 'subject'], }, };

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/jhl8041/dooray-mcp'

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