TrailSmith
TrailSmith — weather-aware Carpathian itinerary agent (MCP assignment)
Repository: https://github.com/mashta-lilia/trailsmith-mcp-agent (full commit history; this archive is an export of tracked files at one commit)
A domain-specific data agent that validates, risk-assesses, and replans multi-day hiking itineraries in the Chornohora range. It uses two MCP connections:
Existing server (Part A): OpenWeather MCP — live 5-day forecasts per settlement.
Custom server (Part B):
trailsmith(this repo,trailsmith_mcp/) — four domain tools over a local curated trail dataset.
The agent (Claude Agent SDK) validates an itinerary, spawns one day-assessor
subagent per day in parallel (forecast → deterministic parse → risk score),
spawns replanner subagents for no_go days, merges and re-validates, and
produces a final plan with a visible value trace from raw forecast text to the
decision.
Try it in one command (no API keys needed)
python -m venv .venv
.\.venv\Scripts\pip install -r requirements.txt
.\.venv\Scripts\python scripts\walkthrough.py demo\itinerary_storm.json --fixtures scenario_stormThat runs the whole planning workflow against a recorded forecast — validate, score each day, replan the dangerous one, estimate logistics — with no LLM and no credentials:
[2] day 2 2026-08-21 NESAMOVYTE -> BYSTRETS (10.2 km, 500 m)
forecast: 2026-08-21 conditions='Thunderstorm thunderstorm with heavy rain' ...
risk: 100 no_go
+70 thunderstorm_on_exposed_ridge: Thunderstorm forecast on an exposed ridge.
+35 wet_exposed_ridge: 25.0 mm precipitation on an exposed ridge at 2036 m: ...
[3] day 2 is no_go - replanning
chose ['CH-022', 'CH-014'] (9.3 km) -> 60 caution [relaxation: none]Full walkthrough with live weather and the agent: docs/quickstart.md.
Prerequisites
Python 3.12+ (tested on 3.13)
Go 1.21+ (only to build the OpenWeather MCP binary)
An OpenWeatherMap API key (free tier) and an Anthropic API key
Installation
PowerShell, from the repo root:
python -m venv .venv
.\.venv\Scripts\pip install -r requirements.txt
go install github.com/mschneider82/mcp-openweather@latest
New-Item -ItemType Directory -Force bin
Copy-Item "$env:USERPROFILE\go\bin\mcp-openweather.exe" bin\
Copy-Item .env.example .envThen edit .env:
Variable | Needed for |
| the agent (Claude Agent SDK). Optional if you have run |
| live OpenWeather calls. A new key takes up to ~2 h to activate. |
| optional override; defaults to |
|
|
| optional replay directory name; defaults to |
Secrets live only in .env (git-ignored, along with any .env.* variant).
Nothing sensitive is committed.
Independent start commands
Custom MCP server (separate process):
.\.venv\Scripts\python -m trailsmith_mcpAgent:
.\.venv\Scripts\python -m agent.runner demo\itinerary_clean.jsonSmoke tests:
.\.venv\Scripts\python scripts\smoke_custom_server.py(discovers and calls the custom server over stdio),.\.venv\Scripts\python scripts\smoke_weather_server.py [city](existing server).
The agent starts its own MCP connections; starting trailsmith_mcp manually
demonstrates process separation and independent startability.
Demo inputs
File | Purpose |
| 3-day valley/mixed traverse — clean pass |
| Day 2 crosses the exposed Turkul ridge. Replanning only fires under stormy weather — run it with |
| Unknown segment ID — structured error demo |
| Changed valid input: 5 days, high fitness |
| Changed valid input: low fitness → one soft |
**Before a live demo, run ** — it shifts the dates into the forecast window, re-records the genuine fixtures, and rebuilds the storm scenario against the new dates in one step.
The demo dates must fall inside the live 5-day forecast window. They are set
for 2026-08-20 onward; before a live demo, bump every date and re-run
scripts/fetch_fixtures.py. Outside the window the parser correctly raises
NO_FORECAST_FOR_DATE and the day degrades to weather_known=false /
caution — a legitimate path, but not the one you want to present as the clean
run.
Fixtures and offline replay
Record genuine responses:
.\.venv\Scripts\python scripts\fetch_fixtures.pysaves verbatim tool text tofixtures/openweather/. It also records the invalid-city response — which this server returns as a successful all-zeros body rather than an error, so it is saved as a normal.txt. There is no.error.txtfixture, because the upstream server never produced one.Replay offline: set
REPLAY=1and run the agent normally. The replay server (scripts/replay_weather_server.py) exposes the sameweathercontract and serves the recorded text verbatim — the agent's parsing and error handling run unchanged; nothing is pre-parsed.$env:REPLAY=1 .\.venv\Scripts\python -m agent.runner demo\itinerary_clean.jsonStorm scenario.
no_gorisk requires a thunderstorm or severe conditions, which Carpathian forecasts frequently lack — on a calm day the agent correctly reportsok/cautionand never replans, so the replanning branch cannot be demonstrated on demand.fixtures/scenario_storm/holds a clearly labelled synthetic input (one condition line changed in an otherwise genuine recording) for exercising that branch; see its README, and disclose it when demonstrating. Select it with:$env:REPLAY=1; $env:FIXTURE_SET="scenario_storm" .\.venv\Scripts\python -m agent.runner demo\itinerary_storm.json
Rate limits
OpenWeatherMap free tier allows 60 calls/min. What actually bounds our call volume:
validate_itineraryrejects itineraries longer than 7 days (Itinerary.dayshasmax_length=7), so at most 7 day-assessors are spawned.Each day-assessor is capped at
maxTurns=6, so it cannot loop on the weather API after a failure.Worst case is therefore well under the per-minute limit. The width of the parallel batch is decided by the Claude Code CLI's Task scheduler, not by this code — we bound the total number of calls, not their concurrency.
Cost guardrails (agent/orchestrator.py): max_budget_usd=1.50 and
max_turns=30 on the main loop, plus per-subagent maxTurns. These are hard
SDK limits, not prompt instructions; agent/runner.py prints the run's turn
count and dollar cost, and flags a run that stopped on a cap.
Verifying the whole system
.\.venv\Scripts\python scripts\verify.pyRuns 12 checks — both MCP connections and their tool discovery, process separation, a successful call on each, structured-error vs empty-success, conservative degradation on an unusable forecast, byte-identical dataset regeneration, and the test suite. No Anthropic credentials needed.
Tests
.\.venv\Scripts\python -m pytest tests -q45 unit tests cover validation rules, risk heuristics, graph search, logistics, the forecast-text parser (including malformed input), and regression tests for every contract and correctness bug found during review.
Documentation
Start at the documentation index.
Doc | Answers |
How do I get this running? | |
How is it put together, and where does each result go? | |
What exactly does each tool accept and return? | |
Why this way, and what are the limitations? | |
Why isn't it behaving as documented? | |
How is it demonstrated? | |
Where did the trail data come from? |
Scripts
Script | Purpose |
| Prepare the demo for today: shift demo dates into the forecast window, re-record genuine fixtures, rebuild the date-pinned storm scenario, print the demo commands |
| One-command proof of the whole system: both MCP connections, process separation, error contracts, failure degradation, dataset reproducibility, tests |
| Run the whole domain workflow deterministically, no LLM or credentials |
| Start the custom server in a separate process, list and call its tools |
| Call the existing OpenWeather MCP server (needs a key) |
| Record genuine API responses for offline replay |
| Serve recorded fixtures under the same |
| Regenerate the trail dataset deterministically |
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/mashta-lilia/trailsmith-mcp-agent'
If you have feedback or need assistance with the MCP directory API, please join our Discord server