Renfe MCP Server
Click on "Deploy 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., "@Renfe MCP Server What trains go from Madrid to Barcelona tomorrow?"
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.
Renfe MCP Server ๐
A Model Context Protocol (MCP) server for querying Renfe (Spanish national railway) train schedules using official GTFS data. Integrates seamlessly with Claude Desktop and other MCP-compatible clients.
โจ Features
๐ Search trains between any two Spanish cities on a specific date with pagination
๐ฐ Check prices - real-time price scraping from Renfe website with pagination support
๐ Find stations in any city (Madrid has 7 stations!)
๐ Flexible date parsing - accepts ISO, European, and written date formats
๐ Auto-updates - automatically downloads latest GTFS schedules from Renfe
โก Fast & accurate - uses official Renfe GTFS data with complete timetables
๐ฏ Smart filtering - handles service calendars, holidays, and exceptions
๐ ๏ธ Claude Desktop ready - works out of the box with MCP clients
Related MCP server: railinfo-mcp
๐ Quick Start
Prerequisites
Python 3.12 or higher
uv (recommended) or pip
Installation
Clone the repository
git clone https://github.com/yourusername/renfe_mcp.git cd renfe_mcpInstall dependencies
uv syncRun the server (GTFS data downloads automatically)
uv run python -m renfe_mcp.server
๐ Usage
Standalone Testing
Test the search functionality directly:
from renfe_mcp.schedule_searcher import ScheduleSearcher
from renfe_mcp.price_checker import check_prices
# Search trains
searcher = ScheduleSearcher("renfe_schedule")
trains = searcher.search("Madrid", "Barcelona", "2025-11-20")
# Check prices
prices = check_prices("Madrid", "Barcelona", "2025-11-20")Claude Desktop Integration
Add to your Claude Desktop config file:
Windows (%APPDATA%\Claude\claude_desktop_config.json):
{
"mcpServers": {
"renfe": {
"command": "uv",
"args": [
"--directory",
"C:\\Users\\YourName\\path\\to\\renfe_mcp",
"run",
"python",
"-m",
"renfe_mcp.server"
]
}
}
}macOS (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"renfe": {
"command": "uv",
"args": [
"--directory",
"/path/to/renfe_mcp",
"run",
"python",
"-m",
"renfe_mcp.server"
]
}
}
}Linux (~/.config/Claude/claude_desktop_config.json):
{
"mcpServers": {
"renfe": {
"command": "uv",
"args": [
"--directory",
"/path/to/renfe_mcp",
"run",
"python",
"-m",
"renfe_mcp.server"
]
}
}
}Restart Claude Desktop, and you can ask:
"Show me trains from Madrid to Barcelona tomorrow"
"What's the earliest train from Barcelona to Valencia on December 1st?"
"What train stations are in Madrid?"
"How many trains run between Madrid and Sevilla in the afternoon?"
"Check prices for trains from Madrid to Barcelona on December 1st"
"What are the ticket prices for the first 5 trains?"
๐ ๏ธ MCP Tools
1. search_trains
Find trains between two cities on a specific date with pagination support.
Parameters:
origin(string): Origin city name (e.g., "Madrid", "Barcelona")destination(string): Destination city name (e.g., "Valencia", "Sevilla")date(string, optional): Travel date in flexible formats:ISO:
"2025-11-28"European:
"28/11/2025"Written:
"November 28, 2025"Default: today's date
page(integer, optional): Page number to display (default: 1)per_page(integer, optional): Results per page (default: 10, max: 50)
Example Output:
Found 36 train(s) total
Showing page 1 of 4 (10 trains)
1. AVE
Madrid Pta.Atocha - Almudena Grandes โ Barcelona-Sants
Departs: 6:16:00 | Arrives: 9:05:00
Duration: 2h 49min
2. AVE
Madrid Pta.Atocha - Almudena Grandes โ Barcelona-Sants
Departs: 6:27:00 | Arrives: 9:25:00
Duration: 2h 58min
...
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
To see more trains, use page=2
Total pages: 42. find_station
Search for train stations in a city.
Parameters:
city_name(string): City name to search (e.g., "Madrid")
Example Output:
Found 7 stations:
All stations found:
1. Madrid-Chamartรญn-Clara Campoamor (ID: 17000)
2. Madrid - Atocha Cercanรญas (ID: 18000)
3. Madrid Pta.Atocha - Almudena Grandes (ID: 60000)
...3. get_train_prices
Check actual ticket prices by scraping the Renfe website with pagination support.
Parameters:
origin(string): Origin city name (e.g., "Madrid", "Barcelona")destination(string): Destination city name (e.g., "Valencia", "Sevilla")date(string, optional): Travel date (same formats assearch_trains)page(integer, optional): Page number to display (default: 1)per_page(integer, optional): Results per page (default: 5, max: 20)
Example Output:
PRICE CHECK RESULTS
From: Madrid -> Barcelona
Date: 2025-11-17
Showing 5 train(s)
1. AVE
Departs: 06:16 | Arrives: 09:05
Duration: 2h 49min
Price: 94.90 EUR | [Available]
2. AVE
Departs: 06:27 | Arrives: 09:25
Duration: 2h 58min
Price: 118.60 EUR | [Available]
...
To see more prices, try page=2Note: This tool scrapes the Renfe website and may take a few seconds to complete. Pagination now matches search_trains so you can get prices for trains on any page (e.g., page 2 shows prices for trains 6-10).
๐ Data Updates
The server includes automatic GTFS data updates from Renfe's open data portal.
Automatic Updates
On server startup, it checks for new data and downloads if needed:
uv run python -m renfe_mcp.server
# [CHECK] Checking data versions:
# Server: 2025-11-15T00:40:21
# Local: 2025-11-10T00:30:15
# [UPDATE] Server has newer data
# [DOWNLOAD] Downloading GTFS data...
# [OK] GTFS data updated successfully!Manual Updates
Check and update if needed:
uv run python -m renfe_mcp.update_dataForce update (download regardless of version):
uv run python -m renfe_mcp.update_data --forceThe update system:
โ Compares server version with local version
โ Only downloads when new data is available
โ Stores version info in
renfe_schedule/.last_updatedโ Automatically extracts GTFS CSV files
๐๏ธ Architecture
renfe_mcp/
โโโ pyproject.toml # Dependencies & build config
โโโ README.md # This file
โโโ src/renfe_mcp/ # Main package
โ โโโ __init__.py # Package exports
โ โโโ server.py # FastMCP server implementation
โ โโโ config.py # Pydantic configuration
โ โโโ exceptions.py # Exception hierarchy
โ โโโ logging.py # Structured logging
โ โโโ security.py # Auth & rate limiting
โ โโโ price_checker.py # Price checking module
โ โโโ schedule_searcher.py # GTFS schedule search
โ โโโ station_service.py # Unified station lookups
โ โโโ update_data.py # GTFS data updater
โ โโโ scraper/ # Price scraper package
โ โโโ __init__.py # Package exports
โ โโโ scraper.py # RenfeScraper with DWR protocol
โ โโโ dwr.py # DWR utilities
โ โโโ models.py # Pydantic models
โ โโโ exceptions.py # Scraper exceptions
โ โโโ stations.json # Station code database
โโโ tests/ # Test suite
โ โโโ test_final_integration.py
โ โโโ test_security.py
โ โโโ ...
โโโ renfe_schedule/ # GTFS data (auto-downloaded)
โโโ stops.txt # Station information
โโโ routes.txt # Train routes
โโโ trips.txt # Trip schedules
โโโ stop_times.txt # Arrival/departure times
โโโ calendar.txt # Service schedules
โโโ calendar_dates.txt # Holiday exceptions
โโโ .last_updated # Version trackingHow It Works
City to Station Mapping: Fuzzy matches city names to station IDs
Date Filtering:
Checks
calendar.txtfor service schedules (day of week)Applies exceptions from
calendar_dates.txt(holidays, special dates)
Route Finding:
Joins trips, stop_times, and stops tables
Validates stop sequences and pickup/dropoff permissions
Ensures origin comes before destination
Results: Returns all trains sorted chronologically with proper numeric time sorting
Key Implementation Details
โ Handles multiple stations per city (e.g., Madrid has 7)
โ Respects service exceptions (holidays, maintenance)
โ Validates passenger boarding/alighting permissions (
pickup_type,drop_off_type)โ Fixed sorting bug: Proper numeric time sorting (not lexicographic!)
โ CSV column whitespace handling (strips on load)
โ Complete result sets (no truncation)
๐บ๏ธ Supported Routes
The server supports any route in the Renfe network:
High-Speed (AVE): Madrid-Barcelona, Madrid-Sevilla, Madrid-Valencia
Long-Distance (ALVIA, Intercity): Major city connections
International (AVE INT): Cross-border services
Regional: Local routes across Spain
Commuter (Cercanรญas): Urban networks
Popular Cities:
Madrid (7 stations), Barcelona, Valencia
Sevilla, Mรกlaga, Bilbao, Zaragoza
Alicante, Cรณrdoba, Granada, Murcia
100+ cities across Spain!
Use find_station to discover available stations in any city.
๐ง Development
Project Setup
# Clone and install
git clone https://github.com/yourusername/renfe_mcp.git
cd renfe_mcp
uv sync
# Run the server
uv run python -m renfe_mcp.server
# Run tests
uv run python tests/test_final_integration.pyDependencies
fastmcp (>=0.7.0) - MCP server framework
pandas (>=2.3.3) - GTFS data processing
pydantic (>=2.11.7) - Data validation and models
pydantic-settings (>=2.0.0) - Environment-based configuration
httpx (>=0.27.0) - Modern HTTP client for price scraping
python-dateutil (>=2.8.2) - Flexible date parsing
json5 (>=0.12.0) - JavaScript object parsing for DWR responses
python-dotenv (>=1.0.0) - Environment variables
Configuration
Configure via environment variables (prefix RENFE_) or .env file:
# Authentication
RENFE_ENABLE_AUTH=true
RENFE_API_KEY=your-secret-key
# Rate Limiting
RENFE_RATE_LIMIT_ENABLED=true
RENFE_MAX_REQUESTS_PER_MINUTE=30
RENFE_MAX_REQUESTS_PER_HOUR=200
# Development
RENFE_DEV_MODE=false
RENFE_LOG_LEVEL=INFO๐ Data Source
GTFS data from Renfe's Open Data Portal:
API Endpoint:
https://data.renfe.com/api/3/action/resource_showResource ID:
25d6b043-9e47-4f99-bd91-edd51d782450Update Frequency: Updated regularly by Renfe (checked on server startup)
Format: GTFS (General Transit Feed Specification)
Size: ~800 KB compressed, ~40 MB extracted
๐ Known Issues
Windows console may show encoding errors with Unicode characters (functionality not affected)
Very large result sets (100+ trains) can be verbose but complete
๐ค Contributing
Contributions welcome! Please:
Fork the repository
Create a feature branch (
git checkout -b feature/amazing-feature)Commit your changes (
git commit -m 'Add amazing feature')Push to the branch (
git push origin feature/amazing-feature)Open a Pull Request
Ideas for Contributions
Add price information(โ Implemented via web scraping)Support for train status/delays
Multi-leg journey planning
Visualization of routes on maps
Additional query filters (train type, duration, etc.)
Return trip price checking
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
Renfe Operadora for providing open GTFS data
Anthropic for Claude and the Model Context Protocol
The GTFS community for standardizing transit data
๐ฎ Support
Issues: GitHub Issues
Discussions: GitHub Discussions
MCP Docs: Model Context Protocol
๐ Related Projects
SNCF MCP Server - Similar server for French railways
FastMCP - The framework powering this server
MCP Servers - Official MCP server implementations
๐ Sources & Inspiration
renfe-bot by @emartinez-dev - Telegram bot for Renfe train ticket monitoring. The DWR (Direct Web Remoting) protocol reverse-engineering and price scraping techniques were inspired by renfe-bot's implementation. This MCP server features a custom-built scraper using modern Python (httpx, pydantic) while preserving the core DWR protocol logic.
Built with โค๏ธ using FastMCP and Claude
Travel smart, travel by train! ๐
Available Tools
3 toolsfind_stationA
Search for train stations in a city and return matching options.
Useful for checking what stations are available in a city before searching for journeys.
Args: city_name: City name to search for (e.g., "Madrid", "Barcelona", "Valencia") api_key: API key for authentication (optional if configured via environment)
Returns: A formatted string showing all matching stations with their IDs and full names.
Inputs: city_name (required), api_key. Returns: result
get_train_pricesA
Check actual ticket prices for trains between two cities using web scraping with pagination.
NOTE: This tool scrapes the Renfe website and may take a few seconds to complete. It complements the search_trains tool by providing real-time price information. This endpoint has stricter rate limits due to web scraping.
Args: origin: Starting city name (e.g., "Madrid", "Barcelona", "Valencia") destination: Destination city name (e.g., "Madrid", "Barcelona", "Sevilla") date: Travel date. Accepts flexible formats: - ISO: "2025-11-28" (RECOMMENDED) - European: "28/11/2025" - Written: "November 28, 2025" or "28 November 2025" If not provided, checks prices for today's date. page: Page number to display (default: 1) per_page: Number of results per page (default: 5, max: 20) api_key: API key for authentication (optional if configured via environment)
Returns: Formatted string with train prices, availability, and booking information.
Inputs: origin (required), destination (required), date, page, +2 more. Returns: result
search_trainsA
Search for train journeys between two cities on a specific date.
Args: origin: Starting city name (e.g., "Madrid", "Barcelona", "Valencia") destination: Destination city name (e.g., "Madrid", "Barcelona", "Sevilla") date: Travel date. Accepts flexible formats: - ISO: "2025-11-28" (RECOMMENDED) - European: "28/11/2025" - Written: "November 28, 2025" or "28 November 2025" If not provided, searches for today's date. page: Page number to display (default: 1) per_page: Number of results per page (default: 10, max: 50) api_key: API key for authentication (optional if configured via environment)
Returns: Formatted string with available train options including times and durations.
Inputs: origin (required), destination (required), date, page, +2 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogโฆ
TDQS
Scored across 3 tools
Each tool serves a distinct purpose: station lookup, journey search, and price retrieval. No overlap in functionality.
All tools follow a consistent verb_noun pattern in snake_case: find_station, get_train_prices, search_trains.
Three tools cover the core workflow of finding stations, searching journeys, and checking prices. While minimal, it's appropriate for the scope.
Covers the essential travel information needs: station lookup, journey search, and pricing. Missing booking or detailed trip info, but acceptable for an info-focused server.
Maintenance
Related MCP Connectors
Omio MCP server for ChatGPT, Claude and any AI agent: search trips, find the cheapest day and start booking in your own Omio account. Cotlet works in the account through your Cloud Browser, a real Chrome where you sign in to Omio yourself; Cotlet does not store your password and you need no Omio API key. About the official Omio API: Omio has no public API for your own account (checked 24 Oct 2026). Its affiliate programme lists a Search API for partners, and its app in ChatGPT searches trips; Your Bookings, saved travelers and checkout work only on omio.com and in the Omio app. Setup and FAQ: https://cotlet.dev/integrations/omio-api-mcp-server
Check UK Delay Repay, UK261 flights and TfL refunds. Save claims and check commutes on request.
Belgian trains for AI agents: live journeys, departures, delays, disruptions. Free, no key.
Cached UK train departures and qualified platforms, powered by National Rail Enquiries.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides real-time Dutch Railways (NS) data for journey planning, live departures, disruptions, and station search.3-
- AlicenseNot gradedqualityDmaintenanceEnables real-time Indian Railways information retrieval, including live train running status, station schedules, and upcoming arrivals/departures.ISC
- FlicenseAqualityDmaintenanceEnables querying SNCF train schedules and stations in France using the official Navitia API, with support for flexible date parsing and real-time journey planning.31-
- AlicenseNot gradedqualityBmaintenanceEnables querying SNCF Open Data (train schedules, stations, punctuality, etc.) through natural language or direct tool calls, with dataset search, metadata retrieval, and ODSQL querying.105 npmMIT