Skip to main content
Glama
README.md
# AllTrails MCP Client

A Model Context Protocol (MCP) server and Python package for searching hiking trails from AllTrails.com. Includes smart caching to avoid rate limiting.

## āš ļø Important: Rate Limiting

**AllTrails.com implements CAPTCHA and rate limiting.** This package includes a caching system to minimize requests:

- āœ… **Cache-first**: Stores up to 15 trails per park for 7 days
- šŸ”„ **Automatic refresh**: Updates cache after expiration
- šŸ’¾ **SQLite storage**: Local database (`trails_cache.db`)
- 🚫 **Use sparingly**: Best for personal, low-volume usage

## Features

- 🄾 Search trails by US National Park (all 63 parks supported)
- šŸ“ Get detailed trail information
- šŸ’¾ Smart caching system (7-day cache)
- šŸ¤– MCP server for Claude Desktop integration
- šŸ› ļø CLI tools for quick searches
- šŸ Python API for programmatic access

## Installation

### From PyPI (when published)
```bash
pip install alltrails-mcp
```

### Development Install
```bash
git clone https://github.com/dbrown540/alltrails-mcp-client.git
cd alltrails-mcp-client
pip install -e .
```

## Quick Start

### Python API
```python
from alltrails_mcp import NationalPark, search_trails_with_cache

# Search with automatic caching
trails = search_trails_with_cache(NationalPark.YOSEMITE.value)

for trail in trails[:5]:
    print(f"{trail['name']} - {trail['difficulty']} - {trail['length']}")
```

### CLI
```bash
# Search trails
alltrails-search search us/california/yosemite-national-park --limit 5

# Get trail details
alltrails-search details us/california/half-dome-trail

# Show cache info and location
alltrails-search cache

# Clear the cache
alltrails-search cache --clear

# View current configuration
alltrails-search config

# Set cache expiration to 14 days
alltrails-search config --set-cache-days 14
```

### MCP Server (Claude Desktop)

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "alltrails": {
      "command": "/path/to/.venv/bin/python",
      "args": ["/path/to/alltrails-mcp-client/src/alltrails_mcp/server.py"],
      "env": {
        "ALLTRAILS_CACHE_DAYS": "14"
      }
    }
  }
}
```

**Optional environment variables:**
- `ALLTRAILS_CACHE_DAYS`: Cache expiration in days (default: 7)

Then ask Claude: "Find trails in Yosemite National Park"

## National Parks

All 63 US National Parks are available via the `NationalPark` enum:

```python
from alltrails_mcp import NationalPark, get_park_slug, list_parks

# Use enum
park = NationalPark.YOSEMITE
slug = park.value  # 'us/california/yosemite-national-park'

# Look up by name
slug = get_park_slug("Yellowstone")

# List all parks
all_parks = list_parks()
```

See `PARKS_SUMMARY.md` for complete list.

## Cache Management

```python
from alltrails_mcp import TrailCache

cache = TrailCache()

# Get cache info
info = cache.get_cache_info()
print(f"Parks cached: {info['total_parks']}")

# Clear specific park
cache.clear_cache("us/california/yosemite-national-park")

# Clear entire cache
cache.clear_cache()

# Force refresh (bypass cache)
from alltrails_mcp import search_trails_with_cache
trails = search_trails_with_cache(park_slug, force_refresh=True)

# Use custom cache location
from pathlib import Path
custom_cache = TrailCache(db_path=Path("/custom/path/cache.db"))

# Use custom cache expiration (e.g., 14 days)
custom_cache = TrailCache(cache_days=14)
```

**Cache Location:**
- Linux/macOS: `~/.cache/alltrails-mcp/trails_cache.db`
- Fallback: `~/.alltrails_mcp/trails_cache.db`
- Custom: Pass `db_path` to `TrailCache()`

**Cache Expiration Configuration:**

Cache expiration can be configured in multiple ways with the following priority:

1. **Programmatic** (highest priority): Pass `cache_days=14` to `TrailCache()`
2. **Environment variable**: Set `ALLTRAILS_CACHE_DAYS=14`
3. **Saved configuration**: Use CLI command `alltrails-search config --set-cache-days 14`
4. **Default**: 7 days

```bash
# Set cache expiration persistently via CLI
alltrails-search config --set-cache-days 14

# View current configuration
alltrails-search config

# Override via environment variable
export ALLTRAILS_CACHE_DAYS=30
```

Configuration is saved to `~/.cache/alltrails-mcp/config.json` and persists across sessions.

The cache is **automatically managed** - users don't need to interact with it directly unless they want to clear it or customize the location/expiration.

## Examples

See the `examples/` directory:
- `demo.py` - Simple demonstration of key features

Run with:
```bash
python examples/demo.py --park ZION
python examples/demo.py --stats
python examples/demo.py --clear-cache
```

## Project Structure

```
alltrails-mcp-client/
ā”œā”€ā”€ src/alltrails_mcp/      # Main package
│   ā”œā”€ā”€ __init__.py          # Package exports
│   ā”œā”€ā”€ scraper.py           # AllTrails scraping logic
│   ā”œā”€ā”€ cache.py             # SQLite caching system
│   ā”œā”€ā”€ parks.py             # National Park enums
│   ā”œā”€ā”€ server.py            # MCP server
│   └── cli.py               # Command-line interface
ā”œā”€ā”€ examples/                # Example scripts
ā”œā”€ā”€ pyproject.toml          # Package configuration
└── README.md               # This file
```

## API Reference

### Core Functions

**`search_trails_in_park(park_slug: str) -> List[Dict]`**
- Search for trails (no caching)
- Returns: List of trail dictionaries

**`search_trails_with_cache(park_slug: str, cache=None, force_refresh=False, limit=15) -> List[Dict]`**
- Search with automatic caching
- Returns cached data if valid (<7 days old)

**`get_trail_by_slug(slug: str) -> Dict`**
- Get detailed trail information
- Example slug: `us/tennessee/alum-cave-trail`

### Trail Dictionary Format

```python
{
    "name": "Half Dome Trail",
    "url": "https://www.alltrails.com/trail/...",
    "summary": "Experience this 14.2-mile...",
    "difficulty": "Hard",
    "length": "14.2 mi",
    "rating": "4.8"
}
```

## Publishing to PyPI

See `PUBLISHING.md` for detailed instructions.

Quick steps:
```bash
# Build
python -m build

# Upload
twine upload dist/*
```

## License

MIT License - See LICENSE.md

## Acknowledgments

- Original MCP server by Srinath Srinivasan
- Forked and enhanced by Danny Brown
- Trail data from [AllTrails](https://www.alltrails.com/)
- Built with [Model Context Protocol](https://modelcontextprotocol.io/)

## Disclaimer

This tool scrapes publicly available data from AllTrails. Use responsibly and respect AllTrails' terms of service. The caching system helps minimize requests.