Skip to main content
Glama
niondigital

MoCo MCP Server

by niondigital

get_user_holidays

Retrieve annual holiday data with utilization calculations and remaining vacation days for workforce planning and time management.

Instructions

Get all user holidays for a specific year with utilization calculations and remaining vacation days

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
yearYesYear to retrieve holidays for (e.g., 2024)

Implementation Reference

  • Main handler function executing the tool logic: validates input year, fetches holiday entitlements and taken holidays from API service, processes data into summary (total taken, entitlement, utilization, remaining), formats readable output.
    handler: async (params: z.infer<typeof GetUserHolidaysSchema>): Promise<string> => {
      const { year } = params;
    
      // Validate year
      if (!validateYear(year)) {
        return createValidationErrorMessage({
          field: 'year',
          value: year,
          reason: 'invalid_year'
        });
      }
    
      try {
        const apiService = new MocoApiService();
        
        // Get both entitlements and actual taken holidays
        let entitlements: any[] = [];
        let takenHolidays: any[] = [];
        
        try {
          entitlements = await apiService.getUserHolidays(year);
        } catch (error) {
          console.error('DEBUG: Failed to get entitlements:', error);
        }
        
        try {
          console.error('DEBUG: About to call getTakenHolidays...');
          takenHolidays = await apiService.getTakenHolidays(year);
          console.error('DEBUG: getTakenHolidays returned:', takenHolidays.length, 'items');
        } catch (error) {
          console.error('DEBUG: Failed to get taken holidays:', error);
          console.error('DEBUG: Error details:', error instanceof Error ? error.message : 'Unknown error');
        }
    
        // Debug logging
        console.error(`DEBUG: Got ${entitlements.length} entitlements and ${takenHolidays.length} taken holidays for year ${year}`);
        console.error('DEBUG: Entitlements:', JSON.stringify(entitlements, null, 2));
        console.error('DEBUG: Taken holidays:', JSON.stringify(takenHolidays, null, 2));
    
        if (takenHolidays.length === 0) {
          // Show entitlement info if available, otherwise just empty
          return formatHolidaysWithNoData(year, entitlements);
        }
    
        const summary = createHolidaySummary(takenHolidays, entitlements, year);
        console.error('DEBUG: Summary created:', JSON.stringify(summary, null, 2));
        return formatHolidaysSummary(summary);
    
      } catch (error) {
        return `Error retrieving holidays for ${year}: ${error instanceof Error ? error.message : 'Unknown error'}`;
      }
    }
  • Zod schema defining input validation for the tool: requires integer 'year' parameter.
    const GetUserHolidaysSchema = z.object({
      year: z.number().int().describe('Year to retrieve holidays for (e.g., 2024)')
    });
  • src/index.ts:34-42 (registration)
    Tool registration: imported from './tools/userHolidaysTools.js' (line 23) and added to AVAILABLE_TOOLS array used by MCP server for tool listing and execution dispatching.
    const AVAILABLE_TOOLS = [
      getActivitiesTool,
      getUserProjectsTool,
      getUserProjectTasksTool,
      getUserHolidaysTool,
      getUserPresencesTool,
      getUserSickDaysTool,
      getPublicHolidaysTool
    ];
  • Supporting API service method that fetches user holiday entitlements for the specified year from MoCo /users/holidays endpoint, handling 404 gracefully.
    async getUserHolidays(year: number): Promise<UserHoliday[]> {
      try {
        return await this.makeRequest<UserHoliday[]>('/users/holidays', {
          year: year
        });
      } catch (error) {
        // If 404 error (Resource not found), return empty array instead of throwing error
        // This happens when no holiday data exists for the year yet
        if (error instanceof Error && error.message.includes('Resource not found')) {
          return [];
        }
        // Re-throw other errors
        throw error;
      }
    }
  • Supporting API service method fetching actual taken vacation days from MoCo /schedules endpoint by filtering for absence code '4' (Urlaub/vacation).
    async getTakenHolidays(year: number): Promise<any[]> {
      // Calculate year date range
      const startDate = `${year}-01-01`;
      const endDate = `${year}-12-31`;
      
      console.error(`DEBUG API: Trying to fetch schedules for ${startDate} to ${endDate}`);
      
      try {
        // Schedules endpoint has different response structure, use direct request
        // Based on previous success with makeRequest showing 63 schedules
        const allSchedules = await this.makeRequest<any[]>('/schedules', {
          from: startDate,
          to: endDate
        });
        
        console.error(`DEBUG API: Found ${allSchedules.length} total schedules for ${year}`);
        if (allSchedules.length > 0) {
          console.error('DEBUG API: First few schedules:', JSON.stringify(allSchedules.slice(0, 3), null, 2));
        }
        
        // Filter for absences (schedules with assignment type "Absence")
        const absences = allSchedules.filter(schedule => 
          schedule.assignment && 
          schedule.assignment.type === 'Absence'
        );
        console.error(`DEBUG API: Found ${absences.length} absences with assignment codes:`, absences.map(a => a.assignment?.code + ' (' + a.assignment?.name + ')'));
        
        // Look specifically for vacation/holiday codes (we need to figure out which code is for vacation)
        const vacationCodes = ['3', '4', '5']; // Common vacation codes to try
        const holidays = absences.filter(schedule => 
          vacationCodes.includes(schedule.assignment?.code)
        );
        console.error(`DEBUG API: Found ${holidays.length} potential holidays with codes:`, holidays.map(a => a.assignment?.code + ' (' + a.assignment?.name + ')'));
        
        // Filter for only vacation days (assignment code "4")
        const vacationDays = absences.filter(schedule => 
          schedule.assignment?.code === '4' && schedule.assignment?.name === 'Urlaub'
        );
        console.error(`DEBUG API: Found ${vacationDays.length} actual vacation days (code 4)`);
        
        return vacationDays;
      } catch (error) {
        console.error('DEBUG API: Error fetching schedules:', error);
        console.error('DEBUG API: Error details:', error instanceof Error ? error.message : 'Unknown error');
        return [];
      }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/niondigital/moco-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server