webling-mcp
Click on "Deploy 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., "@webling-mcpwelche mitglieder haben ihren beitrag noch nicht bezahlt?"
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.
webling-mcp
Read-only MCP-Server und Chat-App für die Vereinsverwaltung Webling. Mitgliederdaten werden pseudonymisiert, bevor sie ein Sprachmodell erreichen. Gebaut für einen Sportverein und dort im Einsatz.
In English: A read-only MCP server and chat web app for a sports club's member database. Every tool response is built from a field whitelist, so the language model only ever sees pseudonyms. Real names are swapped back in on the way out, between server and browser. 187 tests enforce that no personal data reaches the model API.
Das Problem
Ein Vereinsvorstand will fragen können: „Wer hat noch nicht bezahlt?" oder „Wer hat dieses Jahr ein rundes Jubiläum?". Ein Sprachmodell beantwortet das gut. Aber jede Tool-Antwort läuft durch die API eines Drittanbieters, und Klarnamen von Mitgliedern haben dort nach DSGVO nichts verloren.
Related MCP server: Universal Database MCP
Die Lösung: Das Modell sieht nie einen Namen
Jede Anfrage durchläuft drei Stufen.
Stufe | Was passiert | Code |
Eingang | Bekannte Namen in der Frage werden durch Pseudonyme ersetzt, bevor die Frage an die API geht |
|
Verarbeitung | Tool-Antworten entstehen aus einer Feld-Whitelist. Das Modell bekommt Pseudonyme ( |
|
Ausgang | Pseudonyme in der fertigen Antwort werden erst auf dem Weg zum Browser zu Klarnamen aufgelöst |
|
Die Whitelist ist konstruktiv: Antworten werden aus erlaubten Feldern aufgebaut, statt verbotene herauszufiltern. Ein neues Feld in Webling kann deshalb nicht versehentlich durchrutschen. Ein PII-Sweep-Test prüft jede Tool-Antwort.
Im lokalen Einsatz mit Claude Code gibt es einen zweiten Ausgabekanal:
Namenslisten wie Mahnliste, Jubiläen und Aufstellungen landen als
Markdown-Datei unter output/ und verlassen den Rechner nie.
Komponenten
src/
├── webling_mcp/ MCP-Server (FastMCP, stdio)
│ ├── server.py Einstieg, Fehlerbehandlung
│ ├── tools.py 10 Tools, auch von der Chat-App genutzt
│ ├── privacy.py Feld-Whitelist, einzige Stelle für Freigaben
│ ├── domain.py Auswertungen: Beiträge, Jubiläen, Statistik
│ ├── client/ Webling-API-Client, nur GET
│ └── rag/ Dokumentensuche, Maskierung beim Indexieren
└── webling_chat/ Chat-PWA (FastAPI)
├── app.py Web-App, Login, Streaming
├── chat.py Tool-Use-Schleife gegen die Anthropic-API
├── auth.py Argon2id, serverseitige Sessions, Rate-Limit
├── policy.py welche Rolle welche Tools sieht
├── vormaskierung.py Namen raus, bevor die Frage die API erreicht
└── ruecksubstitution.py Namen zurück, auf dem Weg zum BrowserTools
Tool | Beschreibung |
| Mitglieder (pseudonymisiert) mit Status, Beitrag und Beitrittsjahr, filterbar nach Mannschaft und Geburtsjahr |
| Einzelmitglied per Pseudonym |
| Mannschaften mit Mitgliederzahl |
| Dateinamen im Jahresordner |
| Mahnliste, Namen nur in lokaler Datei |
| Runde Geburtstage, Namen nur in lokaler Datei |
| Aufstellungen mit Rang, Namen nur in lokaler Datei |
| Statistik nach Geburtsjahr und Geschlecht |
| Hybridsuche über maskierte Vereinsdokumente |
| Maskierter Volltext eines indexierten Dokuments |
Mitgliedsstatus und Beitrag
Das Modell sieht die Mitgliedskategorie und den Jahresbeitrag. Den Beitrag rechnet aber nicht das Modell, sondern der Server, deterministisch aus einer festen Beitragsordnung.
Das Webling-Feld für den Beitrag wird bewusst nicht gelesen. Ein Abgleich mit echten Daten zeigte Leerwerte und Beträge, die nicht zur Kategorie passten. Und bei Geld ist eine plausible Falschauskunft teuer, während sich Modell-Arithmetik nicht testen lässt.
Ein Konsistenz-Check (scripts/status_check.py) findet Mitglieder, deren
Alter nicht zur Kategorie passt. Die Konsole zeigt dabei nur Pseudonyme.
Tool-Antworten melden außerdem die Datenabdeckung, etwa wie viele Mitglieder einen gepflegten Status haben. So kann das Modell sagen, wenn eine Auswertung auf unvollständigen Daten beruht, statt sie als vollständig auszugeben.
Dokumentensuche
Hybridsuche (BM25 plus lokale Embeddings, Reciprocal Rank Fusion) über
Satzung, Ordnungen, Protokolle und Finanzberichte. Personenbezogene Daten werden beim
Indexieren maskiert (rag/maskierung.py):
Mitglieder deterministisch über die Mitgliederliste (
M-<id>, wie in den Tools)Nicht-Mitglieder per spaCy-NER (
P-<Dok>-<n>)E-Mail, Telefon und IBAN per Regex
Der Index (SQLite FTS5 plus sqlite-vec) enthält dadurch nie Klarnamen.
Embedding-Modell: intfloat/multilingual-e5-small, lokal auf der CPU.
Ingest anstoßen, wenn neue Dokumente in Webling liegen:
venv\Scripts\python scripts/ingest.pyChat-App
Installierbare Web-App mit Login und Streaming-Antworten. Läuft als FastAPI-App hinter einem HTTPS-Reverse-Proxy auf einem VPS.
Ein Konto pro Person, Passwörter mit Argon2id, kein Selbst-Registrieren
Sessions serverseitig und einzeln widerrufbar
Vorgeschaltete Basic Auth hält Bots und Rateversuche vom eigentlichen Login fern
Rollenmodell in
policy.py: Neue Rollen sind eine Datenänderung, kein UmbauDer Gesprächsverlauf bleibt serverseitig und pseudonym
Betrieb: VPS-Betriebsanleitung
Qualitätssicherung
187 Tests, alle mit fiktiven Personen und ohne Zugriff auf die echte API
PII-Sweep: Jede Tool-Antwort wird auf verbotene Felder geprüft
PII-Stichprobe am echten Index (
scripts/pii_stichprobe.py): prüft, dass kein Klarname aus dem Pseudonym-Mapping im Suchindex steht. Die Konsole zeigt nur Zähler.Read-only ist testgesichert: Der API-Client kennt nur
get()
Designentscheidungen
Jede Ausbaustufe hat eine eigene Spec, jeweils mit den verworfenen Alternativen und dem Grund dafür.
Setup
python -m venv venv
venv\Scripts\python -m pip install -e ".[dev]"
copy .env.example .env # API-Key eintragen, nur Lese-Rechte
venv\Scripts\python -m pytestRegistrierung in Claude Code (.mcp.json im Projekt- oder Parent-Ordner):
{
"mcpServers": {
"webling": {
"command": "<absoluter-pfad>/webling-mcp/venv/Scripts/python.exe",
"args": ["-m", "webling_mcp.server"]
}
}
}Sicherheit
API-Key mit nur Lese-Rechten. Der Server kann nichts schreiben, der Code enthält keine Schreiboperationen.
Keine Persistierung von Mitgliederdaten im MCP-Server, kein Cache
Kein PII in Logs, nur Zähler und Fehlertypen
Lizenz
MIT, siehe LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Read-only Wikidata tools and identity evidence. Local optional Google KG; bounded public remote.
Text-to-SQL MCP server: read-only queries on PostgreSQL, MySQL and SQL Server with your real schema
Query and audit AppSheet apps in natural language via Knotrik's pre-scanned definitions.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceLets Claude / ChatGPT / Gemini interact with a dive center's data — divers, bookings, courses, invoices, equipment, waivers — via natural language.MIT
- FlicenseAqualityCmaintenanceA small MCP server that lets an LLM query PostgreSQL, MySQL, MariaDB, SQL Server, or SQLite databases safely — read-only, role-restricted, and with sensitive data blacked out.4-
- AlicenseAqualityAmaintenanceLocal pseudonymisation MCP server that detects PII in text, replaces it with opaque tokens before sending to cloud LLMs, and restores tokens afterward.268 npm2MIT
- AlicenseAqualityAmaintenancePrivacy-first MCP server for querying personal health and finance data with AI. Built with Python, FastMCP, and SQLite. Local-first and open source.2206MIT