{"name":"eu.projektionisten/mobility","slug":"projektionisten-mobility","title":"MobilityMCP","description":"Journeys, departures, line courses, disruptions in Germany; nearby sharing as currently reported.","url":"https://mcp.market/server/projektionisten-mobility","rating":null,"grade":"C","score":67,"certified":false,"status":"active","category":"other","tags":[],"presence":{"score":8,"stars":null,"forks":null,"downloads_week":null,"last_push_at":null,"license":null},"uptime":{"percent":100,"checks":2,"ok":2,"last_checked_at":"2026-09-23T03:20:52.074Z","last_ok_at":"2026-09-23T03:20:52.074Z","latency_ms":153},"claimed":false,"transport":"remote","callable_via_gateway":true,"default_price_micros":0,"repository":null,"website":"https://ai.projektionisten.eu/mcp-landingpage/","version":"0.3.0","remotes":[{"type":"streamable-http","url":"https://ai.projektionisten.eu/mmcp"}],"packages":[],"tools":[{"name":"connections","description":"Plant ÖPNV-Verbindungen von A nach B, deutschlandweit, Fernrouten eingeschlossen — **als Daten, für Ergebnisse, die du weiterverarbeitest**. Steht `show_connections` in deinem Werkzeug-Satz, ist das der Vordereingang für die Frage eines Menschen. Für „wie komme ich von X nach Y\" kommt die Auskunft aus diesen Werkzeugen, nicht aus dem Allgemeinwissen. **Pflicht sind BEIDE Endpunkte**: `origin_id` UND `destination_id` aus einer Ortsauflösung, mit `origin_type`/`destination_type` — ODER `origin_lat`+`origin_lon`+`destination_lat`+`destination_lon`; ein NAME in einem Id-Feld ist ein Argument-Fehler. **Optional**: `time`, `is_arrival_time`; `via_id` bzw. `via_lat`+`via_lon` mit `via_type`; die hart einschränkenden Filter `modes`, `only_lines`/`exclude_lines`, `submodes_allow`/`submodes_deny`, `max_transfers`, `max_walk_minutes`/`max_walk_meters`, `walk_speed`, `accessibility_profile`, `include_rental_bike`, `prefer_flat`, `mobility_profile`; `verbosity`, `limit`, `render_payload`. **Höhenmeter**: nur Fuß-/Rad-Abschnitte tragen `ascentInMeters`/`descentInMeters`. **Durchbindung**: `staySeated: true` an einem Abschnitt heißt, der Fahrgast bleibt aus dem vorigen sitzen — kein Umstieg, also auch keinen zählen. Fehlt das Feld, ist nichts gesagt; nie selbst herleiten. **Rad-Tempo**: Bei einer Radfahrt setzt `cycling_profile` das Tempo des Fahrers und damit die gemeldete Dauer — `family` bei kleinen Kindern, `ebike` bei E-Bike/Pedelec; sonst weglassen (= `normal`). **Fahrradmitnahme**: Geht es um ein Rad, sprich je Abschnitt `bikeCarriageConditions` aus (Bedingungen des Verbunds zur Abfahrtszeit); `bikesAllowed`/`bikeCarriageNote` sind nur die Grundregel, `bikeCarriageCoverage` die Wissensgrenze. **Genannter Wunsch**: Nennt jemand, was ihn stört (\"nicht in der Innenstadt parken\"), hol die Option, die das löst, als EIGENEN Aufruf (`mobility_profile`) und empfiehl sie aus ihrem Nutzen — mit dem Nachteil, den die Antwort ihr gibt. **Anleitung**: `get_usage_guide` mit `tool='connections'` — lies sie, bevor du filterst. **Anti-Fab**: Linien, Zeiten, Halte, Anlagen und Gleise ausschließlich aus dem Output dieses Aufrufs.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"accessibility_profile":{"description":"Mobility profile by name: `\"Standard\"` (default), `\"WheelchairRobust\"`,\n`\"WalkerComfort\"` or `\"IndividualComfort\"`. Each bundles its accessibility\nconstraints and walk speed; another name is an argument error. The two\nwheelchair profiles find no ride at all today — the answer then carries\n`accessibility_routing` with `status: no_data` beside ordinary connections,\nwhich are to be reported as ordinary ones. What each profile constrains is\nin the usage guide.","type":["string","null"]},"cycling_profile":{"description":"Wer auf dem Rad sitzt, und damit das Tempo der Rad-Abschnitte: `family`\n(mit kleinen Kindern), `normal` (Default, unverändert) oder `ebike`\n(Pedelec). Ein anderer Name ist ein Argument-Fehler.","type":["string","null"]},"cycling_speed":{"description":"Rad-Tempo in Metern/Sekunde, 1 bis 12 — außerhalb ein Argument-Fehler.\nÜberschreibt `cycling_profile`. Richtwerte: Familie ≈2.8, normal ≈5,\nPedelec ≈6.5.","format":"double","type":["number","null"]},"destination_id":{"description":"Destination id. Same form as `origin_id`.","type":["string","null"]},"destination_lat":{"description":"Destination latitude. Same use as `origin_lat`.","format":"double","type":["number","null"]},"destination_lon":{"description":"Destination longitude. Goes with `destination_lat`.","format":"double","type":["number","null"]},"destination_type":{"description":"What `destination_id` is. Same values as `origin_type`.","type":["string","null"]},"exclude_lines":{"description":"Line blacklist, same token form as `only_lines`. A journey is dropped if\nany transit leg uses one of them.","items":{"type":"string"},"type":["array","null"]},"extended":{"description":"`true` keeps the map data in the text: every stop's coordinate, every\nleg's polyline, and the whole stop sequence with them — for an application\nthat DRAWS the route, at two to three times the answer. A chat client\nleaves it off.","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"]},"include_rental_bike":{"description":"`true` adds a rental-bike leg (park-and-bike / station rental). Equivalent\nto naming `\"bike\"` in `modes` together with a transit mode.","type":["boolean","null"]},"is_arrival_time":{"description":"`true` reads `time` as the desired ARRIVAL time instead of the departure\ntime.","type":["boolean","null"]},"limit":{"description":"Maximum number of journeys, at least 1. Default 5, values above 15 are\nserved as 15.","format":"int64","type":["integer","null"]},"max_transfers":{"description":"Upper bound on interchanges: `0` = direct, up to `3`. Omit unless the user\nconstrains transfers: the backend then derives the search depth from the\ntrip's air-line distance and escalates it when the first attempt finds\nnothing, so omitting never loses a connection.","format":"int64","type":["integer","null"]},"max_walk_meters":{"description":"Cap on the summed walking DISTANCE in metres. Works like\n`max_walk_minutes`, on the metres walked.","format":"int64","type":["integer","null"]},"max_walk_minutes":{"description":"Cap on the summed walking TIME in minutes. A post-filter drops journeys\nabove it; if that leaves nothing, the backend searches once more avoiding\nfootpaths before the answer is empty.","format":"int64","type":["integer","null"]},"mobility_profile":{"description":"How the first and the last mile may be covered, by name: `\"transit\"`\n(default — both ends on foot), `\"transit_plus_sharing\"` (a shared bike),\n`\"door_to_door\"` (being driven), `\"park_and_ride\"` or `\"bike_and_ride\"`\n(one's OWN car or bicycle, left where the transit leg starts). Another name\nis an argument error. It widens those two ends, restricts no ride and\npromises nothing. When to set which, and how it composes with `modes`, is\nin the usage guide.","type":["string","null"]},"modes":{"description":"Transport-mode restriction, not a preference: nothing outside the list is\nplanned. The footpath always stays allowed — the way to, from and between\nstops goes on foot — while `[\"foot\"]` on its own plans no ride at all.\nEntries: `\"bike\"`, `\"bike_rental\"`, `\"foot\"`, `\"car\"`, `\"taxi\"`, `\"scooter\"`,\n`\"transit\"`, `\"bus\"`, `\"tram\"`, `\"rail\"`, `\"subway\"`, `\"ferry\"`; several\ncombine. An entry outside that list is an argument error, not a dropped\nfilter. Omitted or empty = all standard transit modes, the ferry\nincluded. Set only when the user insists on a mode; the guide has the\nvocabulary and the traps.","items":{"type":"string"},"type":["array","null"]},"only_lines":{"description":"Line whitelist. Entries are line tokens as printed on the vehicle (`\"6\"`,\n`\"U3\"`); a journey is kept only if every transit leg uses one of them.","items":{"type":"string"},"type":["array","null"]},"origin_id":{"description":"Origin id. A DHID (`de:NNNNN:NNN`) for a stop, otherwise the resolver's\n`main` id of the address or POI. Resolve the place first — a name here is\nan argument error.","type":["string","null"]},"origin_lat":{"description":"Origin latitude, WGS-84 decimal degrees — the fallback when no id is at\nhand, and the one retry worth making when resolved ids find nothing.","format":"double","type":["number","null"]},"origin_lon":{"description":"Origin longitude. Goes with `origin_lat`.","format":"double","type":["number","null"]},"origin_type":{"description":"What `origin_id` is: `\"stop\"` (default), `\"address\"` or `\"poi\"`. A stop id\nis auto-prefixed `GTFS.de:`; the other two are forwarded verbatim so the\nbackend resolves the real name.","type":["string","null"]},"prefer_flat":{"description":"`true` plant die hügel-ärmste statt der sonst gewählten Rad-Route: die\nSuche gewichtet die Steigung und nimmt dafür Umwege in Kauf, nur auf\nRad-Abschnitten. Keine Zusage — ohne flachere Alternative kommt dieselbe\nRoute; die Höhenmeter der Antwort sagen es. Wann setzen: die Anleitung.","type":["boolean","null"]},"render_payload":{"description":"`true` appends the same journeys again as raw JSON, addressed to the user\nrather than to the model — the map geometry an application draws from. A\nchat client leaves this off: it is the whole answer twice.","type":["boolean","null"]},"submodes_allow":{"description":"Fine submode whitelist — finer than `modes`, which only separates\nbus/tram/rail/subway. Entries: `\"sbahn\"`, `\"regionalbahn\"`, `\"ice\"`,\n`\"ic\"`, `\"ir\"`, `\"nj\"`, `\"fernverkehr\"`, `\"stadtbahn\"`, `\"ubahn\"`,\n`\"bus\"`, `\"regionalbus\"`, `\"stadtbus\"`. A journey is kept only if every\ntransit leg matches one.","items":{"type":"string"},"type":["array","null"]},"submodes_deny":{"description":"Fine submode blacklist, same vocabulary as `submodes_allow`. A journey is\ndropped if any transit leg matches one.","items":{"type":"string"},"type":["array","null"]},"time":{"description":"ISO 8601 timestamp (e.g. `\"2026-06-15T08:30:00Z\"`). Omit to plan from now.\nResolve a spoken time with the time tool rather than computing one.","format":"date-time","type":["string","null"]},"verbosity":{"description":"How much of each journey comes back: `\"compact\"` (default — everything an\nanswer is cited from) or `\"full\"` (adds the stops in between). A third\nword is an argument error, not the default.","type":["string","null"]},"via_id":{"description":"Intermediate stop the route must pass through („über X\"), as an id in the\nsame form as `origin_id`. The route is then planned A → via → B.","type":["string","null"]},"via_lat":{"description":"Via latitude, for an intermediate address or POI without an id. Goes with\n`via_lon`.","format":"double","type":["number","null"]},"via_lon":{"description":"Via longitude. Goes with `via_lat`.","format":"double","type":["number","null"]},"via_type":{"description":"What `via_id` is. Same values as `origin_type`.","type":["string","null"]},"walk_speed":{"description":"Walking speed of the foot legs in metres/second, between 0.3 and 3 m/s —\noutside that it is an argument error. Default ≈1.33, slow ≈0.7, brisk\n≈2.0. Overrides the walk speed of `accessibility_profile`.","format":"double","type":["number","null"]}},"$schema":"https://json-schema.org/draft/2020-12/schema","description":"Unified connection request. For stops, provide origin_id and destination_id.\nFor arbitrary locations (e.g. addresses, POIs), provide coordinates — and as\nthe one retry worth making when resolved ids find nothing: an id the routing\ngraph does not know answers empty rather than with an error.\n\n`Default` is derived so a caller in a test can name the two or three fields\nits case is about; the request grows by optional fields often enough that\nspelling out two dozen `None`s at every call site is its own source of noise.","title":"ConnectionRequest"}},{"name":"departures","description":"Abfahrten oder Ankünfte für EINE Haltestelle — **als Daten, für Ergebnisse, die du weiterverarbeitest**. Steht `show_departures` in deinem Werkzeug-Satz, ist das der Vordereingang für die Frage eines Menschen. Für „wann fährt von X\", „letzte Stadtbahn von X\" kommt die Auskunft aus diesen Werkzeugen, nicht aus dem Allgemeinwissen; für eine A→B-Frage aus `connections`. **Pflicht** ist eine konkrete Stop-`id` aus einer vorhergehenden Ortsauflösung (z.B. `'de:03241:57'`); ein Haltestellen-NAME in `id` ist ein Argument-Fehler, keine leere Tafel. **Optional**: `time` und `is_arrival_time`; `modes`; `direction` (Halt-Name, in dessen Richtung gefahren wird) bzw. für eine weiche Angabe `target_bearing` mit `bearing_tolerance`; `arrival_departure`; für „letzte Fahrt des Tages\" `time_range_seconds` zusammen mit `last_of_window`; und für den Umfang `verbosity`, `limit` sowie `render_payload`. `modes` und `direction` schränken hart ein. **Eine leere Tafel ist keine Auskunft**: blieb sie mit `['tram']` („Straßenbahn\") leer, mit `['tram','subway']` nachfassen — sonst ohne den Filter. **Anleitung**: `get_usage_guide` mit `tool='departures'` — die Fenster-Kette für „letzte Fahrt\", die Echtzeit-, Ausfall- und Zitier-Felder. **Anti-Fab**: Linien, Richtungen, Zeiten, Gleise, Verspätung und Ausfall ausschließlich aus dem Output dieses Aufrufs.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"arrival_departure":{"description":"`\"arrivals\"` (when vehicles reach `id`) or `\"departures\"` (default) — a\nthird value is an argument error. Wins over `is_arrival_time` when both\nare set.","type":["string","null"]},"bearing_tolerance":{"description":"Angular tolerance in degrees for `target_bearing`. Default ±60°.","format":"double","type":["number","null"]},"direction":{"description":"Name of a stop the user wants to head TOWARD („Richtung Wettbergen\") —\nnot a routing destination. The board keeps only departures heading that\nway, whether the named stop is the terminus or a stop downstream of the\nqueried one. Matching is case-insensitive and area-prefix-tolerant.","type":["string","null"]},"extended":{"description":"`true` keeps the map data in the text: every stop's coordinate, the whole\ncourse of each run, and a polyline where the board carries one — for an\napplication that DRAWS the board. It multiplies the answer. A chat client\nleaves it off.","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"]},"id":{"description":"Stop id to read the board of, as a DHID (`\"de:03241:57\"`). Resolve the\nstop first — a name here is an argument error.","type":"string"},"is_arrival_time":{"description":"`true` reads `time` as an ARRIVAL time — the same as\n`arrival_departure = \"arrivals\"`.","type":["boolean","null"]},"last_of_window":{"description":"Which end of a `time_range_seconds` window to read: omitted or `false` the\nFIRST departures, `true` the LAST ones (the end-of-service question). An\nanswer carrying `window_truncated: true` beside its board did NOT reach the\nwindow's end — its last entry is then not the last departure. Without a\nwindow it has no effect.","type":["boolean","null"]},"limit":{"description":"Maximum number of departures, at least 1. Default 5, values above 15 are\nserved as 15.","format":"int64","type":["integer","null"]},"modes":{"description":"Transport-mode filter; the board then shows nothing else. Entries:\n`\"bus\"`, `\"tram\"`, `\"subway\"`, `\"train\"`/`\"rail\"`, `\"ferry\"`,\n`\"transit\"`; several combine. Another entry — a street mode, a misspelling\n— is an argument error, not a dropped filter: a board lists scheduled\nservices. Omitted or empty = all modes. A Stadtbahn or\nlight-rail mention needs BOTH labels — `[\"tram\",\"subway\"]`: which of the\ntwo such a network carries depends on the dataset rather than on the\nvehicle. Set the filter only when the user really asks for a vehicle type;\nthe guide has the rest of the vocabulary and the traps.","items":{"type":"string"},"type":["array","null"]},"render_payload":{"description":"`true` appends the same board again as raw JSON, addressed to the user\nrather than to the model — for an application that draws a departure\nboard. A chat client leaves this off: it is the whole answer twice.","type":["boolean","null"]},"target_bearing":{"description":"Target bearing in degrees (0=N, 90=E, 180=S, 270=W) for a SOFT direction\n(„Richtung Norden\", „Richtung Stadt\") instead of a stop name. The board\nkeeps only departures whose course lies within `bearing_tolerance` of it.\nMutually exclusive with `direction`.","format":"double","type":["number","null"]},"time":{"description":"ISO 8601 timestamp (e.g. `\"2026-06-15T08:30:00Z\"`). Omit for now. Resolve\na spoken time with the time tool rather than computing one.","format":"date-time","type":["string","null"]},"time_range_seconds":{"description":"Time WINDOW in seconds, starting at `time`. Together with `last_of_window`\nthis answers „letzte Fahrt\": pick it so the window ENDS after end of\nservice (from the evening on, `28800` = 8 h rather than 4 h). Omit for a\nnormal next-N lookup.","format":"int64","type":["integer","null"]},"verbosity":{"description":"How much of each departure comes back: `\"compact\"` (default — everything\nan answer is cited from) or `\"full\"` (adds the onward stops of the run,\nand with them the per-stop cancellation marker). A third word is an\nargument error, not the default.","type":["string","null"]}},"required":["id"],"$schema":"https://json-schema.org/draft/2020-12/schema","description":"A departure board for one stop. `Default` is derived for the same reason as\non [`ConnectionRequest`].","title":"TimetableRequest"}},{"name":"disruptions","description":"Aktuelle Störungen, Baustellen und Liniensperrungen im ÖPNV. Für „gibt es Störungen\", „Ausfälle in X\" ist dieses Werkzeug die Auskunft, nicht das Allgemeinwissen. **Datenlage — wichtig**: Störungsmeldungen liegen derzeit für Niedersachsen, Bremen und Hamburg vor; außerhalb gibt es dafür KEINE Datengrundlage. (Verbindungen und Abfahrten sind davon nicht betroffen — die sind deutschlandweit.) Eine leere Antwort ist deshalb nur dann eine Entwarnung, wenn das Feld `coverage` sie als solche ausweist; außerhalb der abgedeckten Gebiete heißt sie, dass du es nicht weißt. **Keine Pflicht-Args** — ohne Filter kommen die aktiven Meldungen, gekappt auf `limit`. Optional: `line` (Liniennummer/-token, z.B. `'6'`, `'U3'`) und `stop` (Haltestellen-Name) verknüpfen UND; `area` (Stadt/Gemeinde) bestimmt das `coverage` und sortiert die unverorteten Meldungen — es unterdrückt sie nicht: die kommen getrennt in `unplaced` zurück, auch ohne `area`. Nenne nur Filter, die der Nutzer wirklich nannte. **Format**: kompakter Einrück-Text (TOON), kein JSON; die Schreibweise steht in der Anleitung. **Anleitung**: `get_usage_guide` mit `tool='disruptions'` — die sechs `coverage`-Werte, die beiden Listen, die Felder einer Meldung und woran eine gekappte Antwort zu erkennen ist. **Anti-Fab**: nur zurückgegebene Meldungen nennen; eine Meldung ohne betroffene Linie und ohne betroffenen Halt ist eine allgemeine Störung und wird keiner Linie zugeschrieben, eine Meldung aus `unplaced` keinem Ort.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"area":{"description":"Area or city name (`\"Hannover\"`). Matches the municipality the affected\nstops lie in, and decides the `coverage` the answer reports. It never\nsuppresses a report: the ones it cannot place come back in `unplaced`.","type":["string","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"]},"include_unplaced":{"description":"`false` leaves the `unplaced` list out of the answer (default `true`).\nIt only shortens the answer — `coverage` still counts what was left out,\nso it never turns into an all-clear.","type":["boolean","null"]},"limit":{"description":"Maximum number of disruptions, at least 1. Default 5, values above 15 are\nserved as 15. It shortens the answer, it does not choose better entries —\nan answer that had to leave something out says so (`truncated` + `total`).","format":"int64","type":["integer","null"]},"line":{"description":"Line token as printed on the vehicle (`\"6\"`, `\"169\"`, `\"U3\"`). A\ndisruption is kept only if it names that line — under one of its\n`affected_lines` or one of its `affected_line_refs`.","type":["string","null"]},"stop":{"description":"Stop name (`\"Kröpcke\"`). Case-insensitive substring match against the\ndisruption's `affected_stops`.","type":["string","null"]}},"$schema":"https://json-schema.org/draft/2020-12/schema","description":"Disruption query. All three filters are optional; with\nnone set, ALL active disruptions are returned (\"alle aktiven\"). At least one\nfilter narrows the result — never guess a line/stop the user did not name.","title":"DisruptionsRequest"}},{"name":"get_usage_guide","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.","write_action":false,"price_micros":0,"input_schema":{"type":"object","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"]}},"$schema":"https://json-schema.org/draft/2020-12/schema","description":"What the tool takes.","title":"UsageGuideRequest"}},{"name":"line_course","description":"Linienverlauf: die Halte-Folge einer ÖPNV-LINIE und ihre gezeichnete Strecke für die Karte — „wo fährt die Y entlang\", „welche X-Linien gibt es\". Für Linien-Fragen: diese Auskunft, nicht das Allgemeinwissen. **Pflicht ist EINES**: `query` — Name/Nummer, wie ein Mensch sie schreibt (`'Heide-Shuttle'`, `'HS 2'`); ODER `id` aus einer früheren Antwort = GENAU EINE Linie. Sonst frag nach. **Optional**: `area` — der Ort, in dem die Linie fährt (`'Hannover'`; Dutzende Linien heißen `'100'`), `limit` (Default 8), `render_payload`, `format`. **Die Antwort**: je Fahrtrichtung ein Verlauf mit `headsign`, den `halts` als Namen und `pathOnMap` — der Strecke im Text, auf max. ~50 m vereinfacht; volle Auflösung: `render_payload: true`. **Mehrdeutig**: meint die Frage mehr Linien als eine Antwort ganz liest, kommt statt `lines` die Liste `candidates` (Nummer, Betreiber, Id) — ungezeichnet; dann den Ort erfragen oder mit `id` nachfassen. **Grenzen**: `geometryDegraded: true` heißt Luftlinien-Kette statt Straßenverlauf, `note` sagt es. Je Richtung EIN Fahrtmuster; ist `patternsTotal` größer, fährt sie üblicherweise so. `matchedTotal` über der Zahl der Linien heißt Ausschnitt. Unbekannter Ort: `note` sagt es, nichts wurde eingegrenzt. **Nicht dafür**: A→B (`connections`), Abfahrten (`departures`), Störungen (`disruptions`). **Anleitung**: `get_usage_guide` mit `tool='line_course'`. **Anti-Fab**: Linien, Halte, Reihenfolge, Strecke nur aus diesem Aufruf; findet sich keine, sag das.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"area":{"description":"The town or city the line runs in (`\"Hannover\"`), where the user named\none — the other way to make a line number mean ONE line. Beside `query`;\nno effect beside `id`, which already means one line.","type":["string","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"]},"id":{"description":"A line id out of an earlier answer (`\"de:VBN-VH:6002:_3\"`) — the one way\nto name exactly one line when a name means several.","type":["string","null"]},"limit":{"description":"Maximum number of lines, at least 1. Default 8, values above 15 are\nserved as 15. Ignored beside `id`, which is one line.","format":"int64","type":["integer","null"]},"query":{"description":"Line name or number, as written on the vehicle or in the timetable\n(`\"Heide-Shuttle\"`, `\"HS 2\"`, `\"U3\"`). Matched against the beginning of\nboth, without case and without separators.","type":["string","null"]},"render_payload":{"description":"`true` appends the whole answer again, addressed to the user rather than\nto the model: the halts with their coordinates, and every course's line\nat the resolution it was drawn at rather than the simplified `pathOnMap`\nthe text carries. For an application that needs the exact line; a client\nthat draws the answer's own `pathOnMap` leaves this off.","type":["boolean","null"]}},"$schema":"https://json-schema.org/draft/2020-12/schema","description":"A line, by the name a rider writes or by an id an earlier answer carried.\nExactly one of the two is needed: a call that names neither does not say\nwhich line it means. `area` narrows a name that means several lines to the\none running in a named place.","title":"LineCourseRequest"}},{"name":"link_datetime","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`) geht direkt als `connections.time` bzw. `departures.time` weiter. 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}`.","write_action":false,"price_micros":0,"input_schema":{"type":"object","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"],"$schema":"https://json-schema.org/draft/2020-12/schema","title":"LinkDateTimeRequest"}},{"name":"nearby","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.","write_action":false,"price_micros":0,"input_schema":{"type":"object","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"],"$schema":"https://json-schema.org/draft/2020-12/schema","title":"NearbyRequest"}},{"name":"resolve_location","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.","write_action":false,"price_micros":0,"input_schema":{"type":"object","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"],"$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.","title":"StopsRequest"}},{"name":"reverse_geocode","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.","write_action":false,"price_micros":0,"input_schema":{"type":"object","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"],"$schema":"https://json-schema.org/draft/2020-12/schema","title":"ReverseGeocodeRequest"}},{"name":"search_place","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.","write_action":false,"price_micros":0,"input_schema":{"type":"object","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"],"$schema":"https://json-schema.org/draft/2020-12/schema","title":"SearchPlaceRequest"}},{"name":"show_connections","description":"**Der Vordereingang für jede Verbindungsfrage eines Menschen**, auch wenn er nur nach Zeiten fragt: plant die Fahrt wie `connections` und liefert sie zusätzlich als Ansicht aus, die ein Wirt mit Ansichten dem Nutzer zeigt — je Verbindung eine Karte mit Zeiten, Dauer, Umstiegen und Echtzeit-Lage. **Beantwortest du einem Menschen eine Verbindungsfrage, ruf dies statt `connections`**, das für Ergebnisse ist, die du weiterverarbeitest. **Pflicht sind BEIDE Endpunkte**, wie dort: `origin_id` UND `destination_id` — oder die vier Koordinaten-Felder; `render_payload` entfällt. Der Antwort-Text ist der von `connections`; die Rohdaten daneben tragen nur die Felder, die die Ansicht zeichnet, ihr Kartenverlauf davon im `_meta`. **Anleitung**: `get_usage_guide` mit `tool='connections'`. **Anti-Fab**: Linien, Zeiten, Halte und Gleise ausschließlich aus dem Output dieses Aufrufs.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"accessibility_profile":{"description":"Mobility profile by name: `\"Standard\"` (default), `\"WheelchairRobust\"`,\n`\"WalkerComfort\"` or `\"IndividualComfort\"`. Each bundles its accessibility\nconstraints and walk speed; another name is an argument error. The two\nwheelchair profiles find no ride at all today — the answer then carries\n`accessibility_routing` with `status: no_data` beside ordinary connections,\nwhich are to be reported as ordinary ones. What each profile constrains is\nin the usage guide.","type":["string","null"]},"cycling_profile":{"description":"Wer auf dem Rad sitzt, und damit das Tempo der Rad-Abschnitte: `family`\n(mit kleinen Kindern), `normal` (Default, unverändert) oder `ebike`\n(Pedelec). Ein anderer Name ist ein Argument-Fehler.","type":["string","null"]},"cycling_speed":{"description":"Rad-Tempo in Metern/Sekunde, 1 bis 12 — außerhalb ein Argument-Fehler.\nÜberschreibt `cycling_profile`. Richtwerte: Familie ≈2.8, normal ≈5,\nPedelec ≈6.5.","format":"double","type":["number","null"]},"destination_id":{"description":"Destination id. Same form as `origin_id`.","type":["string","null"]},"destination_lat":{"description":"Destination latitude. Same use as `origin_lat`.","format":"double","type":["number","null"]},"destination_lon":{"description":"Destination longitude. Goes with `destination_lat`.","format":"double","type":["number","null"]},"destination_type":{"description":"What `destination_id` is. Same values as `origin_type`.","type":["string","null"]},"exclude_lines":{"description":"Line blacklist, same token form as `only_lines`. A journey is dropped if\nany transit leg uses one of them.","items":{"type":"string"},"type":["array","null"]},"extended":{"description":"`true` keeps the map data in the text: every stop's coordinate, every\nleg's polyline, and the whole stop sequence with them — for an application\nthat DRAWS the route, at two to three times the answer. A chat client\nleaves it off.","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"]},"include_rental_bike":{"description":"`true` adds a rental-bike leg (park-and-bike / station rental). Equivalent\nto naming `\"bike\"` in `modes` together with a transit mode.","type":["boolean","null"]},"is_arrival_time":{"description":"`true` reads `time` as the desired ARRIVAL time instead of the departure\ntime.","type":["boolean","null"]},"limit":{"description":"Maximum number of journeys, at least 1. Default 5, values above 15 are\nserved as 15.","format":"int64","type":["integer","null"]},"max_transfers":{"description":"Upper bound on interchanges: `0` = direct, up to `3`. Omit unless the user\nconstrains transfers: the backend then derives the search depth from the\ntrip's air-line distance and escalates it when the first attempt finds\nnothing, so omitting never loses a connection.","format":"int64","type":["integer","null"]},"max_walk_meters":{"description":"Cap on the summed walking DISTANCE in metres. Works like\n`max_walk_minutes`, on the metres walked.","format":"int64","type":["integer","null"]},"max_walk_minutes":{"description":"Cap on the summed walking TIME in minutes. A post-filter drops journeys\nabove it; if that leaves nothing, the backend searches once more avoiding\nfootpaths before the answer is empty.","format":"int64","type":["integer","null"]},"mobility_profile":{"description":"How the first and the last mile may be covered, by name: `\"transit\"`\n(default — both ends on foot), `\"transit_plus_sharing\"` (a shared bike),\n`\"door_to_door\"` (being driven), `\"park_and_ride\"` or `\"bike_and_ride\"`\n(one's OWN car or bicycle, left where the transit leg starts). Another name\nis an argument error. It widens those two ends, restricts no ride and\npromises nothing. When to set which, and how it composes with `modes`, is\nin the usage guide.","type":["string","null"]},"modes":{"description":"Transport-mode restriction, not a preference: nothing outside the list is\nplanned. The footpath always stays allowed — the way to, from and between\nstops goes on foot — while `[\"foot\"]` on its own plans no ride at all.\nEntries: `\"bike\"`, `\"bike_rental\"`, `\"foot\"`, `\"car\"`, `\"taxi\"`, `\"scooter\"`,\n`\"transit\"`, `\"bus\"`, `\"tram\"`, `\"rail\"`, `\"subway\"`, `\"ferry\"`; several\ncombine. An entry outside that list is an argument error, not a dropped\nfilter. Omitted or empty = all standard transit modes, the ferry\nincluded. Set only when the user insists on a mode; the guide has the\nvocabulary and the traps.","items":{"type":"string"},"type":["array","null"]},"only_lines":{"description":"Line whitelist. Entries are line tokens as printed on the vehicle (`\"6\"`,\n`\"U3\"`); a journey is kept only if every transit leg uses one of them.","items":{"type":"string"},"type":["array","null"]},"origin_id":{"description":"Origin id. A DHID (`de:NNNNN:NNN`) for a stop, otherwise the resolver's\n`main` id of the address or POI. Resolve the place first — a name here is\nan argument error.","type":["string","null"]},"origin_lat":{"description":"Origin latitude, WGS-84 decimal degrees — the fallback when no id is at\nhand, and the one retry worth making when resolved ids find nothing.","format":"double","type":["number","null"]},"origin_lon":{"description":"Origin longitude. Goes with `origin_lat`.","format":"double","type":["number","null"]},"origin_type":{"description":"What `origin_id` is: `\"stop\"` (default), `\"address\"` or `\"poi\"`. A stop id\nis auto-prefixed `GTFS.de:`; the other two are forwarded verbatim so the\nbackend resolves the real name.","type":["string","null"]},"prefer_flat":{"description":"`true` plant die hügel-ärmste statt der sonst gewählten Rad-Route: die\nSuche gewichtet die Steigung und nimmt dafür Umwege in Kauf, nur auf\nRad-Abschnitten. Keine Zusage — ohne flachere Alternative kommt dieselbe\nRoute; die Höhenmeter der Antwort sagen es. Wann setzen: die Anleitung.","type":["boolean","null"]},"submodes_allow":{"description":"Fine submode whitelist — finer than `modes`, which only separates\nbus/tram/rail/subway. Entries: `\"sbahn\"`, `\"regionalbahn\"`, `\"ice\"`,\n`\"ic\"`, `\"ir\"`, `\"nj\"`, `\"fernverkehr\"`, `\"stadtbahn\"`, `\"ubahn\"`,\n`\"bus\"`, `\"regionalbus\"`, `\"stadtbus\"`. A journey is kept only if every\ntransit leg matches one.","items":{"type":"string"},"type":["array","null"]},"submodes_deny":{"description":"Fine submode blacklist, same vocabulary as `submodes_allow`. A journey is\ndropped if any transit leg matches one.","items":{"type":"string"},"type":["array","null"]},"time":{"description":"ISO 8601 timestamp (e.g. `\"2026-06-15T08:30:00Z\"`). Omit to plan from now.\nResolve a spoken time with the time tool rather than computing one.","format":"date-time","type":["string","null"]},"verbosity":{"description":"How much of each journey comes back: `\"compact\"` (default — everything an\nanswer is cited from) or `\"full\"` (adds the stops in between). A third\nword is an argument error, not the default.","type":["string","null"]},"via_id":{"description":"Intermediate stop the route must pass through („über X\"), as an id in the\nsame form as `origin_id`. The route is then planned A → via → B.","type":["string","null"]},"via_lat":{"description":"Via latitude, for an intermediate address or POI without an id. Goes with\n`via_lon`.","format":"double","type":["number","null"]},"via_lon":{"description":"Via longitude. Goes with `via_lat`.","format":"double","type":["number","null"]},"via_type":{"description":"What `via_id` is. Same values as `origin_type`.","type":["string","null"]},"walk_speed":{"description":"Walking speed of the foot legs in metres/second, between 0.3 and 3 m/s —\noutside that it is an argument error. Default ≈1.33, slow ≈0.7, brisk\n≈2.0. Overrides the walk speed of `accessibility_profile`.","format":"double","type":["number","null"]}},"$schema":"https://json-schema.org/draft/2020-12/schema","description":"Unified connection request. For stops, provide origin_id and destination_id.\nFor arbitrary locations (e.g. addresses, POIs), provide coordinates — and as\nthe one retry worth making when resolved ids find nothing: an id the routing\ngraph does not know answers empty rather than with an error.\n\n`Default` is derived so a caller in a test can name the two or three fields\nits case is about; the request grows by optional fields often enough that\nspelling out two dozen `None`s at every call site is its own source of noise.","title":"ConnectionRequest"}},{"name":"show_connections_slim","description":"**Dieselbe Verbindungs-Ansicht wie `show_connections`, nur schlank ausgeliefert**: das Kartenwerk lädt die Ansicht als Skript, statt es mitzubringen. **Nimm dies nur, wenn ausdrücklich nach der schlanken Auslieferung gefragt wird** — sonst `show_connections`. Sonst unverändert: plant die Fahrt wie `connections` und liefert sie zusätzlich als Ansicht aus. **Pflicht sind BEIDE Endpunkte**, wie dort: `origin_id` UND `destination_id` — oder die vier Koordinaten-Felder; `render_payload` entfällt. Der Antwort-Text ist der von `connections`; die Rohdaten daneben tragen nur die Felder, die die Ansicht zeichnet, ihr Kartenverlauf davon im `_meta`. **Anleitung**: `get_usage_guide` mit `tool='connections'`. **Anti-Fab**: Linien, Zeiten, Halte und Gleise ausschließlich aus dem Output dieses Aufrufs.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"accessibility_profile":{"description":"Mobility profile by name: `\"Standard\"` (default), `\"WheelchairRobust\"`,\n`\"WalkerComfort\"` or `\"IndividualComfort\"`. Each bundles its accessibility\nconstraints and walk speed; another name is an argument error. The two\nwheelchair profiles find no ride at all today — the answer then carries\n`accessibility_routing` with `status: no_data` beside ordinary connections,\nwhich are to be reported as ordinary ones. What each profile constrains is\nin the usage guide.","type":["string","null"]},"cycling_profile":{"description":"Wer auf dem Rad sitzt, und damit das Tempo der Rad-Abschnitte: `family`\n(mit kleinen Kindern), `normal` (Default, unverändert) oder `ebike`\n(Pedelec). Ein anderer Name ist ein Argument-Fehler.","type":["string","null"]},"cycling_speed":{"description":"Rad-Tempo in Metern/Sekunde, 1 bis 12 — außerhalb ein Argument-Fehler.\nÜberschreibt `cycling_profile`. Richtwerte: Familie ≈2.8, normal ≈5,\nPedelec ≈6.5.","format":"double","type":["number","null"]},"destination_id":{"description":"Destination id. Same form as `origin_id`.","type":["string","null"]},"destination_lat":{"description":"Destination latitude. Same use as `origin_lat`.","format":"double","type":["number","null"]},"destination_lon":{"description":"Destination longitude. Goes with `destination_lat`.","format":"double","type":["number","null"]},"destination_type":{"description":"What `destination_id` is. Same values as `origin_type`.","type":["string","null"]},"exclude_lines":{"description":"Line blacklist, same token form as `only_lines`. A journey is dropped if\nany transit leg uses one of them.","items":{"type":"string"},"type":["array","null"]},"extended":{"description":"`true` keeps the map data in the text: every stop's coordinate, every\nleg's polyline, and the whole stop sequence with them — for an application\nthat DRAWS the route, at two to three times the answer. A chat client\nleaves it off.","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"]},"include_rental_bike":{"description":"`true` adds a rental-bike leg (park-and-bike / station rental). Equivalent\nto naming `\"bike\"` in `modes` together with a transit mode.","type":["boolean","null"]},"is_arrival_time":{"description":"`true` reads `time` as the desired ARRIVAL time instead of the departure\ntime.","type":["boolean","null"]},"limit":{"description":"Maximum number of journeys, at least 1. Default 5, values above 15 are\nserved as 15.","format":"int64","type":["integer","null"]},"max_transfers":{"description":"Upper bound on interchanges: `0` = direct, up to `3`. Omit unless the user\nconstrains transfers: the backend then derives the search depth from the\ntrip's air-line distance and escalates it when the first attempt finds\nnothing, so omitting never loses a connection.","format":"int64","type":["integer","null"]},"max_walk_meters":{"description":"Cap on the summed walking DISTANCE in metres. Works like\n`max_walk_minutes`, on the metres walked.","format":"int64","type":["integer","null"]},"max_walk_minutes":{"description":"Cap on the summed walking TIME in minutes. A post-filter drops journeys\nabove it; if that leaves nothing, the backend searches once more avoiding\nfootpaths before the answer is empty.","format":"int64","type":["integer","null"]},"mobility_profile":{"description":"How the first and the last mile may be covered, by name: `\"transit\"`\n(default — both ends on foot), `\"transit_plus_sharing\"` (a shared bike),\n`\"door_to_door\"` (being driven), `\"park_and_ride\"` or `\"bike_and_ride\"`\n(one's OWN car or bicycle, left where the transit leg starts). Another name\nis an argument error. It widens those two ends, restricts no ride and\npromises nothing. When to set which, and how it composes with `modes`, is\nin the usage guide.","type":["string","null"]},"modes":{"description":"Transport-mode restriction, not a preference: nothing outside the list is\nplanned. The footpath always stays allowed — the way to, from and between\nstops goes on foot — while `[\"foot\"]` on its own plans no ride at all.\nEntries: `\"bike\"`, `\"bike_rental\"`, `\"foot\"`, `\"car\"`, `\"taxi\"`, `\"scooter\"`,\n`\"transit\"`, `\"bus\"`, `\"tram\"`, `\"rail\"`, `\"subway\"`, `\"ferry\"`; several\ncombine. An entry outside that list is an argument error, not a dropped\nfilter. Omitted or empty = all standard transit modes, the ferry\nincluded. Set only when the user insists on a mode; the guide has the\nvocabulary and the traps.","items":{"type":"string"},"type":["array","null"]},"only_lines":{"description":"Line whitelist. Entries are line tokens as printed on the vehicle (`\"6\"`,\n`\"U3\"`); a journey is kept only if every transit leg uses one of them.","items":{"type":"string"},"type":["array","null"]},"origin_id":{"description":"Origin id. A DHID (`de:NNNNN:NNN`) for a stop, otherwise the resolver's\n`main` id of the address or POI. Resolve the place first — a name here is\nan argument error.","type":["string","null"]},"origin_lat":{"description":"Origin latitude, WGS-84 decimal degrees — the fallback when no id is at\nhand, and the one retry worth making when resolved ids find nothing.","format":"double","type":["number","null"]},"origin_lon":{"description":"Origin longitude. Goes with `origin_lat`.","format":"double","type":["number","null"]},"origin_type":{"description":"What `origin_id` is: `\"stop\"` (default), `\"address\"` or `\"poi\"`. A stop id\nis auto-prefixed `GTFS.de:`; the other two are forwarded verbatim so the\nbackend resolves the real name.","type":["string","null"]},"prefer_flat":{"description":"`true` plant die hügel-ärmste statt der sonst gewählten Rad-Route: die\nSuche gewichtet die Steigung und nimmt dafür Umwege in Kauf, nur auf\nRad-Abschnitten. Keine Zusage — ohne flachere Alternative kommt dieselbe\nRoute; die Höhenmeter der Antwort sagen es. Wann setzen: die Anleitung.","type":["boolean","null"]},"submodes_allow":{"description":"Fine submode whitelist — finer than `modes`, which only separates\nbus/tram/rail/subway. Entries: `\"sbahn\"`, `\"regionalbahn\"`, `\"ice\"`,\n`\"ic\"`, `\"ir\"`, `\"nj\"`, `\"fernverkehr\"`, `\"stadtbahn\"`, `\"ubahn\"`,\n`\"bus\"`, `\"regionalbus\"`, `\"stadtbus\"`. A journey is kept only if every\ntransit leg matches one.","items":{"type":"string"},"type":["array","null"]},"submodes_deny":{"description":"Fine submode blacklist, same vocabulary as `submodes_allow`. A journey is\ndropped if any transit leg matches one.","items":{"type":"string"},"type":["array","null"]},"time":{"description":"ISO 8601 timestamp (e.g. `\"2026-06-15T08:30:00Z\"`). Omit to plan from now.\nResolve a spoken time with the time tool rather than computing one.","format":"date-time","type":["string","null"]},"verbosity":{"description":"How much of each journey comes back: `\"compact\"` (default — everything an\nanswer is cited from) or `\"full\"` (adds the stops in between). A third\nword is an argument error, not the default.","type":["string","null"]},"via_id":{"description":"Intermediate stop the route must pass through („über X\"), as an id in the\nsame form as `origin_id`. The route is then planned A → via → B.","type":["string","null"]},"via_lat":{"description":"Via latitude, for an intermediate address or POI without an id. Goes with\n`via_lon`.","format":"double","type":["number","null"]},"via_lon":{"description":"Via longitude. Goes with `via_lat`.","format":"double","type":["number","null"]},"via_type":{"description":"What `via_id` is. Same values as `origin_type`.","type":["string","null"]},"walk_speed":{"description":"Walking speed of the foot legs in metres/second, between 0.3 and 3 m/s —\noutside that it is an argument error. Default ≈1.33, slow ≈0.7, brisk\n≈2.0. Overrides the walk speed of `accessibility_profile`.","format":"double","type":["number","null"]}},"$schema":"https://json-schema.org/draft/2020-12/schema","description":"Unified connection request. For stops, provide origin_id and destination_id.\nFor arbitrary locations (e.g. addresses, POIs), provide coordinates — and as\nthe one retry worth making when resolved ids find nothing: an id the routing\ngraph does not know answers empty rather than with an error.\n\n`Default` is derived so a caller in a test can name the two or three fields\nits case is about; the request grows by optional fields often enough that\nspelling out two dozen `None`s at every call site is its own source of noise.","title":"ConnectionRequest"}},{"name":"show_departures","description":"**Der Vordereingang für jede Abfahrtsfrage eines Menschen**: liest die Tafel einer Haltestelle wie `departures` und liefert sie zusätzlich als Ansicht aus, die ein Wirt mit Ansichten dem Nutzer zeigt — je Abfahrt Linie, Ziel, Gleis/Steig, Zeit und Echtzeit-Lage. **Beantwortest du einem Menschen eine Abfahrtsfrage, ruf dies statt `departures`**, das für Ergebnisse ist, die du weiterverarbeitest. **Pflicht ist die Halte-Id**, wie dort: `id` — eine Id aus `resolve_location`, kein Haltestellen-Name; `render_payload` entfällt. Der Antwort-Text ist der von `departures`; die Rohdaten daneben tragen nur die Felder, die die Ansicht zeichnet. **Anleitung**: `get_usage_guide` mit `tool='departures'`. **Anti-Fab**: Linien, Ziele, Zeiten und Gleise ausschließlich aus dem Output dieses Aufrufs.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"arrival_departure":{"description":"`\"arrivals\"` (when vehicles reach `id`) or `\"departures\"` (default) — a\nthird value is an argument error. Wins over `is_arrival_time` when both\nare set.","type":["string","null"]},"bearing_tolerance":{"description":"Angular tolerance in degrees for `target_bearing`. Default ±60°.","format":"double","type":["number","null"]},"direction":{"description":"Name of a stop the user wants to head TOWARD („Richtung Wettbergen\") —\nnot a routing destination. The board keeps only departures heading that\nway, whether the named stop is the terminus or a stop downstream of the\nqueried one. Matching is case-insensitive and area-prefix-tolerant.","type":["string","null"]},"extended":{"description":"`true` keeps the map data in the text: every stop's coordinate, the whole\ncourse of each run, and a polyline where the board carries one — for an\napplication that DRAWS the board. It multiplies the answer. A chat client\nleaves it off.","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"]},"id":{"description":"Stop id to read the board of, as a DHID (`\"de:03241:57\"`). Resolve the\nstop first — a name here is an argument error.","type":"string"},"is_arrival_time":{"description":"`true` reads `time` as an ARRIVAL time — the same as\n`arrival_departure = \"arrivals\"`.","type":["boolean","null"]},"last_of_window":{"description":"Which end of a `time_range_seconds` window to read: omitted or `false` the\nFIRST departures, `true` the LAST ones (the end-of-service question). An\nanswer carrying `window_truncated: true` beside its board did NOT reach the\nwindow's end — its last entry is then not the last departure. Without a\nwindow it has no effect.","type":["boolean","null"]},"limit":{"description":"Maximum number of departures, at least 1. Default 5, values above 15 are\nserved as 15.","format":"int64","type":["integer","null"]},"modes":{"description":"Transport-mode filter; the board then shows nothing else. Entries:\n`\"bus\"`, `\"tram\"`, `\"subway\"`, `\"train\"`/`\"rail\"`, `\"ferry\"`,\n`\"transit\"`; several combine. Another entry — a street mode, a misspelling\n— is an argument error, not a dropped filter: a board lists scheduled\nservices. Omitted or empty = all modes. A Stadtbahn or\nlight-rail mention needs BOTH labels — `[\"tram\",\"subway\"]`: which of the\ntwo such a network carries depends on the dataset rather than on the\nvehicle. Set the filter only when the user really asks for a vehicle type;\nthe guide has the rest of the vocabulary and the traps.","items":{"type":"string"},"type":["array","null"]},"target_bearing":{"description":"Target bearing in degrees (0=N, 90=E, 180=S, 270=W) for a SOFT direction\n(„Richtung Norden\", „Richtung Stadt\") instead of a stop name. The board\nkeeps only departures whose course lies within `bearing_tolerance` of it.\nMutually exclusive with `direction`.","format":"double","type":["number","null"]},"time":{"description":"ISO 8601 timestamp (e.g. `\"2026-06-15T08:30:00Z\"`). Omit for now. Resolve\na spoken time with the time tool rather than computing one.","format":"date-time","type":["string","null"]},"time_range_seconds":{"description":"Time WINDOW in seconds, starting at `time`. Together with `last_of_window`\nthis answers „letzte Fahrt\": pick it so the window ENDS after end of\nservice (from the evening on, `28800` = 8 h rather than 4 h). Omit for a\nnormal next-N lookup.","format":"int64","type":["integer","null"]},"verbosity":{"description":"How much of each departure comes back: `\"compact\"` (default — everything\nan answer is cited from) or `\"full\"` (adds the onward stops of the run,\nand with them the per-stop cancellation marker). A third word is an\nargument error, not the default.","type":["string","null"]}},"required":["id"],"$schema":"https://json-schema.org/draft/2020-12/schema","description":"A departure board for one stop. `Default` is derived for the same reason as\non [`ConnectionRequest`].","title":"TimetableRequest"}}],"scan":{"score":67,"grade":"C","scanned_at":"2026-09-22T21:27:22.519Z","report":{"scannerVersion":"0.1.9","scannedAt":"2026-09-22T21:27:22.528Z","components":{"code":{"score":-1,"max":25,"notes":["remote-only server, no package to scan"]},"reliability":{"score":20,"max":20,"notes":["remote reachable in 800ms"]},"poisoning":{"score":13,"max":15,"notes":["13 tool descriptions checked"]},"auth":{"score":10,"max":15,"notes":["open endpoint, read-only tools"]},"maintenance":{"score":3,"max":15,"notes":["no repository listed"]},"identity":{"score":4,"max":10,"notes":["verified namespace with website, no repo"]}},"findings":[{"id":"poison.long-description","severity":"low","component":"poisoning","title":"Unusually long tool description (over 2,000 characters)","evidence":"tool connections: …Plant ÖPNV-Verbindungen von A nach B, deutschlandweit, Fernrouten eingeschlossen — **als Daten, für Ergebnisse, die du weiterverarbeitest**. Steht `show_connections` in deinem Werkzeug-Satz, ist das der Vordereingang für die Frage eines Menschen. Für „wie komme ich von X nach Y\" kommt die Auskunft aus diesen Werkzeugen, nicht aus dem Allgemeinwissen. **Pflicht sind BEIDE Endpunkte**: `origin_id` UND `destination_id` aus einer Ortsauflösung, mit `origin_type`/`destination_type` — ODER `origin_lat`+`origin_lon`+`destination_lat`+`destination_lon`; ein NAME in einem Id-Feld ist ein Argument-Fehler. **Optional**: `time`, `is_arrival_time`; `via_id` bzw. `via_lat`+`via_lon` mit `via_type`; die hart einschränkenden Filter `modes`, `only_lines`/`exclude_lines`, `submodes_allow`/`submodes_deny`, `max_transfers`, `max_walk_minutes`/`max_walk_meters`, `walk_speed`, `accessibility_profile`, `include_rental_bike`, `prefer_flat`, `mobility_profile`; `verbosity`, `limit`, `render_payload`. **Höhenmeter**: nur Fuß-/Rad-Abschnitte tragen `ascentInMeters`/`descentInMeters`. **Durchbindung**: `staySeated: true` an einem Abschnitt heißt, der Fahrgast bleibt aus dem vorigen sitzen — kein Umstieg, also auch keinen zählen. Fehlt das Feld, ist nichts gesagt; nie selbst herleiten. **Rad-Tempo**: Bei einer Radfahrt setzt `cycling_profile` das Tempo des Fahrers und damit die gemeldete Dauer — `family` bei kleinen Kindern, `ebike` bei E-Bike/Pedelec; sonst weglassen (= `normal`). **Fahrradmitnahme**: Geht es um ein Rad, sprich je Abschnitt `bikeCarriageConditions` aus (Bedingungen des Verbunds zur Abfahrtszeit); `bikesAllowed`/`bikeCarriageNote` sind nur die Grundregel, `bikeCarriageCoverage` die Wissensgrenze. **Genannter Wunsch**: Nennt jemand, was ihn stört (\"nicht in der Innenstadt parken\"), hol die Option, die das löst, als EIGENEN Aufruf (`mobility_profile`) und empfiehl sie aus ihrem Nutzen — mit dem Nachteil, den die Antwort ihr gibt. **Anleitung**: `get_usage_guide` mit `tool='connections'` — lies sie, bevor du filterst. **Anti-Fab**: Linien, Zeiten, Halte, Anlagen und Gleise ausschließlich aus dem Output dieses Aufrufs.…"},{"id":"maint.no-repo","severity":"low","component":"maintenance","title":"No source repository listed"}],"inputs":{"probes":[{"url":"https://ai.projektionisten.eu/mmcp","reachable":true,"authRequired":false,"latencyMs":800,"serverInfo":{"name":"MobilityMCP","version":"0.3.0"}}],"packages":[],"repo":{"found":false},"icon":{"url":null,"source":"none"},"presence":{"stars":null,"forks":null,"downloadsWeek":null,"license":null,"lastPushAt":null,"score":8}}}},"grade_history":[],"reviews":[]}