update_progress
Update the Progress Update field on Jira issues with structured weekly updates, delivered items, and next steps. Refresh dates or modify specific sections while preserving existing content.
Instructions
Update the Progress Update field (customfield_15112) on a Jira issue. This field uses a structured template with three sections:
Weekly Update: "ℹ️ Update for week of [date]:" - automatically includes current date
Delivered: "✅ What we've delivered so far:"
What's Next: "❓ What's next:"
Options:
Use refreshDate=true to update just the date while preserving all existing content
Only sections you explicitly provide will be updated; others are preserved from existing content
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| issueKey | Yes | The issue key (e.g., "TSSE-984") | |
| refreshDate | No | If true, updates the date to today while preserving all existing content. Use this to "refresh" the progress update without changing the content. | |
| weeklyUpdate | No | Text to add after the weekly header. Current date will be auto-inserted. | |
| delivered | No | Text describing what was delivered | |
| whatsNext | No | Text describing upcoming work |
Implementation Reference
- src/jira-client.ts:1135-1227 (handler)Core handler function implementing the update_progress tool logic: fetches current progress field, parses existing content into sections, applies updates (including date refresh and section replacements), constructs new ADF document, and updates the Jira issue via API.export async function updateProgressField( issueKey: string, options: { refreshDate?: boolean; weeklyUpdate?: string; delivered?: string; whatsNext?: string; } ): Promise<{ success: boolean; updatedSections: string[]; parsedExisting?: { weeklyUpdate: string; delivered: string; whatsNext: string } }> { const PROGRESS_FIELD_ID = 'customfield_15112'; // Fetch current field value const currentValue = await getIssueCustomField(issueKey, PROGRESS_FIELD_ID); // Parse existing content const existing = parseProgressUpdateADF(currentValue); // Format current date const currentDate = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric', }); // Determine which sections to update const updatedSections: string[] = []; let weeklyUpdate = existing.weeklyUpdate; let delivered = existing.delivered; let whatsNext = existing.whatsNext; // Handle refreshDate option - preserve existing content but update the date if (options.refreshDate) { // Extract just the content part from weeklyUpdate (remove old date or [date] placeholder if present) // The parsed weeklyUpdate may be: // - "December 10, 2025 - Some content" // - "[date] - Some content" // - Just "[date]" // - Just content with no date prefix let contentOnly = weeklyUpdate; // Remove date pattern like "December 10, 2025 - " or "December 10, 2025" const dateMatch = contentOnly.match(/^[A-Z][a-z]+ \d{1,2}, \d{4}\s*-?\s*/); if (dateMatch) { contentOnly = contentOnly.slice(dateMatch[0].length); } // Remove [date] placeholder pattern like "[date] - " or "[date]" const placeholderMatch = contentOnly.match(/^\[date\]\s*-?\s*/); if (placeholderMatch) { contentOnly = contentOnly.slice(placeholderMatch[0].length); } contentOnly = contentOnly.trim(); weeklyUpdate = contentOnly ? `${currentDate} - ${contentOnly}` : currentDate; updatedSections.push('weeklyUpdate (date refreshed)'); } // Handle explicit weeklyUpdate option if (options.weeklyUpdate !== undefined) { weeklyUpdate = options.weeklyUpdate ? `${currentDate} - ${options.weeklyUpdate}` : currentDate; updatedSections.push('weeklyUpdate'); } if (options.delivered !== undefined) { delivered = options.delivered; updatedSections.push('delivered'); } if (options.whatsNext !== undefined) { whatsNext = options.whatsNext; updatedSections.push('whatsNext'); } // Create the updated ADF document const updatedADF = createProgressUpdateADF(weeklyUpdate, delivered, whatsNext); // Update the field await jiraFetch<void>(`/issue/${issueKey}`, { method: 'PUT', body: JSON.stringify({ fields: { [PROGRESS_FIELD_ID]: updatedADF, }, }), }); return { success: true, updatedSections, parsedExisting: existing, }; }
- src/index.ts:522-553 (schema)Input and output schema definitions (Zod) for the update_progress tool, defining parameters like issueKey, refreshDate, weeklyUpdate, delivered, whatsNext and response structure.{ title: 'Update Progress', description: `Update the Progress Update field (customfield_15112) on a Jira issue. This field uses a structured template with three sections: - Weekly Update: "ℹ️ Update for week of [date]:" - automatically includes current date - Delivered: "✅ What we've delivered so far:" - What's Next: "❓ What's next:" Options: - Use refreshDate=true to update just the date while preserving all existing content - Only sections you explicitly provide will be updated; others are preserved from existing content`, inputSchema: { issueKey: z.string().describe('The issue key (e.g., "TSSE-984")'), refreshDate: z.boolean().optional().describe('If true, updates the date to today while preserving all existing content. Use this to "refresh" the progress update without changing the content.'), weeklyUpdate: z.string().optional().describe('Text to add after the weekly header. Current date will be auto-inserted.'), delivered: z.string().optional().describe('Text describing what was delivered'), whatsNext: z.string().optional().describe('Text describing upcoming work'), }, outputSchema: { success: z.boolean(), updatedSections: z.array(z.string()).optional(), parsedExisting: z.object({ weeklyUpdate: z.string(), delivered: z.string(), whatsNext: z.string(), }).optional(), error: z.object({ message: z.string(), statusCode: z.number().optional(), details: z.unknown().optional(), }).optional(), }, },
- src/index.ts:520-582 (registration)MCP server registration of the 'update_progress' tool, including schema, description, and thin wrapper handler that performs input validation and delegates to the core updateProgressField implementation.server.registerTool( 'update_progress', { title: 'Update Progress', description: `Update the Progress Update field (customfield_15112) on a Jira issue. This field uses a structured template with three sections: - Weekly Update: "ℹ️ Update for week of [date]:" - automatically includes current date - Delivered: "✅ What we've delivered so far:" - What's Next: "❓ What's next:" Options: - Use refreshDate=true to update just the date while preserving all existing content - Only sections you explicitly provide will be updated; others are preserved from existing content`, inputSchema: { issueKey: z.string().describe('The issue key (e.g., "TSSE-984")'), refreshDate: z.boolean().optional().describe('If true, updates the date to today while preserving all existing content. Use this to "refresh" the progress update without changing the content.'), weeklyUpdate: z.string().optional().describe('Text to add after the weekly header. Current date will be auto-inserted.'), delivered: z.string().optional().describe('Text describing what was delivered'), whatsNext: z.string().optional().describe('Text describing upcoming work'), }, outputSchema: { success: z.boolean(), updatedSections: z.array(z.string()).optional(), parsedExisting: z.object({ weeklyUpdate: z.string(), delivered: z.string(), whatsNext: z.string(), }).optional(), error: z.object({ message: z.string(), statusCode: z.number().optional(), details: z.unknown().optional(), }).optional(), }, }, async ({ issueKey, refreshDate, weeklyUpdate, delivered, whatsNext }) => { try { if (!issueKey || !issueKey.trim()) { throw new Error('issueKey is required'); } if (!refreshDate && weeklyUpdate === undefined && delivered === undefined && whatsNext === undefined) { throw new Error('At least one of refreshDate, weeklyUpdate, delivered, or whatsNext must be provided'); } const result = await updateProgressField(issueKey, { refreshDate, weeklyUpdate, delivered, whatsNext, }); 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:19-23 (helper)Import of updateProgressField from jira-client.ts, used by the tool handler.updateProgressField, getSprintTasks, CUSTOM_FIELD_MAP, JiraApiError, } from './jira-client.js';