Skip to main content
Glama
defevan

mountainproject

by defevan
README.md
# mp-mcp

MCP server for [Mountain Project](https://www.mountainproject.com) — search routes and areas, run route-finder filters, and query your personal tick list live from MP.

Built for [Cursor](https://cursor.com) and any MCP-compatible agent.

## Disclaimer

**This project is not affiliated with, endorsed by, or connected to [Mountain Project](https://www.mountainproject.com) or [onX Maps, Inc.](https://www.onxmaps.com/)** Mountain Project is a trademark of onX Maps, Inc.

- **Personal use only.** This tool is intended for individual climbers to access their own tick data and browse public route information — not for bulk scraping, republishing MP content, or building a competing database.
- **Terms of service.** Users are responsible for complying with [Mountain Project's terms of service](https://www.mountainproject.com/about/terms). Automated access may be restricted or blocked by MP at any time.
- **Session security.** Your `ap_session` cookie is a login credential. Do not commit `~/.mp-mcp/session.json`, paste cookies into public chats, or store cookies in shared config files. The session file is written with restrictive permissions (`0600`), but treat it like a password.
- **No warranty.** This software is provided as-is under the MIT license. Route data accuracy remains the responsibility of Mountain Project and its community contributors.

## Features

- **Public route discovery** — search, route/area details, route-finder filters (no auth)
- **Personal logbook** — list, filter, and aggregate your ticks pulled live from MP
- **Browser login** — one-time `npm run login` captures your session automatically (no CSV export, no DevTools)
- **Polite by default** — rate limiting between requests

## Quick start (humans)

### 1. Install

```bash
git clone https://github.com/defevan/mp-mcp.git
cd mp-mcp
npm install
npm run build
npx playwright install chromium   # first time only, for login
```

### 2. Log in to Mountain Project

```bash
npm run login
```

A browser opens to Mountain Project. Sign in normally — the script detects when you're logged in and saves `~/.mp-mcp/session.json`. The login tab will **not** reload while you sign in.

Re-run when the session expires (~30 days).

### 3. Add to Cursor

Add to `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "mountainproject": {
      "command": "node",
      "args": ["/absolute/path/to/mp-mcp/dist/server.js"]
    }
  }
}
```

Restart Cursor or reload MCP servers.

### 4. Try it

Ask in chat:

- "Search trad 5.10 routes in Yosemite Valley"
- "Get beta on The Nose"
- "List my ticks from 2024"
- "How many days out did I have this summer?"

---

## For agents

This section is for LLM agents using the MCP tools directly.

### Server

- **Name:** `mountainproject`
- **Transport:** stdio
- **Entry:** `node dist/server.js` (run `npm run build` first)

### Auth model

| Priority | Source | Notes |
|----------|--------|-------|
| 1 | In-memory session | Set via `mp_set_session` |
| 2 | `~/.mp-mcp/session.json` | Written by `npm run login` |
| 3 | Env vars | `MP_SESSION_COOKIE`, `MP_USER_ID` (CI fallback) |

Tick tools call `GET /user/{id}/{username}/tick-export` with the session cookie. Ticks are parsed in memory and cached (default 15 min). **Never ask the user to export a CSV manually.**

If auth fails, tell the user to run `npm run login` in the project directory or use `mp_set_session`.

### Tool reference

#### Public (no auth)

| Tool | Args | Returns |
|------|------|---------|
| `mp_search` | `query`, `types?` (`routes`/`areas`), `limit?` | Matching routes/areas with id, grade, stars, url, lat/lng |
| `mp_get_route` | `routeId` | Full route detail: beta, protection, FA, parent area |
| `mp_get_area` | `areaId` | Area description, access notes, route counts |
| `mp_find_routes` | `areaId`, `gradeMin?`, `gradeMax?`, `type?`, `styles?`, `minStars?`, `sort?`, `limit?` | Filtered routes from route-finder (CSV export, max 1000) |
| `mp_resolve_id` | `urlOrId` | Parse numeric ID from MP URL or `routes.123` / `areas.456` |

#### Authenticated

| Tool | Args | Returns |
|------|------|---------|
| `mp_auth_status` | — | `{ authenticated, userId, username, tickCount? }` |
| `mp_set_session` | `apSession`, `xsrfToken?`, `userId?`, `username?`, `persist?` | Update session at runtime |
| `mp_fetch_ticks` | — | Force-refresh tick list from MP |
| `mp_list_ticks` | `year?`, `gradeMin?`, `gradeMax?`, `style?`, `areaContains?`, `limit?` | Filtered ticks (auto-fetches if cache stale) |
| `mp_tick_stats` | `groupBy` (`year`/`grade`/`style`/`area`), `yearFrom?`, `yearTo?` | Aggregated counts |

### Agent workflow examples

**Trip planning (no auth):**

```
mp_search → mp_resolve_id → mp_find_routes / mp_get_route
```

**Logbook analysis (auth required):**

```
mp_auth_status → mp_list_ticks / mp_tick_stats
```

**Area deep-dive:**

```
mp_search(query, types=["areas"]) → mp_get_area → mp_find_routes(areaId, gradeMin, gradeMax)
```

### Grade filters for `mp_find_routes`

Use YDS strings: `5.8`, `5.10a`, `5.11d`, etc. The server maps these to MP's internal route-finder rank codes.

### Rate limiting

Default 500 ms between MP requests (`MP_RATE_LIMIT_MS`). Prefer fewer, broader tool calls over many narrow ones.

### Data source notes

- Public data: MP `/api/v2/*` and `/route-finder-export`
- Ticks: authenticated `/user/{id}/{username}/tick-export`
- MP's official Data API is deprecated; this server uses the same endpoints the website uses
- Respect MP's terms of service; this tool is for personal use

---

## Environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `MP_SESSION_FILE` | `~/.mp-mcp/session.json` | Session storage path |
| `MP_TICKS_CACHE_TTL_MS` | `900000` | Tick cache TTL (15 min) |
| `MP_RATE_LIMIT_MS` | `500` | Delay between MP requests |
| `MP_USER_AGENT` | `mp-mcp/1.0` | HTTP User-Agent |
| `MP_SESSION_COOKIE` | — | Fallback session cookie |
| `MP_USER_ID` | — | Fallback user ID |
| `MP_XSRF_TOKEN` | — | Optional CSRF cookie |
| `MP_USERNAME` | — | Optional username slug |

---

## Development

```bash
npm run build      # compile TypeScript → dist/
npm run dev        # run server via tsx (stdio)
npm run login      # browser auth flow
```

Smoke test:

```bash
node -e "import('./dist/mp-client.js').then(m => m.getRoute(105924807).then(console.log))"
```

---

## Session refresh

When tools return auth errors:

```bash
npm run login
```

Or call `mp_set_session` with a fresh `ap_session` cookie value.

---

## License

MIT — Copyright (c) 2026 Evan Jones. See [LICENSE](LICENSE).

TDQS

A3.6/5.0

Scored across 10 tools

Disambiguation4/5

Most tools are clearly distinguished by resource and action (search, get_route, get_area, find_routes, resolve_id, tick operations). Minor overlap exists between mp_search and mp_find_routes (both find routes, though in different contexts) and between mp_fetch_ticks and mp_list_ticks (list auto-fetches, fetch forces refresh), but descriptions clarify the boundaries.

Naming Consistency4/5

All tools share the mp_ prefix and most follow verb_noun structure (mp_search, mp_get_route, mp_set_session, mp_fetch_ticks, mp_list_ticks). Two names deviate: mp_auth_status (noun phrase) and mp_tick_stats (noun phrase), which break the pattern slightly but remain predictable and readable.

Tool Count5/5

Ten tools is well-scoped for a climbing data and personal tick-list server. Each tool covers a distinct aspect of the domain—searching, retrieving, resolving IDs, session management, and tick lifecycle—without unnecessary redundancy or bloat.

Completeness5/5

The tool surface covers the core read-only workflows for Mountain Project: searching and fetching routes/areas, resolving URLs to IDs, and managing personal tick data (auth, session, refresh, list, stats). No obvious dead ends; the main missing operations like creating/deleting ticks or routes are external to the API's likely scope.

Maintenance

ActivityMaintained
ResponsivenessNo issues