SkyQuery developer portal
Everything you need to drive SkyQuery from code, a terminal, or an AI agent: a five-minute quickstart, the offline sandbox, the full MCP tool reference, the CLI, and the public metadata API.
Quickstart
SkyQuery requires Python 3.12 or newer.
# Install the CLI and the MCP server from source
uv tool install git+https://github.com/KarthikSubramanian07/skyquery
# Prove it works, offline, with no keys
skyquery demo
skyquery resolve Vega
skyquery --json ephemeris "99942 Apophis" --start 2029-04-13 --stop 2029-04-14
Then register the MCP server with your client. For Claude Desktop, edit claude_desktop_config.json:
{
"mcpServers": {
"skyquery": {
"command": "skyquery-mcp",
"env": { "SKYQUERY_REPLAY": "0" }
}
}
}
Omit the env block to stay in offline replay mode.
Sandbox: offline replay mode
SkyQuery ships with recorded fixtures and runs against them by default, so every example on this page works with no network and no keys. This is the sandbox: deterministic answers, zero load on public services. Leave it with --live on the CLI or SKYQUERY_REPLAY=0 in the environment.
Authentication and API keys
You do not need an account or a SkyQuery key. The metadata API on this site is public and unauthenticated. Two upstream services take an optional free key, which SkyQuery stores only in your OS keychain:
| Service | Command | Where to get a key |
|---|---|---|
| NASA ADS | skyquery login ads |
https://ui.adsabs.harvard.edu/user/settings/token |
| NASA Open APIs | skyquery login nasa |
https://api.nasa.gov/ (or keep DEMO_KEY) |
Remove a key with skyquery logout <service> and check what is set with skyquery status.
MCP tool reference
Every tool returns a typed, unit-tagged result with a provenance record. The same list, with full JSON Schemas for each tool's input, is available at /api/v1/tools.
apophis_demo
The headline demo: asteroid Apophis size, its 2029 close approach, a paper.
Answers "where is Apophis, how big is it, and what is the latest paper" in one call, combining SBDB, Horizons, and the literature with full provenance.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
with_paper |
boolean | no | true |
Returns: ApophisReport.
astronomy_picture_of_the_day
Fetch NASA's Astronomy Picture of the Day (APOD) for a date, or today.
Works with the public DEMO_KEY out of the box; configure a free NASA key via skyquery login for higher rate limits.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
date |
string or null | no | null |
Returns: AstronomyPicture.
cone_search
Return catalog sources within a radius of a position.
center may be an object name (resolved via SIMBAD) or "RA DEC" in degrees. catalog is "gaia" for Gaia DR3, or a VizieR catalog id such as "II/246" for 2MASS. Every column is unit-tagged. Radius is capped at 5 degrees and row_limit at 100 to protect free public services.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
center |
string | yes | ||
radius_deg |
number | no | 0.05 |
> 0, <= 5.0 |
catalog |
string | no | "gaia" |
|
row_limit |
integer | no | 20 |
>= 1, <= 100 |
Returns: CatalogTable.
convert_frame
Transform coordinates between reference frames (ICRS, FK5, FK4, Galactic).
Uses astropy's tested transforms, never hand-rolled trigonometry. Returns the position in the target frame with the frame explicitly labeled.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
ra_deg |
number | yes | ||
dec_deg |
number | yes | ||
from_frame |
"icrs" | "fk5" | "fk4" | "galactic" |
no | "icrs" |
|
to_frame |
"icrs" | "fk5" | "fk4" | "galactic" |
no | "galactic" |
Returns: SkyPosition.
convert_units
Convert a value between physical units with astropy's tested conversions.
Example: convert a parallax in mas, a distance in pc to ly, a velocity in km/s. Returns the converted value tagged with its new unit. Rejects unit mismatches.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
value |
number | yes | ||
from_unit |
string | yes | ||
to_unit |
string | yes |
Returns: Measurement.
crossmatch
Match a list of target names to their nearest source in a catalog.
Resolves each name to a position, then finds the nearest catalog source within tolerance_arcsec. Reports both matches (with separation) and any targets with no source inside the tolerance. At most 50 targets per call.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
targets |
array of string | yes | ||
catalog |
string | no | "gaia" |
|
tolerance_arcsec |
number | no | 5.0 |
> 0, <= 60.0 |
Returns: CrossMatchOutput.
distance_from_parallax
Convert a parallax in milliarcseconds to a distance in parsecs.
Rejects non-positive parallaxes, for which distance is undefined, rather than returning a nonsense number.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
parallax_mas |
number | yes |
Returns: Measurement.
get_ephemeris
Compute a solar-system body's apparent ephemeris from JPL Horizons.
Returns a time series of ICRS position, distance (delta, in AU), range rate, and V magnitude for a body such as "99942 Apophis", "Ceres", or "C/2023 A3". observer_location is a Horizons code; "500@399" is geocentric. This is the capability the other astronomy MCP servers skip, so prefer it for "where is <body> on <date>" questions. Windows that would exceed ~2000 samples are rejected.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
target |
string | yes | ||
start |
string | yes | UT start date, YYYY-MM-DD or YYYY-MM-DD HH:MM | |
stop |
string | yes | UT stop date, YYYY-MM-DD or YYYY-MM-DD HH:MM | |
step |
string | no | "1h" |
Sampling step such as 1h, 30m, or 1d |
observer_location |
string | no | "500@399" |
Returns: Ephemeris.
get_small_body
Look up an asteroid or comet's physical and orbital parameters (JPL SBDB).
Returns diameter, absolute magnitude, albedo, rotation period, and osculating orbital elements, each unit-tagged. Pair with get_ephemeris to answer "how big is it and where is it".
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
designation |
string | yes |
Returns: SmallBody.
object_dossier
Resolve an object and, optionally, attach recent papers about it.
Combines object intelligence with a literature lookup in one call. Use when a user asks "tell me about X" and wants both the numbers and the references.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
name |
string | yes | ||
with_papers |
boolean | no | true |
Returns: ObjectDossier.
resolve_object
Resolve an astronomical object name or identifier to normalized data.
Returns canonical coordinates (ICRS degrees), object type, cross-identifiers, and measured properties (parallax, proper motion, redshift, magnitudes), each carrying its unit and a provenance record you can cite. Try SIMBAD-style names like "Vega", "M31", "Betelgeuse", or catalog ids. This is usually the first call: downstream tools take the returned RA/Dec.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
name |
string | yes |
Returns: Object.
search_literature
Search the astronomy literature (NASA ADS, or arXiv when no ADS key is set).
Returns normalized paper records with title, authors, year, bibcode, and a resolvable URL. ADS needs a free token configured via skyquery login; without one, SkyQuery falls back to arXiv automatically. rows is capped at 50.
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
query |
string | yes | ||
rows |
integer | no | 5 |
>= 1, <= 50 |
prefer |
string | no | "ads" |
Returns: search_literatureOutput.
session_citations
Return the deduplicated acknowledgments for every source used this session.
Call this at the end of a research conversation to get a ready-to-paste citations block honoring each service's acknowledgment policy.
Takes no parameters.
Returns: session_citationsOutput.
CLI reference
Add --json before any command for machine-readable output, and --live to query live services.
| Command | What it does |
|---|---|
skyquery demo |
Apophis size, 2029 close approach, and a paper |
skyquery resolve <name> |
Resolve an object name to coordinates and measured properties |
skyquery ephemeris <target> --start --stop --step |
JPL Horizons ephemeris for a solar-system body |
skyquery small-body <designation> |
Asteroid or comet physical and orbital parameters |
skyquery cone <center> --radius --catalog --rows |
Cone search Gaia or a VizieR catalog |
skyquery literature <query> --rows --prefer |
Search ADS or arXiv |
skyquery convert <value> <from> <to> |
Unit conversion with astropy |
skyquery frame <ra> <dec> --from --to |
Coordinate frame transform |
skyquery apod --date |
NASA Astronomy Picture of the Day |
skyquery setup / status / cite |
Local directories, configuration, citations |
skyquery login <service> / logout <service> |
Manage optional keys in the OS keychain |
Metadata API
A small, public, read-only REST API describes SkyQuery's tools and data sources so agents can decide whether to install it. It does not run astronomy queries; those run locally through the MCP server or CLI. The full contract is the OpenAPI 3.1 spec.
| Method | Path | Returns |
|---|---|---|
| GET | /api/v1 |
API index with links |
| GET | /api/v1/tools |
Every MCP tool with its input JSON Schema |
| GET | /api/v1/tools/{name} |
One MCP tool |
| GET | /api/v1/sources |
Upstream data sources and whether they need a key |
| GET | /api/v1/status |
Service status and version |
curl -s https://skyquery-mcp.pages.dev/api/v1/tools/get_ephemeris
Errors
Errors are JSON with a stable machine-readable code and a hint:
{
"error": {
"status": 404,
"code": "tool_not_found",
"message": "No MCP tool named 'get_ephemerides'.",
"hint": "List valid tool names at /api/v1/tools.",
"docs": "https://skyquery-mcp.pages.dev/developers#metadata-api"
}
}
Codes: not_found, tool_not_found, method_not_allowed, rate_limited, internal_error. Responses are cacheable, CORS-enabled, and need no authentication.
Rate limits
Each client may make 600 requests per 60 seconds. Every response reports where you stand, in the IETF RateLimit header format and the common X-RateLimit-* form:
RateLimit-Policy: "default";q=600;w=60
RateLimit: "default";r=599;t=42
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-RateLimit-Reset: 42
Over the limit, the API returns 429 with a rate_limited error and a Retry-After header giving the seconds to wait. The data changes only on release, so cache responses (they allow 5 minutes) instead of polling.
Versioning and deprecation
The API version is in the path: /api/v1. The policy agents can rely on:
- Within v1, changes are additive only. New endpoints, new optional fields, and new error codes may appear. Existing fields are never removed, renamed, or retyped.
- Breaking changes ship as a new version (
/api/v2), announced in this section and in the commit history on GitHub. - An old version keeps working for at least 6 months after its successor ships. During that time its responses carry a
Deprecationheader (RFC 9745) with the date it was deprecated, aSunsetheader (RFC 8594) with the date it stops answering, and aLink: <https://skyquery-mcp.pages.dev/developers#versioning-and-deprecation>; rel="deprecation"header pointing here. - After the sunset date the old paths return
410 Gonewith a JSON error naming the replacement.
No version is deprecated today.
Machine-readable resources
- llms.txt: when and how an agent should use SkyQuery
- openapi.json: OpenAPI 3.1 description of the metadata API
- /.well-known/api-catalog: RFC 9727 API catalog
- /.well-known/mcp.json: MCP server card (also at /.well-known/mcp/server-card.json) with the install command, stdio launch command, and every tool's input schema
- Markdown versions of every page: send
Accept: text/markdown, or append.md(for example /developers.md) - Source code and issues