jira_update_issue
Modify existing JIRA issues by updating fields, transitioning statuses, adding worklogs, or adjusting components and labels directly from your workflow.
Instructions
Updates an existing JIRA issue with field changes, status transitions, and worklog entries
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| assignee | No | ||
| components | No | ||
| description | No | ||
| issueKey | Yes | ||
| labels | No | ||
| notifyUsers | No | ||
| priority | No | ||
| summary | No | ||
| transition | No |
Implementation Reference
- The UpdateIssueHandler class provides the core execution logic for the 'jira_update_issue' tool, including parameter validation, mapping to use case request, execution delegation, response formatting, and comprehensive error handling.export class UpdateIssueHandler extends BaseToolHandler< UpdateIssueParams, string > { private readonly formatter: IssueUpdateFormatter; /** * Create a new UpdateIssueHandler with necessary dependencies * * @param updateIssueUseCase - Use case for updating issues with validation */ constructor(private readonly updateIssueUseCase: UpdateIssueUseCase) { super("JIRA", "Update Issue"); this.formatter = new IssueUpdateFormatter(); } /** * Execute the handler logic * Updates an existing JIRA issue with comprehensive validation and formatting * Delegates business logic to the use case * * @param params - Parameters for issue update */ protected async execute(params: UpdateIssueParams): Promise<string> { try { // Step 1: Validate parameters const validatedParams = this.validateParameters(params); this.logger.info(`Updating JIRA issue: ${validatedParams.issueKey}`); // Step 2: Map parameters to use case request const useCaseRequest: UpdateIssueUseCaseRequest = this.mapToUseCaseRequest(validatedParams); // Step 3: Execute the use case this.logger.debug("Delegating to UpdateIssueUseCase", { issueKey: validatedParams.issueKey, hasTransition: !!validatedParams.transition, hasFieldUpdates: Object.keys(useCaseRequest.fields || {}).length > 0, }); const updatedIssue = await this.updateIssueUseCase.execute(useCaseRequest); // Step 4: Format and return success response this.logger.info(`Successfully updated issue: ${updatedIssue.key}`); return this.formatter.format(updatedIssue); } catch (error) { this.logger.error(`Failed to update JIRA issue: ${error}`); throw this.enhanceError(error, params.issueKey); } } /** * Validate parameters using Zod schema */ private validateParameters(params: UpdateIssueParams): UpdateIssueParams { const result = updateIssueParamsSchema.safeParse(params); if (!result.success) { const errorMessage = `Invalid issue update parameters: ${formatZodError( result.error, )}`; throw new IssueUpdateParamsValidationError(errorMessage); } return result.data; } /** * Map handler parameters to use case request * Transforms update parameters into use case format with proper field mapping */ private mapToUseCaseRequest( params: UpdateIssueParams, ): UpdateIssueUseCaseRequest { const useCaseRequest: UpdateIssueUseCaseRequest = { issueKey: params.issueKey, notifyUsers: params.notifyUsers, }; // Map basic fields this.mapBasicFields(params, useCaseRequest); // Map transition this.mapTransition(params, useCaseRequest); // Map array operations (labels and components) this.mapArrayOperations(params, useCaseRequest); return useCaseRequest; } /** * Map basic issue fields (summary, description, priority, assignee) */ private mapBasicFields( params: UpdateIssueParams, useCaseRequest: UpdateIssueUseCaseRequest, ): void { if ( params.summary || params.description || params.priority || params.assignee ) { useCaseRequest.fields = {}; if (params.summary) { useCaseRequest.fields.summary = params.summary; } if (params.description) { // Convert description to ADF format const adfDescription = ensureADFFormat(params.description); if (adfDescription) { useCaseRequest.fields.description = adfDescription; } } if (params.priority) { useCaseRequest.fields.priority = { name: params.priority }; } if (params.assignee) { useCaseRequest.fields.assignee = { accountId: params.assignee }; } } } /** * Map transition information */ private mapTransition( params: UpdateIssueParams, useCaseRequest: UpdateIssueUseCaseRequest, ): void { if (params.transition) { useCaseRequest.transition = { id: params.transition.id, fields: params.transition.fields, }; } } /** * Map array operations for labels and components */ private mapArrayOperations( params: UpdateIssueParams, useCaseRequest: UpdateIssueUseCaseRequest, ): void { if (params.labels || params.components) { useCaseRequest.fields = useCaseRequest.fields || {}; this.mapLabelsOperation(params, useCaseRequest); this.mapComponentsOperation(params, useCaseRequest); } } /** * Map labels operation */ private mapLabelsOperation( params: UpdateIssueParams, useCaseRequest: UpdateIssueUseCaseRequest, ): void { if ( params.labels && params.labels.operation === "set" && useCaseRequest.fields ) { useCaseRequest.fields.labels = params.labels.values; } } /** * Map components operation */ private mapComponentsOperation( params: UpdateIssueParams, useCaseRequest: UpdateIssueUseCaseRequest, ): void { if ( params.components && params.components.operation === "set" && useCaseRequest.fields ) { useCaseRequest.fields.components = params.components.values.map( (name) => ({ name }), ); } } /** * Enhance error messages for better user guidance */ private enhanceError(error: unknown, issueKey?: string): Error { const issueContext = issueKey ? ` for issue '${issueKey}'` : ""; if (error instanceof JiraNotFoundError) { return new Error( `❌ **Issue Not Found**\n\nIssue '${issueKey}' was not found${issueContext}.\n\n**Solutions:**\n- Verify the issue key is correct (format: PROJECT-123)\n- Check if the issue exists in your JIRA instance\n- Ensure you have permission to view the issue\n\n**Example:** \`jira_update_issue issueKey=PROJ-123 summary="Updated summary"\``, ); } if (error instanceof JiraPermissionError) { return new Error( `❌ **Permission Denied**\n\nYou don't have permission to update issue '${issueKey}'.\n\n**Solutions:**\n- Check your JIRA permissions for this project\n- Contact your JIRA administrator\n- Verify you're assigned to the issue or have edit permissions\n\n**Required Permissions:** Edit Issues, Transition Issues (for status changes)`, ); } if (error instanceof JiraApiError) { return new Error( `❌ **JIRA API Error**\n\n${error.message}\n\n**Solutions:**\n- Check your field values are valid for this issue type\n- Verify required fields are provided for transitions\n- Ensure array operations reference existing values\n\n**Example:** \`jira_update_issue issueKey=PROJ-123 summary="New summary" priority=High\``, ); } if (error instanceof Error) { return new Error( `❌ **Update Failed**\n\n${error.message}\n\n**Solutions:**\n- Check your parameters are valid\n- Verify the issue exists and is accessible\n- Ensure you have the necessary permissions\n\n**Example:** \`jira_update_issue issueKey=PROJ-123 summary="Updated summary"\``, ); } return new Error( "❌ **Unknown Error**\n\nAn unknown error occurred during issue update.\n\nPlease check your parameters and try again.", ); } }
- Zod schema defining the input parameters for the jira_update_issue tool, including issueKey, fields like summary/description/priority/assignee, array operations for labels/components, transition, and notifyUsers.export const updateIssueParamsSchema = z.object({ issueKey: issueKeySchema, // Fields to update summary: z.string().min(1).max(255).optional(), description: z.string().max(32767).optional(), priority: z.enum(["Highest", "High", "Medium", "Low", "Lowest"]).optional(), assignee: z.string().min(1).max(255).optional(), // Array operations labels: z .object({ operation: z.enum(["set", "add", "remove"]), values: z.array(z.string().min(1).max(255)), }) .optional(), components: z .object({ operation: z.enum(["set", "add", "remove"]), values: z.array(z.string().min(1).max(255)), }) .optional(), // Transition transition: z .object({ id: z.string().min(1), fields: z.record(z.string(), z.unknown()).optional(), }) .optional(), // Notification settings notifyUsers: z.boolean().optional().default(true), });
- src/features/jira/tools/configs/issue-tools.config.ts:55-59 (registration)Tool configuration object that registers the 'jira_update_issue' tool with name, description, input schema, and handler binding.name: "jira_update_issue", description: "Updates an existing JIRA issue with field changes, status transitions, and worklog entries", params: updateIssueParamsSchema.shape, handler: tools.jira_update_issue.handle.bind(tools.jira_update_issue), },
- src/features/jira/tools/factories/tool.factory.ts:107-108 (registration)Factory function creates the tools.jira_update_issue object by instantiating UpdateIssueHandler and binding its handle method.jira_update_issue: { handle: async (args: unknown) => updateIssueHandler.handle(args),
- No, correction: actually in tool.registry.ts but match was approximate. Wait, search had registry line 71: jira_update_issue: tools.jira_update_issue,`❌ **Issue Not Found**\n\nIssue '${issueKey}' was not found${issueContext}.\n\n**Solutions:**\n- Verify the issue key is correct (format: PROJECT-123)\n- Check if the issue exists in your JIRA instance\n- Ensure you have permission to view the issue\n\n**Example:** \`jira_update_issue issueKey=PROJ-123 summary="Updated summary"\``, ); } if (error instanceof JiraPermissionError) { return new Error( `❌ **Permission Denied**\n\nYou don't have permission to update issue '${issueKey}'.\n\n**Solutions:**\n- Check your JIRA permissions for this project\n- Contact your JIRA administrator\n- Verify you're assigned to the issue or have edit permissions\n\n**Required Permissions:** Edit Issues, Transition Issues (for status changes)`, ); } if (error instanceof JiraApiError) { return new Error( `❌ **JIRA API Error**\n\n${error.message}\n\n**Solutions:**\n- Check your field values are valid for this issue type\n- Verify required fields are provided for transitions\n- Ensure array operations reference existing values\n\n**Example:** \`jira_update_issue issueKey=PROJ-123 summary="New summary" priority=High\``, ); } if (error instanceof Error) { return new Error( `❌ **Update Failed**\n\n${error.message}\n\n**Solutions:**\n- Check your parameters are valid\n- Verify the issue exists and is accessible\n- Ensure you have the necessary permissions\n\n**Example:** \`jira_update_issue issueKey=PROJ-123 summary="Updated summary"\``, ); } return new Error( "❌ **Unknown Error**\n\nAn unknown error occurred during issue update.\n\nPlease check your parameters and try again.", ); } }