Weather-Prediction MCP Server
A weather MCP server that provides current conditions, forecasts, and prediction tools (umbrella, travel recommendations) so agents can answer natural-language weather questions.
README
Weather-Prediction MCP Server + Agent Bricks Agent
A weather MCP server built with FastMCP that exposes weather-forecast tools to a Databricks Agent Bricks agent, so the agent can answer natural-language weather questions and make simple predictions/recommendations (e.g. "Will it rain in Chicago tomorrow?", "Should I bring a jacket to Austin this weekend?").
Built as a homework for Day 3 (Agent Bricks + Alpaca paper-trading MCP server), using that
repo's mcp_server/ split as the reference pattern: thin @mcp.tool functions on top of a separate
adapter module that owns all the HTTP/parsing.
Live deployment
Two Databricks Apps (mirroring Day 3's server + agent split):
| App | Role | URL |
|---|---|---|
mcp-weather-server |
MCP server (the 5 tools) | https://mcp-weather-server-7474650707148987.aws.databricksapps.com |
agent-weather-app |
The agent (chat UI, calls the MCP tools) | https://agent-weather-app-7474650707148987.aws.databricksapps.com |
- MCP endpoint (what the agent connects to):
https://mcp-weather-server-7474650707148987.aws.databricksapps.com/mcp - Confirmed running from the server logs:
Starting MCP server 'weather-prediction' with transport 'http' on http://0.0.0.0:8000/mcp. (Opening/mcpin a browser returnsNot Acceptable: Client must accept text/event-stream— that's expected; only an MCP client can speak to it.) agent-weather-appdeclaresmcp-weather-serveras an app resource, and its service principal hasCAN_USEon the server, so the agent can call all 5 tools.
Weather API + auth
Open-Meteo — chosen because it needs no signup, no API key, and no credit card (free for non-commercial use, ~10k calls/day). Two key-less endpoints are used:
- Geocoding API (
geocoding-api.open-meteo.com) — turns a city name into latitude/longitude. - Forecast API (
api.open-meteo.com) — current conditions + daily forecast.
Because there are no credentials, there is no Databricks secret to manage for this project.
(If you swap in a keyed provider like WeatherAPI.com, fetch the key in weather_adapter.py via
WorkspaceClient().secrets.get_secret() — the same pattern as Day 3's alpaca_broker.py — and
nothing else changes.)
Architecture
Agent Bricks agent --(MCP tool calls, streamable HTTP)--> weather_mcp_server.py
| |
| natural-language weather Q&A | (thin @mcp.tool funcs)
v v
final answer <---------------------------------------- weather_adapter.py
|
| (all HTTP + parsing)
v
Open-Meteo geocoding + forecast APIs
weather_mcp_server.py— FastMCP server; each tool is a thin wrapper that delegates to the adapter and returns a clean dict (or{"status": "error", ...}on failure).weather_adapter.py— the adapter/broker module (likealpaca_broker.py): allrequestscalls and response parsing live here, plus the WMO weather-code → text mapping. No rawrequestscalls exist inside any@mcp.toolfunction.
Tools
Minimum three capabilities (current / forecast / prediction), plus two stretch tools:
| Tool | Kind | What it does |
|---|---|---|
get_current_weather(location) |
current | Temperature, feels-like, humidity, precipitation, wind, conditions for now. |
get_forecast(location, days=3) |
forecast | Daily high/low, precip chance & amount, max wind, conditions for the next N days (1–16). |
predict_umbrella_needed(location, day_offset=0) |
prediction | Derived yes/no: umbrella if precip chance ≥ 40% or ≥ 0.1 in expected. Returns the reasoning + thresholds. |
get_travel_recommendation(location, day_offset=0) |
prediction | Multi-factor packing advice (umbrella / jacket / sunscreen / wind), each with its threshold. |
compare_cities_weather(locations, day_offset=0) |
stretch | Side-by-side forecast for several cities + picks the "nicest" via a simple score. |
location accepts a city name ("Chicago", "Austin, TX", "London") or a "lat,lon" pair
("41.8781,-87.6298"). day_offset is 0 = today, 1 = tomorrow, etc.
Why the prediction tools aren't just passthroughs
predict_umbrella_needed and get_travel_recommendation apply explicit thresholds (configurable via
env vars in app.yaml) to the raw forecast and return the decision plus the reason, rather than
echoing the API. Defaults:
| Threshold | Default | Meaning |
|---|---|---|
UMBRELLA_PRECIP_CHANCE_PCT |
40 | Umbrella if max precip probability ≥ this |
UMBRELLA_PRECIP_AMOUNT |
0.1 in | …or total precip ≥ this |
JACKET_TEMP_F |
55 | Jacket if the day's high ≤ this |
SUNSCREEN_TEMP_F |
75 | Sunscreen if sunny and high ≥ this |
WIND_ADVISORY_MPH |
25 | Wind warning if max wind ≥ this |
Error handling & edge cases (with examples)
Every tool catches errors and returns a structured {"status": "error", "message": ...} dict — the
MCP-appropriate analog of an HTTP 4xx — so a bad input or an API outage never reaches the agent as a
stack trace. Concrete cases:
| Input | Result | Where |
|---|---|---|
Unknown city — get_current_weather("Xyzzyville") |
{"status":"error","message":"Could not find a location matching 'Xyzzyville'. Try a 'City, ST' form or a 'lat,lon' pair."} |
adapter raises ValueError (weather_adapter.py:130), tool catches (weather_mcp_server.py:86) |
Empty location — get_current_weather("") |
ValueError("Location is required …") → clean error dict |
weather_adapter.py:110 |
Out-of-range days — get_forecast("Chicago", 999) |
clamped to 1..16 | weather_adapter.py:213 |
Out-of-range day_offset — predict_umbrella_needed("Chicago", 99) |
{"status":"error","message":"day_offset 99 is out of range - only N day(s) … (0 = today)."} |
weather_mcp_server.py:60 |
Too few cities — compare_cities_weather(["Austin"]) |
{"status":"error","message":"Provide at least two locations to compare."} |
weather_mcp_server.py:272 |
| One bad city in a compare | that city goes into an errors[] array; the rest still return |
weather_mcp_server.py:302 |
| API / network outage | generic Exception caught + logger.exception(...), returns {"status":"error","message":"Could not fetch …: <e>"} |
e.g. weather_mcp_server.py:88 |
lat,lon input — get_current_weather("41.88,-87.63") |
resolved directly, no geocoding call | weather_adapter.py (_LATLON_RE) |
Agent behavior on error: the system prompt tells the agent to relay the error and ask the user
to clarify rather than guess — see the guardrail screenshot (will it rain? with no location → the
agent asks for a location and invents nothing).
Code map (nothing left to inference)
| Requirement | Exact location |
|---|---|
| FastMCP + streamable-HTTP transport | weather_mcp_server.py:324 — mcp.run(transport="http", host="0.0.0.0", port=port) |
Tools via @mcp.tool (thin wrappers) |
weather_mcp_server.py lines 69, 93, 117, 186, 252 |
No raw requests in tools — all HTTP in the adapter |
weather_adapter.py: _get():95, geocode():100, get_current():151, get_forecast():201. The server imports weather_adapter and never calls requests. |
| Docstrings (Args/Returns) | every tool function in weather_mcp_server.py |
| Prediction = threshold logic, not a passthrough | constants at weather_mcp_server.py:47-51; applied in predict_umbrella_needed:117 and get_travel_recommendation:186; overridable via app.yaml |
| Clean error handling | try/except in every tool; adapter raises typed ValueError with messages |
| System prompt + guardrails | agent/system_prompt.md |
| No secrets | Open-Meteo is key-less; .env git-ignored; no WorkspaceClient().secrets used |
This MCP server is stateless — no model or DB loaded per request. The only external calls are two key-less Open-Meteo endpoints, all confined to
weather_adapter.py.
Files
weather_mcp_server.py— FastMCP server exposing the 5 toolsweather_adapter.py— adapter: all Open-Meteo HTTP calls + parsing + WMO code mappingrequirements.txt/app.yaml— Databricks App config for the MCP server.env.example— local dev env template (all optional; no key required)agent/system_prompt.md— the Agent Bricks system promptagent/agent_setup.md— how to register the MCP server + build the agent, and the tool list
Setup
1. Run locally
pip install -r requirements.txt
python weather_mcp_server.py # serves MCP over streamable HTTP on :8000
Sanity-check the adapter without MCP:
python -c "import json, weather_adapter as w; print(json.dumps(w.get_current('Chicago'), indent=2))"
Or point an MCP Inspector at
http://localhost:8000 to list and call the tools.
2. Deploy as a Databricks App
Same flow as Day 3's mcp_server/:
- Put this folder in a Databricks Git folder.
- Compute > Apps > Create app > Custom, name it e.g.
weather-mcp, and point its source at this folder (so it picks upapp.yaml). - Deploy, then copy the app URL — you'll register it as an external MCP server next.
No secrets step is needed (Open-Meteo is key-less).
3. Register the MCP server + build the agent
See agent/agent_setup.md for the full steps (mirrors Day 3's README):
register the app URL as an external MCP, create an Agent Bricks agent, add the 5 tools, and paste the
system prompt from agent/system_prompt.md.
Demonstration (agent Q&A)
Real tool outputs from the live Open-Meteo API (captured 2026-08-09; your numbers will differ):
Q1 — "What's the weather like in Chicago right now?"
Agent calls
get_current_weather("Chicago")→{"location": "Chicago, Illinois, United States", "temperature": 83.9, "feels_like": 90.6, "humidity_pct": 68, "wind_speed": 11.2, "conditions": "Overcast", "as_of": "2026-08-09T12:15"}Answer: "Right now in Chicago it's about 84°F (feels like 91°F because of the humidity — 68%), overcast, with an 11 mph wind."
Q2 — "Should I bring an umbrella to Seattle tomorrow?"
Agent calls
predict_umbrella_needed("Seattle", day_offset=1)→{"location": "Seattle, Washington, United States", "date": "2026-08-10", "umbrella_needed": false, "precip_chance_pct": 2, "conditions": "Overcast", "reason": "No umbrella needed. 2026-08-10 in Seattle... only a 2% chance of precipitation... below the 40% / 0.1 in threshold."}Answer: "No need — tomorrow in Seattle is overcast but only a 2% chance of rain, well below the 40% umbrella threshold."
Q3 — "Should I pack a jacket for Seattle this weekend?"
Agent calls
get_travel_recommendation("Seattle", day_offset=1)→{"location": "Seattle, Washington, United States", "date": "2026-08-10", "recommendations": ["No special gear needed - mild conditions expected."], "forecast": {"temp_high": 74.7, "temp_low": 55.2, "conditions": "Overcast"}}Answer: "You should be fine without a jacket during the day — highs around 75°F. Evenings dip to the mid-50s, so a light layer wouldn't hurt after sunset."
Q4 (stretch) — "Which has nicer weather this weekend: Austin, Seattle, or Denver?"
Agent calls
compare_cities_weather(["Austin","Seattle","Denver"], day_offset=1)→ ranks by score and reports thebestcity with its high/low, conditions, and precip chance.
Notes / guardrails
- Clean errors, not stack traces. A bad location (
get_current_weather("Xyzzy")) returns{"status": "error", "message": "Could not find a location matching 'Xyzzy'. Try a 'City, ST' form or a 'lat,lon' pair."}, and the system prompt tells the agent to ask the user to clarify rather than guess. - No hallucinated weather. The system prompt requires the agent to base every weather claim on a tool result and to say so if a tool fails.
- No secrets committed. Open-Meteo needs none;
.envis git-ignored.
推荐服务器
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 模型以安全和受控的方式获取实时的网络信息。