# xhelio-spice Spacecraft ephemeris made easy — auto-managed SPICE kernels for heliophysics missions. **xhelio-spice** wraps [SpiceyPy](https://github.com/AndrewAnnex/SpiceyPy) with automatic kernel download, caching, and loading. Ask for a spacecraft position and xhelio-spice handles the rest: downloading the right NAIF kernels, loading them in the correct order, and returning results as Python dicts or pandas DataFrames. ## Installation ```bash pip install xhelio-spice ``` For MCP server support (Claude Desktop, Claude Code, Cursor, etc.): ```bash pip install xhelio-spice[mcp] ``` ## Quick Start ```python from xhelio_spice import get_position, get_trajectory # Where is Parker Solar Probe right now? pos = get_position("PSP", observer="SUN", time="2024-01-15", frame="ECLIPJ2000") print(f"PSP is {pos['r_au']:.3f} AU from the Sun") # Get a month of trajectory data as a DataFrame df = get_trajectory( "PSP", observer="SUN", time_start="2024-01-01", time_end="2024-01-31", step="1h", frame="ECLIPJ2000", ) print(df[["r_au"]].describe()) ``` Kernels are automatically downloaded from [NAIF](https://naif.jpl.nasa.gov/) on first use and cached in `~/.xhelio_spice/kernels/`. ## Supported Missions ### With SPICE Kernels (auto-downloaded) - **PSP** (Parker Solar Probe) — 2018-2030 - **Solar Orbiter** (SOLO) — 2020-2030 - **STEREO-A** — 2017-2031 - **Juno** — 2011-present (updated regularly) - **Voyager 1/2** — 1981-2100 / 1989-2100 - **New Horizons** — 2019-2030 ### NAIF IDs Only (no auto-download yet) - **ACE**, **Wind**, **DSCOVR**, **MMS** (1-4) — no public SPK kernels exist - **Cassini**, **MAVEN** — require multi-segment kernel loading (planned) - **Galileo**, **Pioneer 10/11**, **Ulysses**, **MESSENGER**, **STEREO-B** ### Natural Bodies Sun, Earth, Moon, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto ## API Reference ### Position & Trajectory ```python from xhelio_spice import get_position, get_trajectory, get_state # Single position pos = get_position("ACE", observer="EARTH", time="2024-06-01", frame="GSE") # Full state (position + velocity) state = get_state("PSP", observer="SUN", time="2024-01-15", frame="ECLIPJ2000") # Trajectory timeseries (returns pandas DataFrame) df = get_trajectory( "Cassini", observer="SATURN", time_start="2010-01-01", time_end="2010-12-31", step="6h", frame="ECLIPJ2000", include_velocity=True, ) ``` ### Coordinate Transforms ```python from xhelio_spice import transform_vector, list_available_frames # J2000 to Ecliptic v_ecl = transform_vector([1.0, 0.0, 0.0], "2024-01-15", "J2000", "ECLIPJ2000") # RTN transform (requires spacecraft) v_rtn = transform_vector( [5.0, -3.0, 1.0], "2024-01-15", from_frame="ECLIPJ2000", to_frame="RTN", spacecraft="PSP", ) # List all frames print(list_available_frames()) ``` ### Mission Registry ```python from xhelio_spice import resolve_mission, list_supported_missions # Resolve name aliases naif_id, key = resolve_mission("Parker Solar Probe") # -> (-96, "PSP") # List all spacecraft missions = list_supported_missions() ``` ### Kernel Management ```python from xhelio_spice import get_kernel_manager km = get_kernel_manager() km.ensure_mission_kernels("PSP") # Download + load print(km.get_cache_info()) # Cache stats km.unload_all() # Free memory ``` ## Configuration | Method | Description | |--------|-------------| | `XHELIO_SPICE_KERNEL_DIR` env var | Override kernel cache directory | | `KernelManager(kernel_dir=...)` | Per-instance override | | Default | `~/.xhelio_spice/kernels/` | ## MCP Server xhelio-spice includes an [MCP](https://modelcontextprotocol.io/) server for LLM tool use: ```bash # Run directly xhelio-spice-mcp # Or via Python python -m xhelio_spice.server ``` ### Claude Desktop Configuration Add to `claude_desktop_config.json`: ```json { "mcpServers": { "xhelio-spice": { "command": "xhelio-spice-mcp" } } } ``` ### Available MCP Tools | Tool | Description | |------|-------------| | `get_ephemeris` | Position/velocity — single time (inline) or timeseries (CSV) | | `compute_distance` | Distance between two bodies | | `transform_coordinates` | Coordinate frame transform | | `list_spice_missions` | Supported missions | | `list_coordinate_frames` | Available frames with descriptions | | `manage_kernels` | Kernel cache management | ### MCP smoke test For a CI-safe MCP check that does not request kernel downloads, run: ```bash uv run --extra mcp python scripts/smoke_mcp_list_tools.py --json ``` The smoke starts the stdio server with an isolated temporary kernel cache, runs MCP `initialize` + `list_tools`, and verifies the advertised tool names. ## License MIT