Skywise

Skywise

Skywise is a weather-prediction MCP server that provides current conditions, forecasts, historical data, severe weather alerts, air quality, and travel recommendations. It powers an Agent Bricks agent to answer natural-language weather questions and make simple predictions like 'Will it rain in Chicago tomorrow?'

Category
Visit Server

README

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.


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.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured