skyportal-mcp
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., "@skyportal-mcp get photometry data for supernova ZTF24abcd"
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.
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 pageFor 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 |
| Read | Light curve data as CSV (mag or flux format) |
| Read | Spectroscopic observations (summary, CSV, or JSON) |
| Read | Classification history with probabilities |
| Read | User comments and ML annotations |
| Read | Host galaxy properties and offset |
| Read | Complete TNS/AstroNote report in one call |
Analysis — analysis.py
Tool | Mode | Description |
| Read / Write (local) | Rise/fade times, peak brightness; notebook mode writes |
| Read / Write (local) | Color curves (g-r); notebook mode writes |
Observing — observing.py, astro_utils.py
Tool | Mode | Description |
| Read | Observing windows from Keck, VLT, Gemini, Palomar, etc. |
| Read | MJD / JD / ISO / Unix time conversion |
| Read | Links to Legacy Survey, PanSTARRS, SDSS, NED, SIMBAD, etc. |
| Read | Cone search in SkyPortal |
Filtering — filtering.py
Tool | Mode | Description |
| Read | Search the scanning page for candidates matching criteria |
| Read | Documentation for available filter parameters |
| Read | Generate MongoDB pipeline JSON for a watchlist (output only, not saved to Fritz) |
Bulk Analysis — bulk_analysis.py
Tool | Mode | Description |
| Write (local) | Writes a Jupyter notebook to |
| Write (local) | Writes code to |
| Write (local) | Writes a notebook to |
| Write (local) | Writes a notebook to |
| Write (local) | Writes code to visualize ZTF field and CCD coverage |
API Access — api.py
Tool | Mode | Description |
| Read / ⚠️ Write (SkyPortal) | Direct API calls to any endpoint — POST/PUT/DELETE will modify your SkyPortal account |
| Read | API endpoint documentation |
| 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 toolsanalyze_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:
Follow the tutorial: https://github.com/fritz-marshal/fritz/blob/main/doc/filter_tutorial.md
Use MongoDB Compass to build and test filters visually
Export the pipeline from Compass
Import to Fritz
ALTERNATIVE - Direct Use: You can also use the generated JSON directly:
Copy the generated JSON
Import to Fritz or use in MongoDB Compass as a starting point
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
Scored across 23 tools
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.
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.
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.
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
Related MCP Connectors
MCP server that lets AI assistants use all OneSchema features exposed via the public API.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Related MCP Servers
- AlicenseBqualityDmaintenanceMCP 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.2322 npm2BSD 3-Clause
- FlicenseNot gradedqualityDmaintenanceMCP server that wraps three NASA public APIs (Astronomy Picture of the Day, Mars rover photos, and near-Earth objects) as tools for AI assistants.-
- AlicenseAqualityBmaintenanceA 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.131MIT
- AlicenseNot gradedqualityBmaintenanceAn 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 PyPI2MIT