Tideline
FreeNot checkedMCP server that provides tide predictions, station lookup, and tidal event alerts for US coastal locations using live NOAA data.
About
MCP server that provides tide predictions, station lookup, and tidal event alerts for US coastal locations using live NOAA data.
README
Tidal calendar for the US coast. Generates ICS calendar files with high/low tides, king tide alerts, tidepooling windows, flood risk events, Perigean spring tides, and more. Comes with a web dashboard, a CLI, and an MCP server so Claude can answer tide questions directly.
Data source: NOAA CO-OPS API — free, no account or API key required. US coastal stations only.
Requirements
- Python 3.11 or later — for the backend, CLI, and MCP server
- Node.js 18 or later — for the web dashboard (optional if you only use the CLI)
- Windows, macOS, or Linux
Installation
Step 1 — Get the code
git clone https://github.com/Earththing/Moon_and_Tides.git
cd Moon_and_Tides
Step 2 — Install Python dependencies
pip install -r requirements.txt
This installs FastAPI, httpx, ephem (for sunrise/sunset), icalendar, the MCP SDK, and everything else the backend needs.
Step 3 — Register the tideline command
pip install -e .
This makes tideline available as a command in your terminal. If you skip this step, replace every tideline command below with python -m app.cli — they are otherwise identical.
Step 4 (optional) — Install the web dashboard
cd frontend
npm install
cd ..
This downloads the React/TypeScript frontend dependencies (~150 MB in node_modules). Skip if you only plan to use the CLI or API.
Getting the app running
The app has two parts: a backend (Python/FastAPI) that handles all data fetching, caching, and ICS generation, and a frontend (React) that provides the interactive dashboard. You need both running to use the web interface.
Terminal 1 — Start the backend
python -m uvicorn app.main:app --reload
What this does: starts the FastAPI data server on port 8000. It handles all communication with NOAA, builds ICS calendar files, computes sunrise/sunset times, and serves the REST API that the frontend calls. The --reload flag means it automatically restarts when you change a Python file — you never need to stop and restart it manually during development.
You'll see:
INFO: Uvicorn running on http://127.0.0.1:8000
INFO: Application startup complete.
You can verify it's working at http://localhost:8000/docs — that's the interactive API explorer.
Terminal 2 — Start the frontend
cd frontend
npm run dev
What this does: starts the Vite development server on port 5173. Vite serves the React dashboard and also acts as a proxy — when the dashboard calls /api/v1/... or /calendar/..., Vite forwards those requests to the backend on port 8000. This means you only ever need to open one URL in your browser.
You'll see:
VITE v8.x ready in 300ms
➜ Local: http://localhost:5173/
Step 3 — Open the dashboard
Go to http://localhost:5173 in your browser.
Search for a city or address, and the dashboard will find the nearest NOAA tide station and show today's tide curve, nearby stations, upcoming events, and a calendar download button.
Quick start — CLI only
If you just want tide data without the web interface:
# Today's tides near you (fastest way to check)
tideline preview "Seattle WA"
# Download a full-year calendar file
tideline ics "Seattle WA" --year 2026 --out seattle_tides_2026.ics
Import the .ics file into Google Calendar, Apple Calendar, or Outlook.
CLI reference
All commands accept a place name, a station ID, or coordinates. If no NOAA station exists at the location you search, the nearest one is used automatically and you'll be told how far away it is.
tideline preview — Today's tides at a glance
tideline preview "Seattle WA"
tideline preview "San Francisco, CA"
tideline preview --station 9447130
tideline preview --lat 47.81 --lon -122.38
Output:
Today's tides at 9447130:
02:06 (2:06 AM) H 10.32 ft
09:32 (9:32 AM) L -0.87 ft
17:41 (5:41 PM) H 10.69 ft
22:34 (10:34 PM) L 7.91 ft
tideline tides — Browse predictions
# Today's tides (first 20 events)
tideline tides "Seattle WA"
# Specific year — shows first 20 events
tideline tides "Seattle WA" --year 2026
# Single date
tideline tides "Seattle WA" --date 2026-06-21
# By station ID
tideline tides --station 9447130 --date 2026-06-21
# By coordinates
tideline tides --lat 47.81 --lon -122.38 --date 2026-06-21
# Show more rows (default is 20)
tideline tides "Seattle WA" --year 2026 --count 100
Times are shown in both 24-hour and 12-hour AM/PM format. Use tideline ics (below) to save a full year as a calendar file.
tideline ics — Generate a calendar file
# Full year, saves to tides_9447130_2026.ics in current folder
tideline ics "Seattle WA" --year 2026
# Choose the output filename
tideline ics "Seattle WA" --year 2026 --out seattle_2026.ics
# Alerts only — all-day events for king tides, extremes, Perigean tides
# Good for overlaying on top of a main calendar without clutter
tideline ics "Seattle WA" --year 2026 --alerts-only --out alerts_2026.ics
# By station ID
tideline ics --station 9447130 --year 2026 --out seattle_2026.ics
# By coordinates
tideline ics --lat 47.81 --lon -122.38 --year 2026 --out tides.ics
After saving, the command shows a breakdown of what's in the file:
Saved 432,817 bytes to seattle_2026.ics
Events included:
🌊 High tides 1410
🏖 Low tides 1410
⚠️ King tides 52
⚠️ Extreme lows 52
🌕 Perigean spring tides 6
🚨 Flood risk days 0
🦀 Tidepooling windows 124
Total 3054
Event types in the ICS file:
| Icon | Event | Type | When |
|---|---|---|---|
| 🌊 | High Tide | Timed (15 min) | Every high tide |
| 🏖 | Low Tide | Timed (15 min) | Every low tide |
| ⚠️ | King Tide | All-day | Top 10% of highs |
| ⚠️ | Extreme Low | All-day | Bottom 10% of lows |
| 🌕 | Perigean Spring Tide | All-day | Moon at perigee + new/full moon |
| 🚨 | Flood Risk | All-day | Predicted high exceeds NOAA flood threshold |
| 🦀 | Tidepooling Window | All-day | Low tide during daylight hours |
| ⚓ | Slack Water | Timed (10 min) | Tide reversal (harmonic stations only) |
| 🌊 | King Tide Nearby | All-day | King tide at a station within your radius |
tideline stations — Find NOAA stations near you
# All stations within 50 miles (default)
tideline stations "Seattle WA"
# Wider search
tideline stations "Seattle WA" --radius 100
# Limit results
tideline stations "Seattle WA" --radius 50 --count 3
Output:
Location: Seattle, King County, Washington, United States
ID Name Miles Harmonic
------------------------------------------------------------
9447130 Seattle 0.4 yes
9445958 Bremerton 13.9 yes
9444900 Port Townsend 27.3 yes
9446484 Tacoma 23.8 yes
Harmonic stations have full tidal constituent data. Tidepooling windows and slack water events require a harmonic station.
tideline extremes — Highest and lowest tides of the year
tideline extremes "Seattle WA" --year 2026
tideline extremes --station 9447130 --year 2026
Output:
Station: 9447130 | Year: 2026
Top 10 Highest Tides:
2026-01-05 07:07 (7:07 AM) 13.01 ft
2026-12-26 07:22 (7:22 AM) 13.01 ft
...
Top 10 Lowest Tides:
2026-06-15 11:33 (11:33 AM) -4.30 ft
2026-06-16 12:22 (12:22 PM) -4.20 ft
...
Web dashboard
The web dashboard at http://localhost:5173 gives you an interactive view of all the same data.
Features
Location search — type any city, address, or landmark. The app geocodes it and finds the nearest NOAA station. If no station exists at your exact location, a banner tells you which station is being used and how far away it is.
Tide curve chart — shows the tidal pattern for the selected date with:
- 24-hour and 12-hour times on hover
- Colored dots for high (blue) and low (green) tides with height labels
- A "now" line showing the current time (day view only)
- Flood threshold line if NOAA has one for the station
- Day/night shading (toggle with the 🌙 button) — night hours are shaded dark blue with a gradual dawn/dusk transition showing sunrise and sunset times
Four chart views — select with the Day / Week / Month / Year buttons (hover each for a description):
- Day — 6-minute tide curve for a single day
- Week — high & low tides across 7 days (use ← → to navigate weeks)
- Month — high & low tides for the full month
- Year — monthly average high & low bars
Date navigation — ← and → arrows move by one day/week/month/year depending on the view. The date picker jumps to a specific date. A Today button appears when you're not on today.
Nearby stations panel — lists the 5 nearest NOAA stations with live tide badges showing current height and direction. Click any station to switch to it.
Today's tides list — the current tide event is highlighted. Shows times in 12-hour format.
Calendar options — choose which event types to include in the downloaded ICS. Options disabled for your station (e.g. slack water on a non-harmonic station) show a tooltip explaining why.
Download button — shows the total event count before you download. Expand "Show event breakdown" to see counts by type.
Coming up feed — upcoming events in the next 30 days: king tides (amber), tidepooling windows (green), and Perigean spring tides. Shows up to 6; click "View all" to see the full list on the Alerts page.
Alerts page — full list of all upcoming events for the selected station and year. Also reachable from the Alerts tab in the nav bar — it remembers your last station.
Web API
The backend exposes a REST API at http://localhost:8000. Open http://localhost:8000/docs for an interactive explorer where you can try any endpoint.
| Endpoint | What it does |
|---|---|
POST /geocode |
Convert address → lat/lon |
GET /api/v1/stations/nearest?lat=&lon=&count=5 |
Nearest NOAA stations with distance |
GET /api/v1/stations/radius?lat=&lon=&radius_miles=50 |
All stations within a radius |
GET /api/v1/station/{id} |
Station metadata, tidal range, flood thresholds |
GET /api/v1/tides/day?station_id=&date=YYYY-MM-DD |
6-min curve + hilo for one day |
GET /api/v1/tides/range?station_id=&begin=&end= |
Hilo data for a date range |
GET /api/v1/tides/year-summary?station_id=&year= |
Monthly means and extremes |
GET /api/v1/special-events?station_id=&year= |
King tides, Perigean tides, flood risk, tidepooling |
GET /api/v1/solar-day?lat=&lon=&date= |
Sunrise/sunset in local time |
GET /api/v1/solar-range?lat=&lon=&begin=&end= |
Sunrise/sunset for a date range |
GET /api/v1/ics-preview?station_id=&year=&options= |
Event counts without building the file |
GET /calendar/2026/47.81,-122.38.ics?options=hilo,alerts |
Download ICS by coordinates |
GET /calendar/2026/47.81,-122.38-alerts.ics |
Alerts-only ICS by coordinates |
Example — try this in your browser while the backend is running:
http://localhost:8000/api/v1/tides/day?station_id=9447130&date=2026-07-04
http://localhost:8000/api/v1/solar-day?lat=47.81&lon=-122.38&date=2026-07-04
http://localhost:8000/api/v1/special-events?station_id=9447130&year=2026
MCP server (for Claude Desktop)
The MCP server lets Claude answer tide questions by calling real NOAA data directly. Once configured, you can ask Claude things like:
- "When is high tide in Seattle tomorrow?"
- "What are the best tidepooling days near Bodega Bay this summer?"
- "Find the lowest tide within 50 miles of San Francisco in July 2026"
- "Are there any king tides in Puget Sound this month?"
Setup
Find your Claude Desktop config file:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Add this (replace the path with your actual path):
{
"mcpServers": {
"tideline": {
"command": "python",
"args": ["C:\\full\\path\\to\\Moon_and_Tides\\mcp_server.py"]
}
}
}
On macOS/Linux use forward slashes:
{
"mcpServers": {
"tideline": {
"command": "python",
"args": ["/full/path/to/Moon_and_Tides/mcp_server.py"]
}
}
}
Restart Claude Desktop after saving. The MCP server starts automatically when Claude opens — you do not need to run it yourself.
Available tools
| Tool | What you can ask |
|---|---|
geocode |
Find lat/lon for an address |
find_stations |
"What NOAA stations are near Portland OR?" |
get_tides_day |
"What are today's tides in Bodega Bay?" |
get_tides_range |
"Show me tides for the week of July 4th in Seattle" |
get_station_info |
"What's the tidal range at station 9447130?" |
get_tidal_type |
"Is Astoria OR diurnal or semidiurnal?" |
get_extreme_tides |
"What's the highest tide in Seattle this summer?" |
find_extreme_in_radius |
"Find king tides within 75 miles of San Francisco in January" |
check_flood_risk |
"Any flood risk tides in Miami this winter?" |
get_slack_water |
"When is slack water in Puget Sound on June 21?" |
get_tidepooling_windows |
"Best tidepooling days near Monterey in July?" |
get_perigean_spring_tides |
"When are the Perigean spring tides in 2026?" |
generate_ics_url |
"Give me a calendar link for Seattle tides 2026" |
Caching
All data is cached locally in cache/tides.db (SQLite, created automatically). The cache keeps data indefinitely and only re-fetches when something is likely to have changed.
| Data | Kept | Re-fetched when |
|---|---|---|
| Tide predictions — past years | Forever | Never (NOAA doesn't revise completed years) |
| Tide predictions — current/future year | Forever | Once a year (harmonic constants may be updated) |
| Station list | Forever | Every 30 days (new stations added occasionally) |
| Tidal ranges | Forever | Only if manually deleted |
| Flood level thresholds | Forever | Only if manually deleted |
| Perigean spring tide dates | Forever | Astronomical — one computation per year |
| Sunrise/sunset times | Forever | Astronomical — never changes for a given date |
The cache is fully transparent — repeat commands are instant and tests never hit the network. To force a full refresh, delete cache/tides.db.
Running tests
# Fast tests — no network required, runs in ~5 seconds
python -m pytest tests/ -m "not live and not slow" -v
# Tests that hit the real NOAA API (requires internet)
python -m pytest tests/ -m "live" -v
# Frontend tests
cd frontend
npm test
Current counts: 45 Python tests, 21 TypeScript tests, all passing.
Importing your tides calendar
Google Calendar
- Go to calendar.google.com → Settings (gear icon) → Import & export
- Click Import, select your
.icsfile, choose which calendar to add it to - Click Import
For a live-updating subscription instead of a one-time import, use the calendar URL:
http://localhost:8000/calendar/2026/47.81,-122.38.ics?options=hilo,alerts,perigean
In Google Calendar: Other calendars → From URL, paste the link.
Apple Calendar
- One-time import: File → Import, select the
.icsfile - Subscribe (updates automatically): File → New Calendar Subscription, paste the URL above
Outlook
File → Open & Export → Import/Export → Import an iCalendar file.
Imported events into the wrong Google Calendar?
If you added the .ics to the wrong calendar and want to remove all tide events:
The script: scripts/delete_tide_events.gs
Steps:
- Go to script.google.com and click New project
- Delete any existing code and paste the entire contents of
scripts/delete_tide_events.gs - Set
CALENDAR_NAMEat the top to the exact name of the calendar you imported into (find it in the left sidebar of Google Calendar) - Leave
DRY_RUN = truefor now - Click Save, then Run — select
deleteTideEventsin the dropdown - On first run, approve the permissions Google asks for
- Check the Execution log at the bottom — it lists everything it would delete
- When satisfied, change
DRY_RUN = falseand run again to actually delete - If you hit Google's rate limits mid-run, just run again — it resumes where it left off
The script removes all event types that Tideline creates:
| Title prefix | Event type |
|---|---|
🌊 High Tide |
High tide events |
🏖 Low Tide |
Low tide events |
⚠️ King Tide |
King tide alerts |
⚠️ Extreme Low |
Extreme low tide alerts |
🌕 Perigean Spring Tide |
Perigean events |
🚨 Flood Risk |
Flood risk events |
🦀 Tidepooling Window |
Tidepooling windows |
⚓ Slack Water |
Slack water events |
🌊 King Tide Nearby |
Radius alerts |
It will not touch any other events in the calendar.
Project structure
app/
tide_data.py — NOAA fetch + SQLite cache + to_12h() helper
station_finder.py — Station search, haversine distance, tidal type
ics_builder.py — RFC-5545 ICS: all 9 event types, returns event counts
alert_engine.py — Extreme tide detection, flood risk, radius sweep
special_events.py — Slack water, tidepooling windows, Perigean tides
solar_cache.py — Sunrise/sunset via ephem, cached in SQLite
geocode.py — Nominatim address → lat/lon
cli.py — tideline CLI (preview/tides/ics/stations/extremes)
main.py — FastAPI web server + all REST endpoints
mcp_server.py — MCP server for Claude Desktop (13 tools)
frontend/
src/
pages/
Dashboard.tsx — Main dashboard (chart, stations, tides, feed)
AlertsPage.tsx — Full upcoming events list
HelpPage.tsx — Calendar import instructions
MapPage.tsx — Station map (stub — see TODO.md)
components/
TideCurveChart.tsx — Day/week/month/year chart with day/night shading
DateNav.tsx — Date navigation + day/night toggle
NearbyStations.tsx — Station list with live tide badges
TideEventList.tsx — Today's tide events with current highlight
CalendarOptions.tsx — ICS event type checkboxes
AlertRadiusSlider.tsx
DownloadButton.tsx — Shows event counts, links to ICS
ComingUpFeed.tsx — Upcoming alerts and opportunities
LocationSearch.tsx — Debounced geocode autocomplete
NavBar.tsx / TopBar.tsx
api.ts — All fetch functions + TypeScript types
station-store.ts — localStorage for last-selected station
tokens.ts — Design system colors
scripts/
delete_tide_events.gs — Google Apps Script: bulk-remove tide events
tests/ — 45 Python tests, 21 TypeScript tests
cache/ — SQLite DB (auto-created, gitignored)
TODO.md — Remaining work: map page, missing tests, viz layer
Notes and limitations
- US only — NOAA CO-OPS covers the contiguous US, Alaska, Hawaii, and US territories. No international stations.
- Nearest station substitution — if you search "Edmonds WA" and there's no station there, the app uses the nearest one (Seattle, 14 miles). The CLI prints a note; the web app shows a banner.
- Tidal heights are relative to MLLW (Mean Lower Low Water) — the average of all lower low water heights. Negative heights are normal and mean the tide is below the average low.
- Times are in the station's local time — standard or daylight, whichever applies on that date.
- Harmonic stations — slack water and tidepooling features require a harmonic station. These are the primary stations with full tidal constituent analysis. Subordinate stations (marked "no" in the Harmonic column) have predicted tides but not the 6-minute curves needed for those features.
- The
tidelinecommand — available afterpip install -e .. Without it, usepython -m app.clias a drop-in for every example above.
Installing Tideline
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/Earththing/Moon_and_TidesFAQ
Is Tideline MCP free?
Yes, Tideline MCP is free — one-click install via Unyly at no cost.
Does Tideline need an API key?
No, Tideline runs without API keys or environment variables.
Is Tideline hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Tideline in Claude Desktop, Claude Code or Cursor?
Open Tideline on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare Tideline with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
