sbb-mcp
v0.2.0
Published
MCP server for Swiss Federal Railways (SBB/CFF/FFS) — real-time train schedules, prices, and ticket purchase links for any AI assistant
Maintainers
Readme
sbb-mcp
MCP server for Swiss Federal Railways (SBB/CFF/FFS) -- real-time train schedules, prices, and ticket purchase links for any AI assistant.
Works with Claude Desktop, Claude Code, Cursor, Windsurf, VS Code Copilot, ChatGPT, and any MCP-compatible AI client.
Features
- Search stations -- find any Swiss train station by name
- Train connections -- real-time schedules with departure/arrival times, platforms, transfers
- Ticket prices -- 1st/2nd class with Half-Fare (Halbtax) and GA travelcard support
- Purchase links -- direct deep links to buy tickets on SBB.ch
- Pagination -- browse earlier/later connections
- Trip details -- intermediate stops, occupancy, platform changes
- Journey planning -- built-in prompt for end-to-end trip planning
- Multi-traveler -- family trip pricing when connected to SwissTrip (partner, kids, each with their own reduction card)
- Mock mode -- works without credentials for testing and demos
Quick Start
Claude Desktop
Add to your claude_desktop_config.json:
{
"mcpServers": {
"sbb": {
"command": "npx",
"args": ["-y", "sbb-mcp"],
"env": {
"SMAPI_CLIENT_ID": "your-client-id",
"SMAPI_CLIENT_SECRET": "your-secret",
"SMAPI_SCOPE": "your-scope",
"SMAPI_CONTRACT_ID": "your-contract-id"
}
}
}
}Claude Code
claude mcp add sbb -- npx -y sbb-mcpCursor
Add to .cursor/mcp.json:
{
"mcpServers": {
"sbb": {
"command": "npx",
"args": ["-y", "sbb-mcp"],
"env": {
"SMAPI_CLIENT_ID": "your-client-id",
"SMAPI_CLIENT_SECRET": "your-secret",
"SMAPI_SCOPE": "your-scope",
"SMAPI_CONTRACT_ID": "your-contract-id"
}
}
}
}Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"sbb": {
"command": "npx",
"args": ["-y", "sbb-mcp"],
"env": {
"SMAPI_CLIENT_ID": "your-client-id",
"SMAPI_CLIENT_SECRET": "your-secret",
"SMAPI_SCOPE": "your-scope",
"SMAPI_CONTRACT_ID": "your-contract-id"
}
}
}
}VS Code Copilot
Add to .vscode/mcp.json:
{
"servers": {
"sbb": {
"command": "npx",
"args": ["-y", "sbb-mcp"],
"env": {
"SMAPI_CLIENT_ID": "your-client-id",
"SMAPI_CLIENT_SECRET": "your-secret",
"SMAPI_SCOPE": "your-scope",
"SMAPI_CONTRACT_ID": "your-contract-id"
}
}
}
}Smithery
Install via Smithery:
npx @smithery/cli mcp add fabsforward2-zhoi/sbb-mcpDemo Mode (No Credentials)
Run without any environment variables to use mock data:
npx sbb-mcpThis lets you test the MCP server with realistic Swiss station data without SBB API credentials.
Tools
search_stations
Search for Swiss train stations by name. Returns station IDs needed for other tools.
Input:
query(string, required) -- Station name, e.g. "Zurich", "Bern", "Interlaken"limit(number, optional) -- Max results (default: 10)
Example: "Find stations matching Luzern"
search_connections
Find train connections between two stations. Automatically resolves station names to IDs.
Input:
from(string, required) -- Origin station name or ID (e.g. "Zurich HB" or "8503000")to(string, required) -- Destination station name or IDdate(string, optional) -- Travel date YYYY-MM-DDtime(string, optional) -- Departure time HH:MMarrival_time(boolean, optional) -- Treat time as arrival time
Example: "Show me trains from Zurich to Bern tomorrow at 9am"
get_trip_details
Get detailed stop-by-stop information for a connection including intermediate stops, platforms, and occupancy forecasts.
Input:
trip_id(string, required) -- Trip ID from search_connections
get_more_connections
Load earlier or later trains for a previous search.
Input:
collection_id(string, required) -- Collection ID from search_connectionsdirection("next" | "previous") -- Later or earlier trains
get_prices
Get ticket prices with Swiss reduction card support. Supports multi-traveler family pricing when connected to SwissTrip.
Input:
trip_ids(string[], required) -- Trip IDs from search_connectionstraveler_type("ADULT" | "CHILD", default: "ADULT") -- used when no traveler_names givenreduction_card("HALF_FARE" | "GA" | "NONE", default: "HALF_FARE") -- used when no traveler_names giventraveler_names(string[], optional) -- SwissTrip traveler names for family pricing (requiresSWISSTRIP_TOKEN)
Example: "How much for Zurich to Zermatt for Fabian and Anna?" (with SwissTrip connected, each traveler's reduction card is applied automatically)
get_ticket_link
Get a direct purchase link to buy the ticket on SBB.ch. On mobile with the SBB app installed, opens directly in the app with Halbtax/GA applied automatically. Supports multi-traveler tickets when connected to SwissTrip.
Input:
trip_id(string, required) -- Trip ID to purchasefrom_name(string, required) -- Origin station namefrom_id(string, required) -- Origin station IDto_name(string, required) -- Destination station nameto_id(string, required) -- Destination station IDdate(string, required) -- Travel date YYYY-MM-DDtime(string, required) -- Departure time HH:MMtraveler_type("ADULT" | "CHILD", default: "ADULT") -- used when no traveler_names givenreduction_card("HALF_FARE" | "GA" | "NONE", default: "HALF_FARE") -- used when no traveler_names giventraveler_names(string[], optional) -- SwissTrip traveler names for family tickets (requiresSWISSTRIP_TOKEN)
list_travelers
List all travelers in the user's SwissTrip account (self, partner, kids). Each traveler has their own reduction card. Requires SWISSTRIP_TOKEN.
Example: "Who are my travelers?" → shows all saved travelers with their reduction cards
Prompts
plan_journey
End-to-end journey planning prompt. Searches connections, compares prices, and provides ticket links.
Input:
from(string, required) -- Origin stationto(string, required) -- Destination stationdate(string, optional) -- Travel date
Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| SMAPI_CLIENT_ID | Yes* | OAuth 2.0 client ID from SBB Developer Portal |
| SMAPI_CLIENT_SECRET | Yes* | OAuth 2.0 client secret |
| SMAPI_SCOPE | Yes* | OAuth scope |
| SMAPI_CONTRACT_ID | Yes* | SBB business contract ID |
| SMAPI_ENV | No | int (default) or prod |
| SMAPI_TENANT_ID | No | Azure AD tenant (defaults to SBB tenant) |
| SWISSTRIP_TOKEN | No | SwissTrip auth token for cloud profiles and multi-traveler support |
| SWISSTRIP_URL | No | SwissTrip API base URL (defaults to https://swisstrip.ch) |
*Without SMAPI credentials, the server runs in mock mode with realistic demo data.
SwissTrip Integration (Optional)
Set SWISSTRIP_TOKEN to connect sbb-mcp to your SwissTrip account. This enables:
- Cloud-synced profiles -- your travel profile (name, DOB, reduction card) syncs from SwissTrip instead of local
~/.sbb-mcp/profile.json - Multi-traveler pricing -- add your partner, kids, or travel companions on SwissTrip and get per-person pricing with correct reduction cards
- Family tickets -- pass
traveler_namestoget_pricesandget_ticket_linkfor group pricing
{
"mcpServers": {
"sbb": {
"command": "npx",
"args": ["-y", "sbb-mcp"],
"env": {
"SMAPI_CLIENT_ID": "your-client-id",
"SMAPI_CLIENT_SECRET": "your-secret",
"SMAPI_SCOPE": "your-scope",
"SWISSTRIP_TOKEN": "your-swisstrip-auth-token"
}
}
}
}Without SWISSTRIP_TOKEN, sbb-mcp uses local file-based profiles as before -- no SwissTrip account required.
Available on
Also available as: sbb-mcp-official | swiss-rail-mcp | sbb-cff-ffs-mcp | swiss-train-mcp | swiss-railways-mcp
About
Built on the official SBB Swiss Mobility API (SMAPI) with OSDM-compliant journey planning and pricing. Covers the entire Swiss public transport network including SBB, BLS, SOB, and regional operators.
SBB (Schweizerische Bundesbahnen) / CFF (Chemins de fer federaux suisses) / FFS (Ferrovie federali svizzere) -- Swiss Federal Railways operates one of the densest rail networks in the world with over 10,000 daily connections.
License
FSL-1.1-MIT -- Functional Source License. Free to use for any non-competing purpose. Converts to MIT after 2 years. See LICENSE for details.
