chuk-mcp-celestial
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@chuk-mcp-celestial When is the next full moon and what time does the sun rise in Seattle tomorrow?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
chuk-mcp-celestial
Astronomical & Celestial Data MCP Server
An MCP (Model Context Protocol) server providing moon phases, sun/moon rise/set times, solar eclipse predictions, Earth's seasons, planetary positions/events, and all-sky summaries from the US Navy Astronomical Applications Department API and local Skyfield calculations.
This is a demonstration project provided as-is for learning and testing purposes.
🌐 Try it now - Hosted version available! - No installation required.
Features
🌙 Comprehensive Celestial Data:
Moon phases with exact timing (New Moon, First Quarter, Full Moon, Last Quarter)
Sun and moon rise/set/transit times for any location
Solar eclipse predictions with local circumstances
Earth's seasons (equinoxes, solstices, perihelion, aphelion)
Planetary positions (altitude, azimuth, distance, magnitude, constellation, RA/Dec, elongation, visibility)
Planetary events (rise, set, transit times)
⚡ Flexible Providers:
Navy API - Authoritative US Navy data, all features
Skyfield - 28x faster, offline calculations, research-grade accuracy (included by default)
Hybrid mode - Mix providers per-tool (e.g., Skyfield for moon phases, Navy for eclipses)
S3 storage - Cloud-based ephemeris storage via chuk-virtual-fs
Artifact storage - Computation results persisted via chuk-artifacts (S3, filesystem, memory)
GeoJSON output - Location-based responses follow GeoJSON Feature spec
🔒 Type-Safe & Robust:
Pydantic v2 models for all responses - no dictionary goop!
Enums for all constants - no magic strings!
Full async/await support with httpx
Comprehensive error handling
🔗 Multi-Server Integration:
Combine celestial + time + weather for comprehensive astronomical intelligence
Answer complex questions like "Will the moon be visible tonight with current weather?"
✅ Quality Assured:
70%+ test coverage with pytest
GitHub Actions CI/CD
Automated releases to PyPI
Type checking with mypy
Code quality with ruff
Related MCP server: astronomy-mcp-server
Installation
Comparison of Installation Methods
Method | Setup Time | Requires Internet | Updates | Best For |
Hosted | Instant | Yes | Automatic | Quick testing, production use |
uvx | Instant | Yes (first run) | Automatic | No local install, always latest |
Local | 1-2 min | Only for install | Manual | Offline use, custom deployments |
Option 1: Use Hosted Version (Recommended)
No installation needed! Use our public hosted version:
{
"mcpServers": {
"celestial": {
"url": "https://celestial.chukai.io/mcp"
}
}
}Option 2: Install via uvx (No Installation Required)
Run directly without installing:
{
"mcpServers": {
"celestial": {
"command": "uvx",
"args": ["chuk-mcp-celestial"]
}
}
}Option 3: Install Locally
# With pip
pip install chuk-mcp-celestial
# Or with uv (recommended)
uv pip install chuk-mcp-celestial
# Or with pipx (isolated installation)
pipx install chuk-mcp-celestialSkyfield and NumPy are included by default — all 7 tools work out of the box.
With S3 artifact storage (optional):
pip install "chuk-mcp-celestial[s3]"Then configure in your MCP client:
{
"mcpServers": {
"celestial": {
"command": "chuk-mcp-celestial"
}
}
}Optional: Configure hybrid provider mode (create celestial.yaml):
# Use Skyfield for fast queries, Navy API for everything else
default_provider: navy_api
providers:
moon_phases: skyfield # 28x faster
earth_seasons: skyfield # 33x fasterQuick Start
Install
# No installation required (runs directly)
uvx chuk-mcp-celestial
# Or install from PyPI
uv pip install chuk-mcp-celestial
# Or install from source with dev tools
git clone https://github.com/chuk-ai/chuk-mcp-celestial.git
cd chuk-mcp-celestial
uv pip install -e ".[dev]"Claude Desktop Configuration
{
"mcpServers": {
"celestial": {
"url": "https://celestial.chukai.io/mcp"
}
}
}Or run locally:
{
"mcpServers": {
"celestial": {
"command": "uvx",
"args": ["chuk-mcp-celestial"]
}
}
}Run
# STDIO mode (Claude Desktop, mcp-cli)
chuk-mcp-celestial stdio
# HTTP mode (API access)
chuk-mcp-celestial http --port 8080Supported Providers
Provider | Speed | Offline | Features |
Navy API (default) | ~700ms | No | Moon, sun/moon, eclipses, seasons. Official US government source. |
Skyfield | ~25ms | Yes | Moon phases, seasons, planet position, planet events. JPL ephemeris. |
Both providers are included by default — no extras needed.
Tools
Moon Phases (1 tool)
Tool | Description |
| Upcoming moon phases with exact timing (UT1) |
Sun & Moon (1 tool)
Tool | Description |
| Rise/set/transit times, twilight, moon phase, illumination for a location |
Solar Eclipses (2 tools)
Tool | Description |
| Local eclipse circumstances (type, magnitude, obscuration, timing) |
| All solar eclipses in a year |
Earth Seasons (1 tool)
Tool | Description |
| Equinoxes, solstices, perihelion, aphelion for a year |
Planets (2 tools)
Tool | Description |
| Altitude, azimuth, distance, magnitude, constellation, RA/Dec, elongation, visibility |
| Rise, set, and transit times for a planet on a given date |
Supported: Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
Sky Summary (1 tool)
Tool | Description |
| All-sky summary: every planet's position, moon phase, darkness check — one call |
Environment Variables
Variable | Required | Default | Description |
| No |
| Default provider |
| No | default | Provider for moon phases |
| No | default | Provider for Earth seasons |
| No |
| Provider for planet position |
| No |
| Provider for planet events |
| No |
| Provider for sky summary |
| No | — | Path to celestial.yaml |
| No |
| Ephemeris storage: |
| No |
| S3 bucket for ephemeris |
| No |
| Request timeout (seconds) |
Hybrid Provider Mode
Create celestial.yaml to mix providers per-tool:
default_provider: navy_api
providers:
moon_phases: skyfield # 28x faster, offline
earth_seasons: skyfield # 33x faster, offline
sun_moon_data: navy_api # Full features
solar_eclipse_date: navy_api
solar_eclipse_year: navy_api
planet_position: skyfield # Only provider with planet support
planet_events: skyfield
sky: skyfield # All-sky summaryDevelopment
# Install with dev dependencies
uv pip install -e ".[dev]"
# Run tests
make test
# Run tests with coverage
make test-cov
# Lint and format
make lint
make format
# All checks
make checkDeployment
Hosted Version
No installation required:
{
"mcpServers": {
"celestial": {
"url": "https://celestial.chukai.io/mcp"
}
}
}Docker
make docker-build
make docker-runFly.io
fly launch
fly secrets set AWS_ACCESS_KEY_ID=your_key AWS_SECRET_ACCESS_KEY=your_secret
make fly-deployCross-Server Workflows
chuk-mcp-celestial integrates with the broader chuk MCP ecosystem:
Celestial + Time — Timezone-aware astronomy (sunrise in local time, time until next event)
Celestial + Weather — Observation planning (moon phase + cloud cover forecast)
Celestial + Tides — Coastal photography (golden hour + tide level)
Celestial + Weather — Eclipse viewing (eclipse visibility + weather forecast)
{
"mcpServers": {
"celestial": { "url": "https://celestial.chukai.io/mcp" },
"time": { "url": "https://time.chukai.io/mcp" },
"weather": { "url": "https://weather.chukai.io/mcp" }
}
}License
Apache License 2.0 - See LICENSE for details.
Credits
Built on chuk-mcp-server
Data provided by US Navy Astronomical Applications Department
Links
Available Tools
8 toolsget_earth_seasonsA
Get Earth's seasons and orbital events for a year.
Returns dates and times for equinoxes (equal day/night), solstices (longest/shortest days), and Earth's perihelion (closest to sun) and aphelion (farthest from sun).
Args: year: Year to query (1700-2100) timezone: Timezone offset from UTC in hours. If not provided, UTC (0) is used. dst: Whether to apply daylight saving time adjustment.
Returns: SeasonsResponse with equinoxes, solstices, perihelion, and aphelion.
Tips for LLMs: - Typically 6 events per year (2 equinoxes, 2 solstices, perihelion, aphelion) - Seasons are opposite in Northern and Southern hemispheres - Earth's 23.5 degree axial tilt causes seasons, not distance from sun
Example: seasons = await get_earth_seasons(2024) for event in seasons.data: print(f"{event.phenom}: {event.month}/{event.day}/{event.year} at {event.time}")
Inputs: year (required), timezone, dst.
get_moon_phasesA
Get upcoming moon phases starting from a given date.
Returns the next N moon phase occurrences (New Moon, First Quarter, Full Moon, Last Quarter) with exact times. Useful for planning astronomical observations, photography, or understanding lunar cycles.
Args: date: Start date in YYYY-MM-DD format. No leading zeros required (e.g., "2024-1-5" is valid). Valid range: 1700-01-01 to 2100-12-31 num_phases: Number of phases to return (1-99). Default is 12 (about 3 months of phases). Each lunar cycle has 4 phases, so 12 phases = 3 complete cycles.
Returns: MoonPhasesResponse: Contains: - phasedata: List of phase occurrences with exact dates and times - Each phase includes: phase name, year, month, day, time (in UT1)
Tips for LLMs: - All times are in Universal Time (UT1), not local time - A complete lunar cycle is about 29.5 days (4 phases) - Use num_phases=4 for the next month, 12 for next quarter, 48 for next year - Moon phases are useful for: astronomy, photography (full moon lighting), fishing/hunting (activity patterns), gardening (traditional planting cycles)
Example: # Get next 12 moon phases starting from May 3, 2009 phases = await get_moon_phases("2009-5-3", num_phases=12) for phase in phases.phasedata: print(f"{phase.phase} on {phase.year}-{phase.month}-{phase.day} at {phase.time} UT")
Inputs: date (required), num_phases.
get_planet_eventsA
Get rise, set, and transit times for a planet on a given day at a location.
Returns the times a planet rises above the horizon, transits the meridian (highest point), and sets below the horizon. Essential for planning when to observe a planet.
Args: planet: Planet name. One of: Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto date: Date in YYYY-MM-DD format (e.g., "2025-6-15") latitude: Observer's latitude in decimal degrees (-90 to 90) longitude: Observer's longitude in decimal degrees (-180 to 180) timezone: Timezone offset from UTC in hours (e.g., -8 for PST). When provided, event times are in local time. dst: Whether to apply daylight saving time adjustment.
Returns: PlanetEventsResponse: GeoJSON Feature containing: - geometry: Observer location - properties.data: - planet: Planet name - date: Query date - events: List of rise/set/transit events with times - constellation: Current constellation - magnitude: Apparent visual magnitude - artifact_ref: Reference to stored computation (if artifact store configured)
Tips for LLMs: - Events may be empty if the planet doesn't rise/set that day (polar regions) - Transit time is when the planet is highest — best viewing time - Use with get_planet_position to get full details at a specific time - Outer planets (Jupiter, Saturn) are above the horizon for ~12 hours - Inner planets (Mercury, Venus) are only visible near sunrise or sunset
Example: events = await get_planet_events( planet="Jupiter", date="2025-6-15", latitude=51.5, longitude=-0.1, timezone=1 ) for event in events.properties.data.events: print(f"Jupiter {event.phen} at {event.time}")
Inputs: planet (required), date (required), latitude (required), longitude (required), +2 more.
get_planet_positionA
Get position and observational data for a planet at a specific time and location.
Returns altitude, azimuth, distance, phase illumination, apparent magnitude, constellation, equatorial coordinates (RA/Dec), elongation from the sun, and visibility status. Essential for planning astronomical observations and answering "where is [planet] tonight?" questions.
Args: planet: Planet name. One of: Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto date: Date in YYYY-MM-DD format (e.g., "2025-6-15") time: Time in HH:MM format, 24-hour (e.g., "22:30"). Interpreted as UTC unless timezone is specified. latitude: Observer's latitude in decimal degrees (-90 to 90) longitude: Observer's longitude in decimal degrees (-180 to 180) timezone: Timezone offset from UTC in hours (e.g., -8 for PST, 1 for CET). When provided, the time parameter is interpreted as local time.
Returns: PlanetPositionResponse: GeoJSON Feature containing: - geometry: Observer location - properties.data: Planet position data: - altitude: Degrees above horizon (negative = below horizon) - azimuth: Degrees clockwise from north (0=N, 90=E, 180=S, 270=W) - distance_au / distance_km: Distance from observer - illumination: Phase illumination percentage (0-100) - magnitude: Apparent visual magnitude (lower = brighter) - constellation: IAU constellation abbreviation - right_ascension / declination: Equatorial coordinates (J2000) - elongation: Angular distance from sun in degrees - visibility: "visible", "below_horizon", or "lost_in_sunlight" - artifact_ref: Reference to stored computation (if artifact store configured)
Tips for LLMs: - Lower magnitude = brighter. Venus can reach -4.4, Jupiter -2.7 - Elongation < 10-15 degrees means planet is too close to the sun to see - altitude > 0 means the planet is above the horizon - azimuth tells you where to look: 0=North, 90=East, 180=South, 270=West - For "where is Mars tonight?", use time="21:00" with appropriate timezone - Mercury is hardest to see (small elongation), Venus and Jupiter are easiest
Example: pos = await get_planet_position( planet="Mars", date="2025-6-15", time="22:00", latitude=47.6, longitude=-122.3, timezone=-7 ) data = pos.properties.data if data.visibility == "visible": print(f"Mars is at {data.altitude}° altitude, {data.azimuth}° azimuth") print(f"Magnitude: {data.magnitude}, in {data.constellation}")
Inputs: planet (required), date (required), time (required), latitude (required), +2 more.
get_skyA
Get a complete sky summary — all planets, moon phase, and darkness — in one call.
Returns which planets are visible, their positions and brightness, the current moon phase, and whether the sky is dark enough for observation. This is the recommended tool for "what's in the sky tonight?" questions.
Args: date: Date in YYYY-MM-DD format (e.g., "2026-2-10") time: Time in HH:MM format, 24-hour (e.g., "21:00"). UTC unless timezone specified. latitude: Observer's latitude in decimal degrees (-90 to 90) longitude: Observer's longitude in decimal degrees (-180 to 180) timezone: Timezone offset from UTC in hours (e.g., 0 for GMT, -5 for EST, 1 for CET). When provided, the time parameter is interpreted as local time.
Returns: SkyResponse: GeoJSON Feature containing: - properties.data.visible_planets: Planets above horizon and not lost in sunlight, sorted brightest first. Each has altitude, azimuth, direction, magnitude, constellation, and visibility status. - properties.data.all_planets: All 8 planets regardless of visibility - properties.data.moon: Current phase and illumination percentage - properties.data.is_dark: True if sun is below -6 degrees (civil twilight) - properties.data.summary: One-line text summary for quick display
Tips for LLMs: - Use this instead of calling get_planet_position 8 times - The summary field gives a quick human-readable answer - visible_planets are sorted brightest first (lowest magnitude) - direction field gives compass bearing: "S" = look south, "NE" = northeast - is_dark=False means it's daytime or twilight — planets may not be visible even if above horizon - Combine with weather forecast to check if skies are clear enough to observe
Example: sky = await get_sky( date="2026-2-10", time="21:00", latitude=51.99, longitude=0.84, timezone=0 ) for p in sky.properties.data.visible_planets: print(f"{p.planet}: {p.direction}, magnitude {p.magnitude}, in {p.constellation}") print(sky.properties.data.summary)
Inputs: date (required), time (required), latitude (required), longitude (required), +1 more.
get_solar_eclipse_by_dateA
Get local solar eclipse circumstances for a specific date and location.
Calculates whether a solar eclipse is visible from a given location on a specific date, and if so, provides detailed timing and positional information for all eclipse phases.
Args: date: Date of the eclipse in YYYY-MM-DD format. Valid range: 1800-01-01 to 2050-12-31 latitude: Observer's latitude in decimal degrees (-90 to 90) longitude: Observer's longitude in decimal degrees (-180 to 180) height: Observer's height above mean sea level in meters. Default is 0. Range: -200 to 10000 meters.
Returns: SolarEclipseByDateResponse: GeoJSON Feature with eclipse type, magnitude, obscuration, duration, and local circumstances.
Tips for LLMs: - If description is "No Eclipse at this Location", the eclipse isn't visible here - magnitude >= 1.0 indicates total eclipse; < 1.0 is partial - altitude must be > 0 for eclipse to be visible (sun above horizon) - Use get_solar_eclipses_by_year first to find eclipse dates
Example: eclipse = await get_solar_eclipse_by_date( date="2017-8-21", latitude=46.67, longitude=-122.65, height=15 ) print(f"Eclipse type: {eclipse.properties.description}")
Inputs: date (required), latitude (required), longitude (required), height.
get_solar_eclipses_by_yearA
Get a list of all solar eclipses occurring in a specific year.
Returns all solar eclipses (total, annular, partial, and hybrid) that occur worldwide in the specified year. Use this to find eclipse dates, then use get_solar_eclipse_by_date to get detailed local circumstances.
Args: year: Year to query (1800-2050)
Returns: SolarEclipseByYearResponse with list of eclipse events.
Tips for LLMs: - Most years have 2 solar eclipses, some have 3, rarely 4 - After finding an eclipse date, use get_solar_eclipse_by_date to check visibility
Example: eclipses = await get_solar_eclipses_by_year(2024) for eclipse in eclipses.eclipses_in_year: print(f"{eclipse.event} on {eclipse.year}-{eclipse.month}-{eclipse.day}")
Inputs: year (required).
get_sun_moon_dataA
Get complete sun and moon data for one day at a specific location.
Provides rise, set, and transit times for the sun and moon, twilight times, moon phase, and illumination percentage. Essential for planning outdoor activities, photography, navigation, and astronomical observations.
Args: date: Date in YYYY-MM-DD format. No leading zeros required. latitude: Latitude in decimal degrees. Range: -90 to 90 (negative = South, positive = North) longitude: Longitude in decimal degrees. Range: -180 to 180 (negative = West, positive = East) timezone: Timezone offset from UTC in hours (e.g., -8 for PST, 1 for CET). Positive = East of UTC, Negative = West of UTC. If not provided, UTC (0) is used. dst: Whether to apply daylight saving time adjustment. If not provided, defaults to false. label: Optional user label (max 20 characters) to identify this query in the response
Returns: OneDayResponse: GeoJSON Feature containing: - geometry: Location coordinates - properties.data: Complete sun and moon information: - sundata: List of sun events (rise, set, transit, civil twilight begin/end) - moondata: List of moon events (rise, set, transit) - curphase: Current moon phase description - fracillum: Percentage of moon illuminated (e.g., "92%") - closestphase: Details of the nearest moon phase
Tips for LLMs: - Times are in the requested timezone (or UTC if not specified) - sundata and moondata may be empty in polar regions during extreme seasons - Civil twilight is when the sun is 6 degrees below horizon - Use fracillum to determine moon brightness for night photography or stargazing - Moon transit time indicates when moon is highest in the sky (best viewing)
Example: data = await get_sun_moon_data( date="2005-9-20", latitude=47.60, longitude=-122.33, timezone=-8, dst=True ) sunrise = next(e for e in data.properties.data.sundata if e.phen == "Rise") print(f"Sunrise at {sunrise.time}")
Inputs: date (required), latitude (required), longitude (required), timezone, +2 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Each tool has a clearly distinct purpose with no overlap: get_earth_seasons (Earth's orbital events), get_moon_phases (lunar cycles), get_planet_events (planet rise/set times), get_planet_position (planet positional data), get_sky (complete sky summary), get_solar_eclipse_by_date (local eclipse details), get_solar_eclipses_by_year (yearly eclipse list), and get_sun_moon_data (daily sun/moon times). The descriptions reinforce these boundaries, making tool selection unambiguous.
All tools follow a consistent verb_noun pattern with 'get_' prefix and snake_case: get_earth_seasons, get_moon_phases, get_planet_events, get_planet_position, get_sky, get_solar_eclipse_by_date, get_solar_eclipses_by_year, get_sun_moon_data. This predictability aids agent understanding and tool discovery.
With 8 tools, the server is well-scoped for its celestial/astronomical domain. Each tool serves a specific, non-trivial function (e.g., planetary data, eclipse tracking, sky summaries), and none feel redundant or excessive. The count aligns with typical MCP server ranges (3-15 tools) for comprehensive coverage.
The toolset provides strong coverage for astronomical queries, including planetary positions, lunar phases, solar eclipses, and sky summaries. Minor gaps exist, such as no tool for stellar data (stars/constellations) or historical astronomical events, but core workflows (e.g., 'what's visible tonight?', eclipse planning) are well-supported without dead ends.
Maintenance
Related MCP Connectors
Offline observational astronomy: positions, rise/set, moon phases, eclipses, and seasons.
Read-only astronomy calculations: sun, moon, planets, eclipses, twilight and star positions.
Elevation-corrected sun, moon, twilight, solar and tide data for any point on Earth
Next solar eclipse, eclipse times by place, Moon phases and seasons from the US Naval Observatory.
Related MCP Servers
- AlicenseAqualityBmaintenanceCalculate the altitude, rise, and set times of celestial objects (Sun, Moon, planets, stars, and deep-space objects) for any location on Earth.21531 PyPIMIT
- AlicenseNot gradedqualityDmaintenanceProvides astronomical data including ISS tracking, moon phases, NASA APOD, near-Earth objects, exoplanets, space weather, and upcoming celestial events without requiring an API key.21 PyPIMIT
- AlicenseAqualityDmaintenanceEnables timezone conversion, astronomical calculations, and date utilities through natural language, supporting sunrise/sunset, moon phases, business days, and more.913 npm1ISC
- AlicenseAqualityCmaintenanceProvides deterministic computation of magnetic declination and sky positions (sun, moon, planets) for any location and time, enabling agents to get accurate ephemeris and geomagnetic data without hallucination.2149 PyPIMIT