Skip to main content
Glama
RyanCardin15

LocalTides MCP Server

get_next_moon_phase

Calculate the next occurrence of a specific moon phase (New Moon, First Quarter, Full Moon, Last Quarter) starting from a given date. Specify the number of occurrences and output format (json or text) for precise astronomical planning.

Instructions

Get the next occurrence(s) of a specific moon phase

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
countNoNumber of occurrences to return. Defaults to 1.
dateNoStarting date (YYYY-MM-DD format). Defaults to current date.
formatNoOutput format (json or text)
phaseYesMoon phase to find

Implementation Reference

  • Core handler function that computes the next moon phase dates by iterating daily and detecting phase transitions using SunCalc.getMoonIllumination.
    getNextMoonPhase(params: NextMoonPhaseParams): { date: string, phase: string }[] {
      const startDate = params.date ? new Date(params.date) : new Date();
      const count = params.count || 1;
      const targetPhase = params.phase;
      
      // Map phase names to their approximate values
      const phaseValues: Record<string, number> = {
        [MoonPhaseName.NEW_MOON]: 0,
        [MoonPhaseName.FIRST_QUARTER]: 0.25,
        [MoonPhaseName.FULL_MOON]: 0.5,
        [MoonPhaseName.LAST_QUARTER]: 0.75
      };
      
      const targetPhaseValue = phaseValues[targetPhase];
      const results: { date: string, phase: string }[] = [];
      let currentDate = new Date(startDate);
      
      // Find the next occurrences
      while (results.length < count) {
        // Check every day (could be optimized with better algorithms)
        const illuminationData = SunCalc.getMoonIllumination(currentDate);
        const prevDate = new Date(currentDate);
        prevDate.setDate(prevDate.getDate() - 1);
        const prevIlluminationData = SunCalc.getMoonIllumination(prevDate);
        
        // Check if we've passed the target phase between yesterday and today
        const prevDiff = Math.abs(prevIlluminationData.phase - targetPhaseValue);
        const currentDiff = Math.abs(illuminationData.phase - targetPhaseValue);
        
        // If we're getting closer to the target phase and then further away, we've passed it
        // Or if we're very close to the target phase (within 0.01)
        if ((prevDiff > currentDiff && currentDiff < 0.01) || currentDiff < 0.005) {
          results.push({
            date: currentDate.toISOString().split('T')[0],
            phase: targetPhase
          });
        }
        
        // Move to next day
        currentDate.setDate(currentDate.getDate() + 1);
        
        // Safety check to prevent infinite loops
        if (results.length === 0 && currentDate.getTime() - startDate.getTime() > 366 * 24 * 60 * 60 * 1000) {
          throw new Error('Could not find the specified moon phase within a year.');
        }
      }
      
      return results;
    }
  • Registers the 'get_next_moon_phase' tool with the MCP server, providing schema, description, and execute handler that delegates to MoonPhaseService.
    server.addTool({
      name: 'get_next_moon_phase',
      description: 'Get the next occurrence(s) of a specific moon phase',
      parameters: NextMoonPhaseParamsSchema,
      execute: async (params) => {
        try {
          const results = moonPhaseService.getNextMoonPhase(params);
          if (params.format === 'text') {
            return results.map(result => 
              `Next ${result.phase}: ${result.date}`
            ).join('\n');
          }
          return JSON.stringify(results);
        } catch (error) {
          if (error instanceof Error) {
            throw new Error(`Failed to get next moon phase: ${error.message}`);
          }
          throw new Error('Failed to get next moon phase');
        }
      }
    });
  • Zod schema defining input parameters for the get_next_moon_phase tool, including phase type, optional start date, count, and output format.
    export const NextMoonPhaseParamsSchema = z.object({
      phase: z.enum([
        MoonPhaseName.NEW_MOON,
        MoonPhaseName.FIRST_QUARTER,
        MoonPhaseName.FULL_MOON,
        MoonPhaseName.LAST_QUARTER
      ]).describe('Moon phase to find'),
      date: z.string().optional().describe('Starting date (YYYY-MM-DD format). Defaults to current date.'),
      count: z.number().positive().optional().describe('Number of occurrences to return. Defaults to 1.'),
      format: z.enum(['json', 'text']).optional().describe('Output format (json or text)')
    });

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/RyanCardin15/NOAA-TidesAndCurrents-MCP'

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