Skip to main content
Glama

get_mars_rover_manifest

Retrieve detailed mission manifests for Mars rovers (Curiosity, Opportunity, Spirit), including launch/landing dates, status, total photos, and daily photo counts via NASA-MCP server.

Instructions

Get the mission manifest for a Mars rover (Curiosity, Opportunity, Spirit). Provides mission details like landing/launch dates, status, max sol/date, total photos, and photo counts per sol.

Args: rover_name: Name of the rover (curiosity, opportunity, spirit).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rover_nameYes

Implementation Reference

  • The primary handler function for the 'get_mars_rover_manifest' tool. It validates the rover name, calls the NASA Mars Rover Photos API manifest endpoint using the shared make_nasa_request helper, processes the JSON response, and formats mission details including status, dates, total photos, and a summary of recent sols' photo counts.
    async def get_mars_rover_manifest(rover_name: str) -> str: """Get the mission manifest for a Mars rover (Curiosity, Opportunity, Spirit). Provides mission details like landing/launch dates, status, max sol/date, total photos, and photo counts per sol. Args: rover_name: Name of the rover (curiosity, opportunity, spirit). """ rover_name = rover_name.lower() if rover_name not in ROVER_CAMERAS: return f"Invalid rover name. Available rovers: {', '.join(ROVER_CAMERAS.keys())}" url = f"{NASA_API_BASE}/mars-photos/api/v1/manifests/{rover_name}" data = await make_nasa_request(url) if not data: return f"Could not retrieve mission manifest for {rover_name} 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 Mars Rover Manifest API. URL: {data.get('url')}" # Response should be a dictionary containing 'photo_manifest' if not isinstance(data, dict) or "photo_manifest" not in data: logger.error(f"Unexpected response format from Mars Rover Manifest API: {data}") return "Received unexpected data format from Mars Rover Manifest API." try: manifest = data.get("photo_manifest", {}) result = [ f"Mission Manifest for Rover: {manifest.get('name', 'Unknown')}", f"Status: {manifest.get('status', 'Unknown')}", f"Launch Date: {manifest.get('launch_date', 'Unknown')}", f"Landing Date: {manifest.get('landing_date', 'Unknown')}", f"Max Sol: {manifest.get('max_sol', 'Unknown')}", f"Max Earth Date: {manifest.get('max_date', 'Unknown')}", f"Total Photos: {manifest.get('total_photos', 'Unknown')}", "nPhoto Summary per Sol (showing latest 5 sols with photos):" ] photos_per_sol = manifest.get('photos', []) # Sort by sol descending to show latest first photos_per_sol_sorted = sorted(photos_per_sol, key=lambda x: x.get('sol', -1), reverse=True) display_limit = 5 count = 0 for sol_info in photos_per_sol_sorted: if count >= display_limit: result.append(f"n... and {len(photos_per_sol) - display_limit} more sols with photos.") break result.append(f" Sol {sol_info.get('sol', 'N/A')}: {sol_info.get('total_photos', 0)} photos") result.append(f" Cameras: {', '.join(sol_info.get('cameras', []))}") count += 1 return "n".join(result) except Exception as e: logger.error(f"Error processing Mars Rover Manifest data: {str(e)}") return f"Error processing Mars Rover Manifest data: {str(e)}"
  • The @mcp.tool() decorator registers the get_mars_rover_manifest function as an MCP tool, with schema inferred from the function signature and docstring.
    async def get_mars_rover_manifest(rover_name: str) -> str:
  • Shared helper function used by get_mars_rover_manifest (and other tools) to make authenticated HTTP requests to NASA APIs, handling JSON, binary, and error responses.
    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)}
  • Constant dictionary validating rover names and cameras, used in get_mars_rover_manifest for input validation.
    ROVER_CAMERAS = { "curiosity": ["FHAZ", "RHAZ", "MAST", "CHEMCAM", "MAHLI", "MARDI", "NAVCAM"], "opportunity": ["FHAZ", "RHAZ", "NAVCAM", "PANCAM", "MINITES"], "spirit": ["FHAZ", "RHAZ", "NAVCAM", "PANCAM", "MINITES"] }

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