Busse Göttingen MCP-Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Busse Göttingen MCP-ServerWann fährt der nächste Bus vom Göttingen Bahnhof ab?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Busse Göttingen – MCP-Server
Zweck
Dieser MCP-Server liefert Abfahrten, Tagesfahrpläne und Verbindungen im Göttinger Nahverkehr über die TRIAS-Schnittstelle (VDV 431-2, XML über HTTP POST).
Related MCP server: mcp-sbb-transport
Voraussetzungen und Installation
Node.js ≥ 22
npm install
cp .env.example .envTrage in .env den von Connect Fahrplanauskunft GmbH erhaltenen Wert für RequestorRef ein.
Der RequestorRef ist eine Zugangskennung für die TRIAS-Schnittstelle und wird nicht mit diesem Repository verteilt. Du beantragst ihn selbst bei Connect Fahrplanauskunft GmbH (EFA Deutschland) und trägst ihn in deine eigene .env ein. Ohne gültigen RequestorRef startet der Server nicht.
Start
Für den Produktivbetrieb:
npm run build && npm startWährend der Entwicklung:
npm run devDie Tests sind hermetisch und laufen mit oder ohne lokale .env-Datei: Der RequestorRef wird in tests/setup.ts durch einen Platzhalter ersetzt, und alle Tests laufen gegen einen lokalen Fake-Server, nie gegen die echte Schnittstelle.
Bei jedem Push prüft die GitHub-Action in .github/workflows/ci.yml die Typen, die Tests und den Build (Node.js 22).
Der Server verwendet stdio; stdout ist ausschließlich der MCP-Protokollkanal.
MCP-Client-Konfiguration
Der Server liest seine .env aus dem Arbeitsverzeichnis, in dem er gestartet wird. Deshalb muss der Client ihn mit cwd auf das Projektverzeichnis setzen — sonst findet er die .env nicht und startet mit „RequestorRef fehlt.".
OpenCode (~/.config/opencode/opencode.json):
{
"mcp": {
"servers": {
"busse-goettingen": {
"type": "local",
"command": ["node", "/PFAD/ZUM/PROJEKT/dist/index.js"],
"cwd": "/PFAD/ZUM/PROJEKT"
}
}
}
}Claude Code (~/.claude.json):
{
"mcpServers": {
"busse-goettingen": {
"command": "node",
"args": ["/PFAD/ZUM/PROJEKT/dist/index.js"],
"cwd": "/PFAD/ZUM/PROJEKT"
}
}
}/PFAD/ZUM/PROJEKT steht für das Verzeichnis, in dem du das Projekt geklont hast.
So steht der RequestorRef nicht in der Client-Konfiguration, sondern bleibt in der .env des Projekts. Alternativ kann der Client den RequestorRef auch als Umgebungsvariable setzen; Umgebungsvariablen haben Vorrang vor der .env.
Werkzeuge
stop_search–query(erforderlich), optionaltypeundmaxResults. Sucht Haltestellen und liefert unter anderemstopPointRef; die Suche ist unscharf.departures–stop(Name oderstopPointRef, erforderlich), optionalwhen(UTC),maxResultsundincludeRealtime. Liefert Abfahrten in einem zweistündigen Zeitfenster mit UTC- und Ortszeit.journey–fromundto(Namen oderstopPointRef, erforderlich), optionalwhen(UTC),maxResultsundincludeRealtime. Liefert Verbindungen, Fahrzeiten und Umstiege.timetable–stop(Name oderstopPointRef, erforderlich), optionaldateim FormatJJJJ-MM-TT. Liefert den Tagesfahrplan ohne Echtzeitabfrage.
Bei unscharfer Auflösung nennen data.resolved, data.resolvedFrom oder data.resolvedTo die tatsächlich verwendete Haltestelle. Abweichungen stehen in warnings.
Umgang mit dem RequestorRef
Der RequestorRef ist eine Zugangskennung und verlässt deinen Rechner nicht:
Er steht ausschließlich in
.env, die in.gitignoreliegt..env.exampleenthält nur die Vorlage ohne Wert.Er wird nie protokolliert. Der Server schreibt nichts auf stdout außer dem MCP-Protokoll, und Fehlermeldungen gehen auf stderr.
Er wird aus Fehlertexten entfernt, bevor sie das Werkzeug verlassen (
<RequestorRef>als Platzhalter). Das betrifft auch den Antworttext der Schnittstelle, falls diese den eigenen Request-Body zurückgibt.
Was der Code und was der Zugang betrifft, steht unter Nutzungsbedingungen Connect.
Bekannte Einschränkungen
Die WAF blockiert GET-Anfragen; TRIAS wird deshalb ausschließlich per POST angesprochen.
Das Tageskontingent beträgt 10.000 Aufrufe pro Tag. Der Server zählt seine eigenen Aufrufe mit und weist ab 80 % Auslastung darauf hin.
RequestorRefwird von der API nicht validiert; ein falscher Wert kann erst durch eine API-Antwort auffallen.Die Haltestellen-Auflösung ist unscharf.
data.resolvednennt immer die verwendete Haltestelle.Zeiten werden in UTC und in der Zeitzone
Europe/Berlinausgegeben.Als lokal gekennzeichnet (
isLocal) sind nur die Orte ausGÖTTINGEN_LOCALITIES; voreingestellt ist alleinGöttingen. Gleichnamige Orte wie „Göttingen (Westf)" zählen nicht als lokal.
Verifizierte Beispiele
Live gegen https://v4-api.efa.de/efa/trias geprüft am 20.10.2026 mit
npx tsx scripts/smoke.ts (5 API-Aufrufe):
stop_search
de:03152:33817 Bahnhof, Göttingen (probability 0.25, high)
de:03152:5382 Göttingen Bahnhof (probability 0.25, high)
de:03152:33982 Göttingen Landgericht/Bahnhof (probability 0.239999995)
departures
de:03159:33817::7 | RB86 | Göttingen → Einbeck Mitte
timetabledTime: 2026-10-20T13:25:00Z
timetabledTimeLocal: 2026-10-20T15:25:00+02:00 | realtime: true
warning: Es wurden 20 von mehr Abfahrten zurückgegeben.
timetable
resolved: de:03152:33817, Bahnhof, Göttingen
date: 2026-10-20
RB86 | Göttingen → Einbeck Mitte
timetabledTime: 2026-10-20T13:25:00Z
timetabledTimeLocal: 2026-10-20T15:25:00+02:00
ICE 771 InterCityExpress | Kiel Hbf → Göttingen
timetabledTime: 2026-10-20T13:31:00Z
timetabledTimeLocal: 2026-10-20T15:31:00+02:00
journey
resolvedFrom: de:03152:33817, Bahnhof, Göttingen
resolvedTo: de:03152:33924
departureTime: 2026-10-20T11:10:00Z | departureTimeLocal: 2026-10-20T13:10:00+02:00
arrivalTime: 2026-10-20T11:58:00Z | arrivalTimeLocal: 2026-10-20T13:58:00+02:00
durationMinutes: 48 | interchanges: 2
leg: RB85 | Göttingen → Lenglern Bahnhof
API-Aufrufe: 5Der separate Live-Test der unbekannten ID de:09999:33924 war fehlerfrei und
lieferte confidence: low sowie den Hinweis, dass die ID nicht existiert.
Die aktuelle API-Antwort verwendete dabei Geretsried, Feuerwehrschule;
„Geretsried, Keplerweg“ war ebenfalls in der Antwort enthalten, aber nicht
der zuerst gelieferte Halt. Das ist eine Abweichung von der erwarteten
Fixture-Ausgabe und wird deshalb nicht verschwiegen.
Nutzungsbedingungen Connect
Die Daten dürfen nur für eigene Zwecke verwendet und nicht weiterverkauft werden. Alle Angaben ohne Gewähr.
Code und Zugang
Der Code dieses Servers darf weitergegeben werden. Der Zugang (der RequestorRef) darf es nicht: Die Nutzungsbedingungen von Connect erlauben die Weitergabe der Zugangsdaten nur mit schriftlicher Zustimmung, und Connect behält sich vor, den Zugang bei Verstößen zu sperren.
Ein git clone dieses Projekts enthält kein Credential — die .env ist nicht versioniert. Wer den Code erhält, kann sich mit einem eigenen, bei Connect beantragten RequestorRef Zugang verschaffen. Das ist die beabsichtigte Grenze: Der Code ist offen, der Zugang bleibt bei dem, der ihn beantragt hat.
Wer den Server öffentlich betreiben will (etwa als Dienst für andere), muss das vorher mit Connect klären.
Available Tools
4 toolsdeparturesAbfahrtenA
Liefert Abfahrten einer Haltestelle für ein Zeitfenster von zwei Stunden. stop kann ein Haltestellenname oder eine stopPointRef sein und wird unscharf aufgelöst; when ist ein UTC-Zeitpunkt. includeRealtime steuert Echtzeitdaten, maxResults die Anzahl.
| Name | Required | Description | Default |
|---|---|---|---|
| stop | Yes | ||
| when | No | ||
| maxResults | No | ||
| includeRealtime | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose useful behavior: fuzzy resolution of stop identifiers, UTC semantics for when, a fixed two-hour window, and that includeRealtime toggles realtime data. It omits error behavior for unresolvable stops, defaults, and any rate or data-source caveats.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph that front-loads the core purpose and the two-hour window before moving to parameter behavior. Every clause carries information, though the parameter notes are run together rather than separated, slightly reducing scanability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter tool with no annotations and no output schema, the description covers purpose and all parameters adequately. It does not describe the shape of returned departures or the meaning of realtime vs scheduled entries, which an agent may need to interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does explain all four parameters: stop accepts a name or stopPointRef and is fuzzily resolved, when is a UTC timestamp, includeRealtime controls realtime data, maxResults controls count. It still leaves types, defaults, and maxResults bounds unstated, so it is not fully self-sufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Liefert Abfahrten einer Haltestelle') plus the fixed scope of a two-hour window, which is more precise than the bare title 'Abfahrten'. It does not name or contrast any sibling (stop_search, journey, timetable), so an agent must infer differentiation from the resource alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the resource: an agent can tell this returns a departure board for a stop within a two-hour window. There is no explicit when-to-use/when-not guidance and no reference to the sibling timetable or journey tools, which is a real gap for a transit domain with overlapping tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
journeyFahrten suchenA
Liefert mögliche Verbindungen zwischen zwei Haltestellen mit Strecke, Umstiegen und Zeiten. from und to sind Namen oder stopPointRefs und werden unscharf aufgelöst; when ist UTC. includeRealtime aktiviert Echtzeitdaten, maxResults begrenzt die Verbindungen.
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| from | Yes | ||
| when | No | ||
| maxResults | No | ||
| includeRealtime | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does add real behavioral context: from/to are fuzzy-resolved names or stopPointRefs, when is UTC, includeRealtime toggles live data, maxResults caps the result set. However it is silent on failure behavior (no connection found), defaults, limits, or whether results are cached/scheduled-only.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A tight, front-loaded block: the core purpose comes first, then the parameter semantics. Nearly every clause carries information, with only mild redundancy in re-stating the result contents.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter tool with no annotations and no output schema, the description covers the input contract reasonably well and sketches the return shape (route, transfers, times). It still leaves gaps around error/empty-result behavior, defaults, and depth of realtime semantics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it does: all five parameters are addressed, with the crucial fuzzy-resolution and stopPointRef semantics for from/to and the UTC convention for when. It stops short of giving a concrete format for when, a default for maxResults, or the default for includeRealtime.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb+resource: it returns possible connections between two stops, and it enumerates what those results contain (route, transfers, times). It is clearly distinguishable from siblings like departures or timetable, though it never names them explicitly to reinforce the contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent can infer this is the point-to-point routing tool rather than a stop lookup or departure board. There is no explicit statement of when to prefer journey over departures or timetable, and no prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
stop_searchHaltestellen suchenB
Sucht Haltestellen und liefert stopPointRef, Namen, Orte und Koordinaten. query ist ein Name oder eine Ortsangabe; die Suche ist unscharf. type filtert den TRIAS-Ortstyp, maxResults begrenzt die Treffer.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | ||
| query | Yes | ||
| maxResults | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations the description carries the full burden, and it does disclose two useful traits: the match is fuzzy and the result includes coordinates/references. It says nothing about auth requirements, rate limits, or failure behavior, which leaves meaningful gaps for a network-backed lookup.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly packed sentences with the purpose and return contents front-loaded and parameter notes following. Nothing is padded, though the parameter sentence could be split for readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description compensates by naming the returned fields and the semantics of every parameter. Only the unspecified 'type' values and the absence of downstream-usage hints keep it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description is the only source of parameter meaning, and it covers all three: query as name-or-place with fuzzy matching, type as a TRIAS place-type filter, and maxResults as a result cap. It does not enumerate the allowed 'type' values, which is the one remaining gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (searches stops) and enumerates the return fields (stopPointRef, names, places, coordinates), so an agent can tell it apart from departures/journey/timetable. It stops short of explicitly naming or contrasting those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use or when-not-to-use guidance and no mention of alternatives. The only implicit signal is that 'query' is a name or place, but nothing tells the agent whether to reach for this before departures or timetable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timetableTagesfahrplanA
Liefert den Tagesfahrplan einer Haltestelle für ein Datum. stop kann ein Name oder eine stopPointRef sein und wird unscharf aufgelöst; date ist JJJJ-MM-TT in Europe/Berlin. Echtzeit wird hier nicht abgefragt.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | ||
| stop | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses that stop names are fuzzy-resolved, that the date is interpreted in Europe/Berlin, and that no realtime data is involved, but it says nothing about ambiguous-stop handling, error behavior, or result volume/cap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each earning its place: purpose first, then the two parameters with their formats, then the scoping exclusion. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read tool with no output schema and no annotations, the description covers the essentials: what is returned in principle, parameter formats, timezone, and fuzzy matching. It stops just short of describing output shape or the omitted-date default.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it largely does: 'stop' is documented as accepting either a name or a stopPointRef with fuzzy resolution, and 'date' as YYYY-MM-DD in Europe/Berlin. The only gap is that 'date' is optional yet no default behavior (e.g. today) is stated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: it returns the daily timetable for a stop on a given date. The clause 'Echtzeit wird hier nicht abgefragt' implicitly separates it from the sibling 'departures', but no sibling is named, so differentiation requires inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear exclusions signal — realtime is not fetched here — which tells the agent when to look elsewhere. However, it never names the alternative tool (departures) nor states prerequisites, so the routing is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.1.0- First observed
departures - First observed
journey - First observed
stop_search - First observed
timetable
TDQS
Scored across 4 tools
Each tool targets a distinct operation: stop_search returns stop references, departures gives a two-hour departure window, journey computes connections between stops, and timetable returns a full-day schedule. departures and timetable both relate to a stop but differ by time horizon and real-time inclusion, so confusion is limited.
stop_search uses a verb_noun snake_case pattern, while departures, journey, and timetable are bare nouns. The set is readable but lacks a single predictable naming convention.
Four tools cover the core read-only transit queries without redundancy. Each earns its place and the count is well within a healthy range.
The surface covers stop lookup, departures, journey planning, and timetable, which are the main transit information needs. Minor gaps remain, such as nearby-stop search or line/disruption details, but agents can work around them.
Maintenance
Related MCP Connectors
Journeys, departures, line courses, disruptions in Germany; nearby sharing as currently reported.
Read-only public transit departures, stop search, and city coverage for bus and train users.
Real-time transit stops, routes, arrivals, vehicle positions, and schedules via OneBusAway APIs.
Norwegian trains, buses and ferries: live trips and departures (Entur). Free, no key.
Related MCP Servers
- FlicenseDqualityDmaintenanceProvides access to Berlin's public transport data through the VBB API, enabling users to search stops, get departures, and plan journeys across Berlin-Brandenburg.36-
- FlicenseNot gradedqualityDmaintenanceEnables querying Swiss public transport (trains, buses, trams, boats) for stations, connections, and station boards via the opendata.ch API.-
- AlicenseAqualityCmaintenanceEnables querying public transit data through the Transitous MOTIS API, including station search, journey routing, and generic API actions with caching and rate limiting.4MIT
- AlicenseNot gradedqualityBmaintenanceEnables querying global transit data including agencies, routes, stops, and departures through a GTFS aggregator.8 npmMIT