add_issue
Create a new issue in a Backlog project by specifying summary, type, priority, and optional details like dates, assignee, and custom fields.
Instructions
Creates a new issue in the specified project.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectId | Yes | Project ID | |
| summary | Yes | Summary of the issue | |
| issueTypeId | Yes | Issue type ID | |
| priorityId | Yes | Priority ID | |
| description | No | Creates a new issue in the specified project. | |
| startDate | No | Scheduled start date (yyyy-MM-dd) | |
| dueDate | No | Scheduled due date (yyyy-MM-dd) | |
| estimatedHours | No | Estimated work hours | |
| actualHours | No | Actual work hours | |
| categoryId | No | Category IDs | |
| versionId | No | Version IDs | |
| milestoneId | No | Milestone IDs | |
| assigneeId | No | User ID of the assignee | |
| notifiedUserId | No | User IDs to notify | |
| attachmentId | No | Attachment IDs | |
| parentIssueId | No | Parent issue ID | |
| customFields | No | List of custom fields to set on the issue | |
| organization | No | Optional organization name. Use list_organizations to inspect available organizations. |
Implementation Reference
- src/tools/addIssue.ts:108-135 (handler)Main handler for the 'add_issue' tool. Creates a new issue by calling backlog.postIssue() with the provided parameters and custom fields.
export const addIssueTool = ( backlog: Backlog, { t }: TranslationHelper ): ToolDefinition< ReturnType<typeof addIssueSchema>, (typeof IssueSchema)['shape'] > => { return { name: 'add_issue', description: t( 'TOOL_ADD_ISSUE_DESCRIPTION', 'Creates a new issue in the specified project.' ), schema: z.object(addIssueSchema(t)), outputSchema: IssueSchema, importantFields: ['summary', 'issueKey', 'description', 'createdUser'], handler: async ({ customFields, ...params }) => { const customFieldPayload = customFieldsToPayload(customFields); const finalPayload = { ...params, ...customFieldPayload, }; return backlog.postIssue(finalPayload); }, }; }; - src/tools/addIssue.ts:8-106 (schema)Input schema definition for the 'add_issue' tool, defining all parameters: projectId, summary, issueTypeId, priorityId, description, startDate, dueDate, estimatedHours, actualHours, categoryId, versionId, milestoneId, assigneeId, notifiedUserId, attachmentId, parentIssueId, and customFields.
const addIssueSchema = buildToolSchema((t) => ({ projectId: z.number().describe(t('TOOL_ADD_ISSUE_PROJECT_ID', 'Project ID')), summary: z .string() .describe(t('TOOL_ADD_ISSUE_SUMMARY', 'Summary of the issue')), issueTypeId: z .number() .describe(t('TOOL_ADD_ISSUE_ISSUE_TYPE_ID', 'Issue type ID')), priorityId: z .number() .describe(t('TOOL_ADD_ISSUE_PRIORITY_ID', 'Priority ID')), description: z .string() .optional() .describe( t('TOOL_ADD_ISSUE_DESCRIPTION', 'Detailed description of the issue') ), startDate: z .string() .optional() .describe( t('TOOL_ADD_ISSUE_START_DATE', 'Scheduled start date (yyyy-MM-dd)') ), dueDate: z .string() .optional() .describe(t('TOOL_ADD_ISSUE_DUE_DATE', 'Scheduled due date (yyyy-MM-dd)')), estimatedHours: z .number() .optional() .describe(t('TOOL_ADD_ISSUE_ESTIMATED_HOURS', 'Estimated work hours')), actualHours: z .number() .optional() .describe(t('TOOL_ADD_ISSUE_ACTUAL_HOURS', 'Actual work hours')), categoryId: z .array(z.number()) .optional() .describe(t('TOOL_ADD_ISSUE_CATEGORY_ID', 'Category IDs')), versionId: z .array(z.number()) .optional() .describe(t('TOOL_ADD_ISSUE_VERSION_ID', 'Version IDs')), milestoneId: z .array(z.number()) .optional() .describe(t('TOOL_ADD_ISSUE_MILESTONE_ID', 'Milestone IDs')), assigneeId: z .number() .optional() .describe(t('TOOL_ADD_ISSUE_ASSIGNEE_ID', 'User ID of the assignee')), notifiedUserId: z .array(z.number()) .optional() .describe(t('TOOL_ADD_ISSUE_NOTIFIED_USER_ID', 'User IDs to notify')), attachmentId: z .array(z.number()) .optional() .describe(t('TOOL_ADD_ISSUE_ATTACHMENT_ID', 'Attachment IDs')), parentIssueId: z .number() .optional() .describe(t('TOOL_ADD_ISSUE_PARENT_ISSUE_ID', 'Parent issue ID')), customFields: z .array( z.object({ id: z .number() .describe( t( 'TOOL_ADD_ISSUE_CUSTOM_FIELD_ID', 'The ID of the custom field (e.g., 12345)' ) ), value: z .union([z.number(), z.array(z.number())]) .optional() .describe( 'The ID(s) of the custom field item. For single-select fields, provide a number. For multi-select fields, provide an array of numbers representing the selected item IDs.' ), otherValue: z .string() .optional() .describe( t( 'TOOL_ADD_ISSUE_CUSTOM_FIELD_OTHER_VALUE', 'Other value for list type fields' ) ), }) ) .optional() .describe( t( 'TOOL_ADD_ISSUE_CUSTOM_FIELDS', 'List of custom fields to set on the issue' ) ), })); - Output schema (IssueSchema) defining the shape of the response when an issue is created.
export const IssueSchema = z.object({ id: z.number(), projectId: z.number(), issueKey: z.string(), keyId: z.number(), issueType: IssueTypeSchema, summary: z.string(), description: z.string(), resolution: ResolutionSchema.optional(), priority: PrioritySchema, status: ProjectStatusSchema, assignee: UserSchema.optional(), category: z.array(CategorySchema), versions: z.array(VersionSchema), milestone: z.array(VersionSchema), startDate: z.string().optional(), dueDate: z.string().optional(), estimatedHours: z.number().optional(), actualHours: z.number().optional(), parentIssueId: z.number().optional(), createdUser: UserSchema, created: z.string(), updatedUser: UserSchema, updated: z.string(), customFields: z.array(CustomFieldSchema), attachments: z.array(IssueFileInfoSchema), sharedFiles: z.array(SharedFileSchema), stars: z.array(StarSchema), }); - src/tools/tools.ts:4-103 (registration)Registration of the add_issue tool: imported from './addIssue.js' and added to the 'issue' toolset at line 103.
import { addIssueTool } from './addIssue.js'; import { addIssueCommentTool } from './addIssueComment.js'; import { addProjectTool } from './addProject.js'; import { addPullRequestTool } from './addPullRequest.js'; import { addPullRequestCommentTool } from './addPullRequestComment.js'; import { addWikiTool } from './addWiki.js'; import { updateWikiTool } from './updateWiki.js'; import { countIssuesTool } from './countIssues.js'; import { deleteIssueTool } from './deleteIssue.js'; import { deleteProjectTool } from './deleteProject.js'; import { getCategoriesTool } from './getCategories.js'; import { getCustomFieldsTool } from './getCustomFields.js'; import { getGitRepositoriesTool } from './getGitRepositories.js'; import { getGitRepositoryTool } from './getGitRepository.js'; import { getIssueTool } from './getIssue.js'; import { getIssueCommentsTool } from './getIssueComments.js'; import { getIssuesTool } from './getIssues.js'; import { getIssueTypesTool } from './getIssueTypes.js'; import { getMyselfTool } from './getMyself.js'; import { getNotificationsTool } from './getNotifications.js'; import { getNotificationsCountTool } from './getNotificationsCount.js'; import { getPrioritiesTool } from './getPriorities.js'; import { getProjectTool } from './getProject.js'; import { getProjectListTool } from './getProjectList.js'; import { getPullRequestTool } from './getPullRequest.js'; import { getPullRequestCommentsTool } from './getPullRequestComments.js'; import { getPullRequestsTool } from './getPullRequests.js'; import { getPullRequestsCountTool } from './getPullRequestsCount.js'; import { getResolutionsTool } from './getResolutions.js'; import { getSpaceTool } from './getSpace.js'; import { getSpaceActivitiesTool } from './getSpaceActivities.js'; import { getUserStarsCountTool } from './getUserStarsCount.js'; import { getUsersTool } from './getUsers.js'; import { getUserRecentUpdatesTool } from './getUserRecentUpdates.js'; import { getWatchingListCountTool } from './getWatchingListCount.js'; import { getWatchingListItemsTool } from './getWatchingListItems.js'; import { addWatchingTool } from './addWatching.js'; import { updateWatchingTool } from './updateWatching.js'; import { deleteWatchingTool } from './deleteWatching.js'; import { markWatchingAsReadTool } from './markWatchingAsRead.js'; import { getWikiTool } from './getWiki.js'; import { getWikiPagesTool } from './getWikiPages.js'; import { getWikisCountTool } from './getWikisCount.js'; import { markNotificationAsReadTool } from './markNotificationAsRead.js'; import { resetUnreadNotificationCountTool } from './resetUnreadNotificationCount.js'; import { updateIssueTool } from './updateIssue.js'; import { updateProjectTool } from './updateProject.js'; import { updatePullRequestTool } from './updatePullRequest.js'; import { updatePullRequestCommentTool } from './updatePullRequestComment.js'; import { getDocumentTool } from './getDocument.js'; import { getDocumentsTool } from './getDocuments.js'; import { getDocumentTreeTool } from './getDocumentTree.js'; import { getVersionMilestoneListTool } from './getVersionMilestoneList.js'; import { addVersionMilestoneTool } from './addVersionMilestone.js'; import { updateVersionMilestoneTool } from './updateVersionMilestone.js'; import { deleteVersionTool } from './deleteVersion.js'; import { addDocumentTool } from './addDocument.js'; export const allTools = ( backlog: Backlog, helper: TranslationHelper ): ToolsetGroup => { return { toolsets: [ { name: 'space', description: 'Tools for managing Backlog space settings and general information.', enabled: false, tools: [ getSpaceTool(backlog, helper), getSpaceActivitiesTool(backlog, helper), getUsersTool(backlog, helper), getUserStarsCountTool(backlog, helper), getMyselfTool(backlog, helper), getUserRecentUpdatesTool(backlog, helper), ], }, { name: 'project', description: 'Tools for managing projects, categories, custom fields, and issue types.', enabled: false, tools: [ getProjectListTool(backlog, helper), addProjectTool(backlog, helper), getProjectTool(backlog, helper), updateProjectTool(backlog, helper), deleteProjectTool(backlog, helper), ], }, { name: 'issue', description: 'Tools for managing issues and their comments.', enabled: false, tools: [ getIssueTool(backlog, helper), getIssuesTool(backlog, helper), countIssuesTool(backlog, helper), addIssueTool(backlog, helper), - src/backlog/customFields.ts:34-55 (helper)Helper function customFieldsToPayload() used by the handler to convert custom field arrays into the proper payload format before posting.
export function customFieldsToPayload( customFields: CustomFieldInput[] | undefined ): Record<string, string | number | string[] | number[] | undefined> { if (customFields == null) { return {}; } const result: Record< string, string | number | string[] | number[] | undefined > = {}; for (const field of customFields) { if (field.value !== undefined) { result[`customField_${field.id}`] = field.value; } if (field.otherValue !== undefined) { result[`customField_${field.id}_otherValue`] = field.otherValue; } } return result; }