Powder Compass MCP
by petelittle
README.md
# Powder Compass MCP ❄️
A small local [MCP](https://modelcontextprotocol.io) server that gives
Claude Desktop a set of **honest, tested tools** for scoring a ski or
snowboard day — plus the unit converters an imperial-units skier needs
to feed it.
The scoring is a faithful port of the Rust CLI
[powder-compass](https://github.com/petelittle/powder-compass):
same bands, same verdicts, same practical tips, same safety override —
ported, not redesigned.
> Fun planning only — always check the resort's official conditions
> and avalanche information before you go.
## The tools
| Tool | What it does |
|---|---|
| `powder_score` | Score a day out of 100 from fresh snow (cm), temperature (°C), wind (km/h) and visibility (1–5). Returns the score, a points breakdown, a verdict and one practical tip. |
| `convert_temperature` | °C ↔ °F, direction stated explicitly, rounded to 1 decimal place. |
| `convert_wind` | km/h ↔ mph, direction stated explicitly, rounded to 1 decimal place. |
| `convert_snow` | cm ↔ inches, direction stated explicitly, rounded to 1 decimal place. |
Out-of-range or unknown-unit inputs are **rejected with a clear
error** — never silently clamped or guessed. That is a design rule,
not an accident (see *Why this exists* below).
## Quick start
Requires Python 3.10+ and [uv](https://docs.astral.sh/uv/).
```sh
uv run pytest -q # run the test suite (13 tests)
uv run mcp dev server.py # poke the tools by hand in the MCP Inspector
```
## Use it in Claude Desktop
Add an entry like this to Claude Desktop's `claude_desktop_config.json`
(Settings → Desktop app → Local MCP servers → **Edit config** shows you
the exact file your install actually reads), then restart Claude:
```json
{
"mcpServers": {
"PowderCompass": {
"command": "uv",
"args": [
"run",
"--directory",
"C:\\path\\to\\powder-compass-mcp",
"python",
"server.py"
]
}
}
}
```
> **Windows note (learned the hard way):** if `mcp install` tells you
> *"Claude app not found"*, your Claude Desktop is probably the
> MSIX-packaged build. Its real config file may live outside the app
> package, e.g. at
> `%LOCALAPPDATA%\Claude-Data\<package-id>\claude_desktop_config.json`.
> The **Edit config** button in Settings always opens the true file —
> trust it, not the textbook paths. Back the file up before editing,
> merge the `mcpServers` entry in, and restart Claude fully (tray →
> Quit) so it re-reads the config.
Then just ask, in plain words:
- *"We got 24 cm of fresh snow overnight, it's −8 °C, the wind is
8 km/h and visibility is perfect. How good a ski day is it?"*
→ 96/100, "Champagne-powder alert"
- *"How fast is 60 mph wind in km/h?"* → 96.6 km/h
- *"An American resort reports 10 inches of fresh snow, 20 °F, wind
10 mph, visibility 4 out of 5…"* → Claude converts, then scores:
89/100
## Why this exists
In April 2025 the author ran an experiment: an MCP `add` tool that
quietly returned `a − b` under an honest "Add two numbers" docstring.
The lesson stuck — **a language model trusts a tool's description,
not its code.**
This server is the counterpart. Every tool's behaviour is pinned down
by automated tests (`test_server.py`, pytest) that mirror the original
Rust test suite and add converter and error-case checks, so the
descriptions Claude reads are claims the code has been *proven* to
keep. Trust, but verify — then earn the trust.
## Scoring at a glance
| Category | Max | Bands (points) |
|---|---|---|
| Fresh snow | 40 | 0→0 · 1–4→10 · 5–9→20 · 10–19→30 · 20–29→36 · 30+→40 |
| Temperature | 20 | −12…−3→20 · −18…−13 / −2…0→16 · −25…−19 / 1…2→10 · 3…5→5 · 6+→0 · below −25→6 |
| Wind | 20 | 0–10→20 · 11–20→17 · 21–35→12 · 36–50→6 · 51+→0 |
| Visibility | 20 | 1→2 · 2→6 · 3→11 · 4→16 · 5→20 |
Verdicts run from *"Champagne-powder alert"* (85+) down to
*"Hot-chocolate conditions"* — with a safety override: at −30 °C or
colder, or wind at 70 km/h or more, the verdict is always
**"Red-flag conditions — official advice first"**, whatever the score.
## Tech
- Python + MCP Python SDK 2.3.0 (`mcp[cli]`), managed with uv
- Tests: pytest — `uv run pytest -q`
## Licence
MIT (same as the Rust original).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues