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
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of occurrences to return. Defaults to 1. | |
| date | No | Starting date (YYYY-MM-DD format). Defaults to current date. | |
| format | No | Output format (json or text) | |
| phase | Yes | Moon 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; }
- src/tools/moon-tools.ts:58-78 (registration)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'); } } });
- src/interfaces/moon.ts:32-42 (schema)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)') });