sbb-mcp 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -233
- package/dist/cache.d.ts +2 -0
- package/dist/cache.js +4 -0
- package/dist/cache.js.map +1 -1
- package/dist/formatters.d.ts +13 -0
- package/dist/formatters.js +94 -19
- package/dist/formatters.js.map +1 -1
- package/dist/http.js +59 -3
- package/dist/http.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/look2book.d.ts +98 -0
- package/dist/look2book.js +212 -0
- package/dist/look2book.js.map +1 -0
- package/dist/profile.js +15 -8
- package/dist/profile.js.map +1 -1
- package/dist/shortlink.d.ts +60 -0
- package/dist/shortlink.js +122 -0
- package/dist/shortlink.js.map +1 -0
- package/dist/structured.d.ts +7 -1
- package/dist/structured.js +2 -1
- package/dist/structured.js.map +1 -1
- package/dist/swisstrip.js +21 -5
- package/dist/swisstrip.js.map +1 -1
- package/dist/tools.d.ts +38 -0
- package/dist/tools.js +122 -77
- package/dist/tools.js.map +1 -1
- package/dist/transport/index.d.ts +1 -0
- package/dist/transport/index.js +4 -0
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/setup.d.ts +1 -0
- package/dist/transport/setup.js +59 -0
- package/dist/transport/setup.js.map +1 -0
- package/dist/transport/smapi-auth.d.ts +14 -2
- package/dist/transport/smapi-auth.js +67 -17
- package/dist/transport/smapi-auth.js.map +1 -1
- package/dist/transport/smapi-client.d.ts +25 -1
- package/dist/transport/smapi-client.js +112 -9
- package/dist/transport/smapi-client.js.map +1 -1
- package/dist/transport/smapi-journey.d.ts +11 -5
- package/dist/transport/smapi-journey.js +16 -7
- package/dist/transport/smapi-journey.js.map +1 -1
- package/dist/transport/smapi-mock.js.map +1 -1
- package/dist/transport/smapi-prices.d.ts +43 -9
- package/dist/transport/smapi-prices.js +112 -41
- package/dist/transport/smapi-prices.js.map +1 -1
- package/dist/transport/smapi-types.d.ts +28 -0
- package/dist/widgets.d.ts +30 -3
- package/dist/widgets.js +78 -14
- package/dist/widgets.js.map +1 -1
- package/package.json +7 -3
- package/web/dist/widgets.css +1 -1
- package/web/dist/widgets.js +1 -1
package/README.md
CHANGED
|
@@ -2,49 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/sbb-mcp)
|
|
4
4
|
[](https://fsl.software/)
|
|
5
|
-
[](https://smithery.ai/servers/fabsforward2-zhoi/sbb-mcp)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> **Swiss trains in any AI assistant.** Real-time schedules, ticket prices with Half-Fare/GA discounts, and direct purchase links for Claude Desktop, ChatGPT, Cursor, and any MCP-compatible client.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```
|
|
10
|
+
You: trains from Bern to Zermatt tomorrow at 9am, with Halbtax
|
|
11
|
+
AI: IC 8 14:32 → 17:24 (2h52, 1 transfer in Visp, Pl. 8) — CHF 42.50
|
|
12
|
+
IC 8 15:02 → 17:54 (2h52, 1 transfer in Visp, Pl. 8) — CHF 42.50
|
|
13
|
+
[Buy on SBB.ch ↗]
|
|
14
|
+
```
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
Ask any AI assistant to find Swiss trains. It returns connections, prices with your reduction card applied, and a direct ticket-purchase link to sbb.ch — all through natural language.
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
- **Train connections** -- real-time schedules with departure/arrival times, platforms, transfers
|
|
15
|
-
- **Ticket prices** -- 1st/2nd class with Half-Fare (Halbtax) and GA travelcard support
|
|
16
|
-
- **Purchase links** -- direct deep links to buy tickets on SBB.ch
|
|
17
|
-
- **Pagination** -- browse earlier/later connections
|
|
18
|
-
- **Trip details** -- intermediate stops, occupancy, platform changes
|
|
19
|
-
- **Journey planning** -- built-in prompt for end-to-end trip planning
|
|
20
|
-
- **Destination weather** -- automatic weather forecast for your destination (powered by [swiss-weather-mcp](https://www.npmjs.com/package/swiss-weather-mcp))
|
|
21
|
-
- **Multi-traveler** -- family trip pricing when connected to SwissTrip (partner, kids, each with their own reduction card)
|
|
22
|
-
- **Multilingual** -- output in 9 languages: de, fr, it, en, es, pt, ru, ar, zh (v0.4.0+)
|
|
23
|
-
- **Rich widgets in ChatGPT** -- connection cards, trip timelines, price tables, and ticket cards via the OpenAI Apps SDK (v0.4.1+)
|
|
24
|
-
- **Mock mode** -- works without credentials for testing and demos
|
|
18
|
+
> **Not affiliated with SBB.** Independent, community-maintained MCP server built on SBB's public Swiss Mobility API (SMAPI). Not affiliated with or endorsed by SBB (Schweizerische Bundesbahnen).
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
---
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
## Quick install
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
### ChatGPT (no install — hosted)
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"SMAPI_SCOPE": "your-scope",
|
|
42
|
-
"SMAPI_CONTRACT_ID": "your-contract-id"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
```
|
|
26
|
+
ChatGPT Plus / Pro / Business / Enterprise with Developer Mode enabled:
|
|
27
|
+
|
|
28
|
+
1. **Settings → Connectors** → enable **Developer Mode**
|
|
29
|
+
2. Click **Add custom connector**
|
|
30
|
+
3. **MCP Server URL:** `https://mcp.swisstrip.app/mcp`
|
|
31
|
+
4. **Authentication:** None
|
|
32
|
+
5. Save, then enable via the **+** button in the composer
|
|
33
|
+
|
|
34
|
+
Tool responses render as native ChatGPT widgets (connection cards, trip timelines, price tables) via the OpenAI Apps SDK.
|
|
48
35
|
|
|
49
36
|
### Claude Code
|
|
50
37
|
|
|
@@ -52,288 +39,220 @@ Add to your `claude_desktop_config.json`:
|
|
|
52
39
|
claude mcp add sbb -- npx -y sbb-mcp
|
|
53
40
|
```
|
|
54
41
|
|
|
55
|
-
|
|
42
|
+
Done — try `/mcp` in Claude to confirm it's loaded, then ask about Swiss trains.
|
|
56
43
|
|
|
57
|
-
|
|
44
|
+
### Claude Desktop
|
|
45
|
+
|
|
46
|
+
Add to `claude_desktop_config.json`:
|
|
58
47
|
|
|
59
48
|
```json
|
|
60
49
|
{
|
|
61
50
|
"mcpServers": {
|
|
62
51
|
"sbb": {
|
|
63
52
|
"command": "npx",
|
|
64
|
-
"args": ["-y", "sbb-mcp"]
|
|
65
|
-
"env": {
|
|
66
|
-
"SMAPI_CLIENT_ID": "your-client-id",
|
|
67
|
-
"SMAPI_CLIENT_SECRET": "your-secret",
|
|
68
|
-
"SMAPI_SCOPE": "your-scope",
|
|
69
|
-
"SMAPI_CONTRACT_ID": "your-contract-id"
|
|
70
|
-
}
|
|
53
|
+
"args": ["-y", "sbb-mcp"]
|
|
71
54
|
}
|
|
72
55
|
}
|
|
73
56
|
}
|
|
74
57
|
```
|
|
75
58
|
|
|
76
|
-
|
|
59
|
+
Restart Claude Desktop. That's it — works in **mock mode** out of the box with realistic Swiss station data. Add credentials later for live SBB data (see below).
|
|
77
60
|
|
|
78
|
-
|
|
61
|
+
### Cursor / Windsurf / VS Code Copilot
|
|
79
62
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
63
|
+
Same `mcpServers` block as Claude Desktop, in the respective config file:
|
|
64
|
+
|
|
65
|
+
| Client | Config path |
|
|
66
|
+
|---|---|
|
|
67
|
+
| Cursor | `.cursor/mcp.json` |
|
|
68
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
|
|
69
|
+
| VS Code Copilot | `.vscode/mcp.json` (use top-level `servers` instead of `mcpServers`) |
|
|
70
|
+
|
|
71
|
+
### Try it without installing
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx sbb-mcp
|
|
95
75
|
```
|
|
96
76
|
|
|
97
|
-
|
|
77
|
+
Runs in mock mode with realistic Swiss station data — no setup, no credentials. Useful for testing the protocol or building demos.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Live SBB data (optional)
|
|
82
|
+
|
|
83
|
+
Mock mode works out of the box. For real-time schedules and prices, get credentials from the [SBB Developer Portal](https://developer.sbb.ch) (free signup, OAuth 2.0 + business contract).
|
|
98
84
|
|
|
99
|
-
Add to
|
|
85
|
+
Add to your config's `env` block:
|
|
100
86
|
|
|
101
87
|
```json
|
|
102
88
|
{
|
|
103
|
-
"
|
|
89
|
+
"mcpServers": {
|
|
104
90
|
"sbb": {
|
|
105
91
|
"command": "npx",
|
|
106
92
|
"args": ["-y", "sbb-mcp"],
|
|
107
93
|
"env": {
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
94
|
+
"SMAPI_JOURNEY_CLIENT_ID": "...",
|
|
95
|
+
"SMAPI_JOURNEY_CLIENT_SECRET": "...",
|
|
96
|
+
"SMAPI_JOURNEY_SCOPE": "api://.../.default",
|
|
97
|
+
"SMAPI_TICKETING_CLIENT_ID": "...",
|
|
98
|
+
"SMAPI_TICKETING_CLIENT_SECRET": "...",
|
|
99
|
+
"SMAPI_TICKETING_SCOPE": "api://.../.default",
|
|
100
|
+
"SMAPI_CONTRACT_ID": "..."
|
|
112
101
|
}
|
|
113
102
|
}
|
|
114
103
|
}
|
|
115
104
|
}
|
|
116
105
|
```
|
|
117
106
|
|
|
118
|
-
|
|
107
|
+
SBB issues separate AAD apps per API. The Journey API is for schedules/stations; the Ticketing API for prices/booking links. Set whichever you have approved — the server falls back to mock data per family if a credential set is missing.
|
|
119
108
|
|
|
120
|
-
|
|
109
|
+
For backwards compatibility, single-app setups can use the generic `SMAPI_CLIENT_ID` / `SMAPI_CLIENT_SECRET` / `SMAPI_SCOPE` for both APIs.
|
|
121
110
|
|
|
122
|
-
|
|
123
|
-
npx @smithery/cli mcp add fabsforward2-zhoi/sbb-mcp
|
|
124
|
-
```
|
|
111
|
+
---
|
|
125
112
|
|
|
126
|
-
|
|
113
|
+
## What it does
|
|
127
114
|
|
|
128
|
-
|
|
115
|
+
- **Search stations** — find any Swiss train station by name, get UIC IDs
|
|
116
|
+
- **Train connections** — schedules with departure/arrival times, platforms, transfer info, occupancy forecasts
|
|
117
|
+
- **Ticket prices** — 1st/2nd class with Half-Fare (Halbtax) and GA travelcard support
|
|
118
|
+
- **Purchase links** — direct deep links to buy on SBB.ch (opens the SBB app on mobile with discounts applied)
|
|
119
|
+
- **Pagination** — browse earlier/later connections without losing context
|
|
120
|
+
- **Trip details** — intermediate stops, platforms, real-time status
|
|
121
|
+
- **Destination weather** — auto-included in connection results via [`swiss-weather-mcp`](https://www.npmjs.com/package/swiss-weather-mcp)
|
|
122
|
+
- **Multilingual** — output in 9 languages (`de fr it en es pt ru ar zh`)
|
|
123
|
+
- **ChatGPT widgets** — connection cards, price tables, ticket cards rendered as native UI via OpenAI Apps SDK
|
|
124
|
+
- **Mock mode** — full demo data without credentials
|
|
129
125
|
|
|
130
|
-
|
|
131
|
-
npx sbb-mcp
|
|
132
|
-
```
|
|
126
|
+
---
|
|
133
127
|
|
|
134
|
-
|
|
128
|
+
## Tools
|
|
135
129
|
|
|
136
|
-
|
|
130
|
+
9 MCP tools, all support an optional `language` argument.
|
|
137
131
|
|
|
138
|
-
|
|
132
|
+
| Tool | What it does |
|
|
133
|
+
|---|---|
|
|
134
|
+
| `search_stations` | Find stations by name → UIC IDs |
|
|
135
|
+
| `search_connections` | Schedules between two stations (returns trip IDs) |
|
|
136
|
+
| `get_trip_details` | Stop-by-stop info, platforms, occupancy |
|
|
137
|
+
| `get_more_connections` | Earlier/later trains via pagination |
|
|
138
|
+
| `get_prices` | Ticket prices with reduction card applied |
|
|
139
|
+
| `get_ticket_link` | Direct purchase link to SBB.ch (mobile-app deep link) |
|
|
140
|
+
| `save_profile` | Save user's reduction card + DOB locally for auto-apply |
|
|
141
|
+
| `get_profile` | Read saved profile |
|
|
142
|
+
| `list_travelers` | Multi-traveler family pricing (requires SwissTrip account) |
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
Plus a `plan_journey` prompt for end-to-end trip planning.
|
|
141
145
|
|
|
142
|
-
|
|
143
|
-
// Example: French output
|
|
144
|
-
{ "from": "Zurich HB", "to": "Bern", "language": "fr" }
|
|
145
|
-
```
|
|
146
|
+
### Multilingual
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
Save a default language once per user:
|
|
148
|
+
Every tool accepts `language: "de" | "fr" | "it" | "en" | "es" | "pt" | "ru" | "ar" | "zh"`. Sets `Accept-Language` on SBB API calls so station names come back in the requested language; localizes the buy-button text on deep links.
|
|
150
149
|
|
|
151
150
|
```jsonc
|
|
152
|
-
|
|
151
|
+
// French output
|
|
152
|
+
{ "from": "Zürich HB", "to": "Genève", "language": "fr" }
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
### search_stations
|
|
158
|
-
|
|
159
|
-
Search for Swiss train stations by name. Returns station IDs needed for other tools.
|
|
160
|
-
|
|
161
|
-
**Input:**
|
|
162
|
-
- `query` (string, required) -- Station name, e.g. "Zurich", "Bern", "Interlaken"
|
|
163
|
-
- `limit` (number, optional) -- Max results (default: 10)
|
|
164
|
-
|
|
165
|
-
**Example:** "Find stations matching Luzern"
|
|
166
|
-
|
|
167
|
-
### search_connections
|
|
168
|
-
|
|
169
|
-
Find train connections between two stations. Automatically resolves station names to IDs.
|
|
170
|
-
|
|
171
|
-
**Input:**
|
|
172
|
-
- `from` (string, required) -- Origin station name or ID (e.g. "Zurich HB" or "8503000")
|
|
173
|
-
- `to` (string, required) -- Destination station name or ID
|
|
174
|
-
- `date` (string, optional) -- Travel date YYYY-MM-DD
|
|
175
|
-
- `time` (string, optional) -- Departure time HH:MM
|
|
176
|
-
- `arrival_time` (boolean, optional) -- Treat time as arrival time
|
|
177
|
-
|
|
178
|
-
**Example:** "Show me trains from Zurich to Bern tomorrow at 9am"
|
|
179
|
-
|
|
180
|
-
Results automatically include destination weather when coordinates are available (e.g. **Bern weather:** 6-18°C, mostly sunny, 10% rain).
|
|
181
|
-
|
|
182
|
-
### get_trip_details
|
|
183
|
-
|
|
184
|
-
Get detailed stop-by-stop information for a connection including intermediate stops, platforms, and occupancy forecasts.
|
|
185
|
-
|
|
186
|
-
**Input:**
|
|
187
|
-
- `trip_id` (string, required) -- Trip ID from search_connections
|
|
188
|
-
|
|
189
|
-
### get_more_connections
|
|
190
|
-
|
|
191
|
-
Load earlier or later trains for a previous search.
|
|
192
|
-
|
|
193
|
-
**Input:**
|
|
194
|
-
- `collection_id` (string, required) -- Collection ID from search_connections
|
|
195
|
-
- `direction` ("next" | "previous") -- Later or earlier trains
|
|
196
|
-
|
|
197
|
-
### get_prices
|
|
198
|
-
|
|
199
|
-
Get ticket prices with Swiss reduction card support. Supports multi-traveler family pricing when connected to SwissTrip.
|
|
200
|
-
|
|
201
|
-
**Input:**
|
|
202
|
-
- `trip_ids` (string[], required) -- Trip IDs from search_connections
|
|
203
|
-
- `traveler_type` ("ADULT" | "CHILD", default: "ADULT") -- used when no traveler_names given
|
|
204
|
-
- `reduction_card` ("HALF_FARE" | "GA" | "NONE", default: "HALF_FARE") -- used when no traveler_names given
|
|
205
|
-
- `traveler_names` (string[], optional) -- SwissTrip traveler names for family pricing (requires `SWISSTRIP_TOKEN`)
|
|
206
|
-
|
|
207
|
-
**Example:** "How much for Zurich to Zermatt for Fabian and Anna?" (with SwissTrip connected, each traveler's reduction card is applied automatically)
|
|
208
|
-
|
|
209
|
-
### get_ticket_link
|
|
210
|
-
|
|
211
|
-
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.
|
|
212
|
-
|
|
213
|
-
**Input:**
|
|
214
|
-
- `trip_id` (string, required) -- Trip ID to purchase
|
|
215
|
-
- `from_name` (string, required) -- Origin station name
|
|
216
|
-
- `from_id` (string, required) -- Origin station ID
|
|
217
|
-
- `to_name` (string, required) -- Destination station name
|
|
218
|
-
- `to_id` (string, required) -- Destination station ID
|
|
219
|
-
- `date` (string, required) -- Travel date YYYY-MM-DD
|
|
220
|
-
- `time` (string, required) -- Departure time HH:MM
|
|
221
|
-
- `traveler_type` ("ADULT" | "CHILD", default: "ADULT") -- used when no traveler_names given
|
|
222
|
-
- `reduction_card` ("HALF_FARE" | "GA" | "NONE", default: "HALF_FARE") -- used when no traveler_names given
|
|
223
|
-
- `traveler_names` (string[], optional) -- SwissTrip traveler names for family tickets (requires `SWISSTRIP_TOKEN`)
|
|
224
|
-
|
|
225
|
-
### list_travelers
|
|
226
|
-
|
|
227
|
-
List all travelers in the user's SwissTrip account (self, partner, kids). Each traveler has their own reduction card. Requires `SWISSTRIP_TOKEN`.
|
|
155
|
+
Save a default once via `save_profile` — subsequent calls use it automatically.
|
|
228
156
|
|
|
229
|
-
|
|
157
|
+
---
|
|
230
158
|
|
|
231
|
-
##
|
|
159
|
+
## Hosted MCP endpoint
|
|
232
160
|
|
|
233
|
-
|
|
161
|
+
A public HTTPS endpoint is live at `https://mcp.swisstrip.app/mcp` for clients that prefer remote MCP over local stdio (ChatGPT, Claude Pro remote MCPs, etc.). Same tools, plus rich widgets for ChatGPT.
|
|
234
162
|
|
|
235
|
-
|
|
163
|
+
```bash
|
|
164
|
+
# Test from your terminal
|
|
165
|
+
curl -X POST https://mcp.swisstrip.app/mcp \
|
|
166
|
+
-H 'Content-Type: application/json' \
|
|
167
|
+
-H 'Accept: application/json, text/event-stream' \
|
|
168
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
|
|
169
|
+
```
|
|
236
170
|
|
|
237
|
-
|
|
238
|
-
- `from` (string, required) -- Origin station
|
|
239
|
-
- `to` (string, required) -- Destination station
|
|
240
|
-
- `date` (string, optional) -- Travel date
|
|
171
|
+
---
|
|
241
172
|
|
|
242
|
-
## Environment
|
|
173
|
+
## Environment variables
|
|
243
174
|
|
|
244
175
|
| Variable | Required | Description |
|
|
245
|
-
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
249
|
-
| `SMAPI_CONTRACT_ID` |
|
|
250
|
-
| `SMAPI_ENV` | No | `int` (default)
|
|
251
|
-
| `SMAPI_TENANT_ID` | No | Azure AD tenant (defaults to SBB
|
|
252
|
-
| `SWISSTRIP_TOKEN` | No | SwissTrip
|
|
253
|
-
| `SWISSTRIP_URL` | No | SwissTrip API base URL (defaults to `https://swisstrip.ch`) |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| `SMAPI_JOURNEY_CLIENT_ID` / `_CLIENT_SECRET` / `_SCOPE` | For schedules + stations | OAuth credentials for SBB Journey API |
|
|
178
|
+
| `SMAPI_TICKETING_CLIENT_ID` / `_CLIENT_SECRET` / `_SCOPE` | For prices + booking links | OAuth credentials for SBB Ticketing API (b2p) |
|
|
179
|
+
| `SMAPI_CLIENT_ID` / `_CLIENT_SECRET` / `_SCOPE` | Fallback | Single-app credentials, used for any family without specific vars |
|
|
180
|
+
| `SMAPI_CONTRACT_ID` | With any creds | SBB partner contract identifier |
|
|
181
|
+
| `SMAPI_ENV` | No | `int` (default) \| `prod` \| `mock` |
|
|
182
|
+
| `SMAPI_TENANT_ID` | No | Azure AD tenant override (defaults to SBB's) |
|
|
183
|
+
| `SWISSTRIP_TOKEN` | No | SwissTrip account token for cloud-synced multi-traveler profiles |
|
|
254
184
|
|
|
255
|
-
|
|
185
|
+
Without any SMAPI credentials → mock mode (realistic demo data).
|
|
256
186
|
|
|
257
|
-
|
|
187
|
+
---
|
|
258
188
|
|
|
259
|
-
|
|
189
|
+
## SwissTrip integration (optional)
|
|
260
190
|
|
|
261
|
-
|
|
262
|
-
- **Multi-traveler pricing** -- add your partner, kids, or travel companions on SwissTrip and get per-person pricing with correct reduction cards
|
|
263
|
-
- **Family tickets** -- pass `traveler_names` to `get_prices` and `get_ticket_link` for group pricing
|
|
191
|
+
Connect your [SwissTrip](https://swisstrip.app) account via `SWISSTRIP_TOKEN` to enable:
|
|
264
192
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
"sbb": {
|
|
269
|
-
"command": "npx",
|
|
270
|
-
"args": ["-y", "sbb-mcp"],
|
|
271
|
-
"env": {
|
|
272
|
-
"SMAPI_CLIENT_ID": "your-client-id",
|
|
273
|
-
"SMAPI_CLIENT_SECRET": "your-secret",
|
|
274
|
-
"SMAPI_SCOPE": "your-scope",
|
|
275
|
-
"SWISSTRIP_TOKEN": "your-swisstrip-auth-token"
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
```
|
|
193
|
+
- Cloud-synced travel profile (name, DOB, reduction card) instead of local file
|
|
194
|
+
- Multi-traveler family pricing (partner, kids, each with their own card)
|
|
195
|
+
- Mint a token at https://swisstrip.app/settings/developer
|
|
281
196
|
|
|
282
|
-
|
|
197
|
+
---
|
|
283
198
|
|
|
284
|
-
## Available
|
|
199
|
+
## Available everywhere
|
|
285
200
|
|
|
286
201
|
- [npm](https://www.npmjs.com/package/sbb-mcp)
|
|
287
202
|
- [Official MCP Registry](https://registry.modelcontextprotocol.io)
|
|
288
203
|
- [Smithery](https://smithery.ai/servers/fabsforward2-zhoi/sbb-mcp)
|
|
204
|
+
- [PulseMCP](https://www.pulsemcp.com/servers/fabsbags-sbb)
|
|
205
|
+
- [LobeHub](https://lobehub.com/mcp)
|
|
206
|
+
- ChatGPT custom connector at `https://mcp.swisstrip.app/mcp`
|
|
207
|
+
|
|
208
|
+
Also published under alias names that all forward to `sbb-mcp`: [swiss-rail-mcp](https://www.npmjs.com/package/swiss-rail-mcp), [sbb-cff-ffs-mcp](https://www.npmjs.com/package/sbb-cff-ffs-mcp), [swiss-train-mcp](https://www.npmjs.com/package/swiss-train-mcp), [swiss-railways-mcp](https://www.npmjs.com/package/swiss-railways-mcp).
|
|
289
209
|
|
|
290
|
-
|
|
210
|
+
---
|
|
291
211
|
|
|
292
212
|
## About
|
|
293
213
|
|
|
294
|
-
Built on
|
|
214
|
+
Built on SBB's commercial Swiss Mobility API (SMAPI) with OSDM-compliant journey planning and Azure AD OAuth. Covers SBB plus regional operators (BLS, SOB, MOB, RhB, etc.) — the entire Swiss public transport network with 10,000+ daily connections.
|
|
295
215
|
|
|
296
|
-
|
|
216
|
+
Weather data via [`swiss-weather-mcp`](https://www.npmjs.com/package/swiss-weather-mcp) (MeteoSwiss + Open-Meteo).
|
|
297
217
|
|
|
298
|
-
|
|
218
|
+
Repository: [Fabsbags/swisstrip-web](https://github.com/Fabsbags/swisstrip-web/tree/main/packages/sbb-mcp). Issues: [tracker](https://github.com/Fabsbags/swisstrip-web/issues).
|
|
299
219
|
|
|
300
|
-
|
|
220
|
+
**SBB** (Schweizerische Bundesbahnen) / **CFF** (Chemins de fer fédéraux suisses) / **FFS** (Ferrovie federali svizzere) — Swiss Federal Railways.
|
|
301
221
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
4. **Authentication:** None
|
|
306
|
-
5. Save, then enable the connector via the **+** button in the composer
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## License
|
|
307
225
|
|
|
308
|
-
|
|
226
|
+
[FSL-1.1-MIT](https://fsl.software/) — Functional Source License. Free for any non-competing purpose. Converts to MIT after 2 years. See [LICENSE](LICENSE).
|
|
227
|
+
|
|
228
|
+
---
|
|
309
229
|
|
|
310
230
|
## Changelog
|
|
311
231
|
|
|
232
|
+
### v0.4.3 — README polish
|
|
233
|
+
|
|
234
|
+
Launch-focused README rewrite: install-first structure, ChatGPT custom connector promoted to top, mock-mode-by-default messaging, 9-tool reference table, per-family SBB credential env vars documented. No runtime changes — `sbb-mcp@0.4.2` behavior is identical to `0.4.3`.
|
|
235
|
+
|
|
312
236
|
### v0.4.2 — Repository metadata
|
|
313
237
|
|
|
314
|
-
|
|
238
|
+
Point `repository`, `homepage`, and `bugs` at the monorepo source of truth. No runtime changes.
|
|
315
239
|
|
|
316
240
|
### v0.4.1 — Apps SDK widgets
|
|
317
241
|
|
|
318
|
-
- Five Preact widgets registered as `ui://widget/*.html` resources: stations list, connection list, trip details, prices table, ticket card
|
|
319
|
-
- Tool responses
|
|
320
|
-
- Hosted endpoint live at `https://mcp.swisstrip.app/mcp` for use as a ChatGPT custom connector
|
|
321
|
-
- Widget bundle
|
|
322
|
-
- Server rendering
|
|
242
|
+
- Five Preact widgets registered as `ui://widget/*.html` resources: stations list, connection list, trip details, prices table, ticket card
|
|
243
|
+
- Tool responses include `structuredContent` + `_meta["openai/outputTemplate"]` so ChatGPT renders rich UI
|
|
244
|
+
- Hosted endpoint live at `https://mcp.swisstrip.app/mcp` for use as a ChatGPT custom connector
|
|
245
|
+
- Widget bundle ~25KB (single IIFE, inlined CSS) built via Vite under `web/`
|
|
246
|
+
- Server rendering unchanged for stdio clients
|
|
323
247
|
|
|
324
248
|
### v0.4.0 — Multilingual
|
|
325
249
|
|
|
326
|
-
-
|
|
327
|
-
-
|
|
328
|
-
- `
|
|
329
|
-
-
|
|
330
|
-
-
|
|
331
|
-
- Translations shared with the WhatsApp/Telegram bots via the new [`sbb-i18n`](https://www.npmjs.com/package/sbb-i18n) package.
|
|
250
|
+
- Optional `language` argument on every tool (9 languages)
|
|
251
|
+
- `Accept-Language` passed to SBB SMAPI for localized station names
|
|
252
|
+
- `save_profile` stores preferred language as default
|
|
253
|
+
- **Breaking:** default output locale with no profile is now `en` (was `de-CH`). Set a profile or pass `language: 'de'` to restore previous behavior.
|
|
254
|
+
- Translations shared with WhatsApp/Telegram bots via [`sbb-i18n`](https://www.npmjs.com/package/sbb-i18n)
|
|
332
255
|
|
|
333
256
|
### v0.3.0 — Destination weather
|
|
334
257
|
|
|
335
|
-
-
|
|
336
|
-
|
|
337
|
-
## License
|
|
338
|
-
|
|
339
|
-
[FSL-1.1-MIT](https://fsl.software/) -- Functional Source License. Free to use for any non-competing purpose. Converts to MIT after 2 years. See [LICENSE](LICENSE) for details.
|
|
258
|
+
Auto-include weather forecast in `search_connections` results via [`swiss-weather-mcp`](https://www.npmjs.com/package/swiss-weather-mcp).
|
package/dist/cache.d.ts
CHANGED
package/dist/cache.js
CHANGED
|
@@ -55,4 +55,8 @@ export const TTL = {
|
|
|
55
55
|
PRICES: 2 * 60 * 1000, // 2 minutes
|
|
56
56
|
TRIP_DETAILS: 5 * 60 * 1000, // 5 minutes
|
|
57
57
|
};
|
|
58
|
+
/** Test-only: clear all entries. No effect in production. */
|
|
59
|
+
export function __clearCacheForTesting() {
|
|
60
|
+
store.clear();
|
|
61
|
+
}
|
|
58
62
|
//# sourceMappingURL=cache.js.map
|
package/dist/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAA;AAEpD,MAAM,WAAW,GAAG,KAAK,CAAA;AAEzB,SAAS,YAAY;IACnB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,IAAI,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACjB,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,wDAAwD;IACxD,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,OAAO,IAAI,KAAK;YAAE,MAAK;QAC3B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACjB,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,GAAW;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAC5B,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACjB,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,qDAAqD;IACrD,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACrB,OAAO,KAAK,CAAC,IAAS,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,GAAW,EAAE,IAAO,EAAE,KAAa;IAC7D,IAAI,KAAK,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,YAAY,EAAE,CAAA;QAC9B,0DAA0D;QAC1D,IAAI,OAAO,GAAG,WAAW,GAAG,GAAG,EAAE,CAAC;YAChC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;AACzD,CAAC;AAED,OAAO;AACP,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAK,WAAW;IAC7C,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAS,YAAY;IAC/C,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAc,YAAY;IAC/C,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAQ,YAAY;CACvC,CAAA"}
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAA;AAEpD,MAAM,WAAW,GAAG,KAAK,CAAA;AAEzB,SAAS,YAAY;IACnB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,IAAI,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACjB,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,wDAAwD;IACxD,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,OAAO,IAAI,KAAK;YAAE,MAAK;QAC3B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACjB,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,GAAW;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAC5B,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACjB,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,qDAAqD;IACrD,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACjB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACrB,OAAO,KAAK,CAAC,IAAS,CAAA;AACxB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,GAAW,EAAE,IAAO,EAAE,KAAa;IAC7D,IAAI,KAAK,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,YAAY,EAAE,CAAA;QAC9B,0DAA0D;QAC1D,IAAI,OAAO,GAAG,WAAW,GAAG,GAAG,EAAE,CAAC;YAChC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;AACzD,CAAC;AAED,OAAO;AACP,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAK,WAAW;IAC7C,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAS,YAAY;IAC/C,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAc,YAAY;IAC/C,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAQ,YAAY;CACvC,CAAA;AAEV,6DAA6D;AAC7D,MAAM,UAAU,sBAAsB;IACpC,KAAK,CAAC,KAAK,EAAE,CAAA;AACf,CAAC"}
|
package/dist/formatters.d.ts
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import type { SmapiPlace, SmapiTrip, SmapiTripsCollection, SmapiPriceResult } from './transport/smapi-types.js';
|
|
2
2
|
import type { Lang } from './i18n.js';
|
|
3
|
+
/**
|
|
4
|
+
* Terse one-line summary used when the client renders the Apps SDK widget
|
|
5
|
+
* (see `isWidgetRenderingClient`). Widget clients already show a full card
|
|
6
|
+
* list — returning the long markdown table here just causes the LLM to
|
|
7
|
+
* paraphrase it into a redundant narration right next to the iframe. The
|
|
8
|
+
* structured content still carries all the data the model needs to answer
|
|
9
|
+
* follow-up questions; this string is purely for the chat bubble above the
|
|
10
|
+
* widget.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatStationsTerse(stations: SmapiPlace[], _lang?: Lang): string;
|
|
13
|
+
export declare function formatConnectionsTerse(collection: SmapiTripsCollection, lang?: Lang): string;
|
|
14
|
+
export declare function formatTripDetailsTerse(trip: SmapiTrip, lang?: Lang): string;
|
|
15
|
+
export declare function formatPricesTerse(results: SmapiPriceResult[], lang?: Lang): string;
|
|
3
16
|
export declare function formatStations(stations: SmapiPlace[], lang?: Lang): string;
|
|
4
17
|
export declare function formatConnections(collection: SmapiTripsCollection, lang?: Lang): string;
|
|
5
18
|
export declare function formatTripDetails(trip: SmapiTrip, lang?: Lang): string;
|