Skip to main content

trekking-mcp

CI PyPI MCP Registry

English

Demo: ispezione del server MCP

Server Model Context Protocol (revisione della spec 2026-07-28, SDK Python mcp 2.x) per l'escursionismo sulle Alpi e sugli Appennini italiani: sentieri numerati, rifugi e bivacchi, bollettini valanghe e meteo di quota, esposti a un assistente AI come tool, resource e prompt.

Avvertenza. I bollettini valanghe sono documenti ufficiali di sicurezza. Questo progetto li rilegge e li normalizza, non li interpreta e non produce valutazioni del rischio. Non sostituisce il bollettino integrale, la formazione specifica, ne' il giudizio sul terreno. Usalo per preparare una gita, mai per decidere se farla.

Cosa mostra questo repo

Non e' un wrapper 1:1 su una API. Copre i tre primitivi del protocollo e un paio di meccanismi che si vedono raramente:

Tools 10 tool, due dei quali compongono piu' fonti in un unico risultato
Resources Documenti di riferimento statici + una resource template con URI parametrico
Prompts Workflow riutilizzabili che fissano il metodo, non solo il tono
Elicitation Il server chiede dati all'utente a meta' chiamata, via dependency injection, con le scelte come enum nello schema
Completions Autocompletamento degli ID di zona valanghe, con il provider gia' scelto a restringere
Structured output Ogni tool ha un outputSchema derivato dai modelli Pydantic
Dual transport stdio e Streamable HTTP dallo stesso crea_server()
Osservabilita' Latenza p50/p95, 429 e hit rate per fonte, esposti come resource
Cache hints Ogni risposta dichiara per quanto vale (ttlMs/cacheScope), resource per resource
Coalescing Due chiamate identiche in volo diventano una richiesta sola: un agente chiama i tool in parallelo
Client incluso Un client MCP minimale, per dimostrare di conoscere entrambi i lati
Geometria Point-in-polygon e profili altimetrici in Python puro, senza dipendenze binarie

Installazione

uvx trekking-mcp

Nessuna API key richiesta: tutte le fonti di default sono aperte.

Per contribuire o sviluppare dal clone:

git clone https://github.com/19Alma98/trekking_mcp
cd trekking_mcp
uv sync            # oppure: pip install -e ".[dev]"

Uso con Claude Desktop / Claude Code

{
  "mcpServers": {
    "trekking": {
      "command": "uvx",
      "args": ["trekking-mcp"]
    }
  }
}

In alternativa, come server remoto:

trekking-mcp --transport http --port 8000            # solo 127.0.0.1

# esposto ad altre macchine: va dichiarato chi puo' chiamare
trekking-mcp --transport http --host 0.0.0.0 \
  --allow-host trekking.example.org:* \
  --allow-origin https://app.example.org

# con piu' repliche: le chiavi che sigillano il requestState vanno condivise,
# altrimenti un'elicitation iniziata su una replica muore sull'altra
export TREKKING_MCP_STATE_KEYS="$(python -c 'import secrets; print(secrets.token_hex(32))')"

# produzione: non usare overpass-api.de; alza la concorrenza solo sul tuo mirror
export OVERPASS_URL="https://overpass.example.org/api/interpreter"
# export OVERPASS_CONCURRENCY=4

Il secondo comando senza --allow-host viene rifiutato: l'SDK attiva la protezione da DNS rebinding solo quando il bind e' su localhost, cioe' proprio quando non serve. Vedi DEVELOPMENT.md §3.18.

Su HTTP l'accesso resta aperto (nessuna API key obbligatoria): un tetto per IP (HTTP_RATE_LIMIT_RPM / HTTP_RATE_LIMIT_BURST) limita tools/call e la lettura dei bollettini. Dietro un reverse proxy che riscrive X-Forwarded-For, imposta HTTP_TRUST_PROXY=1 cosi' il tetto e' per client e non per IP del proxy. Su stdio il limite non si applica. Vedi DEVELOPMENT.md §3.35.

Docker

docker build -t trekking-mcp .
docker run --rm -p 8000:8000 trekking-mcp
# health: curl -s localhost:8000/health
# MCP:   http://localhost:8000/mcp

L'immagine ascolta su 0.0.0.0:8000 con --allow-host per localhost e 127.0.0.1. Per un dominio pubblico passa gli argomenti dopo l'immagine, ad es. docker run --rm -p 8000:8000 trekking-mcp trekking-mcp --transport http --host 0.0.0.0 --port 8000 --allow-host 'trekking.example.org:*'.

Tool disponibili

Tool Cosa fa
cerca_localita Da un toponimo alle coordinate: rifugi, cime, valichi, paesi
cerca_sentieri Sentieri numerati in un raggio, filtrabili per numero, ente e difficolta' massima
sentieri_verso_localita Geocoding + sentieri + rifugi in una chiamata: l'ingresso da preferire quando il punto e' un nome
dettaglio_sentiero Dati completi di una relation OSM
profilo_altimetrico Lunghezza reale e dislivello, campionando le quote sul tracciato
cerca_ricoveri Rifugi gestiti, bivacchi e ripari entro un raggio
zona_valanghe_da_coordinate Da un punto alla micro-regione EAWS del bollettino
bollettino_valanghe Bollettino corrente di una zona, da CAAML v6
meteo_quota Previsione oraria corretta per l'elevazione, con zero termico e raffiche
valuta_gita Compone tutto quanto sopra per un sentiero e una data

meteo_quota non risponde con le prime ore della serie di Open-Meteo, che comincia a mezzanotte: parte dall'ora corrente se la data e' oggi, dalle 6 se e' un giorno futuro, e da ora_inizio se lo si indica. Una gita non si prepara guardando la notte. Vedi DEVELOPMENT.md §3.27.

Il flusso tipico non richiede che l'utente conosca un solo codice. Quando il punto di arrivo e' un nome, sentieri_verso_localita fa da solo geocoding, ricerca sentieri e rifugi: e' l'ingresso che le instructions del server indicano per primo, al posto della catena cerca_localita + cerca_sentieri. Da li', valuta_gita per il resto. La zona del bollettino viene dedotta dalle coordinate.

Le resource sono scala://pericolo-valanghe, scala://difficolta-escursionistica, metriche://fonti (latenza, errori e hit rate per fonte) e la template bollettino://{provider}/{zona_id}, i cui due argomenti si autocompletano: scelto slf, zona_id propone solo le zone svizzere.

L'elicitation, in breve

valuta_gita ha bisogno di sapere che difficolta' regge il gruppo e se ha ARTVA, pala e sonda. Sono informazioni che il modello non puo' dedurre e che non deve inventare. Il parametro e' annotato cosi':

profilo: Annotated[ProfiloUscita, Resolve(chiedi_profilo)]

Il parametro non compare nello schema di input del tool, quindi il modello non sa nemmeno che esiste. Prima di eseguire il corpo, il framework esegue il resolver, che restituisce un marker Elicit[ProfiloUscita]: la domanda viene inoltrata al client, l'utente risponde, il valore viene iniettato. Se l'utente rifiuta, la chiamata si interrompe.

Fonti dati e attribuzioni

Fonte Cosa fornisce Licenza
OpenStreetMap via Overpass Sentieri (route=hiking), rifugi, bivacchi ODbL, attribuzione obbligatoria
AINEVA Bollettini valanghe dell'arco alpino italiano Open data, CAAML v6 profilo EAWS
WSL-SLF Bollettini valanghe svizzeri CC BY 4.0
Open-Meteo Previsioni orarie e modello di elevazione CC BY 4.0
EAWS Regions Perimetri delle zone valanghe Open data
Nominatim Geocoding dei toponimi ODbL, usage policy

I sentieri numerati CAI sono mappati dalla community OSM: questo progetto non accede ad alcun dato proprietario del Club Alpino Italiano, che non espone un'API pubblica. La copertura non e' uniforme e l'assenza di un sentiero non significa che non esista.

Sviluppo

uv run pytest              # test
uv run ruff check .        # lint
uv run ruff format --check .
uv run mypy                # type check
uv run python client/ispeziona.py   # client MCP minimale: elenca tool e resource

Sono gli stessi comandi che gira la CI, sulla stessa risoluzione: uv.lock e' versionato e la CI installa con uv sync --frozen, quindi le versioni degli strumenti sono identiche a quelle locali.

Architettura, decisioni di progetto e roadmap: DEVELOPMENT.md.

Licenza

MIT.

Release files for trekking-mcp 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trekking-mcp 1.0.0
File Size Uploaded
trekking_mcp-1.0.0.tar.gz 304.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trekking-mcp 1.0.0
File Interpreter ABI Platform
trekking_mcp-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 372.9 kB

Release files / trekking_mcp-1.0.0.tar.gz

Download URL trekking_mcp-1.0.0.tar.gz
Size 304.1 kB
Tags Source
SHA-256 checksum
How to use checksums
8e00506db699261f44870f05a0d53ea1aa9925a7a540a52878b8b90f88791331
BLAKE2b-256 checksum
How to use checksums
beb64f2090d751c7730ff11238f27e152f6a54a713ebeed812e6cbed975cee9c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / trekking_mcp-1.0.0-py3-none-any.whl

Download URL trekking_mcp-1.0.0-py3-none-any.whl
Size 68.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8491bb1d133f92871a7a2f7997d28d62e3f96608bb8b8852d7c6bb5dfb5f066c
BLAKE2b-256 checksum
How to use checksums
ee96875fcfae8695a3b0079f1e92206da30675b24a5e1d138ae44d3afa00f6a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

1.1.0

2 release files

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page