{
  "markdown": "Deutsch | [English](./README.en.md)\n\n# InfraNode\n\n[![GitHub stars](https://img.shields.io/github/stars/street1983nk/infranode?style=flat&logo=github)](https://github.com/street1983nk/infranode/stargazers)\n[![License: Apache 2.0](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](./LICENSE)\n[![Glama score](https://glama.ai/mcp/servers/street1983nk/infranode/badges/score.svg)](https://glama.ai/mcp/servers/street1983nk/infranode)\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-dev.infranode%2Finfranode-1f6feb)](https://registry.modelcontextprotocol.io)\n[![Smithery](https://img.shields.io/badge/Smithery-infranode-7c3aed)](https://smithery.ai/server/infranode/infranode)\n\n**Die Open-Data-REST-API für Deutschland: eine HTTP-API ohne API-Key für Open\nData zur öffentlichen Infrastruktur, auch als MCP-Server verfügbar.**\n\nDeutsche Städte veröffentlichen viel Open Data, aber jede Quelle hat ihr eigenes\nFormat, eigene Felder und eigene Eigenheiten, und für mehrere braucht es eine\nRegistrierung im jeweiligen Portal. InfraNode normalisiert rund 20 Kategorien,\nWetter (DWD), Luftqualität (UBA), ÖPNV (inklusive Echtzeit-Abfahrten), Verkehr,\nStrompreis (SMARD), Bodenrichtwerte (BORIS), Parken, Ladeinfrastruktur,\nPegelstände, Demografie, Energie und mehr, für **84+ deutsche Städte** hinter\n**einer** Schnittstelle. **Kein API-Key, kein Konto.** Jede Antwort nutzt\ndenselben kanonischen `{ data, meta }`-Umschlag mit Lizenz und Attribution je\nDatensatz. Dieselben Daten stehen KI-Agenten auch als MCP-Server zur Verfügung\n(12 schlanke Read-only-Tools über 78 Datenarten).\nDer Einstieg ist `get_city_overview`, ein einziger Aufruf: Er liefert einen\nKatalog aller Datenarten, die es für eine Stadt gibt, dazu einen Live-Auszug der\nwichtigsten Werte. So sehen Agenten die volle Breite und nicht nur das Wetter.\nInfraNode wächst laufend, neue Datenarten und Städte kommen regelmäßig dazu.\n\nZu den Quellen gehören der Deutsche Wetterdienst (DWD), das Umweltbundesamt\n(UBA), Mobilithek/DELFI, der VBB (Verkehrsverbund Berlin-Brandenburg, CC-BY 4.0),\nGovData, OpenStreetMap, die Bundesnetzagentur, das KBA und weitere.\n\n## Im Einsatz\n\n[![InfraNode-Live-Übersicht für Köln: aktuelles Wetter, amtliche Luftqualität, DWD-Warnungen, Live-Zugabfahrten mit Verspätungen, Baustellen und der vollständige Katalog der Datenarten, alles aus einem Aufruf ohne API-Key](https://infranode.dev/showcase/koeln-live-dashboard.png)](https://infranode.dev)\n\n*Ein einziger `get_city_overview(\"koeln\")`-Aufruf: aktuelles Wetter, amtliche\nLuftqualität, DWD-Warnungen, Live-Zugabfahrten mit Verspätungen, Baustellen und\nder vollständige Datenkatalog der Stadt, aus einem Endpoint ohne API-Key. Jede\nStadt lässt sich live ausprobieren auf\n[infranode.dev](https://infranode.dev).*\n\n## So funktioniert es\n\nEin gemeinsamer HTTP-Client fragt die Upstream-Quellen ab, jede Antwort wird auf\ndas kanonische Schema abgebildet, mit ihrer Attribution durch das Lizenz-Gate\ngeführt und in Redis zwischengespeichert (mit Stale-on-Error-Fallback), danach\nüber eine REST-API und einen MCP-Server ausgeliefert. Fällt eine Quelle aus,\nschlägt sich das in `source_status` nieder. Der Aufruf selbst scheitert nie\ndaran.\n\n```mermaid\nflowchart LR\n    subgraph SRC[\"25+ deutsche Open-Data-Quellen\"]\n        direction TB\n        S1[\"DWD, UBA<br/>Wetter, Luft\"]\n        S2[\"Mobilithek, DELFI, DB<br/>ÖPNV, Echtzeit\"]\n        S3[\"SMARD, BNetzA, MaStR<br/>Energie\"]\n        S4[\"BORIS, GovData, OSM,<br/>KBA, ...\"]\n    end\n\n    subgraph CORE[\"InfraNode-Kern\"]\n        direction TB\n        N[\"Normalisieren<br/>ein kanonisches Schema\"] --> L[\"Lizenz-Gate<br/>Attribution je Datensatz\"] --> C[\"Redis-Cache<br/>Stale-on-Error-Fallback\"]\n    end\n\n    SRC --> CORE\n    CORE --> API[\"REST-API<br/>infranode.dev/api/v1<br/>84 Städte, ohne API-Key\"]\n    CORE --> MCP[\"MCP-Server<br/>mcp.infranode.dev<br/>12 Read-only-Tools\"]\n    API --> APPS[\"Apps &amp; Dashboards\"]\n    MCP --> AGENTS[\"KI-Agenten<br/>Claude, ChatGPT\"]\n```\n\n> Wenn InfraNode dir eine Datenintegration erspart: Ein Stern hilft anderen Entwicklern, das Projekt zu finden.\n\n## Schnellstart\n\nBasis-URL `https://infranode.dev/api/v1`. Kein Key, kein Konto, einfach\naufrufen:\n\n```bash\ncurl https://infranode.dev/api/v1/cities/koeln/weather\n```\n\n```jsonc\n{\n  \"data\": {\n    \"city_slug\": \"koeln\",\n    \"observed_at\": \"2026-06-18T13:00:00Z\",\n    \"source\": \"dwd\",\n    \"attribution\": { \"text\": \"Datenbasis: Deutscher Wetterdienst\", \"modified\": true },\n    \"payload\": { \"kind\": \"weather\", \"temperature_c\": 30.4, \"humidity\": 43.0, \"station_id\": \"02667\" }\n  },\n  \"meta\": { \"source_status\": \"ok\", \"cache_status\": \"hit\", \"correlation_id\": \"...\" }\n}\n```\n\nJede Antwort folgt demselben `{ data, meta }`-Umschlag: Jeder Datensatz trägt\nseine `attribution` (Lizenz und Quelle), und `meta.source_status` sagt, ob die\nUpstream-Quelle Daten geliefert hat. Eine tote Quelle degradiert damit sauber,\nstatt den Aufruf scheitern zu lassen.\n\nÜber alle Datenarten hinweg sind Feldnamen snake_case und englisch, und dasselbe\nKonzept heißt immer gleich: `post_code`, `street`, `house_number`, `place`,\n`name`, `start`, `end`, `distance_km`, `power_kw`, `lat`, `lon`. `post_code` ist\nimmer ein fünfstelliger String (führende Nullen bleiben erhalten), Zeitstempel\nsind ISO 8601 mit Zeitzone, und ein Wert, den die Quelle nicht liefert, ist\n`null`, nie ein leerer String. Manche Antworten führen daneben noch ältere\nDoppelnamen mit identischen Werten (`plz`, `zip`, `strasse`, `hausnummer`, `ort`,\n`city`, `bezeichnung`, `beginn`, `ende`, `art`, `dist_km`, `leistung_kw`,\n`einheit_typ`, dazu die camelCase-Rohfelder der Autobahn-Verkehrsmeldungen).\nDiese Namen sind veraltet, nimm die kanonischen.\n\n> Tipp: Ruf zuerst `/api/v1/cities` auf, um die kanonischen Stadt-Slugs zu\n> finden (etwa `koeln`, `berlin`, `hamburg`), und danach einen stadtbezogenen\n> Endpoint.\n>\n> Der `{slug}` wird tolerant aufgelöst, die exakte ASCII-Form brauchst du also\n> selten: der deutsche Name mit oder ohne Umlaute, jede Groß- und\n> Kleinschreibung, gängige englische Exonyme und Kurzformen führen alle auf den\n> kanonischen Slug (`München`/`münchen`/`munich`/`munchen` → `muenchen`,\n> `cologne` → `koeln`, `frankfurt` → `frankfurt-am-main`). Ein unbekannter Name\n> liefert `404` mit dem Hinweis `Meintest du ...?`, der den nächstliegenden Slug\n> nennt.\n\n[![Run in Postman](https://run.pstmn.io/button.svg)](https://god.gw.postman.com/run-collection/55901679-26601800-bf9d-4ddd-8413-5f273f18be4d)\n\nDie vollständige interaktive Referenz und die Abdeckung je Stadt stehen auf\n[infranode.dev](https://infranode.dev). Die\n[InfraNode API im Postman API Network](https://www.postman.com/alster83-7133231/infranode/overview)\nspiegelt jeden Endpoint mit echten Beispielantworten, sodass sich die\n[InfraNode API Postman Collection](https://www.postman.com/alster83-7133231/infranode/collection/pft781f/infranode-api)\nohne API-Key direkt im Browser ausprobieren lässt.\n\n<!-- Die Endpunktzahl stammt aus docs/openapi.yaml (eine operationId je Operation).\n     Sie muss synchron bleiben: docs-site/scripts/check-endpoint-count.mjs prüft das. -->\n## Daten (84 Städte, 124 Endpunkte)\n\nJede Kategorie unten ist ein REST-Endpoint unter\n`/api/v1/cities/{slug}/<key>`. Über MCP kommen dieselben Daten durch 12 schlanke\nTools: ein paar benannte (`get_city_overview`, `weather`, `air_quality`, `pois`,\n`compare`, die Live-Tafeln) und ein generisches\n`get_city_resource(slug, resource=<key>)` für jede weitere Datenart (sein\n`resource`-Enum listet alle 81 Keys).\n\n| Gruppe | Datenarten (Endpoint-Keys) |\n|--------|----------------------------|\n| **Entdecken** | `list_cities`, `sources`, `compare` (eine Datenart über viele Städte), `overview` (Katalog plus Live-Auszug in einem Aufruf) |\n| **Wetter & Umwelt** | `weather`, `weather-warnings`, `civil-protection-warnings` (BBK NINA), `air-uba` (amtlich), `air` (live), `pollen-uv`, `water-level`, `flood`, `fire-danger`, `bathing-water` |\n| **Mobilität** | `transit`, Live-Abfahrten je Haltestelle (Tool `transit_departures`), `stations` (Katalog), Bahnhofstafeln nach EVA (Tools `station_board_departures`/`station_board_arrivals`, inklusive Nahverkehr und Störungen), `station-departures`, `station-arrivals`, `traffic`, `road-events`, `webcams`, `charging`, `parking` (Live-Belegung), `parking-onstreet`, `park-and-ride`, `mobility-points`, `bike-parking`, `sharing`, `fuel-prices`, `bike-counts` |\n| **Stadt & Menschen** | `base`, `geo`, `demographics`, `indicators`, `sustainability` (SDG-Indikatoren je Kommune als Zeitreihe 2006-2023, Wegweiser Kommune / Bertelsmann Stiftung, CC0), `unemployment`, `tourism`, `construction`, `accidents`, `crime-stats`, `health`, `icu-live`, `holidays`, `election`, `events`, `council-papers` (kommunale Ratsinformationen über OParl: Vorlagen, Anträge und Beschlüsse je Stadt), `pois`, Spielplätze, Märkte, Toiletten und weitere OSM-Typen |\n| **Wirtschaft & Immobilien** | `land-values`, `tax-rates` (Hebesätze für Gewerbe- und Grundsteuer je Kommune), `business-registrations` (Gründungsdynamik je Kreis), `insolvencies` (Insolvenzverfahren je Kreis: Unternehmen und übrige Schuldner, jährlich), `public-tenders` (öffentliche Vergabe: laufende Ausschreibungen und vergebene Aufträge je Stadt) |\n| **Energie & Fahrzeuge** | `power-load`, `power-price`, `energy`, `solar`, `solar-roofs`, `district-heating`, `vehicle-registrations` |\n\n## Verhalten im Betrieb\n\n- **Ohne Key, nur lesend.** Keine Zugangsdaten, keine Schreibzugriffe, keine Nutzerkonten.\n- **Kanonischer Umschlag.** `{ data, meta }` mit Status und Attribution je Quelle.\n- **Sanfte Degradation.** Eine ausgefallene Quelle liefert `source_status`, keinen Fehler.\n- **Sicher entworfen.** SSRF- und Injection-Gates prüfen jede Anfrage, Eingaben laufen gegen feste Allowlists.\n\nDas Sicherheitsmodell steht in [SECURITY.md](./SECURITY.md).\n\n### Paginierung & Kanal-Voreinstellungen\n\nListen von Datenarten (`charging`, `energy`, `events`, `transit`, die\nOSM-Feature-Endpoints) haben bei gleicher URL eine **kanalabhängige\nVoreinstellung**:\n\n- **Direktes REST** liefert die **vollständige** Liste in einem Aufruf (`limit=null`, `returned == total`, `truncated=false`).\n- **GPT Actions** (OpenAI-Header) und **MCP** sind an eine voreingestellte Seitengröße **gebunden**, damit Antworten für Agenten klein bleiben.\n- **`limit=all`** (oder `?all=1`) erzwingt auf jedem Kanal die volle Liste, `limit` und `offset` blättern explizit.\n- **`meta.pagination`** (`total/returned/limit/offset/truncated`) steht auf jedem Kanal, der ausgelieferte Ausschnitt ist also immer nachvollziehbar.\n\nBei `traffic` ist die rohe Polyline optional: `include=geometry` (oder `?full=1`)\nergänzen, die Standardantwort bleibt schlank.\n\n### Stabilität, Changelog & Roadmap\n\nDu baust produktiv auf InfraNode auf? Dann bleib bei Änderungen vorne:\n\n- **[Changelog](https://infranode.dev/changelog/)** listet jede sichtbare Änderung (neue Datenarten, neue Städte, geändertes Verhalten, Fehlerbehebungen, Deprecations), die neueste zuerst. Per [RSS](https://infranode.dev/changelog/feed.xml) abonnierbar.\n- **[Roadmap](https://infranode.dev/roadmap/)** zeigt das Geplante und die Stabilitätszusage: Die API wächst additiv, der Umschlag bleibt stabil, und Änderungen an bestehenden Antworten werden vorher angekündigt (in der Regel 30+ Tage).\n- **[Statusseite](https://status.infranode.dev)** und die GitHub-Releases decken Verfügbarkeit und versionierte Änderungen ab.\n\n## Als MCP-Server nutzen\n\nDieselbe API steht als Remote-MCP-Server bereit, KI-Agenten können also alle 78\nDatenarten als Tools aufrufen. Mit Claude Code genügt eine Zeile:\n\n```bash\nclaude mcp add --transport http infranode https://mcp.infranode.dev/mcp\n```\n\nJeden anderen MCP-Client richtest du auf denselben Remote-Endpoint (Streamable\nHTTP):\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"infranode\": { \"url\": \"https://mcp.infranode.dev/mcp\" }\n  }\n}\n```\n\n- **Cursor / Windsurf:** den Block oben in `~/.cursor/mcp.json` eintragen (oder in die MCP-Einstellungen der App).\n- **VS Code:** `code --add-mcp '{\"name\":\"infranode\",\"url\":\"https://mcp.infranode.dev/mcp\"}'`\n- **Claude Desktop:** denselben `mcpServers`-Block in die `claude_desktop_config.json` eintragen.\n- **ChatGPT:** einen Connector mit der URL `https://mcp.infranode.dev/mcp` anlegen.\n\nAlle Tools tragen die Annotationen `readOnlyHint: true` /\n`destructiveHint: false` / `idempotentHint: true`, MCP-Clients können sie also\ngefahrlos automatisch freigeben. Die MCP-Schicht bringt außerdem fertige\n**Prompts** (`city_briefing`, `compare_air_quality`, `commute_check`) und\n**Ressourcen** (`infranode://cities`, `infranode://sources`) mit. Die\nvollständige Installationsanleitung, das komplette Tool-Manifest mit\nBeispielausgaben, das Berechtigungsmodell und ein Beispiel-Transkript stehen in\n[docs/mcp-install.md](./docs/mcp-install.md). Das Registry-Manifest ist\n[server.json](./server.json).\n\n## In ChatGPT nutzen (Custom-GPT-Action)\n\n**Fertiges GPT:** [InfraNode: German City Data - Weather & Transit](https://chatgpt.com/g/g-6a48bf065e648191b062bc86256c1897-infranode-german-city-data-weather-transit)\nsteht im GPT Store (Research & Analysis) und funktioniert sofort.\n\nFür eine eigene Variante liefert InfraNode eine kuratierte OpenAPI-Spec für\nGPT-Actions: 23 der nützlichsten Operationen (ChatGPT erlaubt höchstens 30 pro\nAction), ohne Key, alle GET.\n\n1. Im [GPT-Editor](https://chatgpt.com/gpts/editor) **Configure → Actions →\n   Create new action → Import from URL** öffnen und\n   `https://infranode.dev/actions/openapi.json` einfügen.\n2. Die Authentifizierung auf **None** stehen lassen, als Datenschutzerklärung\n   `https://infranode.dev/datenschutz/` eintragen.\n3. In den Instructions des GPT festhalten: mit `getCityOverview(slug)` starten,\n   Stadtnamen über `getCities` auflösen und `data.attribution` zitieren (die\n   Datenlizenzen verlangen die Namensnennung).\n\nDetails und empfohlene Instructions:\n[infranode.dev/chatgpt/](https://infranode.dev/chatgpt/). Die Spec wird von\n`scripts/build_actions_spec.py` aus `docs/openapi.yaml` erzeugt.\n\n## Alternativen und wie InfraNode dazu steht\n\nAndere MCP-Server decken Teile des deutschen oder europäischen Datenraums ab.\nFür Open Data auf Stadtebene ist InfraNode am breitesten, und die Projekte unten\nergänzen einander oft:\n\n- **[germany-mcp-server](https://github.com/AiAgentKarl/germany-mcp-server)** Bundes- und Regierungsdaten (Autobahn, DWD, NINA, SMARD, Bundestag). Bundesweit, ohne Tiefe je Stadt.\n- **[db-mcp-server](https://github.com/PaulvonBerg/db-mcp-server)** / db-timetable-mcp nur Fahrpläne der Deutschen Bahn.\n- **[mcp-server-public-transport](https://github.com/mirodn/mcp-server-public-transport)** ÖPNV in Europa, in Deutschland deckt es Berlin/Brandenburg (VBB) ab.\n- **Server für einzelne Städte** (etwa München, Berlin) decken je eine Stadt ab.\n\nInfraNode deckt **84 deutsche Städte und 82 Datenarten** hinter einem\ngehosteten Endpoint ohne API-Key ab: Umwelt, Mobilität, Energie, Wirtschaft und\nStadtleben. Der vollständige Vergleich Seite an Seite steht auf\n[infranode.dev/mcp-vergleich](https://infranode.dev/mcp-vergleich/).\n\n## Selbst hosten (optional)\n\nNötig ist das nicht, der gehostete Endpoint oben ist der schnellste Weg. Der\nCode liegt aber offen. Den API-Stack lokal mit Docker (Compose v2) starten:\n\n```bash\ncp .env.example .env          # example config, contains NO real secrets\ndocker compose -f deploy/docker-compose.yml up\ncurl http://localhost/api/v1/health   # -> {\"status\":\"ok\",\"version\":\"1.0.0\",\"redis\":true}\n```\n\nDen MCP-Server selbst lokal über stdio betreiben (gegen die öffentliche API):\n\n```bash\nuv sync --group mcp\nINFRANODE_MCP_API_BASE=https://infranode.dev/api/v1 uv run python -m infranode.mcp.server\n```\n\nFür alle Einstellungen gilt das Env-Präfix `INFRANODE_` (siehe `.env.example`),\njede Datenquelle hat ihren eigenen `INFRANODE_ENABLE_*`-Schalter. Echte Secrets\nlanden nie im Repo, versioniert ist nur `.env.example`, und die CI fährt einen\ngitleaks-Scan.\n\n## Lizenz: Code und Daten sind getrennt\n\n- **Code:** Apache-2.0 (siehe [LICENSE](./LICENSE)).\n- **Daten:** Die offenen Daten, die InfraNode ausliefert, behalten die Lizenzen\n  ihrer Upstream-Quellen (etwa ODbL für OpenStreetMap, DL-DE-BY für GovData,\n  Namensnennung für DWD). Diese Datenlizenzen und die Attribution werden separat\n  in `DATA-LICENSES.md` geführt. Die Apache-2.0-Lizenz gilt nur für den\n  Quellcode der API, nicht für die durchgereichten Daten.\n\n## Mitmachen\n\nBeiträge sind willkommen. Setup, Gate-Befehle und die Secret-Regel stehen in\n[CONTRIBUTING.md](./CONTRIBUTING.md). Für eine neue Datenquelle ist die\ndeklarative Quellen-Registry in `src/infranode/registry/source_specs.py` der\nStartpunkt (ein `SourceSpec`-Eintrag je Upstream), die vollständige Checkliste\nsteht in CONTRIBUTING.md.\n",
  "bytes": 16760,
  "sha": "730cbe01cde43c1830f8cd69391802242602a10949feda2055e33afb6df4ef3f",
  "repo_slug": "street1983nk/infranode",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_dev_infranode_infranode_30f70373/readme"
}