MCP Surf Forecast
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Surf ForecastFind the best surf near me for an intermediate surfer today."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
๐ MCP Surf Forecast
The AI-powered surf companion that knows every break on the planet.
An MCP server that gives LLMs real-time surf intelligence โ wave quality scoring, beach discovery, session planning, and forecast analysis across 12+ global data sources.
Quick Start ยท Features ยท Tools ยท Prompts ยท Configuration ยท Contributing
๐ What is this?
MCP Surf Forecast turns any AI assistant into a surf-savvy copilot. It's a Model Context Protocol server that exposes surf data, smart tools, and planning prompts โ so Claude, Cursor, ChatGPT, or any MCP client can help you find the perfect wave.
You: "What's the best spot near Lisbon this morning?"
AI: Using wave_quality_index and classify_best_spot_nearby...
๐ #1 Coxos (Ericeira) โ WQI 8.2/10 "Very Good"
6ft+ sets, 14s period, light NE offshore
Best window: 07:00โ10:30 (dropping tide)
๐ฅ #2 Supertubos (Peniche) โ WQI 7.8/10 "Very Good"
Hollow barrels, overhead, advanced surfers only
๐ฅ #3 Carcavelos โ WQI 6.1/10 "Good"
Fun peaks, 3-4ft, great for all levelsRelated MCP server: mcp-ohmy-sql
โจ Features
๐ฏ Wave Quality Index (0โ10)
A proprietary scoring algorithm that condenses swell, wind, tide, consistency, and direction into one number. No more cross-referencing 5 tabs โ just ask "how good is it?"
Score | Label | You should... |
8โ10 | Very Good / Epic | Drop everything and go |
6โ7 | Good | Great session guaranteed |
4โ5 | Fair | Fun if you're not picky |
2โ3 | Poor | Maybe do yoga instead |
0โ1 | Flat | Definitely do yoga |
๐ Global Coverage
Data aggregated from 12+ providers across every major surf region:
Region | Providers |
๐ Global | Surfline, Surf-Forecast, Magicseaweed |
๐ช๐บ Europe | MeoSurf, Windguru |
๐ง๐ท Brazil | Waves.com.br |
๐ฆ๐บ Australia | Coastalwatch, Swellnet |
๐บ๐ธ Hawaii | Surfnewsnetwork |
๐ฎ๐ฉ Indonesia | Baliwaves |
๐ฟ๐ฆ Africa | Wavescape |
๐ง Smart Classification
Not just data โ intelligence. The server tells you where to go based on your skill level, location, and current conditions. Beginners get safe recommendations; pros get the heavy spots.
๐ Tools
Tool | What it does |
| Score any beach 0โ10 with full breakdown |
| Ranked spots by quality within your radius |
| Go / Caution / Avoid for your level |
| Discover spots near GPS coordinates |
| Same, but from a city name |
| Multi-criteria search (region, wave type, skill) |
| Optimal windows considering tide + wind |
| Side-by-side forecast comparison |
| Upcoming swell notifications |
| Gear advice based on water temp + wind chill |
| Complete conditions in one call |
Tool Sequence Diagrams
wave_quality_index
sequenceDiagram
participant Client as MCP Client
participant Tool as wave_quality_index
participant Repo as BeachRepository
participant Forecast as ForecastProvider
participant WQI as WQI Engine
Client->>Tool: { beachId, timestamp? }
Tool->>Repo: getById(beachId)
Repo-->>Tool: Beach (bestSwellDir, bestWindDir, bestTide)
Tool->>Forecast: getForecast(beachId)
Forecast-->>Tool: ForecastEntry[]
Tool->>WQI: calculate(forecast, beachProfile)
Note over WQI: swellScore ร 0.30<br/>windScore ร 0.25<br/>consistency ร 0.15<br/>tideAlignment ร 0.15<br/>directionMatch ร 0.15
WQI-->>Tool: { wqi: 7.8, label, breakdown }
Tool-->>Client: WQI result + summaryclassify_best_spot_nearby
sequenceDiagram
participant Client as MCP Client
participant Tool as classify_best_spot_nearby
participant Repo as BeachRepository
participant WQI as WQI Engine
Client->>Tool: { lat, lon, radiusKm, topN, skillLevel?, minWqi }
Tool->>Repo: findInRadius({ lat, lon }, radiusKm)
Repo-->>Tool: Beach[] with distances
opt skillLevel provided
Tool->>Tool: filter by skillLevel
end
loop For each candidate beach
Tool->>WQI: calculate(beachId)
WQI-->>Tool: { wqi, label, bestWindow }
end
Tool->>Tool: filter wqi >= minWqi
Tool->>Tool: sort by WQI descending
Tool->>Tool: take topN
Tool-->>Client: Ranked list with WQI + highlightsclassify_spot_for_skill
sequenceDiagram
participant Client as MCP Client
participant Tool as classify_spot_for_skill
participant Repo as BeachRepository
participant WQI as WQI Engine
Client->>Tool: { beachId, skillLevel }
Tool->>Repo: getById(beachId)
Repo-->>Tool: Beach (waveType, skillLevel[])
Tool->>WQI: calculate(beachId)
WQI-->>Tool: { wqi, breakdown, forecast }
Tool->>Tool: evaluate(waveSize, power, currents vs skillLevel)
alt Safe for level
Tool-->>Client: { recommendation: "go", reasons }
else Marginal
Tool->>Repo: findAlternative(nearby, beginner-friendly)
Tool-->>Client: { recommendation: "caution", reasons, alternative }
else Dangerous
Tool->>Repo: findAlternative(nearby, safer)
Tool-->>Client: { recommendation: "avoid", reasons, alternative }
endfind_beaches_in_radius
sequenceDiagram
participant Client as MCP Client
participant Tool as find_beaches_in_radius
participant Repo as BeachRepository
participant Geo as Haversine
Client->>Tool: { lat, lon, radiusKm, limit }
Tool->>Repo: getAll()
Repo-->>Tool: Beach[]
loop For each beach
Tool->>Geo: haversineDistance(input, beach)
Geo-->>Tool: distanceKm
end
Tool->>Tool: filter distance <= radiusKm
Tool->>Tool: sort by distance ASC
Tool->>Tool: take limit
Tool-->>Client: Beach[] with distanceKmfind_beaches_near_city
sequenceDiagram
participant Client as MCP Client
participant Tool as find_beaches_near_city
participant Geocode as Nominatim API
participant Radius as find_beaches_in_radius
Client->>Tool: { city, country?, radiusKm, limit }
Tool->>Geocode: geocodeCity(city, country)
Geocode-->>Tool: { lat, lon }
alt Geocoding failed
Tool-->>Client: Error: "Could not geocode city"
else Success
Tool->>Radius: findInRadius(lat, lon, radiusKm, limit)
Radius-->>Tool: Beach[] with distances
Tool-->>Client: Beach[] with distances
endfilter_beaches
sequenceDiagram
participant Client as MCP Client
participant Tool as filter_beaches
participant Repo as BeachRepository
participant WQI as WQI Engine
Client->>Tool: { region?, country?, waveType?, skillLevel?, minWqi, maxResults }
Tool->>Repo: filter({ region, country, waveType, skillLevel })
Repo-->>Tool: Beach[] matching criteria
opt minWqi > 0
loop For each beach
Tool->>WQI: calculate(beachId)
WQI-->>Tool: { wqi }
end
Tool->>Tool: filter wqi >= minWqi
end
Tool->>Tool: take maxResults
Tool-->>Client: Filtered Beach[]best_sessions_today
sequenceDiagram
participant Client as MCP Client
participant Tool as best_sessions_today
participant Repo as BeachRepository
participant Forecast as ForecastProvider
participant WQI as WQI Engine
Client->>Tool: { beachId }
Tool->>Repo: getById(beachId)
Repo-->>Tool: Beach (bestTide, bestWindDir)
Tool->>Forecast: getForecast(beachId, days=1)
Forecast-->>Tool: ForecastEntry[] (hourly)
loop For each hour today (sunrise โ sunset)
Tool->>WQI: calculate(beachId, hour)
WQI-->>Tool: { wqi, tideState, windDirection }
end
Tool->>Tool: find peak WQI windows
Tool->>Tool: group consecutive good hours
Tool-->>Client: SessionWindow[] { startTime, endTime, wqi, confidence }compare_beaches
sequenceDiagram
participant Client as MCP Client
participant Tool as compare_beaches
participant Repo as BeachRepository
participant WQI as WQI Engine
participant Forecast as ForecastProvider
Client->>Tool: { beachIds[], date? }
loop For each beachId
Tool->>Repo: getById(beachId)
Repo-->>Tool: Beach profile
Tool->>WQI: calculate(beachId, date)
WQI-->>Tool: { wqi, breakdown }
Tool->>Forecast: getForecast(beachId)
Forecast-->>Tool: Conditions
end
Tool->>Tool: build side-by-side comparison
Tool-->>Client: Comparison[] { beach, wqi, swell, wind, tide, bestWindow }check_swell_alert
sequenceDiagram
participant Client as MCP Client
participant Tool as check_swell_alert
participant Forecast as ForecastProvider
Client->>Tool: { beachId, minSwellHeightM, daysAhead }
Tool->>Forecast: getForecast(beachId, daysAhead)
Forecast-->>Tool: ForecastEntry[] (multi-day)
Tool->>Tool: filter swellHeightM >= minSwellHeightM
alt Swell found
Tool-->>Client: Matching windows[] { timestamp, height, period, direction }
else No swell
Tool-->>Client: { alert: false, message: "No significant swell in next N days" }
endwetsuit_recommendation
sequenceDiagram
participant Client as MCP Client
participant Tool as wetsuit_recommendation
participant Forecast as ForecastProvider
participant Calc as Wetsuit Calculator
Client->>Tool: { beachId, timestamp?, sessionDurationMin }
Tool->>Forecast: getForecast(beachId)
Forecast-->>Tool: { waterTempC, windSpeedKts, airTempC }
Tool->>Calc: recommendWetsuit(waterTemp, windSpeed, airTemp, duration)
Note over Calc: Wind chill adjustment<br/>Long session adjustment<br/>Thickness lookup table
Calc-->>Tool: { type, thickness, boots, gloves, hood }
Tool-->>Client: Full recommendation + UV advicesurf_conditions_full
sequenceDiagram
participant Client as MCP Client
participant Tool as surf_conditions_full
participant Repo as BeachRepository
participant Forecast as ForecastProvider
participant WQI as WQI Engine
participant Wetsuit as Wetsuit Calculator
Client->>Tool: { beachId, timestamp? }
Tool->>Repo: getById(beachId)
Repo-->>Tool: Beach profile
Tool->>Forecast: getForecast(beachId)
Forecast-->>Tool: Full forecast (marine + weather + ocean)
Tool->>WQI: calculate(beachId, timestamp)
WQI-->>Tool: { wqi, label, breakdown }
Tool->>Wetsuit: recommendWetsuit(waterTemp, wind, airTemp)
Wetsuit-->>Tool: Gear recommendation
Tool->>Tool: assess safety (lightning, fog, currents)
Tool-->>Client: Complete response { marine, wind, weather, sun, ocean, gear, safety, wqi }๐ฌ Prompts
Pre-built conversation starters that turn your AI into a surf expert:
Prompt | Use case |
| Multi-day itinerary with forecasts |
| Morning conditions check |
| Deep dive on a specific break |
| Safe spots for learners |
๐ Quick Start
Prerequisites
Node.js 22+ (download)
npm or pnpm
Install
git clone https://github.com/YOUR_ORG/mcp-surf-forecast.git
cd mcp-surf-forecast
npm installRun the server
# stdio transport (for Claude Desktop, Cursor, etc.)
npm start
# HTTP transport (for network clients, debugging)
npm run start:http
# โ Server running at http://localhost:3000
# Interactive Inspector UI (development)
npm run devConnect your AI client
Claude Desktop โ add to your mcp.json:
{
"mcpServers": {
"surf-forecast": {
"command": "npx",
"args": ["fastmcp", "run", "/path/to/mcp-surf-forecast/src/server.ts"]
}
}
}Cursor / HTTP clients:
{
"mcpServers": {
"surf-forecast": {
"url": "http://localhost:3000"
}
}
}๐งช Testing
Run tests locally
# Run all tests
npm test
# Run tests in watch mode (re-runs on file change)
npm run test:watch
# Run tests with coverage report
npm run test:coverage
# Type check (no emit)
npm run typecheckTest structure
tests/
โโโ unit/ # Pure logic: WQI engine, geo math, schemas
โโโ integration/ # Tools + resources with mock data
โโโ e2e/ # Full MCP server via client connectionVerify MCP compliance
# List all registered resources, tools, and prompts
npm run inspect
# Call a specific tool from terminal
npx fastmcp call wave_quality_index --file src/server.ts beachId=supertubos-peniche
# Open the visual Inspector UI
npm run dev๐ MCP Inspector
The FastMCP Inspector is a visual development tool that lets you browse, test, and debug all your MCP components interactively โ without needing an AI client connected.
Launch the Inspector
npm run devThis opens a browser-based UI with hot reload. Every time you save a file, the Inspector reloads your server automatically.
What you can do in the Inspector
Feature | How |
๐ Browse all tools, resources & prompts | Listed in the sidebar with schemas |
๐งช Call any tool with custom params | Fill in the form, hit "Run", see the response |
๐ Read any resource by URI | Type |
๐ฌ Render prompts with arguments | Preview exactly what the LLM receives |
โ Test error handling | Pass invalid params and verify error messages |
โฑ๏ธ Check response times | Each call shows execution duration |
Inspector from the terminal (headless)
If you prefer CLI over UI:
# List everything the server exposes
npx fastmcp inspect --file src/server.ts
# Output:
# Tools (9):
# - wave_quality_index
# - classify_best_spot_nearby
# - classify_spot_for_skill
# - find_beaches_in_radius
# - find_beaches_near_city
# - filter_beaches
# - best_sessions_today
# - compare_beaches
# - check_swell_alert
#
# Resources (6):
# - surf://providers
# - surf://providers/{providerId}
# - surf://beaches
# - surf://beaches/{beachId}
# - surf://forecast/{beachId}
# - surf://cams/{beachId}
#
# Prompts (4):
# - plan_surf_trip
# - daily_surf_report
# - analyze_spot
# - beginner_spot_finderCall tools directly from terminal
# Score a beach
npx fastmcp call wave_quality_index --file src/server.ts beachId=supertubos-peniche
# Find beaches near coordinates
npx fastmcp call find_beaches_in_radius --file src/server.ts lat=38.7 lon=-9.14 radiusKm=50
# Classify for a beginner
npx fastmcp call classify_spot_for_skill --file src/server.ts beachId=carcavelos skillLevel=beginner
# Check upcoming swell
npx fastmcp call check_swell_alert --file src/server.ts beachId=pipeline-oahu minSwellHeightM=3 daysAhead=5Run server locally for HTTP clients
# Start on port 3000 (default)
npm run start:http
# Or specify a custom port
PORT=8080 npx fastmcp run src/server.ts --transport http --port 8080Then test with curl:
# Health check (server is up)
curl http://localhost:3000
# Or connect a FastMCP client
npx fastmcp call wave_quality_index --url http://localhost:3000 beachId=coxos-ericeiraโ๏ธ Configuration
Environment Variables
Variable | Required | Default | Description |
| No |
| HTTP transport port |
| No |
| Transport type: |
| No |
| Logging level: |
| No |
| User-Agent for geocoding requests |
| CI only | โ | SonarCloud authentication token |
| CI only | โ | Semgrep security scanning token |
sonar-project.properties
sonar.projectKey=mcp-surf-forecast
sonar.organization=<your-github-org>
sonar.sources=src
sonar.tests=tests
sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.exclusions=src/data/**,dist/**Data Configuration
The beach database and provider registry live in src/data/:
beaches.jsonโ Static database of ~50-100 surf spots worldwideproviders.jsonโ Metadata for all data source providers
To add a new beach, just append to beaches.json:
{
"id": "your-spot-name",
"name": "Your Spot",
"region": "Europe",
"country": "Portugal",
"lat": 39.36,
"lon": -9.37,
"waveType": ["beach-break"],
"skillLevel": ["intermediate"],
"bestTide": "mid",
"bestSwellDir": "NW",
"bestWindDir": "E",
"providers": ["surfline", "windguru"],
"camUrl": null
}No code changes required โ the server picks it up automatically.
WQI Weights
The Wave Quality Index scoring weights are defined in src/tools/wqi.ts:
const WQI_WEIGHTS = {
swellScore: 0.30, // Wave height + period
windScore: 0.25, // Offshore vs onshore
consistency: 0.15, // Set frequency
tideAlignment: 0.15, // Current vs ideal tide
directionMatch: 0.15, // Swell direction vs spot's sweet spot
}๐ Project Structure
src/
โโโ server.ts # Composition root โ wires everything together
โโโ resources/ # MCP resources (read-only data endpoints)
โโโ tools/ # MCP tools (computation & actions)
โโโ prompts/ # MCP prompts (LLM interaction templates)
โโโ models/ # Domain entities & Zod schemas
โโโ providers/ # Data access layer (static JSON for MVP)
โโโ data/ # Beach & provider JSON databases
โโโ utils/ # Geo math, geocoding, helpersFull architecture details in docs/01-architecture.md
๐ Built With
Technology | Why | |
๐ | The standard MCP framework | |
๐ก๏ธ | Runtime schema validation | |
๐ | Geographic distance calculations | |
๐งช | Lightning-fast testing | |
๐ | Code quality & security |
๐ค Contributing
We welcome contributions! Whether it's adding new beaches, improving the WQI algorithm, or integrating real-time data sources.
How to contribute
Fork the repo
Create a feature branch (
git checkout -b feature/add-bali-spots)Make your changes
Run tests (
npm test) and type check (npm run typecheck)Open a PR
Easy first contributions
๐๏ธ Add beaches โ Drop entries into
src/data/beaches.json(no code needed!)๐ Tune WQI โ Improve scoring accuracy for specific wave types
๐ Add providers โ Implement a new
ForecastProviderfor a data source๐ Improve prompts โ Better LLM guidance for surf planning
Development workflow
npm run dev # Inspector UI with hot reload
npm test # Run test suite
npm run test:watch # Tests re-run on save
npm run inspect # Validate all MCP components๐ Roadmap
Static beach database (50+ spots worldwide)
Wave Quality Index (0โ10 scoring)
Geo-based search & classification
Parameterized prompts for trip planning
Real-time Surfline API integration
Live cam snapshot analysis
Historical data & trend analysis
User favorites & personalized alerts
Multi-language support
Mobile companion app
๐ Documentation
Full technical documentation lives in docs/:
Document | Topic |
System design & SOLID principles | |
Beach, Forecast, WQI schemas | |
MCP data endpoints | |
Computation & classification | |
Scoring algorithm deep-dive | |
LLM interaction templates | |
CI, SonarCloud, test strategy | |
Dev environment & config |
๐ License
MIT โ see LICENSE for details.
Built for surfers, by surfers. ๐ค
Stop checking 5 different apps. Let AI find your next session.
โญ Star this repo ยท ๐ Report Bug ยท ๐ก Request Feature
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseBqualityDmaintenanceA minimal Python MCP server that provides surf forecasts for a single Surfline spot. It fetches both conditions and rating data through the get_surf_forecast tool.Last updated1
- -license-qualityCmaintenanceAn MCP server that bridges AI assistants with SQL databases, enabling natural language querying across multiple database types with built-in optimization and security.Last updated3
- Flicense-qualityCmaintenanceProvides surf forecast data including swell height, period, direction, and wind conditions for any location worldwide using the Open-Meteo Marine API. It also includes tools to find the best day to surf and integrates with MCP clients via a Python server.Last updated19
- AlicenseAqualityCmaintenanceAn MCP server that enables AI assistants to fetch web content in multiple formats (HTML, JSON, text, Markdown) with intelligent content extraction, chunk management, and browser automation support.Last updated57215MIT
Related MCP Connectors
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP server connecting AI agents to non-custodial staking data across 130+ networks.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/luisaugustomachadomoretto/mcp-surf-forecast'
If you have feedback or need assistance with the MCP directory API, please join our Discord server