TrailSmith

TrailSmith

An MCP server providing domain tools for validating, risk-assessing, and replanning multi-day hiking itineraries in the Chornohora range using curated trail data.

Category
访问服务器

README

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_storm

That 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 .env

Then edit .env:

Variable Needed for
ANTHROPIC_API_KEY the agent (Claude Agent SDK). Optional if you have run claude /login.
OWM_API_KEY live OpenWeather calls. A new key takes up to ~2 h to activate.
OPENWEATHER_MCP_BIN optional override; defaults to bin\mcp-openweather.exe.
REPLAY 1 to serve recorded fixtures instead of the live API.
FIXTURE_SET optional replay directory name; defaults to openweather.

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_mcp
  • Agent: .\.venv\Scripts\python -m agent.runner demo\itinerary_clean.json
  • Smoke 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
demo/itinerary_clean.json 3-day valley/mixed traverse — clean pass
demo/itinerary_storm.json Day 2 crosses the exposed Turkul ridge. Replanning only fires under stormy weather — run it with FIXTURE_SET=scenario_storm (see below)
demo/itinerary_invalid.json Unknown segment ID — structured error demo
demo/itinerary_5day.json Changed valid input: 5 days, high fitness
demo/itinerary_lowfitness.json Changed valid input: low fitness → one soft DAILY_ASCENT_EXCEEDED violation on day 1

**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.py saves verbatim tool text to fixtures/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.txt fixture, because the upstream server never produced one.

  • Replay offline: set REPLAY=1 and run the agent normally. The replay server (scripts/replay_weather_server.py) exposes the same weather contract 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.json
    
  • Storm scenario. no_go risk requires a thunderstorm or severe conditions, which Carpathian forecasts frequently lack — on a calm day the agent correctly reports ok/caution and 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_itinerary rejects itineraries longer than 7 days (Itinerary.days has max_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.py

Runs 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 -q

45 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
Quickstart How do I get this running?
Architecture How is it put together, and where does each result go?
Tool contracts What exactly does each tool accept and return?
Design rationale Why this way, and what are the limitations?
Troubleshooting Why isn't it behaving as documented?
Defence script How is it demonstrated?
Dataset provenance Where did the trail data come from?

Scripts

Script Purpose
scripts/refresh_demo.py 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
scripts/verify.py One-command proof of the whole system: both MCP connections, process separation, error contracts, failure degradation, dataset reproducibility, tests
scripts/walkthrough.py Run the whole domain workflow deterministically, no LLM or credentials
scripts/smoke_custom_server.py Start the custom server in a separate process, list and call its tools
scripts/smoke_weather_server.py Call the existing OpenWeather MCP server (needs a key)
scripts/fetch_fixtures.py Record genuine API responses for offline replay
scripts/replay_weather_server.py Serve recorded fixtures under the same weather contract
scripts/build_dataset.py Regenerate the trail dataset deterministically

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选