update-milestone
Update any field of an existing milestone, such as name, dates, status, or priority, using its milestone ID to keep project timelines accurate.
Instructions
Update an existing milestone
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| milestone_id | Yes | The milestone ID (milestone_id) | |
| name | No | Milestone name | |
| project_id | No | Project ID | |
| phase_id | No | Phase ID | |
| description | No | Milestone description | |
| date | No | Milestone date (YYYY-MM-DD format) | |
| start_date | No | Milestone start date (YYYY-MM-DD format) | |
| end_date | No | Milestone end date (YYYY-MM-DD format) | |
| status | No | Milestone status (numeric) | |
| priority | No | Priority level (1-5, where 1 is highest) | |
| completed | No | Completion status (0=not completed, 1=completed) | |
| completed_date | No | Completion date (YYYY-MM-DD format) | |
| notes | No | Additional notes | |
| color | No | Milestone color (hex color code) | |
| reminder_date | No | Reminder date (YYYY-MM-DD format) | |
| active | No | Active status (1=active, 0=archived) |
Implementation Reference
- The main handler for the 'update-milestone' tool. It uses createTool to define name 'update-milestone', description 'Update an existing milestone', a Zod schema for inputs (milestone_id required; optional fields: name, project_id, phase_id, description, date, start_date, end_date, status, priority, completed, completed_date, notes, color, reminder_date, active), and an async handler that destructures milestone_id from params, then calls floatApi.patch(`/milestones/${milestone_id}`, updateData, milestoneSchema) to update the milestone via the Float API.
// Update milestone export const updateMilestone = createTool( 'update-milestone', 'Update an existing milestone', z.object({ milestone_id: z.union([z.string(), z.number()]).describe('The milestone ID (milestone_id)'), name: z.string().optional().describe('Milestone name'), project_id: z.number().optional().describe('Project ID'), phase_id: z.number().optional().describe('Phase ID'), description: z.string().optional().describe('Milestone description'), date: z.string().optional().describe('Milestone date (YYYY-MM-DD format)'), start_date: z.string().optional().describe('Milestone start date (YYYY-MM-DD format)'), end_date: z.string().optional().describe('Milestone end date (YYYY-MM-DD format)'), status: z.number().optional().describe('Milestone status (numeric)'), priority: z.number().optional().describe('Priority level (1-5, where 1 is highest)'), completed: z.number().optional().describe('Completion status (0=not completed, 1=completed)'), completed_date: z.string().optional().describe('Completion date (YYYY-MM-DD format)'), notes: z.string().optional().describe('Additional notes'), color: z.string().optional().describe('Milestone color (hex color code)'), reminder_date: z.string().optional().describe('Reminder date (YYYY-MM-DD format)'), active: z.number().optional().describe('Active status (1=active, 0=archived)'), }), async (params) => { const { milestone_id, ...updateData } = params; const milestone = await floatApi.patch( `/milestones/${milestone_id}`, updateData, milestoneSchema ); return milestone; } ); - Input schema (Zod) for the update-milestone tool. Defines the required milestone_id (string or number) and all optional updatable fields including name, project_id, phase_id, description, date, start_date, end_date, status, priority, completed, completed_date, notes, color, reminder_date, and active.
z.object({ milestone_id: z.union([z.string(), z.number()]).describe('The milestone ID (milestone_id)'), name: z.string().optional().describe('Milestone name'), project_id: z.number().optional().describe('Project ID'), phase_id: z.number().optional().describe('Phase ID'), description: z.string().optional().describe('Milestone description'), date: z.string().optional().describe('Milestone date (YYYY-MM-DD format)'), start_date: z.string().optional().describe('Milestone start date (YYYY-MM-DD format)'), end_date: z.string().optional().describe('Milestone end date (YYYY-MM-DD format)'), status: z.number().optional().describe('Milestone status (numeric)'), priority: z.number().optional().describe('Priority level (1-5, where 1 is highest)'), completed: z.number().optional().describe('Completion status (0=not completed, 1=completed)'), completed_date: z.string().optional().describe('Completion date (YYYY-MM-DD format)'), notes: z.string().optional().describe('Additional notes'), color: z.string().optional().describe('Milestone color (hex color code)'), reminder_date: z.string().optional().describe('Reminder date (YYYY-MM-DD format)'), active: z.number().optional().describe('Active status (1=active, 0=archived)'), }), - src/tools/index.ts:78-89 (registration)Registration of the updateMilestone export: imported from './project-management/milestones.js' (line 82) and included in both legacyTools (line 241) and tools/allTools (lines 319, 322) arrays, making it available as a legacy granular tool.
import { listMilestones, getMilestone, createMilestone, updateMilestone, deleteMilestone, getProjectMilestones, getUpcomingMilestones, getOverdueMilestones, completeMilestone, getMilestoneReminders, } from './project-management/milestones.js'; - src/types/float.ts:236-259 (helper)milestoneSchema: Zod schema used by update-milestone's handler to validate the Float API response after patching. Defines the structure of a milestone object including milestone_id, project_id, phase_id, name, description, date, start_date, end_date, status, created, modified, created_by, modified_by, active, priority, completed, completed_date, notes, color, reminder_date, and reminder_sent.
// Milestone schema - updated to match Float API v3 structure export const milestoneSchema = z.object({ milestone_id: z.number().optional(), // Float API uses milestone_id, not id project_id: z.number().optional(), phase_id: z.number().nullable().optional(), name: z.string(), description: z.string().nullable().optional(), date: z.string().nullable().optional(), // ISO date format (YYYY-MM-DD) start_date: z.string().nullable().optional(), end_date: z.string().nullable().optional(), status: z.number().nullable().optional(), // Float API uses numeric status codes created: z.string().nullable().optional(), // Float API uses 'created', not 'created_at' modified: z.string().nullable().optional(), // Float API uses 'modified', not 'updated_at' created_by: z.number().nullable().optional(), modified_by: z.number().nullable().optional(), active: z.number().nullable().optional(), // 0 = archived, 1 = active priority: z.number().nullable().optional(), // Priority level (1-5) completed: z.number().nullable().optional(), // 0 = not completed, 1 = completed completed_date: z.string().nullable().optional(), notes: z.string().nullable().optional(), color: z.string().nullable().optional(), reminder_date: z.string().nullable().optional(), reminder_sent: z.number().nullable().optional(), // 0 = not sent, 1 = sent }); - src/tools/base.ts:50-104 (helper)The createTool helper function that wraps the update-milestone handler. It accepts name, description, schema (Zod), and an async handler function. It returns an object with name, description, inputSchema, and a wrapped handler that validates params via schema.parse(), catches errors (FloatApiError, ZodError, and generic errors), and returns a standardized ToolResponse with success/error formatting.
export const createTool = <T, P extends z.ZodType>( name: string, description: string, schema: P, handler: (params: z.infer<P>) => Promise<T> ): { name: string; description: string; inputSchema: P; handler: (params: unknown) => Promise<ToolResponse<T>>; } => { return { name, description, inputSchema: schema, handler: async (params: unknown): Promise<ToolResponse<T>> => { try { const validatedParams = schema.parse(params); const result = await handler(validatedParams); // Extract format from params if available const responseFormat = ((validatedParams as Record<string, unknown>).format as ResponseFormat) || 'json'; return { success: true, data: result, format: responseFormat }; } catch (error) { logger.error(`Error in ${name} tool:`, error); // Handle Float API errors with enhanced formatting if (error instanceof FloatApiError) { return FloatErrorHandler.formatErrorForMcp(error) as ToolResponse<T>; } // Handle parameter validation errors if (error instanceof z.ZodError) { return { success: false, error: `Parameter validation failed: ${error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ')}`, errorCode: 'PARAMETER_VALIDATION_ERROR', details: { validationErrors: error.errors, }, } as ToolResponse<T>; } // Handle other errors return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', errorCode: 'UNKNOWN_ERROR', } as ToolResponse<T>; } }, }; };