get-project-report
Get a project summary report with filters for date range, project ID, client ID, and status to track project performance.
Instructions
Get project summary report
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| start_date | No | Start date for report (YYYY-MM-DD) | |
| end_date | No | End date for report (YYYY-MM-DD) | |
| project_id | No | Filter by project ID | |
| client_id | No | Filter by client ID | |
| status | No | Filter by project status |
Implementation Reference
- src/tools/reporting/reports.ts:42-72 (handler)The getProjectReport tool handler - calls Float API /reports/projects endpoint with optional filters (start_date, end_date, project_id, client_id, status) and returns project summary data including name, client_id, status, total_hours, billable_hours, budget, and budget_used.
// Get project report export const getProjectReport = createTool( 'get-project-report', 'Get project summary report', z.object({ start_date: z.string().optional().describe('Start date for report (YYYY-MM-DD)'), end_date: z.string().optional().describe('End date for report (YYYY-MM-DD)'), project_id: z.number().optional().describe('Filter by project ID'), client_id: z.number().optional().describe('Filter by client ID'), status: z.number().optional().describe('Filter by project status'), }), async (params) => { const response = await floatApi.getPaginated( '/reports/projects', params, z.array( z.object({ project_id: z.number().optional(), name: z.string().optional(), client_id: z.number().optional(), status: z.number().optional(), total_hours: z.number().optional(), billable_hours: z.number().optional(), budget: z.number().optional(), budget_used: z.number().optional(), }) ) ); return response; } ); - src/tools/reporting/reports.ts:46-51 (schema)Input schema for getProjectReport: start_date (optional string), end_date (optional string), project_id (optional number), client_id (optional number), status (optional number).
z.object({ start_date: z.string().optional().describe('Start date for report (YYYY-MM-DD)'), end_date: z.string().optional().describe('End date for report (YYYY-MM-DD)'), project_id: z.number().optional().describe('Filter by project ID'), client_id: z.number().optional().describe('Filter by client ID'), status: z.number().optional().describe('Filter by project status'), - src/tools/reporting/reports.ts:57-68 (schema)Output/response schema for getProjectReport: array of objects with project_id, name, client_id, status, total_hours, billable_hours, budget, budget_used.
z.array( z.object({ project_id: z.number().optional(), name: z.string().optional(), client_id: z.number().optional(), status: z.number().optional(), total_hours: z.number().optional(), billable_hours: z.number().optional(), budget: z.number().optional(), budget_used: z.number().optional(), }) ) - src/tools/index.ts:167-175 (registration)Import and registration of getProjectReport: imported from './reporting/reports.js' and added to the legacyTools array (line 313) which is then exported as part of the 'tools' array (line 319).
// Reporting tools import { getTimeReport, getProjectReport, getPeopleUtilizationReport, } from './reporting/reports.js'; // Legacy tools export (preserved for backward compatibility) export const legacyTools = [ - src/tools/base.ts:50-104 (helper)The createTool helper function used to define getProjectReport. It wraps the handler with input validation (Zod schema parsing), error handling (FloatApiError, ZodError, general errors), and response 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>; } }, }; };