SBB Open Data MCP Server
This server connects AI models to Swiss Federal Railways (SBB) open data from data.sbb.ch β no API key required. It enables:
π Passenger frequency β Retrieve daily average boardings/alightings (DTV, DWV, DNWV) by station, canton, or year.
π¨ Live rail disruptions β Fetch real-time Swiss rail traffic messages (titles, descriptions, causes, affected lines), updated every 5 minutes.
ποΈ Infrastructure projects β Browse active SBB station and line construction projects, filterable by city or project type.
π’ Real estate projects β Explore SBB property developments (residential/commercial), filterable by city or phase (planning, construction, completed).
π Train counts per segment β Get yearly train counts per route for operators like SBB, BLS, SOB, and DB, including passenger and freight traffic.
π€οΈ Platform data β Look up platform length, area, type (e.g. Mittelperron), and step-free accessibility for any SBB station.
π Rolling stock β Retrieve technical specs on trains/railcars including seating capacity (1st/2nd class), year built, length, and weight.
π Station comparison β Side-by-side comparison of up to 10 stations across passenger frequency and platform capacity datasets.
π Stop search β Search the full Swiss DiDok register (all public transport operators) by name or canton, returning UIC numbers, coordinates, and operator info.
π¦ Dataset catalogue β Discover all ~89 available SBB open datasets with IDs, titles, record counts, and update frequencies.
Click on "Install 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., "@SBB Open Data MCP ServerAre there any current disruptions on the Swiss rail network?"
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.
π sbb-opendata-mcp
π¨π Part of the Swiss Public Data MCP Portfolio
MCP server connecting AI models to Swiss Federal Railways (SBB) open data β passenger frequency, live rail disruptions, infrastructure & real-estate projects, train counts, platform data, rolling stock and station search from data.sbb.ch. No API key required.
Demo
Overview
sbb-opendata-mcp gives AI assistants like Claude direct access to public SBB data β no copy-pasting or manual API calls. A question like "How many passengers passed through ZΓΌrich HB every day in 2024?" is answered with real measured data.
The SBB Open Data portal speaks the OpenDataSoft REST API (v2.1). This server
translates it into clean Markdown and JSON for the AI model, and adds MCP
structuredContent alongside the human-readable text so programmatic clients can
consume the underlying records without re-parsing. The server is model-agnostic
and works with any MCP-compatible client.
Anchor demo query: "Compare ZΓΌrich HB, Bern and Basel SBB by passenger frequency and platform capacity." β More use cases by audience β
Related MCP server: swiss-rail-mcp
Features
π Passenger frequency β boardings/alightings by station and year (daily averages)
π¨ Live rail disruptions β traffic messages, updated every 5 minutes
ποΈ Infrastructure projects β station and line construction
π’ Real-estate projects β SBB property development (daily updates)
π Trains per segment β train counts per route (SBB, BLS, SOB β¦)
π€οΈ Platform data β length, type, area, step-free access
π Rolling stock β capacity and year built
π Station comparison β up to 10 stations across multiple datasets
π Stop search β Swiss DiDok register (all of Switzerland)
π¦ Dataset catalogue β list all ~89 SBB open datasets
π No API key β all data is public and free to use
βοΈ Dual transport β stdio for Claude Desktop, Streamable HTTP for cloud deployment
Prerequisites
Python 3.11+
No API key β all data comes from the public data.sbb.ch portal
Install uv (recommended):
curl -LsSf https://astral.sh/uv/install.sh | shInstallation
From PyPI:
pip install sbb-opendata-mcpOr with uvx (no permanent installation):
uvx sbb-opendata-mcpFor local development, install from a clone in editable mode:
git clone https://github.com/malkreide/sbb-opendata-mcp.git
cd sbb-opendata-mcp
pip install -e ".[dev]"Quickstart
# Start the server (stdio mode for Claude Desktop)
sbb-opendata-mcpTry it immediately in Claude Desktop:
"How many people boarded at ZΓΌrich HB daily in 2024?" "Are there any current disruptions on the Swiss rail network?"
Configuration
Environment Variables
The server needs no configuration to run over stdio. The variables below tune the optional Streamable HTTP transport, logging and observability.
Variable | Effect | Default |
| Bind host for the HTTP transport. Keep |
|
| Port for the HTTP transport. |
|
| Comma-separated host allow-list for DNS-rebinding protection (e.g. | localhost only |
| Comma-separated browser-origin allow-list (e.g. | (none) |
| Log verbosity ( |
|
|
|
|
π DNS-rebinding / Origin protection is always on; localhost is allow-listed so local HTTP development works out of the box. Logs go to stderr β stdout is reserved for the stdio JSON-RPC channel.
Claude Desktop Configuration
{
"mcpServers": {
"sbb-opendata": {
"command": "uvx",
"args": ["sbb-opendata-mcp"]
}
}
}Config file locations:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Restart Claude Desktop β the server is downloaded automatically on first use.
Other MCP Clients
Works with Cursor, Windsurf, VS Code + Continue, LibreChat, Cline and self-hosted
models via mcp-proxy β same configuration as above.
Cloud Deployment (Streamable HTTP)
For use via claude.ai in the browser or remote servers (e.g. Render.com). The cloud transport is Streamable HTTP (endpoint /mcp).
Docker (recommended):
# Build + run with explicit resource limits (see docker-compose.yml)
docker compose up --build
# β http://127.0.0.1:8000/mcpThe image is a multi-stage build running as a non-root user; docker-compose.yml
adds read_only, no-new-privileges and memory/CPU/PID limits.
Manual / Render.com:
pip install -e .
# Bind publicly (behind a rate-limiting reverse proxy) and configure
# DNS-rebinding / Origin protection for your hostname:
export MCP_HOST=0.0.0.0
export MCP_ALLOWED_HOSTS="your-app.onrender.com,your-app.onrender.com:*"
export MCP_ALLOWED_ORIGINS="https://your-app.onrender.com"
python -m sbb_opendata_mcp.server --http --port 8000β οΈ Binding: In a network transport the server binds to
127.0.0.1by default so a locally started server is not exposed to your whole network. SetMCP_HOST=0.0.0.0only in a container/cloud environment where binding to all interfaces is intended (the Docker image does this for you), and place the server behind a reverse proxy that enforces rate limiting (and authentication, if the endpoint should not be public). SeeSECURITY.md.
Available Tools
Tool | Description | Data Update |
| Boardings/alightings by station and year (daily avg.) | Annual |
| Live rail traffic messages | Every 5 min. |
| SBB real estate development projects | Daily |
| Train counts per route segment (SBB, BLS, SOB β¦) | Annual |
| Platform data (length, type, area) | Ongoing |
| Rolling stock (capacity, year built) | Ongoing |
| Compare up to 10 stations (multi-dataset) | β |
| Search stops (Swiss DiDok register, all CH) | Ongoing |
| List all ~89 SBB open datasets | β |
All tools support response_format: "markdown" (human-readable) and "json"
(machine-readable), plus pagination. Every tool also returns MCP structuredContent
(the underlying records/metadata) alongside the rendered text.
Example Use Cases
Query | Tool |
"How many people boarded at ZΓΌrich HB daily in 2024?" |
|
"Are there any current disruptions on the Swiss rail network?" |
|
"Compare ZΓΌrich HB, Bern and Basel SBB" |
|
"Which SBB real-estate construction projects are running?" |
|
"How many trains run yearly on the ZΓΌrichβWinterthur route?" |
|
"Which stops exist in WΓ€denswil?" |
|
β More use cases by audience
Architecture
βββββββββββββββββββ βββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
β Claude / AI ββββββΆβ SBB Open Data MCP ββββββΆβ data.sbb.ch β
β (MCP Host) βββββββ (MCP Server) βββββββ β
βββββββββββββββββββ β β β OpenDataSoft REST v2.1 β
β 9 Tools β β (public, no API key) β
β Stdio | Streamable HTTP β β β
β β β passagierfrequenz β
β Shared httpx client β β rail-traffic-information β
β (pooled, lifespan-managed)β β construction-projects β
β ODSQL escaping + Pydantic β β perron Β· rollmaterial β
β validation β β zugzahlen Β· dienststellenβ
βββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββProject Structure
sbb-opendata-mcp/
βββ src/sbb_opendata_mcp/
β βββ __init__.py
β βββ server.py # FastMCP server, all 10 tool definitions
βββ tests/
β βββ test_server.py # Unit + live API smoke tests
βββ audits/ # MCP best-practice audit evidence
βββ docs/assets/demo.svg # README demo asset
βββ .github/workflows/ci.yml # GitHub Actions (Python 3.11/3.12/3.13)
βββ Dockerfile # Multi-stage, non-root runtime image
βββ docker-compose.yml # Local run with resource limits
βββ claude_desktop_config.json # Example Claude Desktop config
βββ pyproject.toml
βββ CHANGELOG.md
βββ CONTRIBUTING.md
βββ SECURITY.md
βββ EXAMPLES.md
βββ LICENSE
βββ README.md # This file (English)
βββ README.de.md # German versionSafety & Limits
Read-only: All 9 tools perform read-only HTTP GET requests β no data is written, modified, or deleted upstream.
No personal data: Queries are transient and not stored. The portal returns aggregated statistics, infrastructure and operational metadata. No PII is processed or retained.
No API key: Data is public and free. There is no authentication and no secret to manage.
Injection-hardened:
year/cantonare regex-validated and every value interpolated into an ODSQLwhereclause is escaped via a central helper.Data freshness: Real-time tools (disruptions) reflect the upstream source at query time; statistical datasets update annually/daily (see the tool table).
Terms of service: Data is published under the data.sbb.ch licence (NonCommercialAllowed-CommercialAllowed-ReferenceRequired).
No guarantees: This server is a community project, not affiliated with SBB. Availability depends on the upstream API.
See SECURITY.md for the full security posture.
Known Limitations
Passenger frequency: Updated annually; the latest full year may lag by some months.
Rail disruptions: Returns all current Swiss rail messages β use
limitand pagination.Trains per segment: Counts are yearly aggregates, not real-time.
Station search: Covers the full Swiss DiDok register (all operators), not just SBB.
No rate limiting of its own: Place a public HTTP deployment behind a rate-limiting reverse proxy.
MCP Protocol Version
This server speaks two protocol eras over the same endpoint. The client's first request on a connection decides which one applies; a later claim from the other era is refused.
Era | Revision | Who reaches it |
|
| What today's clients speak. The server answers with the revision asked for, or with the |
Per-request envelope |
| A request carrying the |
Both revisions are pinned in
tests/test_protocol_version.py and asserted
against the installed SDK, so a Dependabot bump of mcp cannot move either one
silently. This server builds no ASGI app to send an initialize through, so
the gate asserts the SDK constants rather than a measured response β the
weaker form, named rather than left unsaid.
Note that the SDK's LATEST_PROTOCOL_VERSION is an alias for the modern
era, not for the handshake era β pinning against it alone would leave the era
that current clients actually negotiate free to drift.
Update policy. When the gate fails, do not edit the constant blindly: read
the spec changelog between the two revisions, verify the server still behaves,
then move the constant, this section, README.de.md and
CHANGELOG.md together.
Testing
No API key is required.
# Unit tests (no network required)
PYTHONPATH=src pytest tests/ -m "not live"
# Live API smoke tests (require network access to data.sbb.ch)
PYTHONPATH=src pytest tests/ -m live
# Re-record the fixtures from data.sbb.ch (writes tests/fixtures/PROVENANCE.md)
python scripts/record_fixtures.pyThe unit-test payloads are recorded, not invented. Source, retrieval date,
selection rule and SHA-256 per file are in
tests/fixtures/PROVENANCE.md.
tests/fixtures/dataset_fields.json is not a data excerpt but the contract:
the Explore v2.1 API declares each dataset's field names, and a select or
order_by on a field it does not have is answered with HTTP 400 β not with
fewer columns. TestFieldContract holds every field name the server uses
against that declaration, so the next rename fails a test instead of a user's
request. Until 2026-08-08 three of ten tools were permanently broken for
exactly this reason.
Live tests are not run by CI (
-m "not live"). Two of those three broken tools had live tests covering them βtest_live_search_waedenswilandtest_live_list_datasets. The coverage existed; the run did not.
Changelog
See CHANGELOG.md
Contributing
See CONTRIBUTING.md
Security
See SECURITY.md (Deutsch) for the security posture and how to report a vulnerability.
License
MIT License β see LICENSE
Author
Hayal Oezkan Β· github.com/malkreide
Credits & Related Projects
Data: data.sbb.ch β Swiss Federal Railways (SBB) Open Data, OpenDataSoft REST API v2.1
Protocol: Model Context Protocol β Anthropic / Linux Foundation
Related:
swiss-transport-mcp β real-time timetables, journeys & disruptions (opentransportdata.swiss)
swiss-road-mobility-mcp β micromobility & EV charging
zurich-opendata-mcp β MCP server for Zurich city open data
Portfolio: Swiss Public Data MCP Portfolio
Installation
Run via uv's uvx β no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):
{
"mcpServers": {
"sbb-opendata-mcp": {
"command": "uvx",
"args": [
"sbb-opendata-mcp"
]
}
}
}Available Tools
10 toolssbb_compare_stationsARead-onlyIdempotent
Vergleicht mehrere SBB-BahnhΓΆfe anhand Passagierfrequenz und Perrondaten.
Kombiniert drei DatensΓ€tze (Passagierfrequenz, Bahnhofnutzer, Perrons) zu einem kompakten Vergleich. NΓΌtzlich fΓΌr Planungsentscheide, PrΓ€sentationen und Standortanalysen.
Args: params (CompareStationsInput): Parameter: - stations (list[str]): Liste von Bahnhofsnamen (2β10), z.B. ['ZΓΌrich HB', 'Bern'] - year (Optional[str]): Vergleichsjahr, z.B. '2024'
Returns: str: Tabellarischer Vergleich der BahnhΓΆfe mit Passagierfrequenz und Perron-Kennzahlen.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is clear. The description adds that it combines three datasets and returns a table, but doesn't disclose potential failure modes (e.g., unknown station names) or default behavior for year, which is a moderate gap.
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?
The description is well-structured with a clear lead sentence, a context sentence, and organized Args/Returns sections. It is somewhat redundant with the schema (listing parameters) but remains compact and scannable.
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?
There is no output schema, but the Returns section specifies a tabular string with passenger frequency and platform metrics, which is helpful. However, the description omits the response_format option and does not address error handling, making it not fully complete for an agent to invoke correctly in all cases.
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?
The description covers stations and year with examples and constraints, but omits the 'response_format' parameter entirely. While the nested schema provides detailed descriptions, the top-level 'params' has 0% schema coverage, so the description partially compensates but remains incomplete.
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 opens with 'Vergleicht mehrere SBB-BahnhΓΆfe anhand Passagierfrequenz und Perrondaten', a specific verb+resource+criteria. It further distinguishes itself from sibling single-dataset tools by stating it 'Kombiniert drei DatensΓ€tze...' to create a compact comparison, clearly establishing its unique role.
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?
It explicitly lists use cases ('NΓΌtzlich fΓΌr Planungsentscheide, PrΓ€sentationen und Standortanalysen'), providing clear context. However, it does not mention alternatives or when not to use this tool relative to the sibling getters, so it lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_get_infrastructure_construction_projectsARead-onlyIdempotent
Ruft laufende SBB-Infrastruktur-Bauprojekte (BahnhΓΆfe, Strecken, Ausbau) ab.
EnthΓ€lt Projektname, Ort, Projektart, Angebotsschritt und Links zu Projektseiten. Geeignet fΓΌr Stadtplanung, Kommunikation und Raumplanung.
Args: params (ConstructionProjectsInput): Parameter: - city (Optional[str]): Ortsfilter, z.B. 'ZΓΌrich', 'Basel' - project_type (Optional[str]): Projektart, z.B. 'ausbau' - limit (int): Max. Resultate - offset (int): Paginierung - response_format (str): 'markdown' oder 'json'
Returns: str: Liste Infrastruktur-Bauprojekte mit Ort, Art und Projektlinks. Schema: {name, location, type, category, link}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (read-only, idempotent, non-destructive). The description adds value by detailing the return schema (name, location, type, category, link) and explaining the meaning of parameters, which goes beyond the annotation coverage. It does not contradict annotations.
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?
The description is well-structured with a concise opening sentence, a note on contents, a usage line, and clearly formatted Args/Returns sections. Every sentence is informative and there is no redundancy or fluff.
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?
Given the lack of an output schema, the description includes a useful return schema. It also documents all parameters and their purpose, covering the essentials. However, it does not explicitly mention default values (limit=20, offset=0, response_format=markdown) which are present in the schema, so it is not fully self-contained but still sufficiently complete for an agent.
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?
The input schema has only a top-level 'params' field with no description, and nested properties like limit, offset, and response_format lack descriptions. The description compensates by listing all five properties with types, meanings, and examples (e.g., city 'ZΓΌrich', project_type 'ausbau', limit max results, offset pagination, response_format markdown/json).
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 clearly states the tool fetches running SBB infrastructure construction projects (stations, routes, expansion) and lists the contained fields (name, location, type, procurement step, links). This specific verb+resource combination distinguishes it from siblings like sbb_get_real_estate_projects.
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?
The description provides clear usage context by stating it is suitable for city planning, communication, and spatial planning. However, it does not explicitly mention when not to use it or name alternative tools, so it lacks exclusions but still offers strong contextual guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_get_passenger_frequencyARead-onlyIdempotent
Ruft Passagierfrequenzdaten (Ein-/Aussteigende) fΓΌr SBB-BahnhΓΆfe ab.
Datensatz wird jΓ€hrlich aktualisiert. EnthΓ€lt Tagesschnitt (DTV), Werktagesschnitt (DWV) und Nicht-Werktages-Schnitt (DNWV) pro Bahnhof und Jahr.
Args: params (PassengerFrequencyInput): Filterparameter: - station_name (Optional[str]): Bahnhofsname (Teilsuche) - canton (Optional[str]): KantonskΓΌrzel, z.B. 'ZH' - year (Optional[str]): Jahr, z.B. '2024' - limit (int): Max. Resultate (1β100), Standard 20 - offset (int): Offset fΓΌr Paginierung - response_format (str): 'markdown' oder 'json'
Returns: str: Passagierfrequenzdaten mit DTV/DWV-Werten und Paginierungsinfo. Schema: {station, year, daily_avg, workday_avg, non_workday_avg, canton, operator}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds valuable context beyond this: the dataset is updated annually, contains specific average metrics, and the return includes pagination information. This enriches the behavioral understanding without contradicting annotations.
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?
The description is well-structured and concise: a lead sentence on purpose, a brief dataset context, an Args list, and a Returns schema. Every section earns its place without redundancy. It is front-loaded and not overly verbose.
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?
The description is complete for a read-only data retrieval tool: it specifies the dataset scope, update frequency, available metrics, all input parameters with defaults, and a return schema (despite no output schema). Combined with strong annotations, the agent has everything needed to select and invoke the tool correctly.
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?
Although the schema already describes each parameter, the description's Args section adds practical examples and constraints (e.g., 'ZH', '2024', partial search for station_name, default limit 20, response_format options). Since schema coverage is contextually marked as 0% (though schema has descriptions), the description effectively compensates by providing detailed parameter semantics.
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 begins with a clear, specific verb-resource pair: 'Ruft Passagierfrequenzdaten (Ein-/Aussteigende) fΓΌr SBB-BahnhΓΆfe ab' (retrieves passenger frequency data for SBB stations). It further specifies the contained metrics (DTV, DWV, DNWV) and distinguishes itself from sibling tools like disruptions or construction projects.
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?
The description implies usage for passenger frequency queries but does not explicitly state when to use it vs alternatives. No exclusions or alternative tool names are provided. The context is clear, but the guidance is implicit rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_get_platform_dataARead-onlyIdempotent
Ruft Perrondaten (LΓ€nge, FlΓ€che, Typ) fΓΌr SBB-BahnhΓΆfe ab.
EnthΓ€lt PerronlΓ€nge (m), Netto-/BruttoflΓ€che (mΒ²), Perrontyp und Angaben zur schienenfreien ZugΓ€nglichkeit.
Args: params (PlatformDataInput): Parameter: - station_name (Optional[str]): Bahnhofsname, z.B. 'ZΓΌrich HB' - platform_type (Optional[str]): Perrontyp, z.B. 'Mittelperron' - limit (int): Max. Resultate - offset (int): Paginierung - response_format (str): 'markdown' oder 'json'
Returns: str: Perrondaten mit LΓ€nge, FlΓ€che und Typ. Schema: {station, platform_nr, type, length_m, gross_area_m2, net_area_m2, accessible}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive. The description adds context about the specific data returned (units, accessibility) and the output schema, exceeding basic annotation coverage. No contradictions with annotations.
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?
The description is structured with a summary, args, and returns sections. It is somewhat repetitive (schema repeated) but front-loads the purpose and stays within reasonable length for a data-retrieval tool.
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?
Given the lack of an output schema, the description provides a return schema and parameter details, making it self-contained. It does not address edge cases like filtering behavior or pagination caps, but covers essential invocation and output expectations.
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%, but the description lists all parameters with types, examples, and German explanations. It adds meaning by defining 'limit' as 'Max. Resultate' and pagination, and clarifies optional fields, compensating well for the schema 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?
The description clearly states the tool retrieves platform data (length, area, type) for SBB stations, using a specific verb ('Ruft ab') and resource. It distinguishes itself from sibling tools by focusing on platform-specific metrics, making the purpose unambiguous.
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?
The description implies use for platform information via its content but does not explicitly state when to use it over sibling tools or mention alternatives. No exclusion criteria or use-case guidance is provided beyond the inherent purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_get_rail_disruptionsARead-only
Ruft aktuelle BahnverkehrsstΓΆrungen und -meldungen ab (alle 5 Minuten aktualisiert).
EnthΓ€lt Titel, Beschreibung, Ursache, Start-/Endzeitpunkt und betroffene Linien. Ideal fΓΌr Echtzeit-Monitoring und Kommunikation bei Ereignissen.
Args: params (RailDisruptionsInput): Parameter: - limit (int): Max. Meldungen (1β100), Standard 20 - offset (int): Offset fΓΌr Paginierung - response_format (str): 'markdown' oder 'json'
Returns: str: Liste aktueller StΓΆrungsmeldungen mit Zeitfenstern und Beschreibungen. Schema: {title, description, published, start, end, type, author}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and destructiveHint, and the description adds valuable context: data is refreshed every 5 minutes, and the response includes cause, affected lines, and time windows. No contradictions with annotations.
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?
The description is well-structured with a short summary, use-case sentence, parameter list, and return format. Every sentence adds value, and the layout is clean and easy to scan.
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 read-only data-retrieval tool with one nested parameter and no output schema, the description fully covers what the tool returns (list of records with title, description, published, start, end, type, author), the update frequency, and the available parameters. It is complete for its purpose.
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?
The description includes an 'Args' section that explains each parameter (limit, offset, response_format) with default values and allowed options. While the schema also describes these, the description makes the tool usable without needing to inspect the schema, adding clarity.
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 uses a specific verb 'abruft' (retrieves) with a clear resource: current rail disruptions and messages. It explicitly mentions the live update interval (alle 5 Minuten) which distinguishes it from related SBB data tools, making its purpose unmistakable.
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?
It states 'Ideal fΓΌr Echtzeit-Monitoring und Kommunikation bei Ereignissen' which clearly indicates when to use the tool. It does not explicitly name alternatives, but the sibling tools cover other data domains, so the context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_get_real_estate_projectsARead-onlyIdempotent
Ruft laufende SBB-Immobilien-Bauprojekte (Wohn- und GeschΓ€ftsbauten) ab.
TΓ€glich aktualisiert. EnthΓ€lt Projektname, Stadt, Bauphase, NutzflΓ€che, Baudaten und Beschreibungen (DE/FR/IT/EN).
Args: params (RealEstateProjectsInput): Parameter: - city (Optional[str]): Stadt, z.B. 'ZΓΌrich', 'Bern', 'Luzern' - phase (Optional[str]): Projektphase, z.B. 'CONSTRUCTION', 'PLANNING' - limit (int): Max. Resultate - offset (int): Paginierung - response_format (str): 'markdown' oder 'json'
Returns: str: Immobilien-Bauprojekte mit Baustart, Einzug und NutzflΓ€che. Schema: {title, city, phase, start_of_construction, move_in, area_m2, description}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only and non-destructive behavior. The description adds value by disclosing that data is updated daily and that descriptions come in DE/FR/IT/EN, which are not evident from annotations. It also clarifies the output format (markdown/json) and return schema, giving the agent a fuller behavioral picture.
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?
The description is well-structured with a clear header sentence, a data freshness/contents note, and separate Args and Returns blocks. It is not overly verbose, though the Args block duplicates schema property information. Overall, it is efficient and easy to scan, earning a solid score.
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?
The description includes the output schema inline, compensating for the lack of a structured output schema. It covers the key fields (title, city, phase, start_of_construction, move_in, area_m2, description) and mentions daily updates. However, it does not address pagination limitations or error handling, which is a minor gap for a data retrieval tool.
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?
The description provides meaningful examples for city ('ZΓΌrich', 'Bern', 'Luzern') and phase ('CONSTRUCTION', 'PLANNING'), and explains limit as 'Max. Resultate' and offset as 'Paginierung'. While the schema already describes city and phase, the description covers all parameters with usage context, adding value beyond raw schema definitions. The response_format parameter is also clarified with 'markdown' oder 'json'.
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 uses specific verb 'Ruft ab' (fetches/retrieves) with a clearly defined resource: 'SBB-Immobilien-Bauprojekte (Wohn- und GeschΓ€ftsbauten)'. This distinguishes it from sibling tools like infrastructure construction projects by scope (real estate vs. infrastructure). The inclusion of a daily update note and field list further clarifies the specific resource.
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?
The description implies usage for fetching real estate construction projects but provides no explicit guidance on when to use this tool versus alternatives. It does not state exclusions or mention sibling tools, leaving the agent to infer context. The daily update note offers minimal contextual cue but not enough for clear alternative selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_get_rolling_stockARead-onlyIdempotent
Ruft technische Daten zum SBB-Rollmaterial (ZΓΌge, TriebzΓΌge, Wagen) ab.
EnthΓ€lt Fahrzeugtyp, SitzplatzkapazitΓ€t (1./2. Kl.), Baujahr, LΓ€nge und Gewicht.
Args: params (RollingStockInput): Parameter: - vehicle_type (Optional[str]): Fahrzeugtyp, z.B. 'IC 2000', 'TGV', 'FV-Dosto' - limit (int): Max. Resultate - offset (int): Paginierung - response_format (str): 'markdown' oder 'json'
Returns: str: Rollmaterial-Daten mit KapazitΓ€t, Baujahr und technischen Kennzahlen. Schema: {vehicle_type, built_year, seats_1st, seats_2nd, total_seats, length_mm, weight_t}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool as read-only, idempotent, and non-destructive. The description adds a useful return schema and notes pagination behavior, enriching the behavioral context without overstepping annotation coverage.
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?
The description is efficiently structured with a clear purpose statement, a content overview, parameter documentation, and return schema. Every sentence adds value, and the format is easy to scan.
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 rich annotations and no output schema, the description provides everything needed: input parameter docs, return schema, and purpose. A complete picture for a read-only query tool.
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%, but the description thoroughly documents all four nested parameters with types, defaults, and examples (e.g., vehicle types). This fully compensates for the absence of schema descriptions.
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 clearly states the tool retrieves technical data about SBB rolling stock, listing specific content types (vehicle type, seating capacity, year, length, weight). This distinct resource differentiates it from all sibling tools, which focus on other data domains.
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?
The context of use is clear (need rolling stock technical data), but there is no explicit guidance on when to use this tool versus alternatives, nor any mention of exclusions. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_get_trains_per_segmentARead-onlyIdempotent
Ruft Anzahl ZΓΌge pro Streckenabschnitt und Verkehrstyp ab.
Deckt SBB, BLS, SOB, DB und weitere Infrastrukturbetreiberinnen ab. EnthΓ€lt Personenverkehr und GΓΌterverkehr, Trassenkilometer und Stromverbrauch.
Args: params (TrainsPerSegmentInput): Parameter: - line_name (Optional[str]): Streckenbezeichnung (Teilsuche) - operator (Optional[str]): Infrastrukturbetreiberin, z.B. 'SBB', 'BLS' - year (Optional[str]): Jahr, z.B. '2025' - traffic_type (Optional[str]): 'Personenverkehr' oder 'Gueterverkehr' - limit (int): Max. Resultate - offset (int): Paginierung - response_format (str): 'markdown' oder 'json'
Returns: str: Zugzahlen pro Streckenabschnitt mit Operator und Traffiktyp. Schema: {segment, line, operator, year, train_count, traffic_type, track_km}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false. The description adds context about data coverage (operators, traffic types, track_km, Stromverbrauch) and the return schema, but does not disclose additional behavioral traits such as pagination behavior or rate limits. It does not contradict annotations.
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?
The description is well-structured with an introductory paragraph, a bulleted Args list, and a Returns section. Every part is relevant, though it could be slightly trimmed. Minor typos (e.g., 'Traffiktyp') do not hinder clarity.
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, the description provides a return schema and parameter meanings, covering all key aspects for a read-only data retrieval tool. It does not explain defaults or enum constraints, but those are present in the input schema. Overall, it is sufficiently complete for the tool's complexity.
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?
Despite the signal of 0% schema description coverage, the tool description manually enumerates all seven parameters within the nested params object with meaningful explanations (e.g., line_name for partial match, operator examples, traffic_type values, limit/offset for pagination, response_format options). This fully compensates for the schema 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?
The description starts with 'Ruft Anzahl ZΓΌge pro Streckenabschnitt und Verkehrstyp ab' β a specific verb (abrufen) and resource (train counts per segment and traffic type). It clearly distinguishes from siblings like sbb_get_passenger_frequency by focusing on train counts and infrastructure operators.
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?
The description implies usage for retrieving train counts per segment across operators (SBB, BLS, etc.) and traffic types, but it does not explicitly mention when to use this tool over alternatives or any exclusions. There is no reference to sibling tools or specific use-case boundaries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_list_datasetsARead-onlyIdempotent
Listet alle verfΓΌgbaren SBB Open Data DatensΓ€tze (data.sbb.ch) auf.
Gibt Dataset-ID, Titel, Anzahl DatensΓ€tze und Aktualisierungsfrequenz zurΓΌck. NΓΌtzlich zur Γbersicht und Entdeckung neuer DatensΓ€tze.
Returns: str: VollstΓ€ndige Liste aller SBB Open Data DatensΓ€tze. Schema: {dataset_id, title, records_count, update_frequency, themes}
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (read-only, idempotent, non-destructive). The description adds value by specifying the return type ('str') and the schema of the returned list, including fields like dataset_id, title, records_count, update_frequency, and themes. This goes beyond annotations and helps the agent understand what to expect.
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?
The description is concise, with a clear structure: a brief purpose statement, a line about return fields, and a structured 'Returns' section. Every sentence adds value without 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 list tool with no parameters and no output schema, the description is complete. It explains what the tool does, what it returns, and when to use it, fully covering the agent's needs.
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?
Since the tool has zero parameters, there is nothing to explain. The description correctly implies that no input is needed, and the baseline of 4 applies because the description does not obfuscate or add unnecessary parameter detail.
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 clearly states the tool lists all available SBB Open Data datasets from data.sbb.ch, using a specific verb ('listet') and resource ('DatensΓ€tze'). It also explicitly mentions the return fields, distinguishing it from sibling tools that fetch specific data types like passenger frequency or rail disruptions.
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?
The description provides clear context for use: 'NΓΌtzlich zur Γbersicht und Entdeckung neuer DatensΓ€tze' (useful for overview and discovery). It does not explicitly list exclusions or alternatives, but the use case is evident enough to guide an agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sbb_search_stationsARead-onlyIdempotent
Sucht BahnhΓΆfe und Haltestellen der Schweiz (DiDok-Liste des BAV).
Deckt alle ΓΆV-Haltestellen ab (nicht nur SBB). EnthΓ€lt UIC-Nummern, Koordinaten, Kantone und Betreiberinformationen.
Args: params (StationSearchInput): Parameter: - query (str): Suchbegriff (mind. 2 Zeichen), z.B. 'WΓ€denswil', 'ZΓΌrich' - canton (Optional[str]): KantonskΓΌrzel, z.B. 'ZH' - limit (int): Max. Resultate - response_format (str): 'markdown' oder 'json'
Returns: str: Haltestellenliste mit UIC, Kanton und Koordinaten. Schema: {name, uic, canton, operator, coordinates}
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds valuable behavioral context: the data source (DiDok list), coverage of all stops, parameters like minimum query length, and the return schema. This goes beyond the structured annotations.
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?
The description is well-structured and front-loaded with a clear one-line summary. The docstring-style Args section is informative without waste, and every sentence contributes to understanding the tool's purpose, parameters, and output.
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?
Given the tool's moderate complexity and lack of an output schema, the description fully covers the input parameters, return type, and content of the results. It provides enough detail for an agent to select and invoke the tool correctly without ambiguity.
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% for the top-level 'params' parameter, but the description thoroughly documents all sub-parameters (query, canton, limit, response_format) with examples and meaning. It also explains the return format and fields, adding value beyond the schema's limited descriptions.
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 clearly states the tool searches Swiss train stations and stops using the official DiDok list, with a specific verb (Sucht) and resource. It also distinguishes itself by covering all public transport stops, not just SBB, which differentiates it from sibling tools.
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?
The description provides clear context about what this tool does and its scope (all Swiss stops, includes UIC numbers, coordinates, etc.), so an agent can infer when to use it. It does not explicitly mention alternatives or when not to use it, but the context is sufficient.
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. Dates show when Glama detected each change.
10 tool updates
v0.3.4- Changed
sbb_compare_stations4 fields changed- added
Input schema / $defs / CompareStationsInput / properties / response_formatAdded value: +{ + "$ref": "#/$defs/ResponseFormat", + "default": "markdown", + "description": "Ausgabeformat: 'markdown' (lesbar) oder 'json' (maschinenlesbar)" +} - changed
Input schema / $defs / CompareStationsInput / properties / year / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "pattern": "^\\d{4}$", + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / $defs / ResponseFormatAdded value: +{ + "enum": [ + "markdown", + "json" + ], + "title": "ResponseFormat", + "type": "string" +} - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_compare_stationsOutput", - "type": "object" -}New value: +null
- Changed
sbb_get_infrastructure_construction_projects1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_get_infrastructure_construction_projectsOutput", - "type": "object" -}New value: +null
- Changed
sbb_get_passenger_frequency3 fields changed- changed
Input schema / $defs / PassengerFrequencyInput / properties / canton / anyOfPrevious value: -[ - { - "maxLength": 2, - "minLength": 2, - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 2, + "minLength": 2, + "pattern": "^[A-Za-z]{2}$", + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / $defs / PassengerFrequencyInput / properties / year / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "pattern": "^\\d{4}$", + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_get_passenger_frequencyOutput", - "type": "object" -}New value: +null
- Changed
sbb_get_platform_data1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_get_platform_dataOutput", - "type": "object" -}New value: +null
- Changed
sbb_get_rail_disruptions1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_get_rail_disruptionsOutput", - "type": "object" -}New value: +null
- Changed
sbb_get_real_estate_projects1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_get_real_estate_projectsOutput", - "type": "object" -}New value: +null
- Changed
sbb_get_rolling_stock1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_get_rolling_stockOutput", - "type": "object" -}New value: +null
- Changed
sbb_get_trains_per_segment2 fields changed- changed
Input schema / $defs / TrainsPerSegmentInput / properties / year / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "pattern": "^\\d{4}$", + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_get_trains_per_segmentOutput", - "type": "object" -}New value: +null
- Changed
sbb_list_datasets1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_list_datasetsOutput", - "type": "object" -}New value: +null
- Changed
sbb_search_stations2 fields changed- changed
Input schema / $defs / StationSearchInput / properties / canton / anyOfPrevious value: -[ - { - "maxLength": 2, - "minLength": 2, - "type": "string" - }, - { - "type": "null" - } -]New value: +[ + { + "maxLength": 2, + "minLength": 2, + "pattern": "^[A-Za-z]{2}$", + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "title": "Result", - "type": "string" - } - }, - "required": [ - "result" - ], - "title": "sbb_search_stationsOutput", - "type": "object" -}New value: +null
10 tool updates
v0.1.0- First observed
sbb_compare_stations - First observed
sbb_get_infrastructure_construction_projects - First observed
sbb_get_passenger_frequency - First observed
sbb_get_platform_data - First observed
sbb_get_rail_disruptions - First observed
sbb_get_real_estate_projects - First observed
sbb_get_rolling_stock - First observed
sbb_get_trains_per_segment - First observed
sbb_list_datasets - First observed
sbb_search_stations
TDQS
Each tool targets a distinct SBB Open Data dataset or operation. Even similar-sounding tools like infrastructure construction vs real estate projects are clearly differentiated by their descriptions and parameters. No two tools appear to do the same thing.
All tools follow a consistent sbb_<verb>_<object> pattern. Most use sbb_get_* for data retrieval, with sbb_search_stations, sbb_compare_stations, and sbb_list_datasets as readable variations. Naming is uniform and predictable.
With 10 tools, the server is well-scoped. Each tool covers a meaningful SBB Open Data domain without being overwhelming. The count is within the ideal range for a focused data-access server.
The tool set covers major SBB Open Data categories: stations, passenger frequency, platforms, rolling stock, disruptions, train counts, infrastructure, real estate, and a dataset catalog. Minor gaps exist (e.g., no explicit timetable data), but core workflows are well supported and sbb_list_datasets helps discover additional datasets.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
This MCP server provides seamless access to Malaysia's government open data, including datasets, wβ¦
One AI endpoint to search and call 22k+ MCP servers; 50+ hosted tools work instantly, no key.
MCP server for building and testing AI agents with multi-model experimentation and insights.
Related MCP Servers
- AlicenseAqualityCmaintenanceAn MCP server that enables AI assistants to interact with the Netherlands Railways (NS) API for route planning, pricing, and real-time departure information. It provides tools for searching stations, planning trips with connections, and viewing real-time departure boards.31MIT
- AlicenseAqualityDmaintenanceA zero-authentication MCP server for Swiss public transport, enabling users to query train connections, disruptions, station facilities, and plan journeys using natural language.12MIT
- AlicenseAqualityDmaintenanceMCP server for Swiss public transport β connections, stationboards, real-time delays, and direct booking links for SBB.41MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server for real-time Italian railway data, enabling natural language queries about train schedules, delays, departures, arrivals, and live tracking via the Viaggiatreno API.6MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/malkreide/sbb-opendata-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server