gbfs-mcp
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., "@gbfs-mcpCan I bike from downtown to the ferry terminal right now?"
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.
gbfs-mcp
An MCP server for GBFS bikeshare feeds. It works with any of the ~1,500 systems that publish GBFS — Citi Bike, Capital Bikeshare, Vélib', Ecobici — and it's guaranteed to work with BIXI Montréal, because BIXI is the default and the one I actually test against.
The thing I wanted was simple. I'm at work, I want to bike home, and I want to ask Claude whether that's going to work before I walk outside:
me → "I'm at work, can I bike home?"
Claude→ check_route(origin, destination)
→ Yes. 138 bikes across 15 stations near you.
At the other end Regina / de Verdun is empty right now,
but there are 35 bikes and 35 free docks within a 9 minute walk.
Feed last reported 4 minutes ago.That's the whole point. Everything below is in service of that answer being trustworthy.
What it does and what it doesn't
It tells you what a feed says right now. That's it. No history, no predictions, and no saved addresses — you pass coordinates in. I kept it that way on purpose: it stays general enough to work in any city, and nothing personal ends up on a public endpoint.
Two rules run through all of it.
Unknown is not zero. If a feed doesn't report dock counts, that means it doesn't know. If
I returned 0 there you'd ride to a station believing it's full when it might be half empty.
So unknowns say they're unknown. Ask for cargo bikes on a feed that can't count them and you
get unknown, not 0.
Nearby beats exact. These feeds lag. BIXI's median station last reported about 7 minutes
ago, and the slowest 10% are closer to half an hour. So "this station has 2 docks" is a much
weaker answer than "there are 30 docks within 400m". get_neighbourhood and check_route
pool everything nearby for that reason, and every station tells you how old its reading is.
Related MCP server: mcp-citybikes
Tools
Nine of them. Full reference with real output in docs/tools.md.
tool | what it answers |
| Where are the stations near here, or named this? Sorted by distance, with walk times. |
| Everything about one station. |
| How many bikes and docks within a radius. The answer that survives a stale feed. |
| Can I ride A to B right now? Grades both ends good / tight / poor / unknown. |
| Whole system at a glance — totals, empty and full stations, how fresh the data is. |
| Service alerts, filtered to the ones actually in effect. |
| Operator details — timezone, contact, website. |
| What the vehicle type ids mean for this system. |
| What version this feed is, how I worked that out, and what it can and can't tell you. |
Every tool takes an optional system. Before you conclude a system "has no e-bikes", call
describe_system — plenty of older feeds simply cannot report them, and that's a different
thing from having none.
Running it
npm install
npm test # 69 tests against saved real feeds, no network needed
npm run test:live # hits the actual feedsLocally, over stdio
{
"mcpServers": {
"gbfs": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/gbfs-mcp/src/stdio.ts"]
}
}
}Deployed, as a Cloudflare Worker
npx wrangler login
npm run deployIt's stateless JSON-RPC over HTTP. No Durable Objects, no KV, no database. The server is
read-only and never pushes anything to the client, so it doesn't need sessions or SSE — which
is why it scales to zero and costs nothing sitting idle. GET / gives you a description, MCP
clients POST to the same URL.
Adding another city
Four systems are built in: bixi, citibike, capitalbikeshare, ecobici. Add more with
the GBFS_SYSTEMS env var, no code change. Discovery URLs are in
MobilityData's catalog:
GBFS_SYSTEMS = '''[
{"id":"velib","name":"Vélib' Métropole",
"discoveryUrl":"https://velib-metropole-opendata.smovengo.cloud/opendata/Velib_Metropole/gbfs.json"}
]'''There's a pinVersion field too, for when a system's newer feed is broken and you want to
stay on the old one.
The version problem
This is the part that took the most work, so it gets its own doc: docs/gbfs.md.
Short version: GBFS runs from 1.0 to 3.0 and the versions genuinely break each other. Of the systems in the catalog, 964 are on 2.3, 562 on 3.0, 239 on 2.2 (that's BIXI), 167 on 1.1, and 114 on 1.0. You can't just pick one and ignore the rest.
So the client negotiates. If a system publishes gbfs_versions.json it takes the newest
version it understands and follows that URL. Otherwise it reads the version field. If
there's no version field at all, the feed predates 1.1, so it's 1.0.
This isn't box-ticking. Citi Bike defaults to 1.1, and 1.1 has no vehicle_types at all.
Its 2.3 tree does. Negotiating up is the difference between being able to answer "is there an
e-bike here" and not, across 2,509 stations.
Feed quirks I ran into
Every one of these came from pointing the code at a live feed, not from reading the spec. Details in docs/gbfs.md.
BIXI's root
gbfs.jsononly advertises the old 1.0 tree. The2-2tree it actually registers isn't linked from it.BIXI publishes no
gbfs_versionsfeed — 404 everywhere I looked for it.BIXI has a station with a negative
last_reported. Do the arithmetic naively and it looks 56 years old.BIXI's alerts feed still serves entries from 2023 and 2024. Show those unfiltered and you'd tell someone the network is closed for a snowstorm three years ago.
Citi Bike writes its versions as
"v2.3", not"2.3". The spec says bareX.Y. I rejected the prefix at first and it silently stuck the client on 1.1.v3.0 feed URLs drop the
.jsonextension, so I match feeds by name instead of building paths.Station ids are opaque strings.
"345"at BIXI, a UUID at Citi Bike,"ICONIC"at Ecobici. Don't assume they're numbers.
Layout
More detail in docs/architecture.md.
src/core/ pure logic, imports nothing from MCP or Workers
src/mcp/ tool definitions, shared by both transports
src/worker.ts Cloudflare entrypoint
src/stdio.ts local entrypoint
test/fixtures real feeds I captured — v1.1, v2.2 and v3.0src/core/ doesn't know MCP exists. If I ever want this logic behind a plain HTTP API
instead, it lifts out unchanged.
Related
bixi-monitor — long-run history for one BIXI station, plus the dashboard
A second MCP for station 345 specifically — its history and prediction models — is planned separately. This one stays general and holds nothing personal.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
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
Read-only public transit departures, stop search, and city coverage for bus and train users.
Real-time transit stops, routes, arrivals, vehicle positions, and schedules via OneBusAway APIs.
Real-time BART departures, trip planning, fares, stations, and advisories.
Live UK bike-share availability: nearby bikes and stations, popular stations, 90-day history.
Related MCP Servers
- FlicenseAqualityDmaintenanceProvides access to Bay Wheels realtime bikeshare data, enabling users to find nearest available bikes (standard or ebike) and docking stations with available spaces in the San Francisco Bay Area.2-
- AlicenseNot gradedqualityCmaintenanceProvides access to bike sharing station data from CityBik.es API, enabling queries for station availability and locations without authentication.15MIT
- AlicenseNot gradedqualityDmaintenanceProvides real-time access to Montreal's Bixi bike-sharing data through the GBFS API. Enables querying station information, availability, nearby stations, and system alerts.MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying global transit data including agencies, routes, stops, and departures through a GTFS aggregator.2MIT
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/MackTr/gbfs-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server