Weather MCP Server 🌦️
A from-scratch Model Context Protocol (MCP) server that gives Claude Desktop (or any MCP host) live weather data. It wraps the free Open-Meteo API (no API key required), keeps a small SQLite-backed list of favorite cities, and can optionally push weather to a Telegram bot.
- Language / SDK: Python 3.10+ with the official
mcppackage (FastMCP high-level API) - Transport:
stdio - Weather API: Open-Meteo (geocoding + forecast) — keyless, free
- Storage: local SQLite file (
favorites.db)
---
Capabilities
🛠 Tools
| Tool | Arguments | Kind | Description | |------|-----------|------|-------------| | get_current_weather | city (required) | live API | Current conditions for a city: temperature, feels-like, humidity, precipitation, wind, sky condition. | | get_forecast | city (required), days (optional, default 3, 1–16) | live API | Multi-day forecast: per-day min/max temperature, precipitation sum, max wind, sky condition. | | add_favorite_city | city (required) | write → SQLite | Geocodes a city and saves it to the favorites list (deduplicated). | | remove_favorite_city | city (required) | write → SQLite | Removes a city from favorites (case-insensitive, with a geocoding fallback). | | send_telegram_message | text (required) | outbound API | Sends an arbitrary text message to a Telegram chat. (optional — needs .env) | | send_weather_to_telegram | city (required) | live + outbound | Fetches current weather and pushes it to a Telegram chat in one step. (optional — needs .env) |
📄 Resource
| Resource URI | Returns | Logic | |--------------|---------|-------| | weather://favorites | Markdown list of saved cities (name, country, coordinates, when added) | Reads live from the SQLite database on every read — not a stub. |
All weather is fetched live on every call (no hard-coded responses), and the resource always reflects the real, current contents of the database.
Note on resources vs. tools: an MCP host calls tools automatically, but a resource is content you attach to the conversation. In Claude Desktop, open
+ → <weather> → Add from weather → Favorites resourceto load the current favorites into context.
---
Requirements
- Python 3.10+
- The dependencies in
requirements.txt(mcp[cli],httpx,python-dotenv) - An MCP host such as Claude Desktop (optional — you can also test with the MCP Inspector)
---
Setup
1. Clone & create a virtual environment
git clone https://github.com/<your-user>/<repo>.git
cd <repo>
python -m venv .venv
.\.venv\Scripts\Activate.ps1 # Windows PowerShell
# source .venv/bin/activate # macOS / Linux
2. Install dependencies
pip install -r requirements.txt
3. (Optional) Try it locally with the MCP Inspector
The Inspector speaks the same JSON-RPC/stdio protocol and gives you a UI to list tools, call them, and read resources — the fastest way to verify the server before wiring it into a host.
mcp dev server.py
Open the printed http://localhost:... URL, click List Tools, call get_current_weather with {"city": "Kyiv"}, and read the weather://favorites resource.
---
Connect to Claude Desktop
- Open (or create) the Claude Desktop config file:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json
(for the Microsoft Store build it lives under %LOCALAPPDATA%\Packages\Claude_\LocalCache\Roaming\Claude\)*
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
- Add a
weatherserver entry with absolute paths to the venv's Python and
to server.py (see claude_desktop_config.json for a ready example):
{
"mcpServers": {
"weather": {
"command": "C:\\path\\to\\mcp\\.venv\\Scripts\\python.exe",
"args": ["C:\\path\\to\\mcp\\server.py"]
}
}
}
On Windows, escape backslashes (
\\) in JSON. The venv Python is used so thatmcpandhttpxare on the path; nocwdis needed because the database path is resolved relative toserver.py.
- Fully quit and restart Claude Desktop. The
weatherserver should appear
in the tools menu (🔌 / hammer icon), and you can ask Claude about the weather.
ℹ️ The
claude_desktop_config.jsonin this repository is a template/example only. Claude Desktop reads the file in the system location from step 1 — not the copy in the project folder. Copy themcpServersblock into that system file (or merge it if the file already exists).
---
Telegram integration (optional)
The send_telegram_message and send_weather_to_telegram tools forward weather to a Telegram bot. They stay disabled until credentials are provided, so the server runs fine without this step.
- Create a bot: message @BotFather, send
/newbot,
and copy the bot token.
- Find your chat id: message @userinfobot (it
replies with your numeric id), or open https://api.telegram.org/bot<token>/getUpdates after messaging your bot.
- Create
.envnext toserver.py(copy from.env.example):
TELEGRAM_BOT_TOKEN=123456789:AA-your-real-token
TELEGRAM_CHAT_ID=123456789
- Restart Claude Desktop, then ask: *"Send the current weather in Kyiv to my
Telegram."* The message is delivered in Ukrainian.
🔒
.envis listed in.gitignoreand is never committed — the token stays only on your machine.
---
Example dialogs
The assistant replies in the user's language; the prompts below match the screenshots in
examples/.
1. Current weather — required argument
You: Яка зараз погода в Києві?
Claude: → get_current_weather(city="Kyiv")
Зараз у Києві ☁️ хмарно, +22.7 °C (відчувається як +23.4 °C),
вологість 58 %, вітер слабкий — 3.6 км/год, без опадів.
2. Forecast — optional days argument
You: Який прогноз погоди у Львові на найближчі 5 днів?
Claude: → get_forecast(city="Lviv", days=5)
• 21.06 — ☁️ хмарно, +20…+31 °C
• 22.06 — 🌧️ помірний дощ, +21…+30 °C, опади 4.9 мм
• ...
3. Favorites + resource
You: Додай Київ і Львів у мої улюблені, потім прибери Львів.
Claude: → add_favorite_city("Kyiv") → add_favorite_city("Lviv")
→ remove_favorite_city("Lviv")
Готово. (Attach "Favorites resource" to see the live list: Київ.)
4. Weather → Telegram (optional)
You: Скинь мені поточну погоду в Києві в Telegram.
Claude: → send_weather_to_telegram(city="Kyiv")
Готово — повідомлення відправлено у твій Telegram-чат. ✅
Screenshots of these conversations are in examples/.
---
Project structure
mcp/
├── server.py # the MCP server (tools + resource)
├── requirements.txt # pinned dependencies
├── claude_desktop_config.json # example host config
├── .env.example # template for Telegram secrets
├── README.md
├── examples/ # screenshots of Claude Desktop dialogs
├── .env # your Telegram secrets (git-ignored, optional)
└── favorites.db # created at runtime (git-ignored)
---
Known limitations
- City disambiguation is naive. The geocoder takes the top match for a
name. Ambiguous names (e.g. "Springfield") may resolve to the wrong place; the tools surface the resolved City, Region, Country so it is visible.
- Forecast horizon.
daysis clamped to Open-Meteo's supported range (1–16);
out-of-range values are clamped, not rejected.
- Network-dependent. Every weather call hits Open-Meteo live; offline or
rate-limited requests fail with an error surfaced back to the host.
- No caching. Repeated identical questions re-fetch from the API.
favorites.dbis local and unencrypted. It only stores public city
coordinates and is not synced or backed up.
- Telegram is optional and single-chat. The
send_*tools target one
pre-configured TELEGRAM_CHAT_ID; no per-message recipient, no retry, no rate limiting. Without .env they fail with a clear "not configured" message.
- stdio only. No HTTP/SSE transport and no authentication — intended for a
local, single-user host, not a shared/remote deployment.
Security notes
- The server writes only JSON-RPC to
stdout; all diagnostics go to
stderr, as the stdio transport requires.
- No shell execution and no string interpolation into commands → no command
injection surface.
- API arguments are passed as typed query parameters via
httpx, never
concatenated into URLs by hand.
- The only secret (the Telegram token) lives in
.env, which is git-ignored; the
weather API itself is keyless.
---
Credits
- Weather & geocoding data: Open-Meteo (CC BY 4.0).
- Protocol: Model Context Protocol.






