Tutorial: Building a NASA APOD Server
In this tutorial, we will build a simple Python-based MCP server that connects to NASA's API to fetch the Astronomy Picture of the Day (APOD). This project is a great introduction to building MCP servers and takes about 10 minutes to complete.
Prerequisites
- Python 3.10+
npx
(comes with Node.js)uv
(a fast Python package installer):pip install uv
- An API key from api.nasa.gov
Step 1: Set Up Your Environment
First, let's create a new project directory and set up a virtual environment.
# Create project and enter directory
mkdir nasa-mcp-server
cd nasa-mcp-server
# Initialize a uv environment
uv init
# Create and activate the virtual environment
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]" httpx
# Create the server file
touch nasa.py
Step 2: Write the MCP Server Code
Open the nasa.py
file you just created and add the following code. Be sure to replace <NASA_API_TOKEN>
with your actual key from api.nasa.gov.
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("nasa")
# Constants
NASA_API_BASE = "https://api.nasa.gov"
# Replace with your actual NASA API token
NASA_API_KEY = "<NASA_API_TOKEN>"
async def make_nasa_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NASA API with proper error handling."""
params = {"api_key": NASA_API_KEY}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, params=params, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
@mcp.tool()
async def get_astronomy_picture_of_day(date: str = None) -> str:
"""Get NASA's Astronomy Picture of the Day (APOD).
Args:
date: Optional date in YYYY-MM-DD format. If not provided, returns today's image.
"""
url = f"{NASA_API_BASE}/planetary/apod"
if date:
url += f"?date={date}"
data = await make_nasa_request(url)
if not data:
return "Unable to fetch APOD data from NASA API."
image_url = data.get('hdurl') or data.get('url')
result = f"""
🌌 NASA Astronomy Picture of the Day
📅 Date: {data.get('date', 'Unknown')}
📝 Title: {data.get('title', 'Unknown')}
👨🚀 Author: {data.get('copyright', 'NASA')}
📖 Explanation: {data.get('explanation', 'No explanation available')}
{image_url and f"" or "No image available"}
"""
return result
if __name__ == "__main__":
mcp.run(transport='stdio')
This script defines a single tool, get_astronomy_picture_of_day
, which fetches data from the NASA APOD API and formats the response as Markdown.
Step 3: Test the Server with MCPJam Inspector
Now, let's run your new MCP server and test it with the Inspector.
-
Launch the Inspector and Connect to Your Server
Run the following command in your terminal, replacing
<FILE_PATH>
with the absolute path to yournasa.py
file.# Make sure your virtual environment is active first! npx @mcpjam/inspector@latest uv run fastmcp run <FILE_PATH>/nasa.py
MCPJam Inspector will start and automatically connect to your
nasa
server via STDIO. -
Configure an LLM Provider
In the Inspector, navigate to the Settings tab and add an API key for a provider like OpenAI or Anthropic.
-
Test in the Playground
Go to the Playground tab and ask a question that should trigger your tool, for example:
Show me the astronomy picture of the day for 1995-06-20
The LLM should invoke your
get_astronomy_picture_of_day
tool and display the formatted result, including the image!
Congratulations! You've built and tested your first MCP server.