
Bicycle routes generator MCP
io.github.Marc-ArmillasPublished by GitHub account Marc-Armillasv0.5.0Updated Oct 26, 2026
MTB and road cycling routes on real OpenStreetMap trails, saved as GPX with safety warnings.
The publisher's own server: Guide Registry
Overview
Generates MTB and road cycling routes on real OpenStreetMap trails from a place name, saving them as GPX with elevation and safety warnings.
- What you can do
- Generate a loop or point-to-point route from a start place, target distance, trail type, climb limit, seed and ordered via points
- Return the GPX file path plus a summary of distance, climbing, maximum grade and surface percentages
- Report warnings for motor traffic, steep grades, protected areas, bike-forbidden ways and technical sections
- List previously saved routes
- When to use it
- Useful when you want an assistant to plan a mountain bike or road ride from a named location and hand you a GPX file for a bike computer, with notes on traffic and steep sections. Also handy for quickly producing alternative loops by changing the seed, distance or via points.
- Requirements
- Runs locally as a stdio process; the Claude Desktop extension bundles Python via uv, while manual installs need uv (which installs Python). Network access to Nominatim, BRouter (or OpenRouteService) and Overpass. Configuration through environment variables: BIKE_GPX_DIR, BIKE_CONTACT (contact email or URL, recommended by Nominatim policy), BIKE_ENGINE, BIKE_BROUTER_URL, ORS_API_KEY if using OpenRouteService, BIKE_PROTECTED_AREAS, BIKE_DATA_DIR.
Installation
In SourceWeft
- Open Bicycle routes generator MCP in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
Bicycle routes generator MCP
English · Español
[Bicycle routes generator MCP server]
⬇️ Download the Claude Desktop extension (bicycle-routes-generator-mcp.mcpb)
Generates mountain bike and road cycling routes from a location and saves them as GPX with elevation. The track is computed by a routing engine (BRouter or OpenRouteService) on real OpenStreetMap trails and roads: neither the AI nor the application invents coordinates.
You can use it:
- With Claude (Claude Desktop or Claude Code) through a local MCP server: "make me a ~25 km MTB loop from Casa de Campo in Madrid, little climbing, on dirt tracks" (see what happens when you ask Claude).
- From the terminal, without AI:
bicycle-routes generate "Casa de Campo, Madrid" --km 25 --type tracks.
Every route comes with a summary (distance, climbing, maximum grade, % of pavement, dirt track and singletrack) and warnings: sections with motor traffic, grades over 12 %, protected areas, ways where bikes are not allowed and technical sections.
💾 GPX files go to
/tmp/bicycle-routesby default. macOS empties/tmpon restart and cleans up old files, so copy the routes you want to keep (or setBIKE_GPX_DIRto another folder).
⚠️ Always check the route on a map before riding. OpenStreetMap data may be incomplete or out of date, and does not reflect temporary closures or every local regulation. Climbing is computed from a digital elevation model (~90 m) and may differ from what a barometric watch or bike computer records (often by 10-20 %); short ramps may be smoothed out.
Easy install in Claude Desktop (.mcpb extension)
- Download
bicycle-routes-generator-mcp.mcpb(always the latest release), or build it withnpx @anthropic-ai/mcpb pack . dist/bicycle-routes-generator-mcp.mcpb. - Double-click the file (or drag it into Claude Desktop → Settings → Extensions) and click Install.
- Fill in the configuration: the GPX folder (
/tmp/bicycle-routesby default) and a contact email (required by the OpenStreetMap/Nominatim usage policy). The other fields are optional. - Ask Claude: "make me a 25 km MTB loop from Casa de Campo in Madrid on dirt tracks".
No need to install Python: this is a uv extension, so Claude Desktop downloads Python and the
dependencies automatically the first time (it can take a minute). .mcpb is the successor of
the .dxt format; older Claude Desktop versions that only support .dxt cannot run uv
extensions.
Manual install (CLI and Claude Code)
Requirements: macOS, Windows or Linux with uv (it installs Python for you).
Configuration (environment variables)
There are no keys or personal data in the code: everything is configured through environment
variables (or a .env file in the folder you run the CLI from).
Command-line usage
Trail types (--type):
tracks: favours wide dirt tracks, little singletrack and no extreme ramps.mixed(default): general MTB.singletrack: more singletrack, less pavement.road: road bike. Paved roads with little traffic; warns about unpaved sections and only about busy roads (main roads or heavy estimated traffic), not ordinary secondary roads.
Real example (abridged):
More examples with real output in docs/pruebas-reales.md (in Spanish).
Using it with Claude (MCP server)
The server exposes two tools:
generate_route(start, distance_km, max_climb_m?, trail_type?, loop=true, end?, name?, seed?, via?)→ GPX path, summary and warnings.viais a list of places the route must pass through, in order (e.g. "a loop from Casa de Campo passing through El Pardo and Aravaca").list_routes()→ saved routes.
Example: what happens when you ask Claude
You: "Make me a ~40 km MTB loop from Casa de Campo in Madrid."
1. Claude calls the tool, choosing the arguments from your request:
2. The MCP server computes the route on your computer (10-60 seconds):
- Looks up "Casa de Campo, Madrid" in Nominatim (OpenStreetMap) →
40.424, -3.756. - Generates 6 candidate loops with BRouter on real trails, adjusting each one to about 40 km.
- Scores them (distance, traffic, repeated trails, surface, forbidden access, climbing) and keeps the best one.
- Analyses it: climbing, grades, surface, sections with traffic, technical sections and protected areas (Overpass API).
- Saves the GPX with elevation in your GPX folder.
3. It returns this to Claude (real output, abridged; obtained with "seed": 2026 so it can
be reproduced: without a seed every request gives a different loop):
4. Claude answers you in your language, with the summary and every warning. For example (illustrative, Claude's wording varies):
I've created a 37.8 km loop from Casa de Campo with +336 m of climbing: 41 % dirt track, 31 % singletrack and 29 % paved. Watch out for 0.3 km on a road with traffic (km 27.3–27.6) and a steep descent of ~13 % at km 9.2. Climbing comes from an elevation model and may differ from your watch, so check the route on a map before riding. GPX:
/tmp/bicycle-routes/mtb-casa-de-campo-38-km-loop-20261017-163919.gpx
From there you can keep going in the same conversation:
Claude Code
Claude Desktop (without the extension)
The .mcpb extension is the easiest option (see above). To configure it by hand instead:
Settings → Developer → Edit config (claude_desktop_config.json):
Use the absolute path to uv (which uv on macOS/Linux, where uv on Windows), because
Claude Desktop does not always inherit the terminal's PATH. Restart Claude Desktop.
Building the extension
manifest.json describes the extension (uv type, tools and configuration fields) and
.mcpbignore keeps the tests, docs and your .env out of the package.
Publishing a release
-
Bump
versioninmanifest.json,pyproject.tomlandsrc/bicycle_routes/__init__.pytogether. -
Create and push a matching tag:
-
The
ReleaseGitHub Actions workflow runs the tests, buildsbicycle-routes-generator-mcp.mcpband attaches it to a new GitHub Release. The download link at the top of this README always points to the latest one. -
A second job publishes that version to the official MCP Registry as
io.github.Marc-Armillas/bicycle-routes-generator-mcp: it fills inserver.jsonwith the version, the release URL and the SHA-256 of the.mcpb, and logs in with GitHub OIDC (no secret needed). If the registry rejects it, the GitHub Release is already published.
Garmin, Wahoo and other platforms
The application is platform-independent: the output is a standard GPX file. Sending to
platforms is done by optional exporters sharing a common interface
(export(route, config) -> ExportResult, in src/bicycle_routes/exporters/).
- disk (default): saves the GPX in
BIKE_GPX_DIR. - garmin: delegates to an already installed Garmin MCP server (
upload_coursetool).- With Claude (recommended): nothing to configure. Ask "upload it to Garmin" and Claude
will call the Garmin MCP server's
upload_coursewith the generated GPX andactivity_type="mountain_biking"("road_biking"for road routes). - From the CLI: set
BIKE_GARMIN_MCP_COMMANDto the command that starts that server and use--garmin. Garmin credentials are handled by that server, never by this app. - Community Garmin MCP servers use Garmin Connect's unofficial web API and may stop working. The official API (Courses API) is only available to approved businesses.
- With Claude (recommended): nothing to configure. Ask "upload it to Garmin" and Claude
will call the Garmin MCP server's
- wahoo: not implemented. The Cloud API has
POST /v1/routes, but you must request an app and get it approved (notes inexporters/wahoo.py). - Komoot (API only for partners under contract) and Strava (its API cannot create routes): import the GPX manually on their websites.
Routing engines
-
BRouter (default, MIT, no key). Uses the
mtbprofile withStrictNOBicycleaccess=1(avoids ways taggedbicycle=no) andavoid_unsafe=1; forroad, thefastbikeprofile withconsider_traffic=1(the same routes asfastbike-lowtraffic). The publicbrouter.deserver makes no availability guarantees: the app sends at most 1 request per second and caches responses. For heavy use, run a local one (not yet tested in this project): -
OpenRouteService (optional):
BIKE_ENGINE=orsandORS_API_KEY(free plan: 2,000 routes/day, 40/min). Profilecycling-mountain, orcycling-roadforroad.
How the loop is generated
- The place is geocoded with Nominatim (or the coordinates you give are used).
- 3-4 waypoints are placed on a circle passing through the start, with a random orientation
(reproducible with
--seed). - The engine routes start → waypoints → start on real trails.
- The radius is adjusted until the requested distance is approached (about 2-4 requests).
- Six candidates are generated and the best one is picked by distance, traffic, repeated trails, surface, forbidden access, climbing and grades.
With via points (--via / via), your points replace the random ones: the engine routes
start → via 1 → … → via N → start (or → end, for point-to-point), in the given order. The
distance comes from those points, not from --km; a warning is added if it differs by more
than 15 %.
External services and their policies
- Nominatim (place lookup): usage policy. At most 1 request/second, an identifying User-Agent, cached results, no autocomplete or bulk queries. For heavy use, run your own Nominatim.
- Overpass API (protected areas): about 10,000 requests/day per IP as a guideline; one cached query per route.
- brouter.de: public server without guarantees; use a local one for heavy use.
Development
Layout:
The core does not depend on the CLI or the MCP server, so it could later be offered as a remote server (HTTP transport) by changing only the exporter and the transport.
License and attribution
Code under the MIT license. See NOTICE.
Trail and place data © OpenStreetMap contributors, under the ODbL license. Generated GPX files include this attribution in their metadata; keep it if you share them. BRouter elevation: SRTM (CGIAR-CSI).
Source: README.md at commit c5d1cf3
Tools
0Version history
1- v0.5.0LatestOct 18, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts
