mcp-weather-tutorial
Click on "Install 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-tutorialwhat's the weather in Denver?"
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 Tutorial
A working MCP server and two clients, built against Open-Meteo (free, no API key, no signup).
Heads up: most MCP tutorials online are out of date
They open with:
from mcp.server.fastmcp import FastMCP # ModuleNotFoundError on mcp 2.0FastMCP was removed in mcp 2.0. It is now MCPServer, from mcp.server.
Response fields also moved to snake_case (input_schema, not inputSchema).
If a tutorial mentions FastMCP, it is describing 1.x.
Verified against mcp 2.0.0 and claude-agent-sdk 0.2.95.
Related MCP server: open-meteo-mcp
Files
File | What it does | Needs |
| MCP server exposing | nothing |
| Raw protocol client -- no LLM, nothing hidden | nothing |
| Claude picks and chains the tools itself | Claude Code login |
Run it
uv run client_basic.py # defaults to Denver
uv run client_basic.py Lisbon
uv run client_basic.py San Francisco # spaces are fine, no quotes
uv run client_basic.py Portland --pick 1 # 2nd match, not the 1st
uv run client_basic.py Tokyo --days 7
uv run client_basic.py --lat 27.99 --lon 86.93 # skip geocoding entirely
uv run client_basic.py Lisbon --json # also dump the raw payload
uv run client_agent.py # just ask, in English
uv run client_agent.py "should I bring an umbrella in Lisbon tomorrow?"
uv run client_agent.py "compare Tokyo and Seoul this weekend"--pick exists because city names are ambiguous: "Denver" matches five places
and "Portland" two well-known ones. Open-Meteo ranks by population, so the top
hit is a guess. client_basic.py lists every match and marks the one it used;
client_agent.py lets Claude choose and say why.
uv run server.py on its own will look like it hangs. It hasn't -- it is
waiting for a client on stdin.
Debugging
Press F5 in VS Code and pick a configuration. Start with "1. Step into server tools (in-process)".
The thing that catches people out: normally client_basic.py launches
server.py as a subprocess, and a debugger does not follow across a process
boundary. Breakpoints in server.py are silently never hit, which looks like
the tool is not being called at all.
--in-process fixes this. Client() accepts an MCPServer object directly and
runs it in the same process, no pipes involved:
uv run client_basic.py Denver --in-process # identical output, one processNow a breakpoint inside geocode_city hits, and Step Into (F11) on
call_tool(...) walks from the client, through the protocol layer, into the
tool body.
Good breakpoints to start from:
File | Line | What you see |
| the | the schemas generated from your type hints |
| the first | arguments going out as a plain dict |
| first line of | your tool receiving them |
| the | the value before MCP serializes it |
The configs set "justMyCode": false, so you can also step down into the mcp
library itself and watch the JSON-RPC request get built. Set it to true to
stay in your own files.
Debugging the real subprocess
When you specifically want the true stdio path (config 3 debugs the client
only), have the server wait for a debugger. Add this at the top of server.py,
run the client normally, then launch config 4. Attach to server subprocess:
import debugpy
debugpy.listen(5678)
debugpy.wait_for_client() # server pauses here until you attachRemove it when you are done -- it makes the server hang for anything that is
not a debugger. For everyday work --in-process is easier.
Why two tools instead of one
get_forecast takes coordinates, not city names, because Open-Meteo's forecast
endpoint does. Answering "weather in Denver" therefore takes two calls:
geocode_city("Denver") -> lat 39.73915, lon -104.9847
get_forecast(39.73915, -104.9847) -> daily highs and lowsclient_basic.py does that hand-off by hand so you can see it.
client_agent.py never mentions Denver or latitude -- Claude works it out:
[tool] mcp__weather__geocode_city(name='Denver')
[tool] mcp__weather__get_forecast(latitude=39.73915, longitude=-104.9847, days=6)That is the point of the whole exercise.
Two things that will bite you
Return annotations need a schema. A tool annotated -> dict fails with
InvalidSignature: return type <class 'dict'> is not serializable for structured output. Use a TypedDict (see City, Forecast in server.py).
List returns get wrapped, object returns do not. A tool returning a list
arrives as {"result": [...]}, because JSON Schema needs an object at the top
level. A tool returning a TypedDict arrives as-is:
geo.structured_content["result"] # list-returning tool
forecast.structured_content # object-returning tool -- no "result" keyConnecting it to Claude Code
claude mcp add weather -- uv run server.pyThen ask Claude Code about the weather directly. claude mcp remove weather
undoes it.
License
MIT -- see LICENSE.
Design notes
Available Tools
2 toolsgeocode_cityA
Find the latitude and longitude of a city by name.
Returns candidate matches, since city names are ambiguous -- there are Portlands in both Oregon and Maine. Use this before get_forecast, which only accepts coordinates.
Args: name: City name to search for, e.g. "Denver" or "Paris". limit: Maximum number of candidate matches to return.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It explains the tool returns candidate matches due to ambiguity, implying a read-only lookup. However, it does not disclose potential side effects, rate limits, or authorization needs, which would be beneficial.
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?
The description is concise with no filler. It front-loads the purpose, then adds essential context about ambiguity and usage. Every sentence is valuable and efficiently communicates what the tool does.
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?
Given the tool has only two parameters and an output schema is present, the description is sufficiently complete. It explains why multiple results may be returned and how this tool fits into a workflow with its sibling, providing enough context for an AI agent.
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 0%, so the description fully compensates. It explains the 'name' parameter with examples and describes 'limit' as the maximum number of candidate matches, adding meaning beyond the schema's type and default.
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?
The description clearly states the tool finds latitude and longitude of a city by name. It distinguishes itself from the sibling tool 'get_forecast', which accepts coordinates, making the purpose unambiguous.
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?
Explicitly states to use this before get_forecast, and explains that city names are ambiguous, so candidate matches are returned. Provides clear context for when to use and what to expect.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_forecastA
Get the daily weather forecast for a set of coordinates.
This tool does not accept city names. To look up a city, call geocode_city first and pass its latitude and longitude here.
Args: latitude: Degrees north, e.g. 39.74 for Denver. longitude: Degrees east, e.g. -104.98 for Denver. days: How many days ahead to forecast, 1 to 16.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| latitude | Yes | ||
| longitude | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| days | Yes | |
| units | Yes | |
| timezone | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It does not disclose behavioral traits such as rate limits, idempotency, or output format. While it describes input behavior, it lacks details on response structure or side effects, which is adequate but minimal.
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?
The description is concise at 7 lines, front-loads the main purpose, and each sentence adds value without redundancy. No wasted words.
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?
Given the tool has an output schema (not shown) and only 3 simple parameters, the description covers inputs well. However, it lacks a summary of expected output fields or any note on measurement units, which would help complete the context for an agent.
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 0%, so the description compensates by explaining latitude with example (e.g., 39.74 for Denver), longitude similarly, and days with a range (1 to 16). It adds meaning beyond the schema, though it could specify coordinate format (decimal degrees) explicitly.
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?
The description clearly states the tool gets a daily weather forecast for coordinates, and explicitly distinguishes itself from the sibling geocode_city by stating it does not accept city names. The verb 'get' and resource 'forecast' are specific.
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?
The description provides explicit when-to-use and when-not-to-use guidance: to get a forecast for coordinates, and to use geocode_city first for city names. It also gives examples of coordinate formats, aiding correct invocation.
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. Dates show when Glama detected each change.
2 tool updates
v0.1.0- First observed
geocode_city - First observed
get_forecast
TDQS
The two tools have completely distinct purposes: one converts city names to coordinates, the other retrieves forecasts from coordinates. There is no functional overlap.
Both tools follow the same verb_noun snake_case pattern (geocode_city, get_forecast), making them predictable and easy to understand.
With only 2 tools, the server feels minimal, but as a tutorial it is appropriately scoped for the basic workflow of converting a city name to coordinates then getting a forecast.
The server only provides geocoding and daily forecasts, omitting common weather features like current conditions, hourly forecasts, alerts, or historical data. This is notably incomplete for a general weather domain.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
An MCP server for weather information by @kulybaba
An MCP server for weather information by @kulybaba
MCP server for weather with reasoning — umbrella advice, outdoor checks, city comparisons.
Open-Meteo MCP — weather forecast + historical reanalysis + sister APIs
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceA minimal MCP server that provides weather data using Open-Meteo API, designed as a teaching tool for improving AI agent tool interfaces.-
- AlicenseNot gradedqualityBmaintenanceMCP server for Open-Meteo free weather APIs, offering 16 tools for forecast, historical, air quality, marine, flood, ensemble, climate, seasonal, and scheduled data collection with no API key required.77MIT
- FlicenseNot gradedqualityCmaintenanceA proof-of-concept MCP server that provides weather information using the Open-Meteo API, with tools for greeting, getting weather by coordinates, and by location name.-
- FlicenseNot gradedqualityCmaintenanceAn MCP server that provides current weather conditions and forecasts via OpenWeatherMap API to AI agents.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/matjmiles/mcp-weather-tutorial'
If you have feedback or need assistance with the MCP directory API, please join our Discord server