A Model Context Protocol (MCP) server for querying SNCF (French national railway) train schedules using the official Navitia API. Integrates seamlessly with Claude Desktop and other MCP-compatible clients.
- ๐ Search trains between any two French cities with real-time data
- ๐ Find stations in any city across France
- ๐ Flexible date parsing - accepts ISO, European, and written date formats
- โก Real-time data - uses official SNCF Navitia API with live timetables
- ๐ฏ Smart journey planning - shows transfers, duration, and route details
- ๐ International routes - supports cross-border journeys (e.g., Paris-Munich)
- ๐ ๏ธ Claude Desktop ready - works out of the box with MCP clients
- Python 3.12 or higher
- uv (recommended) or pip
- SNCF API key (free registration)
-
Clone the repository
git clone https://github.com/belgrano9/sncf_mcp_server.git cd sncf_mcp_server -
Install dependencies
uv sync
-
Get your SNCF API key
- Register at SNCF Digital API Portal
- Request access to the Navitia API
- Copy your API key
-
Configure environment variables
Create a
.envfile in the project root:SNCF_API=your-api-key-here
โ ๏ธ IMPORTANT: Never commit your.envfile! It's already in.gitignore. -
Test the server
uv run server.py
Test the search functionality directly in Python:
from server import search_trains, find_station
# Search for trains
result = search_trains("Paris", "Lyon", "2025-11-20 14:00")
print(result)
# Find a station
stations = find_station("Paris")
print(stations)Or use the included Jupyter notebook (test_notebook.ipynb) for interactive testing.
Add to your Claude Desktop config file:
Windows (%APPDATA%\Claude\claude_desktop_config.json):
{
"mcpServers": {
"sncf": {
"command": "uv",
"args": [
"--directory",
"C:\\Users\\YourName\\path\\to\\sncf_mcp_server",
"run",
"server.py"
]
}
}
}macOS (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"sncf": {
"command": "uv",
"args": [
"--directory",
"/path/to/sncf_mcp_server",
"run",
"server.py"
]
}
}
}Linux (~/.config/Claude/claude_desktop_config.json):
{
"mcpServers": {
"sncf": {
"command": "uv",
"args": [
"--directory",
"/path/to/sncf_mcp_server",
"run",
"server.py"
]
}
}
}Restart Claude Desktop, and you can ask:
- "Show me trains from Paris to Lyon tomorrow at 2pm"
- "What's the earliest train from Paris Gare de l'Est to Munich tomorrow?"
- "Find all train stations in Paris"
- "How long does it take to get from Bordeaux to Marseille?"
Find trains between two stations with real-time data.
Parameters:
origin(string): Origin station/city name (e.g., "Paris", "Lyon", "Paris Gare de l'Est")destination(string): Destination station/city name (e.g., "Mรผnchen Hbf", "Barcelona")departure_datetime(string, optional): Travel date/time in flexible formats:- ISO:
"2025-11-28 08:00"(recommended) - European:
"28/11/2025 08:00" - Written:
"November 28, 2025 8:00am" - Default: current time
- ISO:
Example Output:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SNCF JOURNEY SEARCH
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ Searched for 'Paris Est':
โ Paris Gare de l'Est (ID: stop_area:SNCF:...)
Paris - Bercy (ID: stop_area:SNCF:...)
Paris Montparnasse (ID: stop_area:SNCF:...)
โ Selected: Paris Gare de l'Est
๐ Searched for 'Mรผnchen Hbf':
โ Mรผnchen Hauptbahnhof (ID: stop_area:OCE:...)
โ Selected: Mรผnchen Hauptbahnhof
๐
Searching for trains departing after: 2025-11-28 08:00
๐ API datetime format: 20251128T080000
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ AVAILABLE TRAINS
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Found 5 journey option(s):
1. Depart: 2025-11-28 08:55 โ Arrive: 2025-11-28 14:54
Duration: 5h 59min | Direct
2. Depart: 2025-11-28 10:55 โ Arrive: 2025-11-28 16:54
Duration: 5h 59min | Direct
3. Depart: 2025-11-28 12:55 โ Arrive: 2025-11-28 19:18
Duration: 6h 23min | 1 change(s)
Route: Paris Gare de l'Est โ Stuttgart Hbf | Stuttgart Hbf โ Mรผnchen Hbf
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Search for train stations in a city or by name.
Parameters:
station_name(string): Station/city name to search (e.g., "Paris", "Lyon Part-Dieu")
Example Output:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
STATION SEARCH
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ Searched for 'Paris':
โ Paris Gare de Lyon (ID: stop_area:SNCF:87686006)
Paris Montparnasse (ID: stop_area:SNCF:87391003)
Paris Gare du Nord (ID: stop_area:SNCF:87271007)
โ Selected: Paris Gare de Lyon
โ
Best match: Paris Gare de Lyon
ID: stop_area:SNCF:87686006
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Educational Proof of Concept Only - May Not Work
Attempts to scrape price information from SNCF's booking system.
- This is an experimental feature for educational purposes only
- May violate SNCF's Terms of Service
- Likely blocked by anti-scraping measures (403 Forbidden)
- NOT recommended for production use
- For real pricing, use commercial APIs (Lyko, Trainline) or SNCF Connect website
Parameters:
origin(string): Origin station/city namedestination(string): Destination station/city namedeparture_datetime(string, optional): Travel date/time (same formats as search_trains)page(integer, optional): Page number (default: 1)per_page(integer, optional): Results per page (default: 5, max: 20)
Example Output (if it worked):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SNCF PRICE CHECK (EXPERIMENTAL)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๏ธ WARNING: Experimental feature
May not work due to anti-scraping measures
For educational purposes only
๐ Route: Paris Gare de Lyon โ Marseille Saint-Charles
๐
Date: 2025-11-17
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Attempting to fetch prices...
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Price check failed: Access forbidden - anti-scraping measures detected
This feature is experimental and may not work.
For real pricing, please visit:
- SNCF Connect: https://www.sncf-connect.com
- Or use commercial API providers
Why This Probably Won't Work:
- SNCF employs anti-scraping measures (403 Forbidden)
- Requires reverse-engineering their booking API
- API structure is proprietary and undocumented
- May violate Terms of Service
Recommended Alternatives for Production:
- Lyko SNCF Connect API - Commercial provider
- Trainline API - Multi-operator booking
- Official SNCF partnership programs
See sncf_scraper/README.md for technical details and ethical considerations.
sncf_mcp_server/
โโโ server.py # FastMCP server implementation
โโโ price_checker.py # Price scraping wrapper (experimental)
โโโ pyproject.toml # Dependencies & project config
โโโ .env # API key (not committed)
โโโ .gitignore # Git ignore rules
โโโ README.md # This file
โโโ test_notebook.ipynb # Jupyter notebook for testing
โโโ sncf_scraper/ # Price scraper module (experimental)
โ โโโ __init__.py # Module exports
โ โโโ models.py # TrainOffer, PriceSearchResult models
โ โโโ scraper.py # SNCFPriceScraper implementation
โ โโโ README.md # Scraper documentation & disclaimers
โโโ tests/ # Test suite
โโโ test_simple.py # Simple train search test
โโโ test_pagination.py # Pagination feature test
โโโ test_search.py # MCP wrapper test
โโโ test_price_scraper.py # Price scraper tests (experimental)
โโโ debug_*.py # Debug/diagnostic scripts
โโโ run_all_tests.py # Test runner
โโโ README.md # Test documentation
- Station Search: Queries Navitia API's
/placesendpoint with fuzzy matching - Journey Planning: Uses
/journeysendpoint with origin, destination, and datetime - Date Parsing: Flexible parser handles multiple date/time formats
- Response Formatting: Returns human-readable journey information with:
- Departure and arrival times
- Journey duration
- Number of transfers
- Route details for multi-leg journeys
- โ Real-time data (no local database needed)
- โ
Flexible date parsing with
python-dateutil - โ European date format support (day-first parsing)
- โ Automatic station ID resolution from city names
- โ Shows top 3 station matches for transparency
- โ Handles both domestic and international routes
- โ Transfer information with route breakdown
- โ Pagination support - Returns 10 results per page (up to 100 journeys)
- โ Comprehensive test suite - See tests/README.md
The server supports any route in the SNCF/Navitia network:
- High-Speed (TGV): Paris-Lyon, Paris-Marseille, Paris-Bordeaux, Paris-Strasbourg
- International: Paris-London (Eurostar), Paris-Munich, Paris-Barcelona, Paris-Brussels
- Long-Distance (Intercitรฉs): Regional connections across France
- TER (Regional Express): Local services
- Cross-border: Connections to Germany, Italy, Spain, Switzerland, Belgium
Major Cities:
- Paris (multiple stations: Gare du Nord, Gare de Lyon, Montparnasse, Est, Austerlitz, Saint-Lazare, Bercy)
- Lyon, Marseille, Bordeaux, Toulouse
- Strasbourg, Nantes, Nice, Lille
- International: London, Munich, Barcelona, Brussels, Geneva, Milan
- 1000+ stations across France and Europe!
Use find_station to discover available stations in any city.
# Clone and install
git clone https://github.com/belgrano9/sncf_mcp_server.git
cd sncf_mcp_server
uv sync
# Set up your API key in .env
echo "SNCF_API=your-api-key-here" > .env
# Run the server
uv run server.py
# Or use FastMCP dev mode
fastmcp dev server.py- fastmcp - MCP server framework
- requests (>=2.32.5) - HTTP client for API calls
- python-dotenv (>=1.2.1) - Environment variable management
- python-dateutil - Flexible date/time parsing
- httpx (>=0.28.1) - Async HTTP client
- loguru (>=0.7.3) - Logging
- rich (>=14.2.0) - Terminal formatting
server.py- Main MCP server withsearch_trainsandfind_stationtools.env- API key configuration (never commit!)test_notebook.ipynb- Interactive testing notebooktests/- Test suite (see tests/README.md)
Run the test suite to verify everything works:
# Run all tests
uv run tests/run_all_tests.py
# Run individual tests
uv run tests/test_simple.py # Simple train search
uv run tests/test_pagination.py # Pagination feature
uv run tests/debug_env2.py # Environment checkSee tests/README.md for detailed test documentation.
Real-time data from SNCF Navitia API:
- API Base URL:
https://api.sncf.com/v1 - Authentication: HTTP Basic Auth (API key as username)
- Coverage: SNCF network across France and international connections
- Update Frequency: Real-time (no manual updates needed)
- Format: JSON responses
- Documentation: Navitia API Docs
- Visit SNCF Digital
- Create an account
- Request access to the Navitia API
- Copy your API key to
.env
- Windows console may show encoding errors with Unicode characters (functionality not affected)
- Station name matching uses first result - use
find_stationfor ambiguous names - International routes may have limited availability depending on API coverage
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
- Add price information (if available in API)
- Support for train status/real-time delays
- Multi-leg journey optimization
- Visualization of routes on maps
- Additional query filters (train type, max transfers, etc.)
- Support for round-trip queries
- Save favorite routes
This project is licensed under the MIT License - see the LICENSE file for details.
- SNCF for providing the Navitia open API
- FastMCP by @jlowin for the excellent MCP framework
- Anthropic for Claude and the Model Context Protocol
- Navitia for powering the transit data API
- Issues: GitHub Issues
- API Documentation: Navitia API Docs
- MCP Docs: Model Context Protocol
- Renfe MCP Server - Similar server for Spanish railways
- FastMCP - The framework powering this server
- MCP Servers - Official MCP server implementations
Built with โค๏ธ using FastMCP and Claude
Voyagez intelligent, voyagez en train! ๐