Skip to main content
Glama
georoen
by georoen
README.md
<p align="center">
  <a href="https://jstaab.de/news/gdi-mcp/">
    <picture>
      <source media="(prefers-color-scheme: dark)" srcset="assets/logo-dark.svg">
      <img alt="GDI Catalogue MCP" src="assets/logo-light.svg" width="480">
    </picture>
  </a>
</p>

<h3 align="center">Geodaten per Prompt — Deutschlands Geodatenkatalog für KI-Agenten</h3>

<p align="center">
  <a href="README.md"><img alt="Deutsch" src="https://img.shields.io/badge/Deutsch-2563EB?style=for-the-badge"></a>
  <a href="README.en.md"><img alt="English" src="https://img.shields.io/badge/English-30363D?style=for-the-badge"></a>
</p>

<p align="center">
  <a href="https://de.wikipedia.org/wiki/Model_Context_Protocol"><img alt="MCP: stdio" src="https://img.shields.io/badge/MCP-stdio-2563EB?style=for-the-badge&labelColor=555555"></a>
  <a href="https://docs.geonetwork-opensource.org/3.12/api/csw/"><img alt="CSW: 2.0.2" src="https://img.shields.io/badge/CSW-2.0.2-0891B2?style=for-the-badge&labelColor=555555"></a>
  <a href="https://www.gdi-de.org/"><img alt="Zugriff: nur lesend" src="https://img.shields.io/badge/Zugriff-nur_lesend-16A34A?style=for-the-badge&labelColor=555555"></a>
  <a href="https://opensource.org/license/mit"><img alt="Lizenz: MIT" src="https://img.shields.io/badge/Lizenz-MIT-6E7781?style=for-the-badge&labelColor=555555"></a>
</p>

<p align="center">
  <a href="#installation">Installation</a> · <a href="#mcp-client-konfigurieren">Client</a> · <a href="#tools">Tools</a> · <a href="#endpunkt">Endpunkt</a> · <a href="#tests-und-einschränkungen">Tests</a> · <a href="#sicherheit-und-nutzungsbedingungen">Sicherheit</a> · <a href="https://jstaab.de/news/gdi-mcp/">Blog-Artikel ↗</a>
</p>

---

Kleiner, lesender MCP-Connector für **Geodatenkatalog.de / GDI-DE**. Nutzt ausschließlich **CSW 2.0.2** mit Dublin-Core-Ausgabe und das offizielle Python-MCP-SDK über **stdio**. Kein offizieller GDI-DE-/BKG-Dienst.

## Installation

Voraussetzungen: Python ≥3.11 und [uv](https://docs.astral.sh/uv/).

Repository klonen und im Projektverzeichnis ausführen:

```bash
uv sync --frozen
uv run --frozen python test_server.py
```

`uv.lock` enthält die aufgelösten Abhängigkeiten.

## MCP-Client konfigurieren

Im MCP-Client den Python-Interpreter und das Skript mit absoluten Pfaden registrieren:

```json
{
  "mcpServers": {
    "gdi-de": {
      "command": "/absolute/path/gdi-geonetwork-mcp/.venv/bin/python",
      "args": ["/absolute/path/gdi-geonetwork-mcp/server.py"]
    }
  }
}
```

Der Client startet den Prozess über stdio; kein Docker oder Port erforderlich. Bei Verschieben des Projekts Pfade aktualisieren.

Beispielprompt:

> Suche im GDI-DE-Katalog nach Lärm in Ingolstadt. Zeig mir anschließend die Metadaten und Ressourcenlinks eines Treffers.

## Tools

| Tool | Eingaben | Ausgabe |
|---|---|---|
| `search_records` | `query`, `limit` (1–50), `start` (ab 1) | Quelle, Trefferzahl, nächste Seite, Metadaten |
| `get_record` | `record_id` aus einem Treffer | Dublin-Core-Metadaten, Themen, Rechte, Ressourcenlinks, Metadaten-Bounding-Boxes |

`search_records` nutzt CSW `GetRecords`, `get_record` nutzt `GetRecordById`. `query` ist eine Wortsuche, keine rohe CQL-Abfrage. Wörter werden per AND und `AnyText LIKE` kombiniert; CQL-Wildcards `%` und `_` bleiben wirksam. `next_record=0` bedeutet Ende.

Ressourcenlinks werden **nicht** automatisch geöffnet. Ein Metadaten-Footprint beweist keine lokale Datenabdeckung. Keine Downloads, Kartenanalyse, räumliche Suchparameter, Schreibfunktionen, Uploads oder Harvesting.

## Endpunkt

Standard: `https://gdk.gdi-de.org/gdi-de/srv/ger/csw`.

Für einen anderen CSW-Katalog `CSW_URL` in der Prozessumgebung setzen (im obigen Client-Beispiel über `env`). Die URL wird ausschließlich vom Betreiber konfiguriert, nicht als Tool-Parameter angeboten. Andere Kataloge sind nicht getestet; CSW 2.0.2 und Dublin-Core-Ausgabe müssen unterstützt werden.

## Tests und Einschränkungen

Offline-Tests prüfen Eingabevalidierung, CQL-Escaping, Metadaten, Pagination, XML-Sicherheit und Antwortgrößenlimit.

```bash
uv run --frozen python test_server.py --live
```

`--live` startet einen echten MCP-Prozess und prüft Suche, Record-Abruf, Pagination und Toolfehler; Internet nötig. Timeouts oder andere Anbieterfehler werden nicht als Erfolg gewertet.

**Livetest bestanden:** GDI-DE-CSW-Suche „Lärm Ingolstadt“ mit 17 Treffern, Record-Abruf, Pagination und Toolfehler über MCP stdio geprüft. Frühere Tests liefen zeitweise in CSW-Suchtimeouts; die Verfügbarkeit hängt vom Anbieter ab. Es gibt keinen alternativen Suchpfad oder automatischen Fallback.

## Sicherheit und Nutzungsbedingungen

HTTP-Zeitlimit 30 Sekunden, maximal 5 MiB Antwort, keine automatischen Redirects oder Wiederholungen. Sichere XML-Verarbeitung ohne DTD/Entities. Katalogfehler und ungültige Eingaben erscheinen als MCP-Toolfehler. Keine Credentials erforderlich oder gespeichert; geschützte Kataloge werden nicht unterstützt.

GDI-DE stellt die Kataloginhalte [über standardisierte Schnittstellen zur freien Verfügung](https://www.gdi-de.org/praxis-projekte/servicefunktionen/geodatenkatalog-de). Daraus folgt keine pauschale Freigabe der verlinkten Geodaten. Für deren Nutzung gelten die jeweiligen Anbieterbedingungen; Quellenvermerke und rechtliche Hinweise beachten. Leere Rechtefelder sind keine Nutzungserlaubnis.

TDQS

A4.2/5.0

Scored across 2 tools

Disambiguation5/5

search_records is for discovery via keywords and pagination, while get_record retrieves a specific record by its exact ID. The two purposes are clearly separated with no overlap, so an agent can easily choose the correct tool.

Naming Consistency5/5

Both tools follow a consistent snake_case verb_noun pattern: search_records and get_record. The plural/singular noun difference reflects the operation (search many vs. get one) and does not break the pattern.

Tool Count3/5

With only two tools, the surface feels thin for a CSW catalogue even though the two provided operations are focused. The count is borderline per the rubric for 1–2 tools, lacking additional conveniences like capabilities or spatial search.

Completeness4/5

The core read-only lifecycle of discovery (search) and retrieval by ID (get_record) is fully covered, including pagination hints. Minor gaps remain, such as no direct spatial/bbox search or get_capabilities operation, but agents can work around these using keyword search.

Maintenance

ActivityMaintained
ResponsivenessNo issues