update_issue_field
Modify custom fields on Jira issues to track decisions, progress, risks, completion percentages, and health status for project management.
Instructions
Update a custom field on a Jira issue. Supported fields: Decision Needed, Progress Update, Decision Maker(s), Risks/Blockers, Completion Percentage, Health Status. You can use either the field name or field ID.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| issueKey | Yes | The issue key (e.g., "TSSE-984") | |
| fieldNameOrId | Yes | Field name or ID. Valid names: Decision Needed, Progress Update, Decision Maker(s), Risks/Blockers, Completion Percentage, Health Status | |
| value | Yes | The value to set. For rich text fields, provide plain text. For select fields, provide the option value. For user fields, provide accountId. For number fields, provide a number. |
Implementation Reference
- src/jira-client.ts:758-810 (handler)Core handler function that resolves custom field ID, formats value according to field type (rich text as ADF, number with special handling, select/user objects), performs PUT request to update Jira issue field, and returns success with field details.export async function updateIssueField( issueKey: string, fieldNameOrId: string, value: unknown ): Promise<{ success: boolean; fieldId: string; fieldName: string }> { const fieldId = resolveFieldId(fieldNameOrId); const fieldName = CUSTOM_FIELD_MAP[fieldId] || fieldId; const fieldType = CUSTOM_FIELD_TYPES[fieldId]; let formattedValue: unknown; switch (fieldType) { case 'richtext': // If value is already an ADF object, use it; otherwise create one from text if (typeof value === 'object' && value !== null && 'type' in value) { formattedValue = value; } else { formattedValue = createADFDocument(String(value)); } break; case 'number': formattedValue = typeof value === 'number' ? value : parseFloat(String(value)); if (isNaN(formattedValue as number)) { throw new Error(`Invalid number value for ${fieldName}: ${value}`); } // Special handling for Completion Percentage: convert percentage (0-100) to decimal (0.0-1.0) if (fieldId === 'customfield_15116') { formattedValue = (formattedValue as number) / 100; } break; case 'select': // Select fields need to be set with { value: "option" } format formattedValue = typeof value === 'object' ? value : { value: String(value) }; break; case 'user': // User picker fields need accountId formattedValue = typeof value === 'object' ? value : { accountId: String(value) }; break; default: formattedValue = value; } await jiraFetch<void>(`/issue/${issueKey}`, { method: 'PUT', body: JSON.stringify({ fields: { [fieldId]: formattedValue, }, }), }); return { success: true, fieldId, fieldName }; }
- src/index.ts:467-514 (registration)MCP tool registration for 'update_issue_field', including title, description, input/output schemas using Zod, and wrapper async handler that validates inputs, calls the core updateIssueField, handles errors with formatError, and returns structured MCP response.server.registerTool( 'update_issue_field', { title: 'Update Issue Field', description: `Update a custom field on a Jira issue. Supported fields: ${Object.values(CUSTOM_FIELD_MAP).join(', ')}. You can use either the field name or field ID.`, inputSchema: { issueKey: z.string().describe('The issue key (e.g., "TSSE-984")'), fieldNameOrId: z.string().describe(`Field name or ID. Valid names: ${Object.values(CUSTOM_FIELD_MAP).join(', ')}`), value: z.union([z.string(), z.number(), z.object({})]).describe('The value to set. For rich text fields, provide plain text. For select fields, provide the option value. For user fields, provide accountId. For number fields, provide a number.'), }, outputSchema: { success: z.boolean(), fieldId: z.string().optional(), fieldName: z.string().optional(), error: z.object({ message: z.string(), statusCode: z.number().optional(), details: z.unknown().optional(), }).optional(), }, }, async ({ issueKey, fieldNameOrId, value }) => { try { if (!issueKey || !issueKey.trim()) { throw new Error('issueKey is required'); } if (!fieldNameOrId || !fieldNameOrId.trim()) { throw new Error('fieldNameOrId is required'); } if (value === undefined || value === null) { throw new Error('value is required'); } const result = await updateIssueField(issueKey, fieldNameOrId, value); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], structuredContent: result, }; } catch (error) { const output = { success: false, ...formatError(error) }; return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }], structuredContent: output, isError: true, }; } } );
- src/index.ts:469-486 (schema)Input and output schema definitions for the update_issue_field tool using Zod validation, specifying parameters issueKey, fieldNameOrId, value and response format with success, fieldId, fieldName, or error.{ title: 'Update Issue Field', description: `Update a custom field on a Jira issue. Supported fields: ${Object.values(CUSTOM_FIELD_MAP).join(', ')}. You can use either the field name or field ID.`, inputSchema: { issueKey: z.string().describe('The issue key (e.g., "TSSE-984")'), fieldNameOrId: z.string().describe(`Field name or ID. Valid names: ${Object.values(CUSTOM_FIELD_MAP).join(', ')}`), value: z.union([z.string(), z.number(), z.object({})]).describe('The value to set. For rich text fields, provide plain text. For select fields, provide the option value. For user fields, provide accountId. For number fields, provide a number.'), }, outputSchema: { success: z.boolean(), fieldId: z.string().optional(), fieldName: z.string().optional(), error: z.object({ message: z.string(), statusCode: z.number().optional(), details: z.unknown().optional(), }).optional(), },
- src/jira-client.ts:719-732 (helper)Helper function to resolve human-readable field name (e.g., 'Health Status') to customfield ID using FIELD_NAME_TO_ID map, or pass-through if already ID; throws error for unknown fields listing valid ones.export function resolveFieldId(fieldNameOrId: string): string { // If it's already a customfield ID, return as-is if (fieldNameOrId.startsWith('customfield_')) { return fieldNameOrId; } // Try to find by name (case-insensitive) const fieldId = FIELD_NAME_TO_ID[fieldNameOrId.toLowerCase()]; if (fieldId) { return fieldId; } throw new Error(`Unknown field: "${fieldNameOrId}". Valid fields are: ${Object.values(CUSTOM_FIELD_MAP).join(', ')}`); }
- src/jira-client.ts:62-69 (helper)Constant mapping of custom field IDs to human-readable names, used for resolution and descriptions in tool schema and error messages.export const CUSTOM_FIELD_MAP: Record<string, string> = { 'customfield_15111': 'Decision Needed', 'customfield_15112': 'Progress Update', 'customfield_15113': 'Decision Maker(s)', 'customfield_15115': 'Risks/Blockers', 'customfield_15116': 'Completion Percentage', 'customfield_15117': 'Health Status', };