Skip to main content
Glama
skyportal-mcp

skyportal-mcp

skyportal-mcp

Beta: This project is under active development. Bug reports, feature requests, and pull requests are very welcome — please open an issue or submit a PR.

A local MCP (Model Context Protocol) server for SkyPortal and Fritz. It runs on your own machine and exposes SkyPortal data as tools that AI coding assistants — Claude Code, Claude Desktop, Cursor — can call directly. Query astronomical transient data — photometry, spectra, classifications, observability — without leaving your AI assistant.

Compatibility: This has been tested with Claude Code and Claude Desktop. It has not been tested with other MCP-compatible clients (e.g., Cursor, OpenAI Codex, Gemini, or other services) — the setup steps for those clients may differ from the instructions below.

Installation

git clone https://github.com/AnastasiaKWei/skyportal-mcp.git
cd skyportal-mcp
pip install -e .

Related MCP server: nasa

Configuration

Set two environment variables:

export SKYPORTAL_URL="https://fritz.science"    # Your SkyPortal/Fritz instance
export SKYPORTAL_TOKEN="your-api-token-here"    # From your profile page

For Fritz, get your token at https://fritz.science/profile — click your username, scroll to API Token, and copy it.

Claude Code

Add to your Claude Code MCP config (~/.claude.json):

{
  "mcpServers": {
    "skyportal": {
      "command": "python",
      "args": ["-m", "skyportal_mcp"],
      "env": {
        "SKYPORTAL_URL": "https://fritz.science",
        "SKYPORTAL_TOKEN": "your-token"
      }
    }
  }
}

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "skyportal": {
      "command": "python",
      "args": ["-m", "skyportal_mcp"],
      "env": {
        "SKYPORTAL_URL": "https://fritz.science",
        "SKYPORTAL_TOKEN": "your-token"
      }
    }
  }
}

Cursor

Add to .cursor/mcp.json in your project root:

{
  "mcpServers": {
    "skyportal": {
      "command": "python",
      "args": ["-m", "skyportal_mcp"],
      "env": {
        "SKYPORTAL_URL": "https://fritz.science",
        "SKYPORTAL_TOKEN": "your-token"
      }
    }
  }
}

Available Tools

Read vs Write

  • Read — queries data from SkyPortal/Fritz; no data is created or modified.

  • Write (SkyPortal) — can create, update, or delete data in your SkyPortal/Fritz account. Use with care; these operations may not be reversible.

  • Write (local) — creates files on your local machine (notebooks, CSVs). Does not touch SkyPortal.

Source Data — source_products.py

Tool

Mode

Description

get_source_photometry

Read

Light curve data as CSV (mag or flux format)

get_source_spectra

Read

Spectroscopic observations (summary, CSV, or JSON)

get_source_classifications

Read

Classification history with probabilities

get_source_comments_and_annotations

Read

User comments and ML annotations

get_source_host_galaxy

Read

Host galaxy properties and offset

get_tns_summary

Read

Complete TNS/AstroNote report in one call

Analysis — analysis.py

Tool

Mode

Description

analyze_light_curve

Read / Write (local)

Rise/fade times, peak brightness; notebook mode writes .ipynb + CSV to disk

analyze_color_evolution

Read / Write (local)

Color curves (g-r); notebook mode writes .ipynb + CSV to disk

Observing — observing.py, astro_utils.py

Tool

Mode

Description

get_source_observability

Read

Observing windows from Keck, VLT, Gemini, Palomar, etc.

convert_time

Read

MJD / JD / ISO / Unix time conversion

get_survey_urls

Read

Links to Legacy Survey, PanSTARRS, SDSS, NED, SIMBAD, etc.

search_sources_near_position

Read

Cone search in SkyPortal

Filtering — filtering.py

Tool

Mode

Description

filter_candidates

Read

Search the scanning page for candidates matching criteria

get_candidate_filter_reference

Read

Documentation for available filter parameters

generate_watchlist_filter

Read

Generate MongoDB pipeline JSON for a watchlist (output only, not saved to Fritz)

Bulk Analysis — bulk_analysis.py

Tool

Mode

Description

generate_bulk_lightcurve_code

Write (local)

Writes a Jupyter notebook to ztf_lightcurves/ for bulk ZTF light curve downloads

generate_cone_search_code

Write (local)

Writes code to ztf_cone_search/ for multi-position cone searches

generate_fritz_bulk_query_code

Write (local)

Writes a notebook to fritz_data/ for bulk Fritz photometry/spectra downloads

generate_alert_download_code

Write (local)

Writes a notebook to ztf_alerts/ for downloading ZTF alert packets

generate_field_visualization_code

Write (local)

Writes code to visualize ZTF field and CCD coverage

API Access — api.py

Tool

Mode

Description

call_skyportal_api

Read / ⚠️ Write (SkyPortal)

Direct API calls to any endpoint — POST/PUT/DELETE will modify your SkyPortal account

get_api_quick_reference

Read

API endpoint documentation

get_tools_quick_reference

Read

Tool usage guide

Test Prompts

Try these prompts after connecting to verify the tools work. Replace source names with ones you have access to on your SkyPortal instance.

Source Data

Photometry:

"Get the g and r band photometry for ZTF20acigmel"

Expects: CSV table with MJD, filter, mag, magerr columns. Should return both ztfg and ztfr data points.

Spectra:

"Show me the spectra for ZTF20acigmel"

Expects: Summary listing each spectrum with date, instrument, wavelength range, and a Fritz link.

Classifications:

"What are the classifications for ZTF20acigmel?"

Expects: List of classifications with type (e.g., SN Ia), probability, classifier name, and date.

Comments and annotations:

"Show me the comments and ML annotations for ZTF20acigmel"

Expects: User comments with text/author/date, plus annotation key-value pairs (e.g., braai score, cross-match results).

Host galaxy:

"What is the host galaxy of ZTF20acigmel?"

Expects: Galaxy name, coordinates, redshift, distance, stellar mass, and angular offset from the transient.

TNS summary:

"Generate a TNS report for ZTF20acigmel"

Expects: Formatted report with coordinates (deg + HMS/DMS), discovery info, photometry summary, classification, spectroscopy, and host galaxy — ready to paste into a TNS submission.

Analysis

Light curve analysis (text):

"Analyze the light curve of ZTF20acigmel in g and r bands. Give me a text summary."

Expects: Per-band summary with peak magnitude, peak date, rise time, fade time, and duration.

Light curve analysis (notebook):

"Analyze the light curve of ZTF20acigmel and generate a notebook"

Expects: Creates a Jupyter notebook with interactive Plotly light curve plots and editable analysis code cells.

Color evolution (text):

"What is the g-r color evolution of ZTF20acigmel? Text summary please."

Expects: Color at peak, color trend (bluing/reddening/stable), and a table of color measurements over time.

Observing

Observability:

"When can I observe ZTF20acigmel from Keck and Palomar tonight?"

Expects: Per-telescope observing windows with rise/set times (UTC and local), transit time, peak altitude, and airmass.

Time conversion:

"Convert MJD 60000 to a calendar date"

Expects: All formats — MJD, JD, ISO datetime, and Unix timestamp.

Survey links:

"Get survey links for RA=150.0, Dec=2.0"

Expects: Clickable URLs for Legacy Survey, PanSTARRS, SDSS, NED, SIMBAD, VizieR, WISE, DSS, and others.

Cone search:

"Search for sources within 10 arcsec of RA=150.0, Dec=2.0"

Expects: List of sources sorted by separation, with source ID, coordinates, separation in arcsec, and saved groups.

API Access

Direct API call:

"Use the SkyPortal API to get the source page for ZTF20acigmel"

Expects: Raw JSON response from /api/sources/ZTF20acigmel.

Multi-Tool Prompts

These prompts exercise multiple tools in sequence, testing the AI assistant's ability to chain tool calls.

Photometry + classification + observability:

"Get the photometry and classification for ZTF20acigmel, then check if it's observable from Keck tonight"

Expects: The assistant calls get_source_photometry, get_source_classifications, and get_source_observability (either in parallel or sequentially), then synthesizes the results.

Cone search + photometry:

"Search for sources within 5 arcsec of RA=210.9, Dec=54.3 and get the photometry for any matches"

Expects: First calls search_sources_near_position, then calls get_source_photometry for each result.

TNS report + observability:

"Generate a TNS summary for ZTF20acigmel and tell me when I can observe it from VLT"

Expects: Calls get_tns_summary and get_source_observability (potentially in parallel), then presents both results.

Light curve analysis + color evolution:

"Analyze both the light curve and color evolution of ZTF20acigmel in text format"

Expects: Calls analyze_light_curve and analyze_color_evolution, presenting rise/fade metrics alongside color trend information.

License

BSD 3-Clause

Available Tools

23 tools
analyze_color_evolutionA

Analyze color evolution and color at peak brightness.

Calculates color curves (band1 - band2) using BOTH methods:

  • Matched: Day-to-day colors (pairs close observations)

  • Interpolated: Rolling/continuous colors (interpolates for smooth curve)

Generates CSV data file + Jupyter notebook with overlaid plots.

Inputs: source_name (required), band1, band2, max_data_gap, +2 more. Returns: result

analyze_light_curveA

Analyze light curve evolution for multiple photometric bands.

Calculates key temporal properties of a transient's light curve including rise time, fade time, total duration, and pre-peak variability (flares) for each requested photometric band.

Handles incomplete light curves:

  • Still rising: Reports time from first detection to current

  • Still fading: Reports time from peak to current

  • Returned to baseline: Reports complete rise + fade times

Generates CSV data file + Jupyter notebook with interactive Plotly plots showing all bands overlaid, plus editable analysis code cells.

Inputs: source_name (required), filter_names, output_format, baseline_threshold. Returns: result

call_skyportal_apiA

Make an API call to SkyPortal.

⚠️ WRITE RISK: POST, PUT, and DELETE requests will permanently modify or delete data on your SkyPortal/Fritz instance. These operations cannot be undone through this tool. Always confirm the endpoint and payload before using a non-GET method.

Inputs: endpoint (required), data, method, params. Returns: result

convert_timeA

Convert between MJD, JD, ISO datetime, and Unix timestamps.

Inputs: value (required), to_format, from_format. Returns: result

filter_candidatesA

Search for candidates matching specific criteria on the scanning page.

This performs query-time filtering of existing candidates (not alert-time filtering). Use this to search the scanning page for candidates matching specific properties.

IMPORTANT - Parameter Validation: Before executing this tool, ALWAYS confirm with the user that the filter parameters are reasonable. Explain what the filter will return and ask if they want to proceed. Examples:

  • "I'll search for SNe Ia with braai score > 0.9 saved after 2024-01-01. Proceed?"

  • "This will find likely galaxy transients (sgScore < 0.3). OK?"

  • "Filtering for TDE candidates with ACAI_score > 0.8. Sound good?"

IMPORTANT - After Results: After showing results, offer to display the filter configuration JSON so the user can save it for future use or configure it in the UI.

Inputs: group_id, page_number, saved_after, max_redshift, +9 more. Returns: result

generate_alert_download_codeA

Generate code to download ZTF alert packets for multiple sources.

This tool generates code that downloads raw ZTF alert packets, which contain the full alert history including candidate info, cutouts, and previous detections.

Use Case: When you need complete alert history or want to access alert-level data that isn't available in forced photometry.

Inputs: sources (required), with_cutouts. Returns: result

generate_bulk_lightcurve_codeA

Generate a Jupyter notebook to bulk download ZTF light curves from Fritz.

Creates a ready-to-run .ipynb notebook that uses ztfquery's Fritz integration to download alert photometry (detection epochs) for multiple sources with multiprocessing, save results to CSV, and create interactive Plotly plots.

Note: This downloads alert photometry, not forced photometry. For forced photometry (including non-detections/upper limits), use the IRSA ZTF forced photometry service.

Requires: ztfquery + Fritz API token. Setup: from ztfquery.io import set_account; set_account('fritz', token_based=True)

Inputs: sources (required), filters, include_plots. Returns: result

generate_cone_search_codeA

Generate code to perform ZTF cone searches at multiple positions.

This tool generates Python code that searches for ZTF detections within a radius of specified sky coordinates. Useful for cross-matching catalogs or checking if known positions have ZTF coverage.

Use Case: When you have a list of coordinates (e.g., from a catalog, TNS, or previous observations) and want to find all ZTF detections nearby.

Inputs: coordinates (required), radius_arcsec. Returns: result

generate_field_visualization_codeA

Generate code to visualize ZTF field and CCD coverage.

This tool generates code to create sky maps showing ZTF field footprints and CCD layouts. Useful for understanding coverage and planning observations.

Use Case: When you need to visualize which parts of the sky are covered by specific ZTF fields or CCDs.

Inputs: field_id (required), ccd_id. Returns: result

generate_fritz_bulk_query_codeA

Generate code to bulk query Fritz/SkyPortal for multiple sources.

This tool generates code that uses ztfquery's Fritz interface to download photometry, spectra, and metadata for multiple sources from Fritz.

Use Case: When you need to download data products from Fritz for many sources at once (faster than individual API calls).

Note: Requires Fritz API token. Setup: from ztfquery.io import set_account; set_account('fritz', token_based=True)

Inputs: sources (required), include_spectra. Returns: result

generate_watchlist_filterA

Generate MongoDB filter JSON for a watchlist to monitor specific coordinates.

Watchlists are alert-time filters that flag new detections near specified sky positions. They run on the Kowalski backend as part of Fritz's alert stream processing. This tool generates the MongoDB aggregation pipeline JSON compatible with Fritz's filter system.

IMPORTANT - This is an ALERT-TIME filter:

  • Runs automatically on every incoming alert from the telescope

  • Different from query-time filtering (filter_candidates tool)

  • Uses MongoDB aggregation pipeline syntax

RECOMMENDED WORKFLOW (MongoDB Compass): Fritz now recommends using MongoDB Compass for filter development:

  1. Follow the tutorial: https://github.com/fritz-marshal/fritz/blob/main/doc/filter_tutorial.md

  2. Use MongoDB Compass to build and test filters visually

  3. Export the pipeline from Compass

  4. Import to Fritz

ALTERNATIVE - Direct Use: You can also use the generated JSON directly:

  1. Copy the generated JSON

  2. Import to Fritz or use in MongoDB Compass as a starting point

  3. Refine and test as needed

Inputs: targets (required), filter_name, max_distance_arcsec. Returns: result

get_api_quick_referenceA

Get the SkyPortal API quick reference guide.

Returns a reference of available API endpoints, required parameters, and usage patterns. Call once to load into context as needed.

Inputs: no named parameters. Returns: result

get_candidate_filter_referenceA

Get the reference for filtering candidates and sources on Fritz/SkyPortal.

Returns documentation on available query parameters for the /api/candidates endpoint: annotation-based filters for ML scores (real/bogus, star/galaxy), classification filters, redshift, photometry annotations, and more.

Call this when a user asks to filter, search, or scan for specific types of transients. It tells you what's filterable via API queries vs what requires fetching data and doing custom computation.

Note: This is for query-time filtering (scanning page searches), NOT for creating alert-time MongoDB filters that run on Kowalski.

Inputs: no named parameters. Returns: result

get_source_classificationsA

Retrieve classifications for a source.

Returns all classifications assigned to the source, including the classification name, probability, and who made the classification.

Inputs: source_name (required). Returns: result

get_source_comments_and_annotationsA

Retrieve comments and annotations for a source.

Returns a summary of user comments and system/ML annotations on the source. Comments are human-readable notes; annotations are structured data (e.g., ML scores, cross-match results).

Inputs: source_name (required). Returns: result

get_source_host_galaxyA

Retrieve host galaxy information for a source.

Returns the associated host galaxy from SkyPortal's galaxy catalogs, including angular separation (offset) and physical distance.

SkyPortal can link sources to host galaxies from catalogs like GLADE+. If a host association exists, this returns the galaxy's properties.

Inputs: source_name (required). Returns: result

get_source_observabilityA

Compute observing windows for a source from specified telescopes.

USE THIS TOOL for all observability questions. Do NOT use the /api/sources/{id}/observability endpoint (that returns a PDF image which cannot be parsed).

Provide either a source_id (auto-resolves RA/Dec from SkyPortal) or explicit ra/dec coordinates.

Inputs: ra, dec, date, source_id, +2 more. Returns: result

get_source_photometryA

Retrieve photometry for a source as a CSV table.

Returns all photometry points for the source in CSV format, suitable for direct analysis or loading into a pandas DataFrame.

Columns returned (mag format): mjd, filter, mag, magerr, limiting_mag, snr, instrument_name, origin

Columns returned (flux format): mjd, filter, flux, fluxerr, snr, instrument_name, origin

Inputs: source_name (required), format, magsys, filters. Returns: result

get_source_spectraA

Retrieve spectra for a source.

By default returns a summary to avoid token overflow. Use verbose=True or format="csv" to get full spectral data.

Inputs: source_name (required), format, verbose. Returns: result

get_survey_urlsA

Get URLs to browse a sky position in common astronomical surveys.

Provide either ra/dec coordinates or a source_id to auto-resolve coordinates from SkyPortal.

Inputs: ra, dec, source_id. Returns: result

get_tns_summaryA

SUMMARY TOOL: Generate complete TNS/AstroNote report for a transient.

USE THIS SINGLE TOOL when asked to create TNS reports, AstroNotes, or comprehensive source summaries. It combines all relevant data in one call.

This tool retrieves and formats ALL information needed for TNS submissions:

  • Source identification (coordinates in deg and HMS/DMS)

  • Discovery information (first detection, magnitude, date, instrument)

  • Latest photometry and peak brightness

  • Classification (type, probability, classifier)

  • Spectroscopy (dates, instruments, redshift)

  • Host galaxy information

Accepts ANY source identifier: SkyPortal obj_id, ZTF name, or TNS name.

When to use:

  • User asks to "create/generate/write TNS report"

  • User asks to "draft AstroNote" or "prepare ATel"

  • User asks for "summary of [source]"

  • User mentions "TNS submission" or "classification report"

Do NOT call multiple other tools (photometry, spectra, classifications) separately when this single tool provides everything together.

Inputs: source_name (required). Returns: result

get_tools_quick_referenceA

Get the MCP tools quick reference guide.

Returns a comprehensive list of all available MCP tools organized by category, with common workflows and usage examples. Call once to load into context when needed.

Inputs: no named parameters. Returns: result

search_sources_near_positionA

Search for sources in SkyPortal near a position (cone search).

Finds all sources within a specified radius of a sky position. Useful for checking if a source already exists in SkyPortal at a given location, or finding nearby sources.

Provide either ra/dec coordinates or a source_id to auto-resolve coordinates.

Inputs: ra, dec, source_id, num_per_page, +1 more. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 23 tools

    Disambiguation4/5

    Most tools target distinct resources (photometry, spectra, classifications, host galaxy, etc.) with clear boundaries. The cluster of generate_* code generation tools and reference tools could confuse, but detailed descriptions and explicit usage guidance mitigate this.

    Naming Consistency5/5

    All tool names follow a consistent snake_case verb_noun pattern (get_source_*, generate_*, analyze_*, filter_candidates, call_skyportal_api). No mixed conventions or irregular styles.

    Tool Count3/5

    23 tools is on the heavy side, falling into the borderline range. Several code generation and reference tools could potentially be merged, but each serves a distinct workflow within the astronomical transient domain.

    Completeness4/5

    The set covers core workflows: source data retrieval, analysis, searching, filtering, and code generation. General API access via call_skyportal_api fills write/update gaps, though dedicated CRUD tools for some entities are absent.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      MCP server that provides tools to query 17+ astronomical databases (e.g., SIMBAD, VizieR, Gaia) via HTTP/TAP APIs, enabling AI applications to access astronomical data through natural language.
      23
      22 npm
      2
      BSD 3-Clause
    • A
      license
      A
      quality
      B
      maintenance
      A local, open-source MCP server that wraps astronomy data services (SIMBAD, JPL Horizons, VizieR, etc.) behind a conversational interface, enabling AI assistants to answer astronomy questions with real, typed, and provenance-tracked data.
      13
      1
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      An MCP server that equips LLM clients with authoritative astrodynamics tools including TLE/SGP4 propagation, Lambert solving, ground-station access, time-scale and coordinate-frame conversions, and more.
      84 PyPI
      2
      MIT