Skip to main content
Glama

get_epic_imagery

Retrieve Earth images from NASA's EPIC camera, choosing between natural or enhanced collections, through the NASA-MCP server for accessible Earth observation data.

Instructions

Get images from the EPIC (Earth Polychromatic Imaging Camera).

Args: collection: Collection type. Options: natural, enhanced.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
collectionNonatural

Implementation Reference

  • The handler function implementing the 'get_epic_imagery' MCP tool. It fetches the latest EPIC images from NASA's API based on the collection type (natural or enhanced), processes the metadata, constructs direct image URLs, and returns a formatted string summary with up to 10 images.
    @mcp.tool() async def get_epic_imagery(collection: str = "natural") -> str: """Get images from the EPIC (Earth Polychromatic Imaging Camera). Args: collection: Collection type. Options: natural, enhanced. """ if collection not in ["natural", "enhanced"]: return "Invalid collection. Available options: natural, enhanced." # Use the 'images' endpoint to get the latest images api_path = f"/EPIC/api/{collection}/images" url = f"{NASA_API_BASE}{api_path}" data = await make_nasa_request(url) if not data: return f"Could not retrieve EPIC images for latest date due to a connection error." # Check for error response (must be a dictionary) if isinstance(data, dict): if "error" in data: return f"API Error: {data.get('error')} - Details: {data.get('details', 'N/A')}" if data.get("binary_content"): return f"Received unexpected binary content from EPIC API. URL: {data.get('url')}" # Ensure data is a list if not isinstance(data, list): logger.error(f"Unexpected non-list response from EPIC API: {data}") return "Received unexpected data format from EPIC API." try: if not data: # Empty list return f"No EPIC images available for the most recent date." result = [f"EPIC images found: {len(data)}"] display_limit = 10 count = 0 for image_meta in data: if count >= display_limit: result.append(f"n... and {len(data) - display_limit} more images.") break image_date_time = image_meta.get('date', 'Unknown') image_identifier = image_meta.get('identifier', 'Unknown') # Use identifier if available image_name = image_meta.get('image', 'Unknown') # Base name like epic_1b_... # Build image URL if image_date_time != 'Unknown' and image_name != 'Unknown': try: # Extract date parts for URL path dt_obj = datetime.strptime(image_date_time, '%Y-%m-%d %H:%M:%S') year, month, day = dt_obj.strftime('%Y'), dt_obj.strftime('%m'), dt_obj.strftime('%d') # Construct archive URL archive_url = f"https://api.nasa.gov/EPIC/archive/{collection}/{year}/{month}/{day}/png/{image_name}.png" # Add API key for direct access image_url_with_key = f"{archive_url}?api_key={API_KEY}" except ValueError: logger.warning(f"Could not parse date {image_date_time} for EPIC image URL construction.") image_url_with_key = "URL construction failed" else: image_url_with_key = "URL not available" result.append(f"nIdentifier: {image_identifier}") result.append(f"Date/Time: {image_date_time}") result.append(f"Caption: {image_meta.get('caption', 'No caption')}") result.append(f"Image Name: {image_name}") result.append(f"Archive URL: {image_url_with_key}") # Coordinates coords = image_meta.get('centroid_coordinates', {}) if coords: result.append(f"Centroid Coordinates: Lat {coords.get('lat', 'N/A')}, Lon {coords.get('lon', 'N/A')}") result.append("-" * 40) count += 1 return "n".join(result) except Exception as e: logger.error(f"Error processing EPIC image data: {str(e)}") return f"Error processing EPIC image data: {str(e)}"
  • Shared helper function used by get_epic_imagery (and other tools) to make HTTP requests to NASA APIs, handle JSON/binary responses, errors, and include 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_epic_imagery function as an MCP tool.
    @mcp.tool()

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