Skip to main content
Glama
pshempel

MCP Time Server Node

by pshempel

next_occurrence

Calculate the next occurrence of a recurring event based on specified patterns like daily, weekly, monthly, or yearly schedules.

Instructions

Find next occurrence of a recurring event

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
patternYesRecurrence pattern
start_fromNoStart searching from
day_of_weekNoFor weekly (0-6, 0=Sunday)
day_of_monthNoFor monthly (1-31)
timeNoTime in HH:mm format
timezoneNoTimezone for calculation (default: system timezone)

Implementation Reference

  • The core handler function implementing the next_occurrence tool logic, including parameter validation, timezone resolution, caching, and delegation to calculation logic.
    export function nextOccurrence(params: NextOccurrenceParams): NextOccurrenceResult {
      debug.recurrence('nextOccurrence called with params: %O', params);
      // Validate string length first
      if (params.start_from && typeof params.start_from === 'string') {
        validateDateString(params.start_from, 'start_from');
      }
    
      const config = getConfig();
      const fallbackTimezone = config.defaultTimezone;
      const timezone = resolveTimezone(params.timezone, fallbackTimezone);
    
      // Validate timezone if provided
      if (params.timezone) {
        debug.validation('Validating timezone: %s', timezone);
        if (!validateTimezone(timezone)) {
          debug.error('Invalid timezone: %s', timezone);
          throw new TimezoneError(`Invalid timezone: ${timezone}`, timezone);
        }
      }
      const cacheKey = getCacheKey(params, fallbackTimezone, timezone);
    
      // Use withCache wrapper instead of manual cache management
      return withCache(cacheKey, CacheTTL.CALCULATIONS, () => {
        try {
          const result = calculateNextOccurrence(params, timezone);
          debug.recurrence('nextOccurrence returning: %O', result);
          return result;
        } catch (error) {
          handleCalculationError(error);
        }
      });
    }
  • TypeScript type definitions for input parameters (NextOccurrenceParams) and output result (NextOccurrenceResult) used by the handler.
    export interface NextOccurrenceParams {
      pattern: RecurrencePattern;
      start_from?: string;
      day_of_week?: number;
      day_of_month?: number;
      time?: string;
      timezone?: string;
    }
    
    export interface NextOccurrenceResult {
      next: string;
      unix: number;
      days_until: number;
    }
  • src/index.ts:157-179 (registration)
    MCP tool registration in TOOL_DEFINITIONS array, including the tool name, description, and input schema.
    {
      name: 'next_occurrence',
      description: 'Find next occurrence of a recurring event',
      inputSchema: {
        type: 'object' as const,
        properties: {
          pattern: {
            type: 'string' as const,
            enum: ['daily', 'weekly', 'monthly', 'yearly'],
            description: 'Recurrence pattern',
          },
          start_from: { type: 'string' as const, description: 'Start searching from' },
          day_of_week: { type: 'number' as const, description: 'For weekly (0-6, 0=Sunday)' },
          day_of_month: { type: 'number' as const, description: 'For monthly (1-31)' },
          time: { type: 'string' as const, description: 'Time in HH:mm format' },
          timezone: {
            type: 'string' as const,
            description: 'Timezone for calculation (default: system timezone)',
          },
        },
        required: ['pattern'],
      },
    },
  • src/index.ts:268-274 (registration)
    Mapping of the 'next_occurrence' tool name to the nextOccurrence handler function in TOOL_FUNCTIONS record.
      next_occurrence: (params: unknown) =>
        nextOccurrence(params as Parameters<typeof nextOccurrence>[0]),
      format_time: (params: unknown) => formatTime(params as Parameters<typeof formatTime>[0]),
      calculate_business_hours: (params: unknown) =>
        calculateBusinessHours(params as Parameters<typeof calculateBusinessHours>[0]),
      days_until: (params: unknown) => daysUntil(params as Parameters<typeof daysUntil>[0]),
    };
  • Internal helper function that performs the core date calculation using the RecurrenceFactory.
    function calculateNextOccurrence(
      params: NextOccurrenceParams,
      timezone: string
    ): NextOccurrenceResult {
      debug.recurrence('calculateNextOccurrence called with params: %O', params);
      // Parse start date
      let startFrom: Date;
      if (params.start_from) {
        debug.parse('Parsing start_from: %s', params.start_from);
        try {
          startFrom = parseTimeInput(params.start_from, timezone).date;
          debug.parse('Parsed start_from date: %s', startFrom.toISOString());
        } catch {
          debug.error('Invalid start_from date: %s', params.start_from);
          throw new DateParsingError('Invalid start_from date', { start_from: params.start_from });
        }
      } else {
        startFrom = new Date();
      }
    
      // Map parameters to new format
      const recurrenceParams = mapToRecurrenceParams(params);
      recurrenceParams.timezone = timezone;
    
      // Calculate next occurrence using factory
      debug.recurrence('Calculating next occurrence with factory');
      const nextDate = factory.calculate(startFrom, recurrenceParams);
      debug.recurrence('Next occurrence date: %s', nextDate.toISOString());
    
      // Format result
      const result: NextOccurrenceResult = {
        next: nextDate.toISOString(),
        unix: Math.floor(nextDate.getTime() / 1000),
        days_until: calculateDaysUntil(nextDate, timezone),
      };
    
      return result;
    }

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/pshempel/mcp-time-server-node'

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