by SandyYuan
A modular Model Context Protocol (MCP) server that provides unified access to multiple astronomical datasets through a clean, extensible architecture.
This MCP server aims to transform big-data astronomy from a software engineering problem into a natural language conversation. Instead of spending months learning astroquery APIs, researchers simply ask for what they need and get clean, processed analysis-ready data products.
One expert solves the complexity once; thousands of scientists benefit forever. A student with little programming experience can now perform the same multi-survey analysis as an expert astronomer using nothing but natural language and an AI assistant.
This isn't just about astronomy—it's a template for democratizing all of science. Every field has brilliant researchers spending 80% of their time on data wrangling instead of discovery. By removing that bottleneck, we accelerate the pace of scientific progress itself.
The result: AI scientists that can seamlessly access and cross-match data from dozens of astronomical surveys, enabling discoveries that would have taken months of setup to attempt just a few years ago.
# Clone the repository git clone https://github.com/SandyYuan/astro_mcp.git cd astro_mcp # Create a dedicated conda environment with Python 3.11+ conda create -n mcp python=3.11 conda activate mcp # Install dependencies pip install -r requirements.txt # Install astronomical libraries for full functionality pip install sparclclient datalab astropy astroquery
# Test basic functionality python test_server.py # Test with a simple query (optional) python -c " import asyncio from server import astro_server async def test(): result = astro_server.get_global_statistics() print('✅ Server working:', result['total_files'], 'files in registry') services = astro_server.list_astroquery_services() print(f'✅ Astroquery: {len(services)} services discovered') asyncio.run(test()) "
Add this configuration to your Cursor MCP settings:
*Configuration content*
To find your conda Python path:
conda activate mcp which python # Copy this path for the "command" field above
Edit your Claude Desktop MCP configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
*Configuration content*
Server won't start:
# Check Python environment conda activate mcp python --version # Should be 3.11+ # Test server manually python server.py # Should start without errors
MCP connection issues:
cwd
) points to the astro_mcp folderMissing astronomical data:
# Install optional dependencies for full functionality conda activate mcp pip install sparclclient datalab astropy astroquery h5py
Once configured, you can ask natural language questions about astronomical data:
The server will automatically:
astro_mcp/
├── server.py # Main MCP server entry point
├── data_sources/ # Modular data source implementations
│ ├── __init__.py
│ ├── base.py # Base class for all data sources
│ ├── desi.py # DESI survey data access
│ ├── astroquery_universal.py # Universal astroquery wrapper
│ └── astroquery_metadata.py # Service metadata and capabilities
├── data_io/ # File handling and conversion
│ ├── __init__.py
│ ├── preview.py # Data preview and structure analysis
│ └── fits_converter.py # FITS format conversion
├── tests/ # Test suite
├── examples/ # Usage examples
└── requirements.txt # Project dependencies
Quick Start: For Cursor & Claude Desktop integration, see the Quick Setup section above.
# Clone the repository git clone https://github.com/SandyYuan/astro_mcp.git cd astro_mcp # Create and activate environment conda create -n mcp python=3.11 conda activate mcp # Install core dependencies pip install -r requirements.txt # Install astronomical libraries pip install sparclclient datalab astropy astroquery # Optional: Install development dependencies pip install pytest coverage
# Test the server components python test_server.py # Check available astroquery services python -c " import asyncio from server import astro_server async def show_services(): services = astro_server.list_astroquery_services() print(f'✅ Discovered {len(services)} astroquery services') for service in services[:5]: # Show first 5 print(f' - {service["full_name"]} ({service["service"]})') asyncio.run(show_services()) "
python server.py
The server provides these main tools:
Data Access:
search_objects
- Find astronomical objects (DESI)astroquery_query
- Universal queries across 40+ astronomical servicesget_spectrum_by_id
- Retrieve detailed spectral data (DESI)Service Discovery:
list_astroquery_services
- Show all available astronomical databasesget_astroquery_service_details
- Detailed service informationsearch_astroquery_services
- Find services by criteriaFile Management:
preview_data
- Inspect saved files with structure analysislist_files
- Manage saved data across all sourcesfile_statistics
- Storage usage and organization infoconvert_to_fits
- Convert data to FITS format# Get object coordinates from SIMBAD astroquery_query( service_name="simbad", object_name="Betelgeuse" ) # Search SDSS for galaxies with SQL astroquery_query( service_name="sdss", query_type="query_sql", sql="SELECT TOP 10 ra, dec, z FROM SpecObj WHERE class='GALAXY' AND z BETWEEN 0.1 AND 0.3" ) # Search VizieR catalogs astroquery_query( service_name="vizier", ra=10.68, dec=41.27, radius=0.1 ) # Convert results to FITS convert_to_fits( identifier="search_results.csv", data_type="catalog" )
Status: ✅ Fully Implemented
Status: ✅ Fully Implemented
Major Services Available:
Capabilities:
Required Dependencies:
pip install astroquery astropy
# data_sources/my_survey.py from .base import BaseDataSource class MySurveyDataSource(BaseDataSource): def __init__(self, base_dir=None): super().__init__(base_dir=base_dir, source_name="my_survey") # Initialize survey-specific clients def search_objects(self, **kwargs): # Implement survey-specific search pass
# server.py from data_sources import MySurveyDataSource class AstroMCPServer: def __init__(self, base_dir=None): # ... existing code ... self.my_survey = MySurveyDataSource(base_dir=base_dir)
The astroquery integration automatically discovers new services. To add custom metadata:
# data_sources/astroquery_metadata.py ASTROQUERY_SERVICE_INFO = { "my_service": { "full_name": "My Custom Service", "description": "Custom astronomical database", "data_types": ["catalogs", "images"], "wavelength_coverage": "optical", "object_types": ["stars", "galaxies"], "requires_auth": False, "example_queries": [ { "description": "Search by object name", "query": "astroquery_query(service_name='my_service', object_name='M31')" } ] } }
Files are automatically organized by data source with comprehensive metadata:
~/astro_mcp_data/
├── file_registry.json # Global file registry with metadata
├── desi/ # DESI-specific files
│ ├── desi_search_*.json # Search results
│ ├── spectrum_*.json # Spectral data
│ └── *.fits # FITS conversions
└── astroquery/ # Astroquery results
├── astroquery_simbad_*.csv # SIMBAD queries
├── astroquery_sdss_*.csv # SDSS results
├── astroquery_vizier_*.csv # VizieR catalogs
└── *.fits # FITS conversions
# Run all tests pytest # Test specific modules pytest tests/test_desi.py pytest tests/test_astroquery.py # Test with coverage pytest --cov=data_sources tests/
git checkout -b feature/new-capability
)mcp>=1.0.0
- Model Context Protocol frameworkpandas>=2.0.0
- Data manipulationnumpy>=1.24.0
- Numerical computingastroquery>=0.4.6
- Universal astronomical database accessastropy>=5.0.0
- FITS files and astronomical calculationssparclclient>=1.0.0
- DESI SPARCL accessdatalab>=2.20.0
- NOAO Data Lab queriesh5py>=3.8.0
- HDF5 file supportpytest>=7.0.0
- Testing framework[Specify your license here]
If you use this software in your research, please cite:
@software{astro_mcp, title={Astro MCP: Universal Astronomical Data Access for AI Agents}, author={[Your Name]}, year={2024}, url={[Repository URL]} }
No version information available