Skip to main content
Glama
pshempel

MCP Time Server Node

by pshempel

days_until

Calculate days remaining until a specific date or event using ISO strings, natural language, or Unix timestamps, with optional timezone adjustments and formatted output.

Instructions

Calculate days until a target date/event

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
target_dateYesTarget date (ISO string, natural language, or Unix timestamp)
timezoneNoTimezone for calculation (default: system timezone)
format_resultNoReturn formatted string (e.g., "in 5 days") instead of number (default: false)

Implementation Reference

  • The core handler function `daysUntil` that implements the tool logic: parses target date, handles timezone conversion, calculates calendar days difference using date-fns, applies caching with withCache, optional human-readable formatting, comprehensive validation, and custom MCP error throwing.
    export function daysUntil(params: DaysUntilParams): DaysUntilResult {
      debug.timing('daysUntil called with params: %O', params);
      // Validate required parameter
      if (!params.target_date) {
        debug.error('target_date is required');
        throw new ValidationError('target_date is required', { field: 'target_date' });
      }
    
      // Validate string length first (general limit for very long strings)
      if (typeof params.target_date === 'string') {
        validateStringLength(params.target_date, LIMITS.MAX_STRING_LENGTH, 'target_date');
      }
    
      const { target_date, timezone: userTimezone, format_result = false } = params;
      const { defaultTimezone } = getConfig();
      const timezone = resolveTimezoneUtil(userTimezone, defaultTimezone);
      debug.timezone('Resolved timezone: %s', timezone);
    
      // Use withCache wrapper with CacheTTL.CALCULATIONS (since TTL depends on result)
      return withCache(
        `days_until:${target_date}:${timezone}:${format_result}`,
        CacheTTL.CALCULATIONS,
        () => {
          // Validate timezone if provided
          if (userTimezone !== undefined && !validateTimezone(timezone)) {
            debug.error('Invalid timezone: %s', timezone);
            throw new TimezoneError(`Invalid timezone: ${timezone}`, timezone);
          }
    
          // Parse target date
          let targetDate: Date;
          debug.parse('Parsing target_date: %s', target_date);
          try {
            targetDate = parseTargetDate(target_date, timezone);
            debug.parse('Parsed date: %s', targetDate.toISOString());
          } catch (error) {
            debug.error(
              'Invalid target_date format: %s, error: %s',
              target_date,
              error instanceof Error ? error.message : String(error)
            );
            throw new DateParsingError(`Invalid target_date format: ${target_date}`, {
              target_date,
              error: error instanceof Error ? error.message : String(error),
            });
          }
    
          // Get current date in the specified timezone
          const now = new Date();
          debug.timing('Current time: %s', now.toISOString());
    
          // Convert both dates to the specified timezone for calendar day comparison
          const nowInTimezone = convertToTimezone(now, timezone);
          const targetInTimezone = convertToTimezone(targetDate, timezone);
          debug.timezone('Now in timezone: %s', nowInTimezone.toISOString());
          debug.timezone('Target in timezone: %s', targetInTimezone.toISOString());
    
          // Calculate calendar days difference
          const daysUntil = differenceInCalendarDays(targetInTimezone, nowInTimezone);
          debug.timing('Days until: %d', daysUntil);
    
          let result: DaysUntilResult;
    
          if (format_result) {
            // Format the result as a human-readable string
            result = formatDaysUntil(daysUntil);
            debug.timing('Formatted result: %s', result);
          } else {
            // Return just the number
            result = daysUntil;
          }
    
          return result;
        }
      );
    }
  • Type definitions: `DaysUntilParams` interface for inputs (target_date required as string|number, optional timezone and format_result) and `DaysUntilResult` union type for output (number or formatted string).
    export interface DaysUntilParams {
      target_date: string | number;
      timezone?: string;
      format_result?: boolean;
    }
    
    export type DaysUntilResult = number | string;
  • `formatDaysUntil` helper function converts raw days number to human-readable phrases like 'Today', 'Tomorrow', 'in X days', or 'X days ago'.
    export function formatDaysUntil(days: number): string {
      if (days === 0) return 'Today';
      if (days === 1) return 'Tomorrow';
      if (days === -1) return 'Yesterday';
      if (days > 0) return `in ${days} days`;
      return `${Math.abs(days)} days ago`;
    }
  • `parseTargetDate` helper parses the target_date input (string|number) into a Date object using the shared parseTimeInput utility.
    export function parseTargetDate(target_date: string | number, timezone?: string): Date {
      // Convert to string first for parseTimeInput
      const input = String(target_date);
      return parseTimeInput(input, timezone).date;
    }
  • Re-export of `daysUntil` handler from './daysUntil', aggregating all tools for easy import and registration in the MCP server.
    export { daysUntil } from './daysUntil';

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