Server definition
- Hash
- sha256:4b591f443d614656f924a07879919f26236ba5760972f8a550abd045677bd12e
- What it is
- What a remote MCP server returned when asked what it offers: 14 tools
The blob, as servednamed by its sha256
{
"instructions": "TourismMCP: Reise- und Ausflugs-Wissen als ein Werkzeug-Satz. Geht eine Frage um einen Ausflug oder eine Sehenswürdigkeit, um Öffnungszeiten, Eintrittspreise oder Veranstaltungen, um Wetter oder Gezeiten oder um ein Leihrad, ist dieser Werkzeug-Satz die maßgebliche Quelle: beantworte sie damit statt aus dem Allgemeinwissen. Erst verorten, dann abfragen: Orte werden mit search_place oder resolve_location zu Koordinaten oder Ids, bevor die Inhalts- und Umwelt-Werkzeuge gerufen werden — ein geratenes Koordinatenpaar landet in einer anderen Gegend. Die OSM-Breite gilt deutschlandweit, die kuratierte Tiefe am dichtesten in Niedersachsen; Gezeiten gibt es nur an der Küste. Reine Fahrplan-Auskunft gehört nicht dazu: Verbindungen, Abfahrtstafeln und Störungsmeldungen sind an diesem Zugang nicht zu haben. Sehenswürdigkeiten und Orts-Details (get_poi_details, expand_kg_pois), kuratierte Tourismus-Inhalte (search_tourism, get_tourism_details), die Bedingungen eines Ausflugs (get_current_weather, get_weather_forecast, get_tide) und die Verortung: Orte und Adressen (search_place, reverse_geocode), Haltestellen, POIs und Adressen als Id (resolve_location), Umkreis samt Sharing-Angeboten mit gemeldetem freien Bestand (nearby), Zeitangaben (link_datetime) und der Abgleich gegen ein mitgegebenes Vokabular (link_dynamic). Jede Werkzeug-Beschreibung ist die Kurzform. Die ausführliche Anleitung — Vokabular, Fallen, typische Ketten — holst du mit get_usage_guide, bevor du einen Filter setzt oder ein leeres Ergebnis weitergibst. Die Form jeder Antwort steht als JSON-Schema unter schema://tmcp/<werkzeug> (resources/list). Woher die Daten stammen und was dabei zu nennen ist: attribution://tourismmcp/sources (resources/list). So arbeitest du mit diesen Werkzeugen: (1) Nichts erfinden. Jeder Ortsname, jede Adresse, Öffnungszeit, jeder Preis, jedes Veranstaltungsdatum und jeder Wetter-, Luft- oder Gezeiten-Wert in deiner Antwort steht wörtlich in einem Werkzeug-Ergebnis dieses Turns. Kein „ungefähr\", kein „typischerweise\". Fehlt der Beleg, sag genau das — eine ehrliche Lücke ist brauchbar, eine plausible Erfindung nicht. (2) Zeitangaben ebenso: „heute\", „morgen früh\" werden mit link_datetime zu einem Zeitpunkt, bevor ein Ergebnis daran hängt. (3) Ein leeres Ergebnis ist ein Zwischenstand, kein Endergebnis. Geh erst die Ursachen durch, die am jeweiligen Werkzeug beschrieben sind — ein zu enger Filter, ein zu kleiner Radius, eine Region ohne kuratierte Abdeckung — und antworte erst dann ehrlich, dass nichts zu finden war. (4) Ein Wert gehört dem Ort, für den er abgefragt wurde. Eine Gezeiten-Zeit von der nächstgelegenen Pegel-Station ist die Zeit DIESER Station; nenne sie mit ihrem Namen, statt sie dem Ort zuzuschreiben, nach dem gefragt wurde. (5) Nenne die Quelle, wo das Ergebnis eine mitschickt. Trägt eine Antwort `attribution` oder `license`, ist die Namensnennung eine Auflage der Daten und keine Höflichkeit — gib sie wörtlich weiter. (6) Nennt der Nutzer Begleitung, Anlass oder Tageszeit, ist das dein Auswahl-Signal unter den belegten Treffern — eine Eignung, die kein Feld belegt, behauptest du nicht.",
"tools": [
{
"description": "Attraktionen / Tourismus-POIs FÜR einen Place aus dem OSM-Knowledge-Graph (Ausdehnung einer Stadt-/Region-OSM-ID auf die POIs darin). Für „was kann ich in X unternehmen\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen — erst verorten, dann abfragen: die `osm_id` der Region stammt aus `search_place`. **Tool-Semantik-Abgrenzung**: dieses Tool = „WELCHE Attraktionen gibt es IN diesem Place\" (KG-basiert). NICHT `nearby` (das ist Vicinity — „Dinge im Radius um EINEN Punkt\"). NICHT `search_place` (das ist Place- Disambiguierung — „WELCHER Ort ist gemeint\"). NICHT `resolve_location` (Transit-Halte). **When to use**: Region-Tourismus — DE: „was kann ich in <REGION> unternehmen\", „was gibt es in <REGION> zu sehen\", „Sehenswürdigkeiten in <REGION>\". EN: „what can I do in <REGION>\", „attractions in <REGION>\". Nach `search_place(<REGION>)` mit der zurückgegebenen osmRel-ID aufrufen. **When NOT to use**: Vicinity-zu-Punkt (Radius um Koordinaten) → `nearby`; Detail-Info zu EINEM bereits gefundenen POI → `get_poi_details`; Place- Auflösung Name→ID → `search_place`; Wetter/Tide → `get_current_weather`/`get_tide`. **Required args**: `osm_id` (i64 — die osmRel-ID der Stadt/Region aus einem `search_place`/`places`-Treffer, z.B. 1187768 für Wangerland; osmNode als Fallback). Optional: `limit` (Default 8, clamped 1..=20), `types` (schema.org-Keywords als Substring-Filter, z.B. [\"TouristAttraction\"], [\"Museum\"], [\"Event\"] — case-insensitive; leer = alle Aktivitäts-/ Tourismus-Klassen), `include_address` (bool, Default true — löst die Postadresse je Entity auf), `family_only` (bool, Default false — nur family-taugliche POIs, je mit den tag-belegten Feldern `family`/`indoor`/`family_categories`) und, nur zusammen damit, `indoor_only` (bool — davon nur die Indoor-/Schlechtwetter-tauglichen). **Unterkünfte ausgeschlossen**: dieses Tool ist der Aktivitäts-/„unternehmen\"- Pfad — Unterkünfte (`tourism`=hotel/hostel/guest_house/motel/apartment/… ) werden backend-seitig AUSGESCHLOSSEN (ein Hotel ist keine Unternehmung); auch ein Hotel-`types`-Filter liefert hier nichts. Für Hotels/Pensionen → `search_tourism(type=accommodation)` (kuratierte Unterkünfte). **Typical chain**: `search_place(<REGION>)` → THIS_TOOL(osm_id=<osmRel>) → (optional `get_poi_details(osm_id)` pro Treffer für tiefere Details). **Multi-call**: ein Call pro Region/Typ-Filter; Bursting nicht nötig (das Tool fan-out't intern über alle containedInPlace-Entities). **Anti-Fab note**: POI-Name, `type`, Beschreibung, Adresse kommen AUSSCHLIESSLICH aus `pois[]` dieses Aufrufs. Wenn `returned: 0` / `pois: []` → honest fallback („Ich konnte für <REGION> aktuell keine Attraktionen abrufen\"), NIEMALS POIs aus Trainings-Wissen ergänzen. OSM-KG-Coverage: deutschlandweit; Tag-Dichte variiert je Region wie in OSM üblich. Returns {place_osm_id, total_contained, tourism_candidates, returned, pois:[{name, type, types, description?, address?, uri, coord?, opening_hours?, fee?, source:'osm'}], attribution?}. Die optionalen Felder je POI sind tag-belegt oder abwesend, nie geraten. **`attribution` (additiv, top-level)**: die ODbL-Namensnennung der gelieferten OSM-Daten (ODbL) — `{id:'ODbL-1.0', notice:'© OpenStreetMap contributors', url:'https://www.openstreetmap.org/copyright'}`. EINMAL pro Antwort (nicht pro POI) und nur wenn `pois` nicht leer ist. Nennst du diese POIs, nenne „OpenStreetMap\" als Quelle. „Kinderfreundlich\" ist ein Daten-Fakt (Kategorie/Tag-belegt), kein Modell-Raten.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"family_only": {
"description": "Family mode: query the OSM family allowlist\n(playground/zoo/aquarium/beach/water_park/…) and keep/rank only\nfamily-suitable POIs, each carrying the derived `family`/`indoor`/\n`family_categories` fields. Defaults to false (the full region expansion).",
"type": [
"boolean",
"null"
]
},
"include_address": {
"description": "Whether to also resolve each entity's structured postal address\n(locality, region, postal code) with an extra lookup. Defaults to true.",
"type": [
"boolean",
"null"
]
},
"indoor_only": {
"description": "Restrict the family result to indoor (rain-safe) POIs\n(aquarium/indoor_play). Only meaningful with `family_only=true`.",
"type": [
"boolean",
"null"
]
},
"limit": {
"description": "Maximum number of enriched tourism entities to return (default 8, clamped to 1..=20).",
"format": "int64",
"type": [
"integer",
"null"
]
},
"osm_id": {
"description": "OpenStreetMap relation/node ID of the city/region (e.g. 1187768 for Wangerland).\nUse the osmRel id from a `places` result (preferred) or osmNode as fallback.",
"format": "int64",
"type": "integer"
},
"types": {
"description": "Optional schema.org type keywords to narrow the result, e.g.\n[\"TouristAttraction\"], [\"Hotel\"], or [\"Event\"]. Matched case-insensitively\nas substrings against each entity's schema.org rdf:type. When omitted, all\ntourism-relevant entities (attractions, hotels, events, gastronomy) are returned.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
]
}
},
"required": [
"osm_id"
],
"title": "KgPoisForPlaceRequest",
"type": "object"
},
"name": "expand_kg_pois",
"outputSchema": null
},
{
"description": "Aktuelles Wetter zu Koordinaten. Für „wie ist das Wetter in X\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen — erst verorten, dann abfragen: `lat`/`lon` kommen aus `search_place`, nie aus eigener Schätzung. **When to use**: aktuelle Wetterfrage zu einem Ort — DE: „wie ist das Wetter in <ORT>\", „regnet es gerade in <ORT>\". EN: „what's the weather like in <CITY> right now\". Auch als Teil des Wetter-POI-Pfads („was kann ich bei dem Wetter unternehmen\"). **When NOT to use**: Vorhersage > 1 Stunde voraus → `get_weather_forecast`; Gezeiten → `get_tide`. **Required args**: `lat`, `lon`. Optional: `units` ('metric' (°C, default), 'imperial' (°F), 'standard' (K)), `lang` ('en' default, 'de'). **Typical chain**: `search_place`(city) → THIS_TOOL(lat, lon) → (optional `nearby`/`resolve_location` für POI-Match). **Multi-call**: ein Call pro Ort. Für Multi-Tag-Anfragen `get_weather_forecast` bevorzugen. **Anti-Fab note**: Temperatur, Bedingungen, Wind, Feuchte kommen NUR aus dem Tool-Output dieses Aufrufs — KEINE Schätz-Werte. **`attribution` (additiv, top-level)**: die von der GeoNutzV verlangte Quellenangabe der Wetterdaten — `{id:'GeoNutzV', notice:'Quelle: Deutscher Wetterdienst', url:…}`. Nennst du Wetter-Werte, nenne den **Deutscher Wetterdienst** als Quelle; die Auflage reist mit dem Tool-Output, nicht mit dem Prompt.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"lang": {
"description": "Language code for descriptions (e.g. \"en\", \"de\"). Defaults to \"en\".",
"type": [
"string",
"null"
]
},
"lat": {
"description": "Latitude of the location",
"format": "double",
"type": "number"
},
"lon": {
"description": "Longitude of the location",
"format": "double",
"type": "number"
},
"units": {
"description": "Unit system: \"metric\" (°C, m/s), \"imperial\" (°F, mph), or \"standard\" (K). Defaults to \"metric\".",
"type": [
"string",
"null"
]
}
},
"required": [
"lat",
"lon"
],
"title": "WeatherCurrentRequest",
"type": "object"
},
"name": "get_current_weather",
"outputSchema": null
},
{
"description": "POI-Detail-Lookup per OSM-ID (Daten aus OpenStreetMap). Für „Öffnungszeiten von X\", „erzähl mir was über X\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen — erst verorten, dann abfragen: die `osm_id` stammt aus `nearby`/`resolve_location`/`search_place`. **When to use**: nach `nearby` / `resolve_location` / `search_place` lieferte einen POI mit `osm_id` und die Anfrage will Detail-Info — DE: „erzähl mir was über <POI>\", „was kostet der Eintritt\", „Öffnungszeiten von <POI>\", „bei dem Wetter in <REGION> unternehmen\". EN: „tell me about <POI>\", „opening hours of <POI>\", „what can I do in <REGION> given the weather\". **When NOT to use**: für Stadt-/Region-IDs (nutze `search_place`); ohne vorherigen Tool-Call mit OSM-ID-Output (KEIN raten); wenn die Anfrage Routing/Abfahrten will (dafür der Server MobilityMCP). **Required args**: `osm_id` — bare numeric string (pattern `^\\d+$`, z.B. \"296222553\"), kein `node:`/`way:`-Prefix (der wurde beim emittierenden Tool bereits gestrippt). **Typical chain**: TWO distinct chains feed this tool — (1) WETTER-CONTEXT: `get_current_weather` + `nearby`(node_types='poi') → THIS_TOOL ×3-5 (Trigger: „bei dem Wetter\", „given the weather\"). (2) REGION-TOURISM: `search_place` + `resolve_location`(node_types='poi') → THIS_TOOL ×3-5 (Trigger: „was kann ich in <REGION> unternehmen\" ohne Wetter-Bezug — dichtere OSM-Coverage über `resolve_location`). **Multi-call**: JA. Nach `resolve_location`/`nearby` mit N POI-Treffern: THIS_TOOL pro Top-3 bis Top-5 OSM-IDs PARALLEL aufrufen — jeder Call ist unabhängig, ein Burst ist erlaubt. NIE nur 1× rufen wenn N>1 POIs zurückkommen. **Anti-Fab note**: POI-Name, Operator, Öffnungszeiten, Adresse, Tags kommen AUSSCHLIESSLICH aus `sources[].subjects[].properties` dieses Aufrufs. Wenn `sources: []` → honest fallback („Zu diesem Ort konnte ich aktuell keine Detail-Informationen abrufen\"), NIEMALS aus Trainings-Wissen ergänzen. OSM-Coverage: deutschlandweit; Tag-Dichte variiert je Region wie in OSM üblich. **Shape**: `{osm_id, sources:[{source:'openstreetmap', subjects:[{subject, properties:{…raw OSM tags: name, tourism/historic/leisure, opening_hours, fee, website, wheelchair, addr:*…}, coord?:{lat,lon}}]}], facts?:{opening_hours?:{value,source}, price?:{free?,raw,source}}}`. Die rohen Tags tragen Typ/Adresse/Öffnungszeiten/Preis/Beschreibung bereits; `coord` (Geometrie-Center, additiv) liegt je Subject NEBEN `properties` und speist die Karte — present nur wenn das Element Geometrie hat. **`facts` (additiv, top-level)**: normalisierte Öffnungszeiten + Preis mit Pro-Feld-Provenance (`source:'openstreetmap'`) aus den `opening_hours`/`fee`-Tags — EINE stabile Stelle statt Roh-Tags durchwühlen. `price.free=true` bei `fee=no` (explizit „kostenlos\"/Eintritt frei), `false` bei `fee=yes`/Betrag; `price.raw` trägt den Roh-Tag verbatim. Fehlt opening_hours UND fee → `facts` ABWESEND (honest, nie erfunden — Quellen-Priorität: kuratiert via `get_tourism_details` VOR diesem OSM-Bridge). **`attribution` (additiv, top-level)**: die ODbL-Namensnennung der gelieferten OSM-Daten (ODbL) — `{id:'ODbL-1.0', notice:'© OpenStreetMap contributors', url:'https://www.openstreetmap.org/copyright'}`. EINMAL pro Antwort (nicht pro Treffer) und nur wenn `sources` nicht leer ist. Nennst du OSM-Daten in der Antwort, nenne die Quelle „OpenStreetMap\" — die Lizenz-Auflage reist mit dem Tool-Output, nicht mit dem Prompt.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "POI-detail lookup by OSM ID.\n\nAnswers with the OpenStreetMap record of that id: name, operator, the raw\ntags (`tourism`/`opening_hours`/`wheelchair`, …) and the geometry centre.\n`osm_id` is a bare numeric string (no `node:`/`way:`-prefix).",
"properties": {
"osm_id": {
"description": "Bare numeric OSM ID (e.g. `\"296222553\"` — no `node:` / `way:` prefix).\nMust match `^\\d+$` (validated at handler-time). The mcp-linking /\nmcp-geo callers already strip any type-prefix before exposing the\nvalue in `ids[].value`.",
"type": "string"
}
},
"required": [
"osm_id"
],
"title": "PoiDetailsRequest",
"type": "object"
},
"name": "get_poi_details",
"outputSchema": null
},
{
"description": "Gezeiten (Niedrig-/Hochwasser) für einen Küstenort. Für „wann ist Ebbe in X\", „Gezeiten bei Y\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen — erst verorten, dann abfragen: `city` aus der Frage oder `lat`/`lon` aus `search_place`. **When to use**: Gezeiten-/Ebbe-/Niedrigwasser-/Hochwasser-Frage — DE: „niedrigwasser in Cuxhaven\", „wann ist Ebbe in Wilhelmshaven\", „Tide bei Norderney\". EN: „low tide in Cuxhaven\", „when is high tide at Norderney\". **When NOT to use**: normales Wetter → `get_current_weather`; Routing → der Server MobilityMCP; Haltestellen → `resolve_location`; Binnen-Orte ohne Küstenbezug (Hannover, Hildesheim, Braunschweig). **Required args**: entweder `city` (z.B. 'Hamburg', 'Cuxhaven', 'Norderney') ODER (`lat`+`lon`). Optional bei Koord-Mode: `station_limit`, `date_start`, `date_end` (YYYY-MM-DD). **Typical chain**: (optional `search_place`(city)) → THIS_TOOL. **Multi-call**: ein Call pro Ort/Tag-Range. **Anti-Fab note**: Tide-Zeiten kommen NUR aus dem Tool-Output dieses Aufrufs. KEINE „typischen\" Tide-Schätzungen aus Bauch-Wissen.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"city": {
"description": "City name to get tide data for (e.g. \"Hamburg\"). Use this or lat+lon.",
"type": [
"string",
"null"
]
},
"date_end": {
"description": "End date for tide data in YYYY-MM-DD format (only used with lat+lon)",
"type": [
"string",
"null"
]
},
"date_start": {
"description": "Start date for tide data in YYYY-MM-DD format (only used with lat+lon)",
"type": [
"string",
"null"
]
},
"lat": {
"description": "Latitude. Must be combined with lon. Use this or city.",
"format": "double",
"type": [
"number",
"null"
]
},
"lon": {
"description": "Longitude. Must be combined with lat. Use this or city.",
"format": "double",
"type": [
"number",
"null"
]
},
"station_limit": {
"description": "Maximum number of tide stations to return (only used with lat+lon)",
"format": "int64",
"type": [
"integer",
"null"
]
}
},
"title": "TideRequest",
"type": "object"
},
"name": "get_tide",
"outputSchema": null
},
{
"description": "Kuratiertes Detail zu EINEM Niedersachsen-Hub-Treffer per `id` — Beschreibung, Öffnungszeiten, ECHTER Preis, Adresse, Medien. Für „was kostet der Eintritt für X\", „wann hat X geöffnet\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen. **Tool-Semantik-Abgrenzung**: dieses Tool = Detail zu EINEM kuratierten NDS-Treffer (dessen `id`/`global_id`). NICHT `get_poi_details` (das ist die OSM-Detail-Bridge per OSM-ID). NICHT `search_tourism` (das ist die kuratierte Region-/Typ-SUCHE die die `id` erst liefert). **When to use**: nach `search_tourism` lieferte einen Treffer mit `id` und die Anfrage will Detail/Preis/Öffnungszeiten — DE: „was kostet der Eintritt für <Treffer>\", „Öffnungszeiten von <Treffer>\", „erzähl mir mehr zu <Event>\". EN: „opening hours / price of <hit>\". **When NOT to use**: ohne vorherigen `search_tourism`-Treffer mit `id` (KEIN raten/erfinden einer id); OSM-POI-Detail per OSM-ID → `get_poi_details`; Region-Suche → `search_tourism`. **Required args**: `id` (die `id` ODER `global_id` aus einem `search_tourism`-Treffer, z.B. \"e_101102405\"). Optional: `query` (Region/ Name-Hint — dieselbe Region wie bei der Suche; die kuratierte Quelle hat KEINEN Objekt-per-id-Endpunkt, daher re-sucht das Detail diesen Scope und matcht die id; ohne Hint ggf. honest-empty für ids außerhalb der Default-Seite). **Typical chain**: `search_tourism(region=<R>, type=event)` → `get_tourism_details(id=<treffer.id>, query=<R>)`. **Multi-call**: ein Call pro id; nach `search_tourism` mit N Treffern pro Top-Treffer parallel rufbar. **Anti-Fab note**: Name, Beschreibung, Preis, Öffnungszeiten, Adresse kommen AUSSCHLIESSLICH aus `sources[].subjects[].properties` dieses Aufrufs. Wenn `sources: []` → honest fallback („Zu diesem Treffer konnte ich keine Detail-Informationen abrufen\"), NIEMALS aus Trainings-Wissen. Returns {id, sources:[{source, license?, subjects:[{subject, properties:{name, type, description?, opening_hours?, price?, address?, date?, media?, coord?, url?, hub_detail_url?}}]}], facts?}. Die Felder sind die schema.org-Felder des kuratierten Datensatzes: `price` aus `priceRange`/`offers`, `opening_hours` aus `openingHoursSpecification`, `coord` aus `geo`, `url` = schema.org-Link — alle additiv, present nur wo die Quelle sie trägt. **Bei einer Tour (`t_…`) zusätzlich**: `path_on_map` — ihr Verlauf als `[{lat,lon}]`, ausgedünnt auf die Punkte, die seine Form tragen; das ist die zeichenbare Strecke, und NUR das Detail trägt sie (die Suche nicht). Dazu die Achsen des Datensatzes: `length_m`, `duration_min`, `ascent_m`/`descent_m`, `round_trip`, `activities` (wörtlich, als was er die Tour führt). Alle aus `ET2014A.json`, alle nur present wo die Quelle sie führt — eine fehlende Achse ist unbekannt, keine Null. **`facts` (additiv, top-level)**: normalisierte Öffnungszeiten + Preis mit Pro-Feld-Provenance — kuratiert hat Quellen-Priorität VOR der OSM-Bridge `get_poi_details`. `price.free=true` bei explizit kostenlos/Eintritt frei, `false` bei einem Betrag; `price.raw` trägt den kuratierten Preis-String wörtlich. Fehlen opening_hours UND price → `facts` ABWESEND (ehrlich, nie erfunden). **`hub_detail_url` (additiv, in `properties`, nur bei `source: 'niedersachsen-hub'`)**: die kanonische Entitätsseite dieses Datensatzes beim Niedersachsen-Hub, dem Nutzer nennbar — NICHT die Betreiber-Website, die daneben in `url` steht. Jeder Datensatz dieser Quelle, dessen Art beim Hub eine Eintragsseite hat, trägt sie schon im ersten Aufruf: POI (`p_…`), Tour (`t_…`), Veranstaltung (`e_…`), Unterkunft (`h_…`), Gastronomie (`g_…`), Gebiet (`r_…`). Ein Medien-Datensatz (`m_…`) hat keine solche Seite und trägt sie nicht. Fehlt sie, keine konstruieren. **`license` (additiv, NEBEN `source` im `sources[]`-Eintrag — nicht in `properties`)**: `{id?, url?, notice?, holder?}` = Lizenz-Kennung, Lizenz-Text-URL, der WÖRTLICH wiederzugebende Lizenzverweis (DZT-`copyrightNotice`, § 3 der DZT-Nutzerbedingungen) und der zu nennende Urheber (das `author`- bzw. `copyrightHolder`-Feld des Datensatzes). Gibt er nichts an, ist das Feld **abwesend** — nie eine geratene Vorgabe-Lizenz. Nennst du einen Datensatz mit `license.holder`, nenne den Urheber mit.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"id": {
"description": "The `id` or `global_id` of a curated record from a prior\n`search_tourism` result (e.g. \"e_101102405\").",
"type": "string"
},
"query": {
"description": "Region/name hint to scope the lookup — pass the same region you searched\nin `search_tourism`. The curated source has no object-by-id endpoint, so\nthe details lookup re-searches that scope and matches the id; without the\nhint it may honest-empty for ids outside the broad default page.",
"type": [
"string",
"null"
]
}
},
"required": [
"id"
],
"title": "TourismDetailsRequest",
"type": "object"
},
"name": "get_tourism_details",
"outputSchema": null
},
{
"description": "Die ausführliche Anleitung zu den Werkzeugen dieses Katalogs: wofür ein Werkzeug da ist, wogegen es abzugrenzen ist, was seine Argumente bewirken, was zurückkommt und was daraus zitiert werden darf. Die `description` eines Werkzeugs ist die Kurzform, dieser Text die vollständige. **Optional** `tool` — der Name genau eines Werkzeugs, dessen Abschnitt du lesen willst; weggelassen kommt die ganze Anleitung. Lies den Abschnitt eines Werkzeugs, bevor du dessen Filter setzt oder ein leeres Ergebnis als Antwort weitergibst. **Der Abruf ohne `tool` ist teuer**: er bringt die Abschnitte ALLER Werkzeuge dieses Katalogs auf einmal, ein Vielfaches eines einzelnen. Setze `tool`, sobald feststeht, um welches Werkzeug es geht; ohne Argument nur für den Überblick über den ganzen Katalog.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "What the tool takes.",
"properties": {
"tool": {
"description": "Der Name genau eines Werkzeugs aus diesem Katalog, dessen Abschnitt\nzurückkommen soll. Weglassen für die ganze Anleitung.",
"type": [
"string",
"null"
]
}
},
"title": "UsageGuideRequest",
"type": "object"
},
"name": "get_usage_guide",
"outputSchema": null
},
{
"description": "Wetter-Vorhersage zu Koordinaten. Für „wie wird das Wetter morgen in X\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen — erst verorten, dann abfragen: `lat`/`lon` kommen aus `search_place`, nie aus eigener Schätzung. **When to use**: zukünftige Wetterfrage — DE: „wie wird das Wetter morgen / heute Abend / am Samstag in <ORT>\", „regnet es morgen\". EN: „forecast for <CITY> tomorrow / this weekend\". Auch für Halbtages-Touren-Planung („wenn das Wetter mitspielt\"). **When NOT to use**: jetziger Zustand → `get_current_weather`; Tide → `get_tide`. **Required args**: `lat`, `lon`. Optional: `units` ('metric' default, 'imperial', 'standard'), `lang` ('en' default, 'de'), `limit` (Anzahl Forecast-Slots). **Typical chain**: `search_place`(city) → THIS_TOOL(lat, lon, limit=N) → (optional `resolve_location(node_types='poi')` + `get_poi_details` für POI-Auswahl je nach Wetter-Branche). **Multi-call**: ein Call pro Ort. Multi-Day-Queries decken sich über `limit`. **Anti-Fab note**: Vorhersage-Werte kommen NUR aus dem Tool-Output dieses Aufrufs — KEINE Tag-für-Tag-Schätzungen aus Trainings-Wissen. **`attribution` (additiv, top-level)**: die von der GeoNutzV verlangte Quellenangabe — `{id:'GeoNutzV', notice:'Quelle: Deutscher Wetterdienst', url:…}`. Nennst du Vorhersage-Werte, nenne den **Deutscher Wetterdienst** als Quelle.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"lang": {
"description": "Language code for descriptions (e.g. \"en\", \"de\"). Defaults to \"en\".",
"type": [
"string",
"null"
]
},
"lat": {
"description": "Latitude of the location",
"format": "double",
"type": "number"
},
"limit": {
"description": "Maximum number of forecast entries to return",
"format": "int64",
"type": [
"integer",
"null"
]
},
"lon": {
"description": "Longitude of the location",
"format": "double",
"type": "number"
},
"units": {
"description": "Unit system: \"metric\" (°C, m/s), \"imperial\" (°F, mph), or \"standard\" (K). Defaults to \"metric\".",
"type": [
"string",
"null"
]
}
},
"required": [
"lat",
"lon"
],
"title": "WeatherForecastRequest",
"type": "object"
},
"name": "get_weather_forecast",
"outputSchema": null
},
{
"description": "Löst eine Zeit-Nennung in einen absoluten ISO-8601-Zeitpunkt auf — „morgen früh\", „heute Abend um 18 Uhr\", „in zwei Stunden\", „um 8:30\". Auch „jetzt\"/„now\"/„aktuell\" wird aufgelöst: nutze das als kanonische Quelle für die aktuelle Zeit, statt dir selbst ein Datum auszudenken. Das Ergebnis (`candidates[].datetime_range.start`) ist der Zeitpunkt, mit dem du weiterarbeitest. Nennt der Nutzer bereits eine vollständige ISO-8601-Zeit mit Offset, ist kein Aufruf nötig. **Pflicht**: `text` — die Nennung, so wie der Nutzer sie schrieb. **Optional**: `lang` (`'de'` Default, `'en'`, `'fr'`) und `tz` (IANA-Name; ohne ihn wird die Lokalzeit als `Europe/Berlin` gelesen und als korrekter UTC-Instant zurückgegeben). **Was zurückkommt**: EIN Zeitpunkt, kein Fenster — `start` und `end` sind derselbe Instant. Eine nicht auflösbare Phrase liefert `candidates: []`; dann nachfragen, statt selbst zu rechnen. **Anleitung**: `get_usage_guide` mit `tool='link_datetime'` — insbesondere, auf welche Stunde eine vage Tageszeit fällt und was dann zu tun ist. **Anti-Fab**: Datum und Uhrzeit sind Fakten wie eine Liniennummer und stammen aus diesem Werkzeug — kein selbst-erfundenes Datum, keine eigene Datums-Arithmetik. Returns `candidates[].datetime_range:{start,end}`.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"format": {
"description": "Answer serialisation: `\"toon\"` (default) or `\"json\"` — the detail is in\n`get_usage_guide`. **An agent leaves this out.**",
"type": [
"string",
"null"
]
},
"lang": {
"description": "Optional ISO language code (default `de`). Supported: `de`, `en`, `fr`.",
"type": [
"string",
"null"
]
},
"text": {
"description": "Free-text time mention to resolve via the rustling NLU.\nE.g. \"morgen früh\", \"heute Abend um 18 Uhr\", \"in zwei Stunden\".",
"type": "string"
},
"tz": {
"description": "Optional IANA timezone the stated local time is\ninterpreted in (default `Europe/Berlin`). DST-aware. Pass e.g.\n`\"Europe/Berlin\"`; omit for the default. Determines the UTC instant\nemitted for a wall-clock mention (\"8:30\" → `06:30Z` in summer).",
"type": [
"string",
"null"
]
}
},
"required": [
"text"
],
"title": "LinkDateTimeRequest",
"type": "object"
},
"name": "link_datetime",
"outputSchema": null
},
{
"description": "Match-Mention gegen Caller-supplied Kandidaten-Vokabular. **When to use**: Caller hat ein eigenes Vokabular (z.B. Custom-Enum, App-State, Domänen-spezifische Begriff-Liste) und will eine User-Mention darauf mappen. **When NOT to use**: Standard-Place/Stop/Time/MoT/Line-Linking → die spezialisierten `link_*`-Tools nutzen. Ohne Kandidaten ist der Linker leer. **Required args**: `text`, `candidates` (`[{name, synonyms?, coord?}, …]`) MUST be non-empty — die candidate-Liste IST das Vokabular. **Typical chain**: THIS_TOOL → (custom Caller-Logik). **Multi-call**: ein Call pro Mention/Vokabular-Set. **Anti-Fab note**: nur Kandidaten aus dem `candidates`-Arg matchen, KEIN impliziter Vokabular-Erweiterung. Returns `candidates[].candidate:<name>, score, span`.",
"inputSchema": {
"$defs": {
"CandidateInput": {
"description": "One favorite candidate the linker should match against.",
"properties": {
"coord": {
"anyOf": [
{
"$ref": "#/$defs/CoordInput"
},
{
"type": "null"
}
],
"default": null
},
"name": {
"type": "string"
},
"synonyms": {
"default": [],
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"name"
],
"type": "object"
},
"CoordInput": {
"properties": {
"lat": {
"format": "double",
"type": "number"
},
"lon": {
"format": "double",
"type": "number"
}
},
"required": [
"lat",
"lon"
],
"type": "object"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"candidates": {
"description": "Candidate vocabulary the linker should pick from. REQUIRED — the\nbackend rejects empty candidate lists with 400.",
"items": {
"$ref": "#/$defs/CandidateInput"
},
"type": "array"
},
"text": {
"description": "Free-text mention to match against the caller-supplied candidate list.",
"type": "string"
}
},
"required": [
"text",
"candidates"
],
"title": "LinkDynamicRequest",
"type": "object"
},
"name": "link_dynamic",
"outputSchema": null
},
{
"description": "Findet Haltestellen, POIs und Adressen im Radius um eine KOORDINATE (Schwerpunkt Hannover/Niedersachsen) — „was ist in der Nähe von <lat,lon>\", „welche Haltestellen liegen um diesen Punkt\". Liegt nur ein Name vor, kommt erst eine Auflösung: `search_place` für eine Stadt oder Region, sonst die Ortsauflösung. **Pflicht**: `latitude`, `longitude`, `radius_m`. **Optional**: `limit` (Default 10); `node_types` — EIN String, mehrere Arten mit Komma: `'stop'`, `'address'`, `'poi'`, die Sharing-Angebote `'bike_rental'`, `'scooter_rental'`, `'car_sharing'`, `'taxi_stand'`, die Abstellanlagen `'park_and_ride'`, `'bike_and_ride'`, oder `'any'` (`'stop,bike_rental'`); `include_mots` (legt die bedienenden Linien über die Haltestellen-Treffer); `only_available` (nur Sharing-Treffer mit gemeldetem freiem Fahrzeug — UNBEKANNTE Verfügbarkeit gilt nicht als frei). **Format**: kompakter Einrück-Text (TOON), kein JSON. **Anleitung**: `get_usage_guide` mit `tool='nearby'` — die Werte im Einzelnen, was `'any'` nicht abdeckt, und was ein Treffer trägt (`category`, `modality`, `parking`, `contactInfo`). **Anti-Fab**: nur die zurückgegebenen Namen, Typen, Distanzen und Verfügbarkeiten nennen; fehlt ein Feld, war es in der Quelle nicht getaggt — Öffnungszeiten und Preise stehen hier NICHT.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"format": {
"description": "Answer serialisation: `\"toon\"` (default) or `\"json\"` — the detail is in\n`get_usage_guide`. **An agent leaves this out.**",
"type": [
"string",
"null"
]
},
"include_mots": {
"description": "`true` overlays the serving transit lines on stop results. Default\n`false`, which keeps the answer small.",
"type": [
"boolean",
"null"
]
},
"latitude": {
"description": "Latitude in WGS-84 decimal degrees.",
"format": "double",
"type": "number"
},
"limit": {
"description": "Maximum number of results, at least 1. Default 10.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"longitude": {
"description": "Longitude in WGS-84 decimal degrees.",
"format": "double",
"type": "number"
},
"node_types": {
"default": null,
"description": "Which kinds of place to answer with: the places the graph holds —\n`\"stop\"`, `\"address\"`, `\"poi\"` — plus the shared-mobility offers\n`\"bike_rental\"`, `\"scooter_rental\"`, `\"car_sharing\"` and `\"taxi_stand\"`,\nplus the places to leave a vehicle of one's own, `\"park_and_ride\"` and\n`\"bike_and_ride\"`, or `\"any\"` for all of them. Several combine in ONE\ncomma-separated string — `\"stop,bike_rental\"`; an array of the same\ntokens is read as that string. A kind outside the ten is an argument\nerror, not a dropped filter. `\"poi\"` alone also switches on the\nnon-tourism filter; omit (or `\"any\"`) for the mixed default, in which each\nrequested kind gets its share of `limit` and the shared-mobility offers\nshare one between them. The two park-and-ride kinds are the exception\n`\"any\"` does NOT cover — ask for them by name, and with a `radius_m` of a\nfew kilometres, because such sites are sparse.",
"type": [
"string",
"null"
]
},
"only_available": {
"description": "Set to `true` for „wo kann ich JETZT eines nehmen\": of the\nshared-mobility offers, only those whose live feed reports at least one\nvehicle ready to be taken are answered with. A station whose\navailability is unknown is NOT returned then, and neither is a taxi\nrank, which has no feed to report one. Omit (or `false`) to list every\nplace in range. The other kinds — `\"stop\"`, `\"address\"`, `\"poi\"`,\n`\"park_and_ride\"`, `\"bike_and_ride\"` — are unaffected either way.",
"type": [
"boolean",
"null"
]
},
"radius_m": {
"description": "Search radius in metres.",
"format": "double",
"type": "number"
}
},
"required": [
"latitude",
"longitude",
"radius_m"
],
"title": "NearbyRequest",
"type": "object"
},
"name": "nearby",
"outputSchema": null
},
{
"description": "Löst Freitext in die Id auf, mit der gefahren wird — die Haltestelle, die Adresse oder den POI hinter „von <X> nach <Y>\", „erzähl mir was über <POI>\". Wo Routing, Abfahrtstafel oder POI-Steckbrief eine Id brauchen, steht es davor — auch wenn der Nutzer die Stadt dazu nennt („Hauptbahnhof Hannover\"). Ein GEBIET (Stadt/Region) verortet `search_place`. **Pflicht**: `query` — nur der Name: `'Kelsterbach Bahnhof'`, NICHT `'für Kelsterbach Bahnhof'`. Wegzulassen sind `für`, `vom`, `von`, `nach`, `bis`; ein führendes `am`/`an`/`in`/`zur`/`auf` bleibt stehen — so heißen echte Halte („Am Wehrhahn\"). **Optional**: `lat`/`lon` (Ranking-Bias), `limit`, `node_types` (`'stop'`/`'address'`/`'poi'`/`'any'`, mehrere mit Komma in EINEM String; eine andere Art ist ein Argument-Fehler), `city_station` (Query = ganze Stadt → deren (Haupt-)Bahnhof). **Art-Wort in `node_types`, nicht in den Namen**: „Haltestelle X\" → `'stop'`, „Adresse X\" → `'address'`, „POI X\"/„Sehenswürdigkeit X\" → `'poi'`, `query` je ohne das Wort. **A→B: zweimal rufen** — Start, Ziel. Jeder Treffer trägt `type` und `location`; NUR ein `stop` hat eine fahrbare DH-Id, nie eine erfinden. **Anleitung**: `get_usage_guide` — Abgrenzung, Argumente, Rangfolge. **Anti-Fab**: nur die Treffer aus dem Output dieses Aufrufs verwenden.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Stop / address / POI lookup by free text, optionally biased toward a\ncoordinate. When `node_types` is `\"poi\"` alone, the backend additionally\ndrops non-tourism POI names (kindergartens, pharmacies, schools) so a\ntourism query is not flooded with everyday amenities.",
"properties": {
"city_station": {
"description": "When `Some(true)` AND the query is a whole CITY,\nresolve it to the city's (Haupt-)Bahnhof stop and return ONLY that stop\n(so „von Hannover nach Celle\" routes Bahnhof→Bahnhof). Forwarded to\nmobility-middleware as `cityStation=true`. A no-op for non-city queries.\nThe orchestrator routing-floor sets this deterministically per endpoint;\nthe model never has to.",
"type": [
"boolean",
"null"
]
},
"format": {
"description": "Answer serialisation: `\"toon\"` (default) or `\"json\"` — the detail is in\n`get_usage_guide`. **An agent leaves this out.**",
"type": [
"string",
"null"
]
},
"lat": {
"description": "Optional latitude (WGS-84) to bias ranking toward nearby stops.",
"format": "double",
"type": [
"number",
"null"
]
},
"limit": {
"description": "Maximum number of results. Defaults to 5 if omitted.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"lon": {
"description": "Optional longitude (WGS-84) to bias ranking toward nearby stops.",
"format": "double",
"type": [
"number",
"null"
]
},
"node_types": {
"default": null,
"description": "Which kinds of place to resolve to: `\"stop\"`, `\"address\"`, `\"poi\"` or\n`\"any\"`. Several combine in ONE comma-separated string — `\"stop,poi\"`;\nan array of the same tokens is read as that string. A kind outside the\nfour is an argument error, not a dropped filter — the shared-mobility\nkinds among them: a rental station and a taxi rank are not in the place\nindex this searches, they are answered by the radius search `nearby`.\nForwarded to\nmobility-middleware as `journey_node_types`. `\"poi\"` alone additionally\ndrops non-tourism POI names (Kindergarten, Apotheke, Schule, …) — use\nthis for tourism queries. Nennt der Nutzer die Art selbst, gehört sie\nhierher statt in `query`: \"Haltestelle X\" → `\"stop\"`, \"Adresse X\" →\n`\"address\"`, \"POI X\"/\"Sehenswürdigkeit X\" → `\"poi\"` (und `query` dann\nohne das Art-Wort).",
"type": [
"string",
"null"
]
},
"query": {
"description": "Free-text query, e.g. \"Hauptbahnhof Hannover\" or \"Linden Markt\". Nur der\nreine Orts-/Haltename — ohne das Wort, das ihn im Satz ankündigt:\n`\"Kelsterbach Bahnhof\"`, nicht `\"für Kelsterbach Bahnhof\"`. Ein\nführendes `am`/`an`/`in`/`zur`/`auf` bleibt dagegen stehen, weil echte\nHaltestellen so heißen (\"Am Wehrhahn\", \"In der Au\").",
"type": "string"
}
},
"required": [
"query"
],
"title": "StopsRequest",
"type": "object"
},
"name": "resolve_location",
"outputSchema": null
},
{
"description": "Benennt, was an einer KOORDINATE liegt — der Ort („was liegt bei <lat,lon>\"), mit `level` eine bestimmte Ebene davon, mit `level='street'` die Straße samt nächster Hausnummer (der Lookup für eine GPS-Startposition). **Abgrenzung**: den Weg zurück (Name → Koordinate und OSM-Ids) geht `search_place`, die fahrbare Halte-Id liefert die Ortsauflösung, und `nearby` listet auf, was UM eine Koordinate liegt, statt den Punkt selbst zu benennen. **Pflicht**: `lat` und `lon` — geschrieben auch `latitude`/`longitude`, so wie `nearby` die Koordinate nimmt; je Aufruf nur eine der beiden Schreibweisen. **Optional**: `radius_m` (Suchradius in METERN; ein Ort, IN dem die Koordinate liegt, hat Abstand 0 und ist in jedem noch so engen Radius dabei — ohne `radius_m` die nächstgelegenen Treffer), `limit` (Höchstzahl Treffer, Default 10, Maximum 50) und `level` — `'place'` (Default: die ganze Ortshierarchie, feinste Ebene zuerst), `'city'` (die Stadt/Gemeinde), `'suburb'` (der Stadtteil) oder `'street'`. Kennt der Datensatz die gewünschte Ebene hier nicht, antwortet die nächst-gröbere, erkennbar am `place_type`; ein unbekannter Wert wirkt wie `'place'`. **Anleitung**: `get_usage_guide` mit `tool='reverse_geocode'`. **Anti-Fab**: nur die zurückgegebenen Orts- und Straßen-Namen verwenden, einschließlich der Hausnummer aus dem Datensatz — nie eine erfinden.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"format": {
"description": "Answer serialisation: `\"toon\"` (default) or `\"json\"` — the detail is in\n`get_usage_guide`. **An agent leaves this out.**",
"type": [
"string",
"null"
]
},
"lat": {
"description": "Latitude of the coordinate to reverse-geocode. Also accepted spelled\n`latitude`, the way the vicinity search takes it — one of the two\nspellings per call.",
"format": "double",
"type": "number"
},
"level": {
"description": "Optional resolution level. `\"place\"` (default) answers with the\ncoordinate's whole admin hierarchy, finest first (suburb → town → county\n→ state → country); `\"city\"` with the town/municipality it lies in;\n`\"suburb\"` with the suburb; `\"street\"` with the nearest STREET/ADDRESS\n(street name + nearest house number, e.g. `\"Münzstraße 3-4\"`) — the level\nneeded to label a real GPS start position. Where the data has no place at\nthe requested level, the next coarser one answers, recognisable by its\n`place_type`. Any other / omitted value behaves as `\"place\"`.",
"type": [
"string",
"null"
]
},
"limit": {
"description": "Optional maximum number of hits, nearest first. Default 10, upper bound\n50; a larger value is served as 50 and `0` as the default. Applies to\nevery level and with or without `radius_m`.",
"format": "uint32",
"minimum": 0,
"type": [
"integer",
"null"
]
},
"lon": {
"description": "Longitude of the coordinate to reverse-geocode. Also accepted spelled\n`longitude`, the way the vicinity search takes it — one of the two\nspellings per call.",
"format": "double",
"type": "number"
},
"radius_m": {
"description": "Optional radius in METRES. When set, returns the places inside the\ncircle, sorted nearest-first and capped to `limit`. A place\nthe coordinate LIES INSIDE is at distance 0 and is therefore in every\nradius, however tight. When omitted, returns the `limit` nearest places.",
"format": "double",
"type": [
"number",
"null"
]
}
},
"required": [
"lat",
"lon"
],
"title": "ReverseGeocodeRequest",
"type": "object"
},
"name": "reverse_geocode",
"outputSchema": null
},
{
"description": "Löst den NAMEN einer Stadt, Region oder eines Bezirks in Koordinaten und OSM-Ids auf — der erste Schritt, wenn ein GEBIET verortet werden muss („was kann ich in <REGION> unternehmen\", „wie ist das Wetter in <CITY>\"). **Für eine HALTESTELLE ist dieses Werkzeug fast immer falsch**: es kennt Gebiete, keine Bahnsteige — auf einen Bahnhofs-Namen antwortet es mit dem Stadtteil, und die Id, die es liefert, ist eine OSM-Id und keine fahrbare Halte-Id. **Trägt die Anfrage `Bahnhof`, `Hauptbahnhof`, `Hbf` oder `Bf`, gehört sie an die Ortsauflösung** — „Köln Hauptbahnhof\" und „Hannover Bahnhof\" also dorthin, nicht hierher: auf das erste antwortet dieses Werkzeug mit einem gleichnamigen Ortsteil (einem in Potsdam), auf das zweite mit der Stadt Hannover. Dasselbe für Adresse und POI — alles, was Start, Ziel oder Abfahrtsort einer Fahrt sein kann; eine Stadt als Fahrt-Endpunkt („von Hannover nach Celle\") ebenfalls. Von einer Koordinate zurück zum Namen geht `reverse_geocode`, die Umgebung einer Koordinate listet `nearby`. **Pflicht**: `name`. **Optional**: `lang` — wird für Symmetrie mit den übrigen Geo-Werkzeugen angenommen, derzeit aber nicht ans Backend durchgereicht und ändert das Ergebnis nicht. **Anleitung**: `get_usage_guide` mit `tool='search_place'` — die Abgrenzung im Detail, die typischen Ketten und der Umgang mit einem mehrdeutigen Namen. **Anti-Fab**: nur die zurückgegebenen Namen und Ids nutzen, keine Bauch-Geographie.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"format": {
"description": "Answer serialisation: `\"toon\"` (default) or `\"json\"` — the detail is in\n`get_usage_guide`. **An agent leaves this out.**",
"type": [
"string",
"null"
]
},
"lang": {
"description": "Optional ISO language code (e.g. \"de\", \"en\"). Currently advisory: the\nplace names are the German ones the data carries, whatever is asked for.\nKept in the signature so a multilingual answer needs no new argument.",
"type": [
"string",
"null"
]
},
"name": {
"description": "Name of the place to search for. Free-text fuzzy match against the place\nindex behind this endpoint (e.g. \"Hannover\", \"Maschsee\", \"Wangerland\").",
"type": "string"
}
},
"required": [
"name"
],
"title": "SearchPlaceRequest",
"type": "object"
},
"name": "search_place",
"outputSchema": null
},
{
"description": "Kuratierte Tourismus-Suche des Niedersachsen-Hubs — die redaktionelle TIEFE die OSM fehlt: EVENTS MIT DATUM, PREISE, Beschreibungen, Medien, Öffnungszeiten, Touren. Für „welche Veranstaltungen sind in X\", „was kostet der Eintritt\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen — erst verorten, dann abfragen: `region`/`query` aus der Frage, `lat`/`lon` nur aus `search_place`. **Tool-Semantik-Abgrenzung**: dieses Tool = die kuratierte Quelle. NICHT `expand_kg_pois` (das ist OSM-BREITE — alle Tags, all-NDS, aber ohne Events/ Preise/Redaktion). Für Region-Tourismus dürfen BEIDE laufen (OSM-Breite ∥ NDS-Kuration). NICHT `nearby` (Radius-um-Punkt), NICHT `search_place` (Place-Disambiguierung). **When to use**: Events — DE: „was ist diese Woche/am Wochenende in <Region> los\", „Veranstaltungen in <Ort>\". EN: „events in <Region> this weekend\". Unterkünfte/Gastro — DE: „Hotels in <Ort>\", „Restaurants in <Ort>\". EN: „hotels/restaurants in <Ort>\". Touren — DE: „touristische Radrouten/Radtouren in <Region>\", „Radwanderwege/Wanderwege am <Ort>\" → `type=tour`; jede Tour trägt dann `length_m`, `duration_min`, `ascent_m`/`descent_m`, `round_trip` und `activities` (wörtlich, als was der Datensatz sie führt: „Fahrrad\", „E-Bike\", „Wandern\", „Kanu\") — DARAN auswählen, nicht am Namen. Bei mehreren die best-passende per `get_tourism_details` zeichnen, die anderen namentlich nennen und fragen, welche noch. **When NOT to use**: reine OSM-Breite/„alle Sehenswürdigkeiten per Tags\" → `expand_kg_pois`; Detail zu EINEM Treffer → `get_tourism_details`; Routing/ Abfahrten, auch „von A nach B mit dem Rad\" → der Server MobilityMCP; Wetter/Tide → `get_current_weather`/`get_tide`. **Required args**: `region` ODER `query` (eines von beiden — Freitext-Region/ Name, z.B. region=\"Wangerland\", query=\"Sielhafenmuseum\"). Optional: `type` (genau eines von \"event\" | \"poi\" | \"accommodation\" (=\"hotel\") | \"gastro\" (=\"restaurant\") | \"tour\" — kuratierte Rad-/Wander-Routen, auch als \"radtour\"/\"radroute\"/\"radwanderweg\"/\"wanderweg\" akzeptiert; weggelassen = alle Typen; unbekannter Wert = alle. OHNE `type=tour` sind Touren praktisch nie unter den Treffern). Im Aktivitäts-Scope (type=\"poi\"/\"attraction\"/\"unternehmen\"/…) sind Unterkünfte AUSGESCHLOSSEN, im Region- wie im Vicinity-Modus (ein Hotel ist keine Unternehmung); für Hotels explizit type=\"accommodation\". `timeframe` (nur für type=event: \"today\" | \"tomorrow\" | \"weekend\" | \"this_week\" | \"month\" | ISO \"YYYY-MM-DD\" | Range \"YYYY-MM-DD..YYYY-MM-DD\"; ohne timeframe = kommende Events ab heute), `limit` (Default 8, clamped 1..=20), `family_only` (bool, Default false — nur die kuratierten Family-Kategorien, je mit der belegten `suitability`-Achse) und, nur zusammen damit, `indoor_only` (bool — davon nur die Schlechtwetter-tauglichen). `activity` (nur mit `type=tour`): wie eine Tour zurückgelegt wird — \"wandern\" | \"fahrrad\" | \"kanu\" + Synonyme (\"wanderweg\"/\"e-bike\"/ \"paddeln\"). Filtert serverseitig auf die GANZE Familie kuratierter Aktivitätswerte, also auch \"Winterwandern\"/\"Nordic Walking\"/ \"Mountainbike\" — 8 % der zu Fuß zurückgelegten Touren tragen keinen \"Wandern\"-Wert; weglassen oder unbekannt = alle. **Coord-Vicinity-Modus (Umkreis, POI-Anker)**: für „<Kategorie> am/bei <POI>\" den POI ZUERST via `search_place` zu einer Coord auflösen, dann `lat`+`lon` setzen (beide nötig; + optional `radius_m`, Default 2000 m, clamped 100..=20000). `region`/`query` sind dann nur Pool-Hint, nicht mehr Pflicht; die Treffer sind auf den Umkreis gefiltert, nächster zuerst, je mit `distance_m` in Metern. NUR in diesem Modus kommt die OSM-Breite dazu, entdoppelt gegen die Kuration (kuratierter Treffer gewinnt): bei `type=gastro` die `amenity`-Gastronomie, im Aktivitäts-Scope (`type=poi`, „unternehmen\") `tourism` ∈ attraction/museum/…, `historic` und `leisure` ∈ park/garden/… — AUSGESCHLOSSEN bleiben Unterkünfte (hotel/hostel) und Alltags-Versorgung (`shop`, Apotheke/Bank/Arzt), beides keine Ausflugsziele. **Typical chain**: `search_tourism(region=<R>, type=event)` → `get_tourism_details(id, query=<R>)` pro Treffer — der Regions-Hinweis ist nötig, sonst antwortet das Detail leer. **Multi-call**: ein Call pro Region/Typ. **Anti-Fab note**: Event-Namen, DATEN, PREISE, POI-Namen, Adressen kommen AUSSCHLIESSLICH aus `pois[]` / `events[]` dieses Aufrufs. Wenn `returned: 0` / `pois: []` / `events: []` → ehrlich sagen, dass für <Region> nichts abrufbar war, NIEMALS Events/Preise/POIs aus Trainings-Wissen ergänzen. Datum eines Events ist tool-belegt (`events[].date` / `pois[].date`, ISO-8601 Europe/Berlin) ODER abwesend — NIE geschätzt. **DZT-Bündelung (zweite kuratierte Quelle, DE-weit)**: kuratierte Treffer AUSSERHALB Niedersachsens kommen aus der DZT-KG (Deutsche Zentrale für Tourismus); Dubletten werden de-dupliziert, in der NDS-Region gewinnt der Niedersachsen-Hub-Eintrag (regionale Tiefe). Bei `type=tour` bleibt sie AUSSEN VOR — sie führt keinen Touren-Inhaltstyp; kuratierte Touren gibt es nur für Niedersachsen, außerhalb ehrlich \"keine Tour abrufbar\". Returns {place, source:'niedersachsen-hub', type, returned, mode?, center?, radius_m?, pois:[{name,type,description?,address?,uri?,date?,price?,media?, coord?,opening_hours?,id?,distance_m?,source?,license?,hub_detail_url?, length_m?,duration_min?,ascent_m?,descent_m?,round_trip?,activities?}], events:[{name,date,location,source?,license?}]}. Das Top-Level `source` bleibt shape-stabil; welche Quelle einen Treffer geliefert hat, sagt sein eigenes `source` ('osm' | 'niedersachsen-hub' | 'dzt'). `id` ist der Schlüssel für `get_tourism_details`; die Felder folgen schema.org. **`license` (additiv, PRO Treffer)**: die Lizenz, die der Datensatz selbst angibt — `{id?, url?, notice?, holder?}`: `id` = Lizenz-Kennung (z.B. 'CC-BY-SA-4.0', 'CC0-1.0', 'ODbL-1.0'), `url` = Lizenz-Text/Deed, `notice` = der WÖRTLICH wiederzugebende Lizenzverweis (DZT-`copyrightNotice`, § 3 der DZT-Nutzerbedingungen; bei OSM-Treffern die ODbL-Namensnennung), `holder` = der zu nennende Urheber (das `author`- bzw. `copyrightHolder`-Feld des Datensatzes). Gibt er nichts an, ist das Feld **abwesend** — nie eine geratene Vorgabe-Lizenz. Nennst du einen Treffer mit `license.holder`, nenne den Urheber mit. **`hub_detail_url` (additiv, PRO Treffer, nur bei `source: 'niedersachsen-hub'`)**: die Entitätsseite dieses Treffers beim Niedersachsen-Hub, dem Nutzer nennbar — NICHT die Betreiber-Website (`uri`). Jeder Treffer, dessen Art beim Hub eine Eintragsseite hat, trägt sie: POI (`p_…`), Tour (`t_…`), Veranstaltung (`e_…`), Unterkunft (`h_…`), Gastronomie (`g_…`), Gebiet (`r_…`). Ein Medien-Datensatz (`m_…`) hat keine und trägt keine; fehlt sie, keine konstruieren. Mit `family_only` trägt jeder Treffer zusätzlich `family`, `suitability` ({family, age_bands, pushchair, seal (Kinderferienland-Siegel), indoor_bad_weather}) und, wo die Quelle sie führt, `price_child`/`price_family` — alle feature-belegt: „kinderfreundlich\" ist belegt, nicht geraten.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"activity": {
"description": "How a TOUR is travelled, for `type=tour`: \"wandern\" (also \"wanderweg\",\n\"spaziergang\", \"hiking\", \"zu Fuß\"), \"fahrrad\" (also \"radtour\", \"e-bike\",\n\"mountainbike\", \"cycling\") or \"kanu\" (also \"paddeln\", \"SUP\"). Each word\nselects the whole family of curated activity values, so a hiking question\nalso finds the records filed under \"Winterwandern\", \"Nordic Walking\" or\n\"Spaziergang\" — 8 % of the walked ones carry no \"Wandern\" value at all.\nWhich value a given record carries is on the record (`activities`).\nOmit to search every activity; an unrecognised word is treated as \"all\"\n(never an error).",
"type": [
"string",
"null"
]
},
"family_only": {
"description": "Family mode: search the curated NDS family categories\n(Tierpark/Freizeitpark/Spielplatz/Erlebnisbad/Badesee/Kletterpark/…) and\noverlay the curated suitability axis (age bands, Kinderwagentauglich,\nKinderferienland-Siegel, Schlechtwetterangebot). Every record is then\nfamily-belegt + carries an additive `suitability` object. Defaults false.",
"type": [
"boolean",
"null"
]
},
"indoor_only": {
"description": "Restrict to rain-safe family records (the\n`suitability.indoor_bad_weather` / Schlechtwetterangebot proxy). Only\nmeaningful with `family_only=true`.",
"type": [
"boolean",
"null"
]
},
"lat": {
"description": "Coord-vicinity mode — center latitude. When `lat` AND `lon`\nare both given the search becomes a vicinity search around the point:\nonly curated hits within `radius_m` are returned (proximity-filtered on\nthe `coord` field), sorted nearest-first with an additive `distance_m`.\nUse it for POI-anchor questions (\"Restaurants am Maschsee\"): resolve the\nPOI to a coord first, then pass it here. `region`/`query` then act as the\nenclosing-city candidate-pool hint (and are no longer required).",
"format": "double",
"type": [
"number",
"null"
]
},
"limit": {
"description": "Maximum number of curated entities to return (default 8, clamped 1..=20).",
"format": "int64",
"type": [
"integer",
"null"
]
},
"lon": {
"description": "Coord-vicinity center longitude (paired with `lat`).",
"format": "double",
"type": [
"number",
"null"
]
},
"query": {
"description": "Free-text query (name / keyword) when not searching a whole region,\ne.g. \"Sielhafenmuseum\". Alias for `region`; one of the two is required.",
"type": [
"string",
"null"
]
},
"radius_m": {
"description": "Coord-vicinity radius in metres (default 2000, clamped 100..=20000).",
"format": "int64",
"type": [
"integer",
"null"
]
},
"region": {
"description": "Region or place to search within, as free text (e.g. \"Wangerland\",\n\"Hooksiel\", \"Hannover\"). Either `region` or `query` must be given;\n`region` is the natural choice for a place-scoped tourism search.",
"type": [
"string",
"null"
]
},
"timeframe": {
"description": "Optional event-date window for `type=event`: \"today\", \"tomorrow\",\n\"weekend\", \"this_week\", \"month\", or an explicit ISO date\n\"YYYY-MM-DD\" / range \"YYYY-MM-DD..YYYY-MM-DD\". With no timeframe the\nadditive `events` list defaults to upcoming events (today onward).",
"type": [
"string",
"null"
]
},
"type": {
"description": "Content type to narrow the search. One of: \"event\", \"poi\",\n\"accommodation\" (a.k.a. \"hotel\"), \"gastro\" (a.k.a. \"restaurant\"),\n\"tour\". Omit to search across all curated types. Unknown values are\ntreated as \"all\" (never an error).",
"type": [
"string",
"null"
]
}
},
"title": "SearchTourismRequest",
"type": "object"
},
"name": "search_tourism",
"outputSchema": null
}
]
}Verify it yourself
curl -s https://api.teppi.xyz/v1/evidence/sha256:4b591f443d614656f924a07879919f26236ba5760972f8a550abd045677bd12e | sha256sum