surf-mcp-server
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., "@surf-mcp-serverWhat are the best spots in Uluwatu for intermediate surfers?"
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.
Surf MCP Server
Ein MCP Server fuer Surfspot-Daten, Spot-Suche, Marine Forecasts und Tide-Daten.
Die Spot-Daten liegen als JSON-Dateien unter src/data/. Forecasts kommen ueber
Open-Meteo Marine, Tide-Daten ueber WorldTides.
Der Server laeuft lokal per Python oder als Container in Kubernetes ueber das mitgelieferte Helm Chart.
Architektur
flowchart LR
Client[MCP Client] -->|streamable-http| Server[Surf MCP Server]
Server --> Tools[MCP Tools]
Tools --> Spots[src/data/*.json]
Tools --> Forecast[Forecast Orchestrierung]
Forecast --> OpenMeteo[Open-Meteo Marine API]
Forecast --> WorldTides[WorldTides API]
WorldTides --> Secret[WORLDTIDES_API_KEY]Related MCP server: surfline-mcp
Voraussetzungen
Python
>=3.10Zugriff auf dieses Repo
Installation der Python-Abhaengigkeiten aus
pyproject.tomlOptional:
uvFuer Tide-Daten: WorldTides API Key als
WORLDTIDES_API_KEY
Abhaengigkeiten:
mcp[cli]requests
Lokales Setup
Vom Repo-Root aus:
cd surf-mcp-server
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e .Alternativ mit uv:
cd surf-mcp-server
uv syncKonfiguration
Open-Meteo braucht keinen API Key. Fuer WorldTides muss ein API Key gesetzt sein,
wenn get_tides oder get_conditions genutzt werden:
export WORLDTIDES_API_KEY="..."Server starten
python src/server.pyDer Server startet mit streamable-http auf 0.0.0.0:8000:
mcp.run(transport="streamable-http")Wenn du ihn auf einem anderen System testest, reicht normalerweise:
Repo kopieren oder klonen
Python-Umgebung erstellen
Dependencies installieren
WORLDTIDES_API_KEYsetzen, falls Tide-Daten genutzt werdenpython src/server.pyaus dem Repo-Root ausfuehren
Projektstruktur
surf-mcp-server/
|-- .github/workflows/build.yml # GitHub Actions Build Pipeline
|-- charts/surf-mcp/ # Helm Chart
|-- src/
| |-- server.py # MCP Tools und Server-Start
| |-- spots.py # Laden der Spot-Dateien
| |-- forecast.py # Forecast- und Tide-Orchestrierung
| |-- data/ # Surfspot JSON-Dateien
| `-- providers/
| |-- open_meteo.py # Open-Meteo Marine API
| |-- worldtides.py # WorldTides API
| `-- stormglass.py # Vorbereiteter Provider
|-- tests/ # Unit Tests
|-- Dockerfile
|-- pyproject.toml
|-- uv.lock
`-- README.mdForecast Flow
sequenceDiagram
participant User as MCP Client
participant Server as Surf MCP Server
participant Data as Spot JSON
participant OM as Open-Meteo
participant WT as WorldTides
User->>Server: get_conditions(spot_id)
Server->>Data: get_spot(spot_id)
Data-->>Server: coordinates
Server->>OM: wave_height, wave_period, wave_direction
OM-->>Server: hourly marine forecast
Server->>WT: tide heights with WORLDTIDES_API_KEY
WT-->>Server: tide heights
Server-->>User: combined forecast + tide_stateVerfuegbare MCP Tools
list_regions()
Gibt alle verfuegbaren Regionen zurueck.
Beispiel-Resultat:
["Airport Reefs", "Lakey", "Uluwatu", "Ungasan", "West Sumbawa"]list_spots(region: string | null = null)
Listet Spots. Optional kann nach Region gefiltert werden.
Beispiel:
{
"region": "Uluwatu"
}Resultat enthaelt:
{
"id": "uluwatu_the_peak",
"name": "Uluwatu - The Peak",
"country": "Indonesia",
"island": "Bali",
"region": "Uluwatu"
}get_spot_info(spot_id: string)
Gibt alle Details fuer einen Spot zurueck.
Beispiel:
{
"spot_id": "lakey_peak"
}find_spots(...)
Findet Spots anhand mehrerer Kriterien.
Parameter:
skill: z.B.intermediate,advanced,expertcountry: z.B.Indonesiaisland: z.B.BalioderSumbawaregion: z.B.Uluwatu,Lakey,West Sumbawatide: z.B.low,mid,highwind: z.B.SE,N,NWswell_direction: z.B.S,SW,Wswell_height_ft: z.B.4
Beispiel:
{
"skill": "intermediate",
"island": "Bali",
"region": "Uluwatu",
"tide": "mid",
"wind": "SE",
"swell_direction": "SW",
"swell_height_ft": 4
}count_spots()
Gibt die Anzahl der Spot-Dateien zurueck.
search_spots(query: string)
Sucht Spots nach Name.
Beispiel:
{
"query": "uluwatu"
}get_forecast(spot_id: string)
Gibt den normalisierten Marine Forecast fuer einen Spot zurueck.
Die Daten kommen aus Open-Meteo Marine:
wave_height_ftwave_period_sswell_directionswell_direction_deg
Beispiel-Resultat:
[
{
"time": "2026-06-11T00:00",
"wave_height_ft": 4.6,
"wave_period_s": 12.1,
"swell_direction": "SW",
"swell_direction_deg": 225
}
]get_tides(spot_id: string)
Gibt Tide-Daten fuer einen Spot zurueck.
Die Daten kommen aus WorldTides. Dafuer muss WORLDTIDES_API_KEY gesetzt sein.
Beispiel-Resultat:
[
{
"time": "2026-06-11T00:00+0000",
"tide_height_ft": 3.2,
"tide_state": "mid"
}
]get_conditions(spot_id: string)
Kombiniert Marine Forecast und Tide-Daten. Pro Forecast-Zeitpunkt wird die
naechste Tide gesucht und als tide_height_ft und tide_state ergaenzt.
Beispiel-Resultat:
[
{
"time": "2026-06-11T00:00",
"wave_height_ft": 4.6,
"wave_period_s": 12.1,
"swell_direction": "SW",
"swell_direction_deg": 225,
"tide_height_ft": 3.2,
"tide_state": "mid"
}
]Docker
Image lokal bauen:
docker build -t surf-mcp-server .Container starten:
docker run --rm \
-p 8000:8000 \
-e WORLDTIDES_API_KEY="$WORLDTIDES_API_KEY" \
surf-mcp-serverGitHub Build Pipeline
Die Pipeline liegt unter .github/workflows/build.yml.
flowchart TD
PushMain[Push auf main] --> Checkout[Checkout]
Checkout --> Login[Login bei GHCR]
Login --> Metadata[Docker Metadata]
Metadata --> Build[Docker Build]
Build --> PushGhcr[Push nach GHCR]
PushGhcr --> Tags[latest + Git SHA]Bei jedem Push auf main wird ein Container Image gebaut und nach GHCR
gepusht:
ghcr.io/steph76k/surf-mcp-server:latestghcr.io/steph76k/surf-mcp-server:<git-sha>
Die Pipeline nutzt GITHUB_TOKEN mit packages: write.
Kubernetes Deployment mit Helm
Das Helm Chart liegt unter charts/surf-mcp/.
flowchart LR
Helm[helm upgrade --install] --> Deployment[Deployment]
Helm --> Service[Service]
Helm --> Ingress[Ingress]
Secret[Kubernetes Secret surf-mcp] --> Deployment
Deployment --> Pod[surf-mcp Pod]
Pod --> GHCR[GHCR Image]
Pod --> WorldTides[WorldTides API]WorldTides Secret erstellen
Vor dem Helm Deployment muss der WorldTides API Key als Kubernetes Secret angelegt werden:
kubectl create secret generic surf-mcp \
--from-literal=worldtides-api-key="$WORLDTIDES_API_KEY"Das Chart liest den Key standardmaessig aus diesem Secret:
env:
- name: WORLDTIDES_API_KEY
valueFrom:
secretKeyRef:
name: surf-mcp
key: worldtides-api-keyInstallieren oder aktualisieren
helm upgrade --install surf-mcp charts/surf-mcp \
--namespace surf-mcp \
--create-namespaceStandardwerte aus charts/surf-mcp/values.yaml:
Image:
ghcr.io/steph76k/surf-mcp-server:latestService:
ClusterIPauf Port8000Ingress: Traefik
Host:
surf-mcp.rke2-cluster1.berger.phSecret:
surf-mcpmit Keyworldtides-api-key
Image Tag ueberschreiben
helm upgrade --install surf-mcp charts/surf-mcp \
--namespace surf-mcp \
--create-namespace \
--set image.tag="<git-sha>"Manifest lokal pruefen
helm template surf-mcp charts/surf-mcpSpot JSON Schema
Jeder Spot ist eine eigene JSON-Datei in src/data/. Der Dateiname sollte zur
spot_id passen.
Beispiel:
{
"spot_id": "uluwatu_the_peak",
"name": "Uluwatu - The Peak",
"country": "Indonesia",
"island": "Bali",
"region": "Uluwatu",
"coordinates": {
"lat": -8.816633,
"lon": 115.08625
},
"conditions": {
"swell": {
"directions": ["S", "SW"],
"min_ft": 1,
"max_ft": 6
},
"wind": {
"offshore": ["SE"]
},
"tide": ["mid", "high"]
},
"wave": {
"direction": "left",
"type": "reef"
},
"ratings": {
"crowd": 10,
"localism": 9,
"risk": 6,
"fun": 9
},
"surfer_level": ["intermediate", "advanced"],
"notes": "At high tide, aim south of the cave when coming in.",
"description": "Short description of the spot.",
"hazards": [
"sharp coral reef",
"strong currents"
]
}Wichtige Daten-Konventionen
surfer_level
surfer_level ist immer ein Array, damit die Suche einzelne Levels sauber
matchen kann:
{
"surfer_level": ["intermediate", "advanced"]
}Nicht mehr verwenden:
{
"surfer_level": "intermediate / advanced"
}Empfohlene Werte:
beginnerintermediateadvancedexpert
Location Felder
country, island und region sind getrennte Felder:
{
"country": "Indonesia",
"island": "Bali",
"region": "Uluwatu"
}Nicht mehr verwenden:
{
"region": "Bali - Uluwatu Area"
}Aktuelle Regionen
Airport ReefsLakeyUluwatuUngasanWest Sumbawa
Neue Spots hinzufuegen
Neue Datei in
src/data/erstellen, z.B.my_spot.jsonspot_idpassend zum Dateinamen setzen, z.B.my_spotSchema wie oben verwenden
JSON validieren:
jq empty src/data/my_spot.jsonAlle Spot-Dateien validieren:
for f in src/data/*.json; do jq empty "$f" || exit 1; doneTests und Checks
python -m compileall src
python -m unittest discover -s tests
helm template surf-mcp charts/surf-mcpHinweise
Spot-Daten werden bei jedem Tool-Aufruf direkt aus
src/data/*.jsongelesen.get_forecastnutzt Open-Meteo Marine und braucht keinen API Key.get_tidesundget_conditionsnutzen WorldTides und brauchenWORLDTIDES_API_KEY.src/providers/stormglass.pyist als optionaler Provider vorbereitet.Das Helm Chart nutzt standardmaessig die im Docker Image enthaltenen Spot-Daten.
Ein externer ConfigMap-Mount fuer Spot-Daten kann ueber
spotData.configMap.enabled=trueaktiviert werden.
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.
Latest Blog Posts
- 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/steph76k/surf-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server