Skip to main content
Glama

get_notifications

Retrieve space weather alerts and notifications from NASA's DONKI system for specified dates and event types to monitor solar activity and space weather conditions.

Instructions

Get DONKI notifications.

Args: start_date: Start date in YYYY-MM-DD format. Defaults to 7 days before current date. end_date: End date in YYYY-MM-DD format. Defaults to current date. notification_type: Notification type. Options: all, FLR, SEP, CME, IPS, MPC, GST, RBE, report.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
start_dateNo
end_dateNo
notification_typeNoall

Implementation Reference

  • Implements the get_notifications MCP tool handler. Fetches DONKI notifications from NASA's API using make_nasa_request helper, handles errors, formats and returns a string summary of notifications with details like ID, type, issue time, header, and truncated body.
    async def get_notifications(start_date: str = None, end_date: str = None, notification_type: str = "all") -> str:
        """Get DONKI notifications.
        
        Args:
            start_date: Start date in YYYY-MM-DD format. Defaults to 7 days before current date.
            end_date: End date in YYYY-MM-DD format. Defaults to current date.
            notification_type: Notification type. Options: all, FLR, SEP, CME, IPS, MPC, GST, RBE, report.
        """
        params = {"type": notification_type}
        if start_date: params["startDate"] = start_date
        if end_date: params["endDate"] = end_date
        
        url = f"{NASA_API_BASE}/DONKI/notifications"
        data = await make_nasa_request(url, params)
    
        if not data: 
            return "Could not retrieve DONKI notifications 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 Notifications API. URL: {data.get('url')}"
    
        try:
            # Ensure data is a list
            if not isinstance(data, list):
                logger.error(f"Unexpected non-list response from Notifications API: {data}")
                return "Received unexpected data format from Notifications API."
                
            # Format notifications results
            if not data: 
                return "No notifications for the specified period and type."
                
            result = [f"Notifications found: {len(data)}"]
            display_limit = 10
            count = 0
            for notification in data:
                if count >= display_limit: 
                    result.append(f"n... and {len(data) - display_limit} more notifications.")
                    break
                result.append(f"nID: {notification.get('messageID', 'Unknown')}")
                result.append(f"Type: {notification.get('messageType', 'Unknown')}")
                result.append(f"Issue Time: {notification.get('messageIssueTime', 'Unknown')}")
                result.append(f"Header: {notification.get('messageHeader', 'N/A')}")
                # Body can be long, maybe truncate
                body = notification.get('messageBody', 'N/A')
                result.append(f"Body: {body[:200]}{'...' if len(body) > 200 else ''}") 
                result.append("-" * 40)
                count += 1
            return "n".join(result)
        except Exception as e:
            logger.error(f"Error processing Notifications data: {str(e)}")
            return f"Error processing notifications: {str(e)}"
  • Shared helper function used by get_notifications to make HTTP requests to NASA APIs, handling JSON/binary responses, errors, and adding 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)}
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It states 'Get DONKI notifications' which implies a read-only operation, but doesn't disclose behavioral traits like rate limits, authentication needs, pagination, error handling, or what 'DONKI' stands for (NASA's Space Weather Database). For a tool with no annotation coverage, this is inadequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized with a clear purpose statement followed by parameter details. The 'Args:' section is well-structured. It could be slightly more concise by integrating defaults into the purpose statement, but overall it's efficient with minimal waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description does well on parameters but lacks behavioral context and output details. For a 3-parameter tool with 0% schema coverage, it's minimally adequate but leaves gaps in understanding the tool's full behavior and results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It fully documents all 3 parameters: start_date (format YYYY-MM-DD, default 7 days before current), end_date (same format, default current date), and notification_type (options: all, FLR, SEP, CME, IPS, MPC, GST, RBE, report with default 'all'). This adds complete meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Get' and resource 'DONKI notifications', making the purpose specific and understandable. It distinguishes this tool from sibling tools that focus on asteroids, Earth imagery, Mars rovers, and other space-related data. However, it doesn't explicitly differentiate from other notification-related tools (none exist in siblings), so it's not a perfect 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention any prerequisites, context for selecting notification types, or comparison with sibling tools. The agent must infer usage from the tool name and parameters alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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