astronomy-mcp-server
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., "@astronomy-mcp-serverWhat is the phase of the moon today?"
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.
Public Hosted Server: https://astronomy.caseyjhand.com/mcp
Overview
Observational astronomy computed in-process by astronomy-engine and a bundled bright-star catalog. Get sky positions, rise/set and twilight times, moon phases, and the next eclipse, equinox, opposition, or conjunction for any place and time, or ask what is visible right now. Two opt-in, network-backed tools add JPL Horizons small-body ephemerides and CelesTrak satellite passes. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
Tool | Description |
| Apparent position of one body or named star: RA/Dec, alt/az, ecliptic, magnitude, phase, Sun elongation, constellation |
| Rise, set, and transit times for a body, plus civil, nautical, and astronomical twilight for the Sun |
| Illuminated fraction, phase name, synodic age, and the next four quarter phases |
| Next eclipses, equinoxes, solstices, moon quarters, oppositions, conjunctions, greatest elongations, or apsides |
| What's up now: naked-eye bodies (and optional bright stars) above the horizon, ranked, with a sky-condition gate |
| Small-body or spacecraft ephemeris from JPL Horizons (opt-in) |
| Visible satellite passes from a CelesTrak element set propagated with SGP4 (opt-in) |
Resources
Resource | Description |
| Reference card for a solar-system body: name, type, mean radius, naked-eye visibility |
Tool-only clients get the same type, radius, and naked-eye fields inline from astronomy_get_sky_position.
Prompts
Prompt | Description |
| Plan a night of stargazing from a place, chaining the astronomy tools with geocoding and weather steps |
Design reference: docs/design.md.
Related MCP server: Precision astronomical ephemeris and planetary positions via the Swiss Ephemeris.
Capability reference
astronomy_get_sky_position tool
body(sun,moon,mercury…pluto) orstaris required, withstarwinning when both are set;starresolves against a bundled 32-star catalog by common name or Bayer designation (Sirius,α CMa), and a miss fails asstar_not_foundlisting the catalogReturns
equatorial, refraction-correctedhorizontal, andeclipticcoordinates plusmagnitude,angular_diameter_arcsec,phase_angle_degrees,illuminated_fraction,sun_elongation_degrees, andconstellationSolar-system bodies also carry
body_metadata, the resource card'stype,mean_radius_km, andnaked_eye; a star has none
astronomy_get_rise_set tool
One
bodysearched forward fromstart(default now) for the nextcountcycles, default 1, max 31Each cycle carries
rise_utc,set_utc,transit_utc, andtransit_altitude_degrees; a circumpolar or never-rising body getsnullrise/set and anoteinstead of an error, and one already up atstartgets anullrise_utcFor
body: "sun", atwilightblock holdscivil,nautical, andastronomicalpairs covering the night after that cycle's set, so eachdawn_utcfalls the day after the cycle's rise
astronomy_get_moon_phase tool
Geocentric: takes only
time(default now) and an optionaltimezoneReturns
illuminated_fraction,phase_name,age_days,next_quarters, andphase_longitude_degrees(0 new, 180 full), which is not thephase_angle_degreesofastronomy_get_sky_position
astronomy_find_events tool
One
event(solar_eclipse,lunar_eclipse,equinox,solstice,moon_quarter,opposition,conjunction,max_elongation,perigee_apogee) and the nextcountoccurrences, default 1, max 20; searches stop at the end of 2100, with a notice when that returns fewerBody-relative events require
body(body_required), and a body the event doesn't apply to fails asbody_not_supported:oppositiontakes mars through pluto,conjunctionany planet,max_elongationmercury or venus, andperigee_apogeethe moon,earth, or a planet;apsis_kindandconjunction_kindlabel which kind came backEclipses take an optional observer (
latitudeandlongitudetogether, elseincomplete_observer) that addslocal_visibleandcontact_altitudes_degreesand limitssolar_eclipseto locally visible events; a global solar search reportspeak_latitude_degrees/peak_longitude_degreesfor total and annular eclipses
astronomy_list_visible tool
Observer coordinates and one evaluation instant,
time(default now, not a window);min_altitude(default 0) andinclude_stars(default false) shape the listReturns
sky_condition(daylight,civil_twilight,nautical_twilight,astronomical_twilight,dark),sun_altitude_degrees, andbodiesranked brightest-and-highest first, each with avisibility_notethat says when daylight, civil twilight, or Sun glare within 15° hides or dims it
astronomy_get_ephemeris tool
designationis passed to Horizons verbatim ("433;"for a numbered asteroid,"DES=1P;CAP"for a periodic comet, a negative SPK-ID for a spacecraft);startdefaults to now,stopto 24 h later, andstepto"1h"(a count plusm,h,d,mo, ory);latitudeandlongitudetogether add alt/azUp to 200 rows inline, and when
truncatedis true the notice names thestartto resume from;target_nameis the object Horizons resolved, since a bare name can land on the wrong one; misses fail asbody_not_found, and spans outside the target's Horizons data astime_out_of_rangeRegistered only when
ASTRONOMY_ENABLE_HORIZONS=true
astronomy_get_satellite_passes tool
Exactly one of
norad_idorname(ISS, Hubble/HST, and Tiangong/CSS resolve directly; other names are substring-matched against CelesTrak, and an ambiguous one fails asambiguous_satellite_namelisting candidates);startmust be within about a month of today, anddaysdefaults to 7, max 10Returns
norad_id,satellite_name, and naked-eye-plausiblepasses(sunlit at peak, observer sky dark), each with rise/peak/set times and azimuths,peak_altitude_degrees, andduration_secondsRegistered only when
ASTRONOMY_ENABLE_SATELLITES=true
astronomy://body/{body} resource
{body}is one ofsun,moon,mercury…pluto, with name completion; anything else fails asunknown_bodyapplication/jsoncard withbody,name,type(star/planet/moon/dwarf),mean_radius_km, andnaked_eye
astronomy_stargazing_plan prompt
Arguments:
locationrequired;date(YYYY-MM-DD) optional, defaults to tonightReturns one user message that chains
astronomy_get_rise_set(sun, then moon),astronomy_get_moon_phase, andastronomy_list_visiblewithinclude_stars, anchored to the observer's local night, plus the geocoding and weather steps this server doesn't cover
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Astronomy-specific:
Keyless, offline, deterministic core: the five core tools need no network, API key, or rate limit, and return the same answer for the same body, time, and observer
Times outside the engine's high-accuracy span (≈1900–2100) fail as
time_out_of_range; the Horizons tool is bounded by each target's own data span insteadTimes are ISO 8601 UTC, and a value with no zone is read as UTC; pass an IANA
timezone(or setASTRONOMY_DEFAULT_TIMEZONE) to get*_localfields alongside UTC. The server never infers a timezone from coordinatesNo geocoding: resolve a place name to latitude/longitude and a timezone upstream, then pass the coordinates (
elevationdefaults to 0 m)The two opt-in extensions each carry their own timeout and retry; an upstream failure surfaces as
horizons_unavailableorcelestrak_unavailableand never falls back to core output
Agent-friendly output:
Uncertainty preserved:
magnitude,angular_diameter_arcsec,phase_angle_degrees, andilluminated_fractionarenullwhere the engine can't compute them, rendered as "unavailable", never zeroedDeterministic visibility notes:
visibility_notecomes from real magnitude, altitude, sky condition, and Sun elongation, not a synthetic scoreTyped error contracts: each declared failure carries a typed
reasonand a recovery hint, so callers can correct and retryExact values behind rounded text:
format()pairs each rounded figure with its exact value in brackets (RA 4.4116 h [4.411597993526305]), so acontent[]-only client loses no precision
Getting started
Public Hosted Instance
A public instance is available at https://astronomy.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"astronomy-mcp-server": {
"type": "streamable-http",
"url": "https://astronomy.caseyjhand.com/mcp"
}
}
}Self-Hosted / Local
Add the following to your MCP client configuration file. The core tools need no configuration; set ASTRONOMY_ENABLE_HORIZONS and/or ASTRONOMY_ENABLE_SATELLITES to true to register the extensions.
{
"mcpServers": {
"astronomy-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/astronomy-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"astronomy-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/astronomy-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with Docker:
{
"mcpServers": {
"astronomy-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/astronomy-mcp-server:latest"]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.4.0 or higher (or Node.js v24+).
No API key. The core is offline, and both extensions (JPL Horizons, CelesTrak) are keyless.
Installation
Clone the repository:
git clone https://github.com/cyanheads/astronomy-mcp-server.gitNavigate into the directory:
cd astronomy-mcp-serverInstall dependencies:
bun installConfigure environment (optional):
cp .env.example .env
# edit .env only to enable the extensions or override a defaultConfiguration
Every variable is optional; the core runs with none set.
Variable | Description | Default |
| Register |
|
| Register |
|
| Fallback IANA timezone when a call omits | none |
| HTTP timeout for Horizons and CelesTrak requests, in ms. |
|
| In-process element-set cache TTL, in ms. The 2 h default follows CelesTrak's refetch guidance. |
|
| JPL Horizons API endpoint. |
|
| CelesTrak GP endpoint. |
|
| Transport: |
|
| HTTP server port. |
|
| HTTP session mode: |
|
| Authentication: |
|
| Log level ( |
|
| Enable OpenTelemetry. |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t astronomy-mcp-server .
docker run --rm -p 3010:3010 astronomy-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/astronomy-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| Prompt definitions ( |
| Offline compute core — |
| JPL Horizons HTTP client (extension). |
| CelesTrak element-set fetch and SGP4 propagation (extension). |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources in the
createApp()arrays insrc/index.tsNormalize raw engine/API values to the domain type; preserve uncertainty as
nulland never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
Read-only astronomy calculations: sun, moon, planets, eclipses, twilight and star positions.
MCP server for aerospace calculations: orbital mechanics, ephemeris, DSN operations, ...
Official Divine API MCP for Western Astrology: Natal, Synastry, Transit, Composite, Progressions.
78 astrology calculations, Tarot, symbolic readings and Vedic calendars via two scoped MCP tools.
Related MCP Servers
- AlicenseAqualityFmaintenanceProvides authoritative astronomical data including moon phases, solar eclipses, and sun/moon rise and set times using the US Navy API or offline Skyfield calculations. It enables users to query Earth's seasons and celestial events for any location and date.81Apache 2.0
- AlicenseNot gradedqualityCmaintenanceA self-contained MCP server that gives AI agents the ability to calculate high-precision astronomical data. It provides tropical zodiac coordinates, planetary speeds, retrograde detection, and house cusps using the trusted Swiss Ephemeris engine. 100%19 PyPI4AGPL 3.0
- AlicenseAqualityCmaintenanceAstrology MCP server that computes natal charts, transits, synastry, progressions, returns, eclipses, retrogrades, and moon phases from a real ephemeris, enabling AI agents to provide accurate astrological calculations without hallucination.1261 npm1MIT
- AlicenseAqualityAmaintenancePrecision-audited astrology MCP for natal charts, transits, synastry and moon phases. No API key.1061 npmMIT