outstations-mcp
README.md
# club-moorage-mcp
MCP server serving yacht-club **moorage** records — size limits, rafting rules, booking
processes, amenities, reciprocal terms, and overnight-comfort ranking. Each record carries
a `relationship`:
- **`outstation`** — a facility the club owns for its own members. Ships bundled with the
three Royal Victoria Yacht Club (RVYC) outstations (Long Harbour, Friday Harbor,
Telegraph Harbour).
- **`reciprocal`** — a partner club that hosts visiting RVYC members as guests, with its own
visitor terms (free nights, fees, max stay, insurance minimum). Ships bundled with the
**whole RVYC reciprocal list — 138 clubs, worldwide**, in two depths:
- **Researched** (`confidence` med/high, 45 clubs) — the BC + Washington coastal set the
boat actually cruises: South Vancouver Island, the Gulf Islands, the Vancouver-side
crossing stops, the San Juans / Anacortes / Bellingham, the Strait of Juan de Fuca /
North Puget Sound. Per-club terms, fees, size limits and Vaan fit.
- **Listed only** (`confidence: low`, 93 clubs) — everything else on the list: California,
Hawaii, Mexico, Bermuda, the Caribbean, eastern Canada, the UK, Australia/NZ and the
rest. Position, address, phone and website only, so a passage plan can ask "whose club
is in this port?" — guest-moorage terms are **not** researched and every record says so.
## Tools
- `list_moorage(clubs?, relationship?)` — all moorage: location, coords, size limits.
- `find_moorage_near(lat, lon, radius_nm=20, clubs?, relationship?, date?)` — nearby moorage, nearest first; annotates live availability when configured.
- `get_moorage(name)` — full record + prose; for an outstation, also the club's general rules.
- `rank_moorage(names, forecast, date?)` — overnight-comfort rank for records that
support anchoring/mooring; dock-only records are returned under `not_ranked`.
Reuses pilotbook-mcp's scoring against a weather-mcp forecast.
- `check_availability(name, date)` — live slip availability for RVYC reservable outstations; requires `RVYC_USERNAME`/`RVYC_PASSWORD`.
The `clubs` filter is an optional list of club codes (e.g. `["RVYC"]`); omit for all clubs.
The `relationship` filter is `"outstation"` or `"reciprocal"`; omit for both. The
agent/context layer decides which clubs are relevant from who is aboard. Discontinued
reciprocals (`available: false`) are omitted from `list`/`find` but still resolve by name.
## Live outstation availability (optional)
`check_availability(name, date)` reports live slip availability for RVYC's two
reservable outstations (Long Harbour, Friday Harbor); `find_moorage_near` and
`rank_moorage` take an optional `date` to annotate results the same way. Telegraph
Harbour is first-come-first-served (booked via the marina) and reciprocal clubs have
no online scheduler, so those return a reason instead of counts.
This layer is **off by default**. Set `RVYC_USERNAME` and `RVYC_PASSWORD` (member
credentials) to enable it; without them the tools return static data plus a
"not configured" note. No credentials or member data are stored in this package.
## Data
Records are markdown (YAML frontmatter + prose) under `src/club_moorage_mcp/data/`
(`clubs/`, `outstations/`, `reciprocals/`). Point at a different directory with
`CLUB_MOORAGE_DATA_PATH`. `pilotbook_anchorage` cross-links a record to the nearest
pilot-book anchorage; the agent calls pilotbook-mcp's `get_anchorage` for seabed/depth.
[**moorage.geojson**](moorage.geojson) is a generated map of every bundled record —
GitHub renders it inline (blue = outstation, green = reciprocal). Regenerate after a data
change with `uv run python ingest/build_geojson.py`; `--check` fails on drift, and
`tests/test_geojson.py` does the same in CI.
Reciprocal records are generated from `ingest/reciprocals.yaml` — edit the YAML, then
`uv run python ingest/build_records.py`. The three RVYC outstations are hand-authored.
The club list is the RVYC 2024 Annual; positions and contacts are RVYC's own reciprocal
map. Per-club terms were researched from secondary sources where they exist at all;
**verify fees, LOA, and availability with the club before arrival.**
## Install
uv sync --dev
## Run the server
uv run club-moorage-mcp
TDQS
B3.3/5.0
Scored across 4 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: finding anchorages near a position, retrieving details for a specific anchorage, listing data sources, and ranking anchorages by comfort. No overlap exists.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern in snake_case: find_anchorages_near, get_anchorage, list_sources, rank_anchorages. No deviations or mixed conventions.
Tool Count4/5
Four tools is slightly below average but appropriate for a focused server covering anchorage lookup and ranking. Each tool earns its place without redundancy.
Completeness4/5
The set covers the core read operations for anchorages: find, get details, rank, and list sources. No obvious dead ends, though write operations are absent (likely by design).
Maintenance
ActivitySlowing
ResponsivenessNo issues