mcp-weather-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-weather-serverDo I need an umbrella in Lisbon this weekend?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-weather-server
A small, tested Model Context Protocol server that connects Claude to a public REST API, here Open-Meteo (free, no API key). Ask Claude "Do I need an umbrella in Lisbon this weekend?" and it calls these tools instead of guessing.
It is deliberately small: one HTTP client module, one server module, typed results, and a test suite that runs offline in about a second. The same shape works for any REST API, database or SaaS tool.
Tools
Tool | Arguments | Returns |
|
| Temperature, feels-like, humidity, wind, precipitation, condition |
|
| Daily min/max, rain chance and amount, max wind, condition |
|
| Current weather for each, plus warmest, coldest and the spread |
City names can carry a country code to disambiguate:
"Springfield, US".Every tool is marked read-only and returns structured JSON with an output schema, so Claude (or any MCP client) gets typed data, not just text.
Units: Celsius, km/h, mm.
Related MCP server: hevy-mcp
What makes it production-shaped
Input validation in the tool schema (Claude sees the limits) and again in code (empty or oversized city,
daysout of range). Bad input is rejected before any HTTP call.Clear errors. Unknown city, upstream 4xx/5xx, timeouts and non-JSON bodies all come back to Claude as a readable tool error ("No place called 'Atlantis' found. Check the spelling, or add a two-letter country code..."), never a stack trace.
Timeouts on every request (5 s connect, 10 s read).
Response cache: place lookups for 24 hours, weather for 10 minutes, so repeated questions do not hammer the API.
Tests with no network and no key. HTTP is faked with
httpx.MockTransport, a guard fails any test that tries to open a real socket, and the tools are exercised through a real MCP client session, plus one test that boots the actual stdio entry point.
Quick start
Requires Python 3.10+ and uv.
git clone <this repo> mcp-weather-server
cd mcp-weather-server
uv sync
uv run weather-mcp # starts the stdio server; Ctrl+C to stopWithout uv: python -m venv .venv && .venv/bin/pip install -e ".[dev]", then .venv/bin/weather-mcp.
Use it from Claude Code
claude mcp add weather -- uv --directory /absolute/path/to/mcp-weather-server run weather-mcpThen ask: "What's the 5-day forecast for Oslo?" (claude mcp list shows it as connected.)
Use it from Claude Desktop
Add this to claude_desktop_config.json (Settings > Developer > Edit Config) and restart Claude Desktop:
{
"mcpServers": {
"weather": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/mcp-weather-server", "run", "weather-mcp"]
}
}
}Run the tests
uv run pytest -qor, in any environment with the dependencies installed, python -m pytest -q. The pytest config puts src/ on the path, so no install step is needed for the tests themselves. No network access or API key is used.
Layout
src/weather_mcp/
client.py # the only file that knows about HTTP: Open-Meteo calls, errors, cache use
server.py # MCP tool definitions, validation, error mapping, stdio entry point
models.py # typed results (pydantic) that become the tools' output schemas
cache.py # tiny TTL cache with an injectable clock
weather_codes.py # WMO weather code -> plain-language condition
tests/
conftest.py # fake Open-Meteo, fake clock, no-network guard
test_client.py # parsing, errors, validation, caching
test_server.py # every tool through a real MCP client session, plus a stdio boot testHow I'd adapt this to your API
The design keeps the API-specific part in one file so the rest carries over unchanged:
Swap
client.pyfor a client of your API (REST, GraphQL, a database driver, a SaaS SDK). Keep the same pattern: async calls, timeouts, auth from an environment variable (never hard-coded), and a small set of named exceptions for "not found", "bad input" and "upstream failed".Define the tools around what your users ask, not around your endpoints. Typically three to six tools with tight argument schemas and typed results in
models.py. Write actions (create, update) get explicit confirmation-friendly arguments and are marked as such.Keep the tests' shape: a fake of your API behind
httpx.MockTransport(or a throwaway SQLite database), unit tests for the client, and end-to-end tests that call each tool through an MCP client session. They run in CI without credentials.Ship the config snippet for Claude Desktop and Claude Code, as above, with the environment variables your API needs.
Built with
Python, the official MCP Python SDK (mcp 2.x, MCPServer), httpx and pydantic. Built with Claude Code.
License
MIT, see LICENSE.
Available Tools
3 toolscompare_citiesCompare citiesARead-onlyIdempotent
Current weather side by side for 2-5 cities, with the warmest and coldest named.
| Name | Required | Description | Default |
|---|---|---|---|
| cities | Yes | Two to five city names |
Output Schema
| Name | Required | Description |
|---|---|---|
| cities | Yes | |
| coldest | Yes | |
| warmest | Yes | |
| spread_c | Yes | Warmest minus coldest current temperature |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, open-world, and idempotent behavior, so the description only needs added context. It usefully discloses that results are presented side by side and that the warmest and coldest cities are named, though it does not describe failure behavior for invalid cities.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence with the key scope and output framing front-loaded. Every phrase contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only comparison tool, the description covers purpose, input range, and notable output behavior. Output schema, parameter schema, and annotations already supply the remaining structured details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the cities parameter already documents the 2-5 item constraint. The description reinforces the same range but adds no new format or syntax guidance beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action and resource: current weather compared side by side for 2-5 cities. The multi-city comparison scope clearly distinguishes it from single-current and forecast siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Strong implied usage for comparing current weather across multiple cities, with the 2-5 city range making the applicable scenario clear. It does not explicitly say when to choose this over get_current or get_forecast, so it stops short of full alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_currentCurrent weatherARead-onlyIdempotent
Current conditions for a city: temperature, feels-like, humidity, wind, precipitation.
| Name | Required | Description | Default |
|---|---|---|---|
| city | Yes | City name, optionally with a country code, e.g. 'Paris' or 'Paris, US' |
Output Schema
| Name | Required | Description |
|---|---|---|
| location | Yes | |
| condition | Yes | Plain-language description of the WMO weather code |
| observed_at | Yes | Local time of the observation (ISO 8601) |
| feels_like_c | No | |
| humidity_pct | No | |
| temperature_c | Yes | |
| wind_speed_kmh | No | |
| precipitation_mm | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety and idempotency profile is covered. The description adds only the returned field set, which duplicates the output schema, and says nothing about freshness, caching, units, or failure behavior for unknown cities.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence with no filler and the key distinction ('current') placed first. The trailing field list is somewhat redundant with the output schema but stays compact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A single-parameter, read-only lookup with an output schema and full annotation coverage needs little prose, and the description covers purpose and scope. Only ambiguity about data freshness and invalid-city handling keeps it short of complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single 'city' parameter already documents the 'Paris' / 'Paris, US' format. The description contributes no additional meaning about the parameter, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific retrieve action ('Current conditions') on a specific resource ('a city') plus the field set returned. The 'current' vs. 'forecast' distinction implicitly separates it from get_forecast, but no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: 'Current conditions' signals this is the now-snapshot tool versus get_forecast, and nothing is said about when to prefer compare_cities. No explicit when-to-use or when-not-to-use guidance is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_forecastDaily forecastARead-onlyIdempotent
Daily forecast for a city: min/max temperature, rain chance and amount, max wind.
| Name | Required | Description | Default |
|---|---|---|---|
| city | Yes | City name, optionally with a country code, e.g. 'Paris' or 'Paris, US' | |
| days | No | Number of days, 1 to 16 |
Output Schema
| Name | Required | Description |
|---|---|---|
| days | Yes | |
| location | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint and idempotentHint, so the safety profile is covered and the description is not required to restate it. The description does add value by naming the specific payload fields (temperature range, rain probability and amount, max wind). It says nothing, though, about how many days are returned or how the 'days' horizon affects the result.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence that front-loads the resource and then enumerates outputs in priority order. Every clause conveys information; nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be described, and annotations cover safety. The remaining gap is the forecast horizon: the description never mentions that a multi-day range (up to 16 days) can be requested, so an agent could reasonably read this as a single-day tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including the 'Paris' / 'Paris, US' city format and the 1-16 day range, so the baseline of 3 applies. The description adds no parameter-level meaning beyond the schema and, in fact, its singular 'Daily forecast' framing is slightly out of step with the multi-day 'days' parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Daily forecast for a city') and enumerates the returned measurements (min/max temperature, rain chance and amount, max wind), which makes it distinguishable from get_current by implication. It never names the siblings get_current or compare_cities, however, so the differentiation is inferential rather than explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the phrase 'Daily forecast for a city'; there is no statement of when to prefer this over get_current (current conditions) or compare_cities. No prerequisites, exclusions, or notes about forecast horizon are given, leaving the agent to infer routing from the tool name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
compare_cities - First observed
get_current - First observed
get_forecast
TDQS
Scored across 3 tools
Each tool targets a distinct temporal or comparative view (current, forecast, multi-city comparison), and descriptions make the boundaries explicit. compare_cities partially overlaps with get_current applied to several cities, but the added ranking output justifies its separate existence.
All three tools follow the same snake_case verb_noun pattern (get_current, get_forecast, compare_cities). The verbs are accurate and predictable, so an agent can guess a tool's intent from its name.
Three tools is on the lean side, but each covers a genuinely distinct weather-query pattern and nothing feels redundant. It sits at the low edge of a well-scoped surface rather than being thin to the point of uselessness.
The core weather workflows (current conditions, daily outlook, multi-city comparison) are covered with no dead ends. Gaps exist around hourly breakdowns, historical data, alerts, and city/geocoding lookup, but agents can work around these for typical queries.
Maintenance
Related MCP Connectors
Global weather via Open-Meteo: forecast, historical, marine, air quality, geocoding, elevation.
NOAA weather for AI agents: conditions, forecasts, observed history. 3 tools, free, no key.
Read-only airport delay, weather, and 24h forecast tools for AI assistants. Airport-level only.
Weather MCP — wraps Open-Meteo API (free, no auth)
Related MCP Servers
- FlicenseAqualityDmaintenanceExposes the Timely.mn v3 time-attendance API as MCP tools for Claude and other clients, allowing queries for company-wide attendance, employee profiles, and attendance reports.4-
- AlicenseNot gradedqualityDmaintenanceExposes the Hevy workout API to Claude, enabling users to manage workouts, routines, exercise templates, body measurements, and user info via natural language.3,367 npmMIT
- AlicenseAqualityBmaintenanceEnables Claude, Cursor, or any MCP client to query your own recovery scores, sleep, strain cycles, workouts, profile, and body measurements through every WHOOP API v2 read endpoint. Tools return records exactly as WHOOP sends them, with paging and date-range filtering, and refresh tokens automatically after a one-time login.113 npm1MIT
- FlicenseNot gradedqualityCmaintenanceExposes five tools that let Claude query training data from the intervals.icu API directly, covering weekly volume, fitness/fatigue/form, recent activities with per-rep detail, wellness metrics, and pace-at-heart-rate trends, with in-memory caching of upstream responses.-