Skip to main content
Glama

Skywise — Weather-Prediction MCP Server + Agent Bricks Agent

A weather-forecast MCP server (FastMCP) plus a Databricks Agent Bricks agent that uses it to answer natural-language weather questions and make simple predictions ("Will it rain in Chicago tomorrow?", "Should I bring a jacket to Austin this weekend?"). An optional dashboard app shows the history of predictions the agent has made.

Built on the Day-3 reference pattern (an MCP-server app + a separate dashboard app, thin @mcp.tool functions over a separate broker/adapter module), and reusing the proven NWS + Lakebase code from an earlier weather app. As in the reference repos, the dashboard Flask app sits at the repo root and the MCP server is the mcp_server/ subfolder.


Weather API + auth used

Provider

Used for

Auth

Notes

Open-Meteo

geocoding, current conditions, multi-day forecast

none (keyless)

worldwide; ~10k calls/day non-commercial

NWS (weather.gov)

active severe-weather alerts

none (keyless)

US-only; requires a descriptive User-Agent header

There is no weather API key anywhere in this project — both providers are free and keyless. The only secret is the Lakebase connection URL, and it is only used to log predictions for the dashboard (see Secrets). No secrets are committed to git; .env is gitignored.


Related MCP server: Weather Prediction MCP Server

Architecture

Natural-language question
        │
        ▼
┌─────────────────────┐        registers as external MCP tool
│  Agent Bricks agent  │◄───────────────────────────────────────┐
│  (system_prompt.md)  │                                         │
└─────────┬───────────┘                                          │
          │ calls MCP tools (streamable-HTTP)                    │
          ▼                                                      │
┌──────────────────────────── Databricks App #1 ───────────────┐│
│  mcp_server/weather_mcp_server.py   (FastMCP, thin @mcp.tool) ││
│      ├─ weather_broker.py   → Open-Meteo (current/historical/  ││
│      │                        forecast/air-quality + geocode)  ││
│      ├─ recommendation.py   → threshold logic (the judgment)  ││
│      ├─ nws_broker.py       → NWS active alerts (US)          ││
│      └─ query_log.py ──────────────┐ (best-effort logging)    ││
└────────────────────────────────────┼─────────────────────────┘│
                                      ▼                          │
                              ┌──────────────┐                   │
                              │   Lakebase    │  reads history ──┘
                              │ weather_queries│
                              └──────▲────────┘
                                     │
┌───────────────────── Databricks App #2 (repo root) ──────────┐
│  app.py  (Flask, read-only)                                   │
│      recent predictions history + live conditions lookup       │
└───────────────────────────────────────────────────────────────┘

Design rule (from the assignment): tools are thin, brokers are fat. No raw requests calls live inside any @mcp.tool function — all HTTP + parsing is in weather_broker.py / nws_broker.py.


MCP tools

Tool

Kind

What it does

get_current_weather(location, units)

required

Current temp, feels-like, humidity, wind, conditions.

get_historical_weather(location, date, units)

required

Actual observed weather for a past date (Open-Meteo ERA5 archive) — not a forecast. Rejects future/malformed dates.

get_travel_recommendation(location, date, units)

required

Derived judgment — applies documented thresholds (umbrella if rain ≥ 40%, jacket/coat by low temp, sunscreen if UV ≥ 6, heat/wind cautions, air-quality caution) and returns the reasoning. Logs to Lakebase.

get_forecast(location, days, units)

additional

N-day (1–16) daily highs/lows, precip chance, UV, wind. Also satisfies the assignment's named forecast capability.

get_severe_weather_alerts(location)

stretch

Active NWS watches/warnings for a US location.

get_air_quality(location)

stretch

Current US AQI + PM2.5/PM10/ozone (Open-Meteo Air Quality API).

compare_cities_weather(locations, units)

stretch

Current conditions for several cities side by side.

get_current_user()

utility

End-user identity from the App's X-Forwarded-User header (mirrors the tutorial MCP server).

The "prediction" tool does more than echo the API: the threshold logic lives in mcp_server/recommendation.py and each rule that fires is returned in a reasons list so the agent can explain why. It also folds in air quality (limit strenuous outdoor activity when US AQI > 100) as a best-effort signal that never breaks the core forecast advice.

A curated seed cache of common US cities (_SEED_COORDS in weather_broker.py) resolves the demo cities (Chicago, Austin, Oklahoma City, …) with zero network calls, and gracefully falls through to live geocoding for anything else.

Error handling: brokers raise a WeatherError with a short message on a bad location or provider outage; every tool catches it and returns {"status": "error", "message": ...} — a clean sentence the agent can react to, never a stack trace.


Repository layout

The dashboard app lives at the repo root (its app.py/app.yaml are the root's), so it deploys by pointing a Databricks App at the repo root — the same shape as the reference repos (root Flask app + an mcp_server/ subfolder). The MCP server is the self-contained mcp_server/ subfolder.

skywise-mcp-agent/            ← ROOT = the read-only dashboard app (Databricks App #2)
├── app.py                    ← Flask: predictions history + live conditions
├── app.yaml                  ← dashboard App config (command + env)
├── requirements.txt          ← dashboard deps (also what setup_secrets.py needs)
├── weather_display.py        ← FE-support helpers (geocode/daily/AQI), ported
├── query_log.py              ← (copy) reads recent predictions
├── lakebase.py               ← (copy) Lakebase connection helper
├── templates/index.html      ← "Nordic Cool" UI (ported from weather-intel app)
├── setup_secrets.py          ← one-time: store LAKEBASE_URL secret
├── databricks.yml            ← optional Asset Bundle for CLI deploys
├── .env.example              ← local dev template (no real secrets)
├── .gitignore
├── README.md                 ← you are here
├── agent/
│   ├── system_prompt.md      ← the agent's system prompt (a deliverable)
│   └── demo_transcripts.md   ← fill in with 3+ demo Q&As after deploy
└── mcp_server/               ← Databricks App #1 (the MCP server) — self-contained
    ├── weather_mcp_server.py ← FastMCP entrypoint, thin @mcp.tool funcs
    ├── weather_broker.py     ← Open-Meteo: geocode / current / historical / forecast
    ├── recommendation.py     ← derived judgment (thresholds + reasoning)
    ├── nws_broker.py         ← NWS active alerts (reused, User-Agent-safe)
    ├── query_log.py          ← best-effort prediction logging to Lakebase
    ├── lakebase.py           ← Lakebase connection helper (reused)
    ├── schema_weather_queries.sql ← DDL + app-role grants for the prediction-log table
    ├── test_weather.py       ← runnable live smoke test (✓/✗ per capability)
    ├── app.yaml              ← App config (env only; no key secret)
    └── requirements.txt

The root (dashboard) app and the mcp_server/ app each carry their own copies of the shared Lakebase modules (lakebase.py, query_log.py) so each deploys as a self-contained Databricks App — the same convention as the reference repos, whose root app is likewise a Flask app beside an mcp_server/ folder.

Dashboard UI (ported "Nordic Cool" design)

The dashboard's templates/index.html reuses the polished front-end from the earlier weather-intelligence app — its self-hosted fonts (Fraunces + Hanken Grotesk), scandi palette, geocode typeahead, and live-conditions panel (yesterday/today/tomorrow cards + an AQI badge and EPA scale). The RAG "sync + semantic search" half of that original page (irrelevant to this assignment) is replaced with the Recent agent predictions history read from Lakebase. Two small endpoints in app.py/weather/geocode and /weather/conditions — feed the reused JS, backed by weather_display.py (a trimmed port of that app's weather_client.py display functions).

Two Skywise touches layered on top of the ported design (palette-native, no new colors): a °F/°C segmented toggle that re-fetches the current city's conditions, and a data-derived insight line ("📈 4°F warmer than yesterday · rain rising to 47% tomorrow") computed only from the three days already on screen — so it never states anything the panel doesn't show.


Setup

1. (Optional) Lakebase for prediction logging

Only needed if you want the dashboard / prediction history. Skip if you just want the required MCP tools + agent.

  1. Create a Lakebase instance with a native-password role and copy its connection URL (postgresql://role:password@host:5432/databricks_postgres?sslmode=require).

  2. Create the table and grant the app role access:

    psql "$LAKEBASE_URL" -f mcp_server/schema_weather_queries.sql

    (or paste the file into a Databricks SQL editor connected to the instance). This creates weather.weather_queries in the same weather schema the weather-intel app uses, and grants schema/table/sequence privileges to the Lakebase role student — the same role the day-1 tutorial and weather-intel app grant to. Review placeholder: if your Lakebase app role isn't student, edit the GRANT ... TO student lines at the bottom of that file first (otherwise the app hits "permission denied" on the first insert).

2. Secrets

The only secret is the Lakebase URL. Store it once by running the root script (install its one dependency first — the root requirements.txt covers it):

pip install -r requirements.txt
python setup_secrets.py

This uses scope database-day2 and key lakebase-url — the same Lakebase secret you already created for the weather-intel app — so no new secret is needed (matching the LAKEBASE_SECRET_SCOPE / LAKEBASE_SECRET_KEY in both app.yaml files). If that secret already exists, you can skip this step.

3. NWS User-Agent

NWS returns HTTP 403 without a descriptive User-Agent. Set your own contact in mcp_server/app.yaml (WEATHER_USER_AGENT, e.g. "(skywise-mcp-agent, you@example.com)"). It is a courtesy contact, not a secret.

4. Run locally (optional)

cd mcp_server
pip install -r requirements.txt
python weather_mcp_server.py       # serves MCP over HTTP on :8000
# dashboard app — run from the repo root (this is where app.py lives)
pip install -r requirements.txt
python app.py                      # serves the dashboard on :8001

5. Deploy the two Databricks Apps — mind the source path

The two apps deploy from different directories. Pointing an App at the wrong directory is the #1 deploy failure: the repo root has an app.yaml (the dashboard), but the mcp_server/ code has its own app.yaml, so each App must point at its own directory.

App

Point the Databricks App source at

Notes

Dashboard (Databricks App #2)

the repo root

root app.py + app.yaml

MCP server (Databricks App #1)

mcp_server/ subfolder

name it mcp-skywise-weather

Via the workspace UI (no CLI required):

  1. Create a Git folder pointing at this repo.

  2. Compute → Apps → Create app for the MCP server: set its source code path to the mcp_server/ subfolder (not the repo root).

    • ⚠️ Name it with an mcp- prefix — e.g. mcp-skywise-weather. Databricks only recognizes an App as an MCP server (for AI Playground / Agent Bricks discovery) when its name starts with mcp- (parallel to the tutorial's mcp-trading-server).

  3. Create a second app for the dashboard: set its source code path to the repo root (any name — the dashboard is not an MCP server). Because the root has its own app.yaml, the container runs the Flask app, not setup_secrets.py. Open each app's URL and confirm it's serving.


Register the MCP server as an external MCP + build the agent

Written from Databricks' current MCP docs (host a custom MCP, MCPs and agent tools). UI labels move around — confirm against your workspace.

What to swap vs. the tutorial's mcp-trading-server: a new app name (mcp-skywise-weather), the skywise mcp_server/ source folder, and no API-key secret (Open-Meteo + NWS are keyless). The Lakebase secret is the same database-day2/lakebase-url you already created — nothing new to store.

  1. Get the MCP endpoint. After the mcp-skywise-weather app deploys, its MCP URL is https://<app-url>/mcp (FastMCP's streamable-HTTP endpoint — the server already runs transport="http", so no code change is needed).

  2. Grant access. On the app → Permissions, grant yourself (and the agent's principal) access. Databricks governs MCP access through Apps permissions, not per-tool grants. (Governance also appears under AI Gateway → MCPs.)

  3. Attach it to an agent in AI Playground. Open AI Playground, pick an LLM endpoint, open Tools, and add the mcp-skywise-weather MCP server. Its @mcp.tool functions appear for selection: get_current_weather, get_historical_weather, get_travel_recommendation, get_forecast, get_severe_weather_alerts, get_air_quality, compare_cities_weather, get_current_user.

  4. Set the instructions. Paste agent/system_prompt.md as the agent's system prompt.

  5. Test, then export. Run the prompts in agent/demo_transcripts.md, capture the tool calls + answers for your submission, then Export / Create agent from the Playground.


Demonstrating the agent (required)

Fill in agent/demo_transcripts.md with at least 3 natural-language questions, the tool calls the agent made, and its final answers (screenshots encouraged). Suggested prompts:

  1. "Will it rain in Chicago tomorrow — should I take an umbrella?"

  2. "What's the weather looking like in Austin this weekend?"

  3. "Are there any severe weather warnings for Oklahoma City right now?"


Assignment Requirements Checklist

Required MCP Tools (minimum 3) ✅

  • get_current_weather(location, units) - current conditions

  • get_forecast(location, days, units) - multi-day forecast

  • get_travel_recommendation(location, date, units) - derived judgment with documented thresholds (not a passthrough)

Stretch Tools (5 bonus tools) ✅

  • get_historical_weather - past weather lookup

  • get_severe_weather_alerts - NWS alerts

  • get_air_quality - AQI data

  • compare_cities_weather - multi-city comparison

  • get_current_user - identity utility

Technical Requirements ✅

  • FastMCP with @mcp.tool decorators

  • Separate adapter modules - weather_broker.py, recommendation.py, nws_broker.py (no HTTP in tool functions)

  • Secrets properly stored - Lakebase URL in Databricks secrets, no API keys needed (Open-Meteo & NWS are keyless)

  • requirements.txt & app.yaml - present for both MCP server and dashboard apps

  • Deployed as Databricks App - mcp-skywise-weather running with mcp- prefix

  • Clear docstrings - Args/Returns documented for all tools

  • Error handling - returns clean error messages, not stack traces

  • Prediction tool logic - applies explicit thresholds in recommendation.py with reasoning

Agent Requirements ✅

  • Agent Bricks agent configured - registered in AI Playground with MCP server

  • System prompt - agent/system_prompt.md with tool selection rules and anti-hallucination guardrails

  • Demo transcripts - agent/demo_transcripts.md with 4+ examples and screenshots

Documentation ✅

  • README.md - architecture diagram, tool list, setup steps, API documentation

  • Weather API documented - Open-Meteo (keyless) + NWS (keyless with User-Agent)

  • No secrets in git - .gitignore configured, .env.example provided

Bonus Features ✨

  • Dashboard app - real-time prediction logging to Lakebase, "Nordic Cool" UI

  • 8 tools total - 3 required + 5 stretch

  • Comprehensive error handling - graceful degradation for API outages

  • Air quality integration - enriches recommendations with AQI data


Notes / reuse

  • NWS handling (nws_broker.py) reuses the mandatory-User-Agent + 4-decimal-coordinate-rounding pattern proven in an earlier weather app, so the common NWS 403/redirect gotchas are handled up front.

  • Air quality (get_air_quality) reuses the Open-Meteo AQI adapter + EPA-category logic from that same weather app.

  • Seed cache (_SEED_COORDS) reuses its curated city→coordinate map.

  • Dashboard UI reuses that app's "Nordic Cool" front-end (fonts, palette, geocode typeahead, live-conditions + AQI panel); its display helpers are ported into weather_display.py (at the repo root).

  • Lakebase helper (lakebase.py) is the standard single-LAKEBASE_URL pattern from the reference apps — no token refresh needed.

  • Test script (test_weather.py) mirrors the reference's test_watchlist.py style — a runnable ✓/✗ smoke test over the live free APIs, no secrets needed.

  • Prediction logging is best-effort: if Lakebase is down or unconfigured, the weather answer is still returned and only the dashboard history is affected.

F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • US weather & geo for AI agents: forecasts, alerts, earthquakes, elevation, geocoding. No keys.

  • OpenWeather MCP — wraps the OpenWeatherMap API (openweathermap.org)

  • WeatherAPI.com MCP — wraps WeatherAPI.com (api.weatherapi.com)

View all MCP Connectors

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/ATP524/skywise-mcp-agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server