nasa
MCP server that wraps three NASA public APIs (Astronomy Picture of the Day, Mars rover photos, and near-Earth objects) as tools for AI assistants.
README
NASA MCP Server
A small but complete Model Context Protocol (MCP) server you can deploy to Google Cloud Run. It wraps three of NASA's free public APIs as tools an AI assistant can call.
This is built as a learning project, so the code and these notes explain the why, not just the how.
What is an MCP server, briefly
MCP is a standard way to expose tools (callable functions), resources (readable data), and prompts (templates) to an AI model. Think of it as a web API designed specifically for LLMs. This project uses tools only.
There are two transports:
- stdio — the server runs as a local subprocess. Used by desktop apps (Claude Desktop, Cursor, IDE plugins). Not what we want here.
- streamable HTTP — the server runs as a normal web service reachable over
a URL. This is the one you use to host on Cloud Run. All MCP traffic flows
through a single endpoint at
/mcp.
Project structure
nasa-mcp-server/
├── server.py # the MCP server + 3 NASA tools
├── requirements.txt # mcp + httpx
├── Dockerfile # container image for Cloud Run
└── .dockerignore
The three tools:
| Tool | What it does |
|---|---|
get_astronomy_picture |
NASA's Astronomy Picture of the Day (optionally for a past date) |
get_mars_photos |
Photos from a Mars rover on a given Earth date |
get_near_earth_objects |
Asteroids passing near Earth in a date range |
Step 1 — Get a NASA API key
- Go to https://api.nasa.gov/ and fill in the short form (name + email).
- The key is emailed to you within a few minutes. No credit card. Registered keys allow ~1,000 requests/hour.
You can skip this at first: the code falls back to NASA's shared DEMO_KEY,
which works instantly but is heavily rate-limited (you'll see 429 errors fast).
Do not paste your key into source code or share it in chat. The server reads it from the
NASA_API_KEYenvironment variable. Locally that's anexport; on Cloud Run it's a Secret Manager secret (Step 4).
Step 2 — Run it locally
cd nasa-mcp-server
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
export NASA_API_KEY=your_key_here # omit to use DEMO_KEY
python server.py
The server starts on http://localhost:8080/mcp.
Step 3 — Test with the MCP Inspector
The Inspector is the official tool for poking at an MCP server by hand. With the server running, in another terminal:
npx @modelcontextprotocol/inspector
In the Inspector UI: set transport to Streamable HTTP, URL to
http://localhost:8080/mcp, connect, then open the Tools tab and run
get_astronomy_picture with no arguments. You should get back today's picture.
Step 4 — Deploy to Google Cloud Run
Prerequisites: a GCP project with billing enabled and the gcloud CLI
installed and authenticated (gcloud auth login).
# Set your project and a region close to you
gcloud config set project YOUR_PROJECT_ID
gcloud config set run/region australia-southeast1 # Sydney; pick your own
# Enable the services we need
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com \
secretmanager.googleapis.com
4a. Store your NASA key in Secret Manager
Never bake the key into the image. Create a secret instead:
printf '%s' 'YOUR_NASA_KEY' | gcloud secrets create nasa-api-key --data-file=-
4b. Deploy from source
gcloud builds the container from the Dockerfile and deploys it in one step:
gcloud run deploy nasa-mcp \
--source . \
--allow-unauthenticated \
--set-secrets=NASA_API_KEY=nasa-api-key:latest
When prompted to grant the runtime service account access to the secret, say
yes (or run gcloud secrets add-iam-policy-binding nasa-api-key --member="serviceAccount:$(gcloud run services describe nasa-mcp --format='value(spec.template.spec.serviceAccountName)')" --role="roles/secretmanager.secretAccessor").
Notes:
- You do not set
PORT— Cloud Run injects it andserver.pyreads it. - On success you get a URL like
https://nasa-mcp-xxxxxxxx.run.app. Your MCP endpoint is that URL plus/mcp.
Quick check it's alive:
curl -X POST https://nasa-mcp-xxxxxxxx.run.app/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
A JSON response with "serverInfo":{"name":"nasa",...} means you're live.
Step 5 — Connect it to Claude
Point the MCP Inspector at your live https://.../mcp URL first to confirm the
tools work remotely. To use it in Claude, add it as a custom connector in
Claude's settings (Settings → Connectors), pasting your /mcp URL. The exact
menu wording changes over time — see the current connector docs at
https://support.claude.com. Then ask Claude something like "what's NASA's
astronomy picture of the day?" and it will call your tool.
⚠️ About --allow-unauthenticated
The deploy command above makes your server publicly reachable by anyone with the URL. For a learning project that's fine, but be aware: strangers could call it and burn through your NASA rate limit. Before relying on it, lock it down. Reasonable next steps, easiest first:
- Require a bearer token — add a check in the server for a shared secret in
the
Authorizationheader, and supply that header from the client. - Keep the service private (drop
--allow-unauthenticated) and require Google IAM auth, putting an authenticating proxy in front for Claude. - Full OAuth 2.1, which the MCP spec defines for remote servers. FastMCP has helpers for this — it's the "proper" answer but the most work.
How the code maps to MCP concepts
FastMCP(name="nasa", ...)creates the server.stateless_http=Trueandjson_response=Trueare the recommended settings for a scalable HTTP deployment — Cloud Run may run several container instances, and stateless mode means none of them rely on in-memory session state.- Each
@mcp.tool()function becomes a callable tool. The docstring is the description the model sees, and the type hints become the input schema — so writing clear docstrings and precise types is the single highest-leverage thing you can do for tool quality. mcp.run(transport="streamable-http")serves everything at/mcp.
Ideas to extend it
- Add a tool for NASA's EPIC (full-disc Earth imagery) or EONET (natural-event
tracking) endpoints — same
_nasa_gethelper, new path. - Swap NASA for a different free API (weather, exchange rates, etc.) — only the tool bodies change; the server scaffolding and deployment stay identical.
- Add an MCP resource (read-only data) alongside the tools.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。