Skip to main content
Glama

get_asteroids_feed

Retrieve near-Earth asteroid data for specified date ranges to monitor potential close approaches and track space objects.

Instructions

Get a list of asteroids based on their closest approach date to Earth.

Args: start_date: Start date for asteroid search in YYYY-MM-DD format. end_date: End date for asteroid search in YYYY-MM-DD format. The Feed date limit is only 7 Days. If not specified, 7 days after start_date is used.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
start_dateYes
end_dateNo

Implementation Reference

  • The handler function for the 'get_asteroids_feed' tool. It queries the NASA NEO Feed API for asteroids within a date range, processes the response to extract details like ID, name, diameter, hazardous status, approach date, distance, and velocity, and returns a formatted string summary.
    async def get_asteroids_feed(start_date: str, end_date: str = None) -> str:
        """Get a list of asteroids based on their closest approach date to Earth.
        
        Args:
            start_date: Start date for asteroid search in YYYY-MM-DD format.
            end_date: End date for asteroid search in YYYY-MM-DD format. 
            The Feed date limit is only 7 Days. If not specified, 7 days after start_date is used.
        """
        params = {
            "start_date": start_date
        }
        
        if end_date:
            params["end_date"] = end_date
        
        url = f"{NASA_API_BASE}/neo/rest/v1/feed"
        data = await make_nasa_request(url, params)
        
        if not data:
            return "Could not retrieve asteroid data due to a connection error."
        
        # Check for error response (must be a dictionary)
        if isinstance(data, dict) and "error" in data:
            return f"API Error: {data.get('error')} - Details: {data.get('details', 'N/A')}"
        if isinstance(data, dict) and data.get("binary_content"):
            return f"Received unexpected binary content from Asteroids Feed API. URL: {data.get('url')}"
    
        try:
            element_count = data.get('element_count', 0)
            near_earth_objects = data.get('near_earth_objects', {})
            
            result = [f"Total asteroids found: {element_count}"]
            
            for date_str, asteroids in near_earth_objects.items():
                result.append(f"nDate: {date_str}")
                result.append(f"Number of asteroids: {len(asteroids)}")
                
                for asteroid in asteroids:
                    result.append(f"n  ID: {asteroid.get('id', 'Unknown')}")
                    result.append(f"  Name: {asteroid.get('name', 'Unknown')}")
                    result.append(f"  Estimated diameter (min): {asteroid.get('estimated_diameter', {}).get('kilometers', {}).get('estimated_diameter_min', 'Unknown')} km")
                    result.append(f"  Estimated diameter (max): {asteroid.get('estimated_diameter', {}).get('kilometers', {}).get('estimated_diameter_max', 'Unknown')} km")
                    result.append(f"  Potentially hazardous: {'Yes' if asteroid.get('is_potentially_hazardous_asteroid', False) else 'No'}")
                    
                    # Information about closest approach
                    close_approaches = asteroid.get('close_approach_data', [])
                    if close_approaches:
                        approach = close_approaches[0]
                        result.append(f"  Approach date: {approach.get('close_approach_date_full', 'Unknown')}")
                        result.append(f"  Distance (km): {approach.get('miss_distance', {}).get('kilometers', 'Unknown')}")
                        result.append(f"  Relative velocity (km/h): {approach.get('relative_velocity', {}).get('kilometers_per_hour', 'Unknown')}")
            
            return "n".join(result)
        except Exception as e:
            logger.error(f"Error processing Asteroids Feed data: {str(e)}")
            return f"Error processing asteroid data: {str(e)}"
  • Shared helper function used by get_asteroids_feed (and other tools) to make HTTP requests to NASA APIs, handle JSON/binary responses, errors, and add the API key.
    async def make_nasa_request(url: str, params: dict = None) -> Union[dict[str, Any], List[Any], None]:
        """Make a request to the NASA API with proper error handling.
        Handles both JSON and binary (image) responses.
        """
        
        logger.info(f"Making request to: {url} with params: {params}")
        
        if params is None:
            params = {}
        
        # Ensure API key is included in parameters
        if "api_key" not in params:
            params["api_key"] = API_KEY
        
        async with httpx.AsyncClient() as client:
            try:
                response = await client.get(url, params=params, timeout=30.0, follow_redirects=True)
                response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
    
                content_type = response.headers.get("Content-Type", "").lower()
                
                if "application/json" in content_type:
                    try:
                        return response.json()
                    except json.JSONDecodeError as json_err:
                        logger.error(f"JSON decode error for URL {response.url}: {json_err}")
                        logger.error(f"Response text: {response.text[:500]}") # Log beginning of text
                        return {"error": "Failed to decode JSON response", "details": str(json_err)}
                elif content_type.startswith("image/"):
                    logger.info(f"Received binary image content ({content_type}) from {response.url}")
                    # Return a dictionary indicating binary content was received
                    return {
                        "binary_content": True, 
                        "content_type": content_type,
                        "url": str(response.url) # Return the final URL after redirects
                    }
                else:
                    # Handle other unexpected content types
                    logger.warning(f"Unexpected content type '{content_type}' received from {response.url}")
                    return {"error": f"Unexpected content type: {content_type}", "content": response.text[:500]}
    
            except httpx.HTTPStatusError as http_err:
                logger.error(f"HTTP error occurred: {http_err} - {http_err.response.status_code} for URL {http_err.request.url}")
                try:
                    # Try to get more details from response body if possible
                    error_details = http_err.response.json()
                except Exception:
                    error_details = http_err.response.text[:500]
                return {"error": f"HTTP error: {http_err.response.status_code}", "details": error_details}
            except httpx.RequestError as req_err:
                logger.error(f"Request error occurred: {req_err} for URL {req_err.request.url}")
                return {"error": "Request failed", "details": str(req_err)}
            except Exception as e:
                logger.error(f"An unexpected error occurred: {str(e)}")
                return {"error": "An unexpected error occurred", "details": str(e)}
  • The @mcp.tool() decorator registers the get_asteroids_feed function as an MCP tool, using its signature and docstring for schema.
    async def get_asteroids_feed(start_date: str, end_date: str = None) -> str:

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AnCode666/nasa-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server