Skip to main content
Glama
Shadhai

IndianRailwaysMCP

by Shadhai
README.md
<div align="center">
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:1488cc,50:2b32b2,100:4facfe&height=220&section=header&text=%F0%9F%9A%82%20Indian%20Railways%20MCP&fontSize=46&fontColor=ffffff&fontAlignY=38&desc=Real-time%20Indian%20Railways%20data%20for%20AI%20assistants&descAlignY=60&descSize=18&animation=fadeIn" width="100%" />
</div>

<div align="center">

<img src="https://img.shields.io/badge/Build-Passing-brightgreen?style=for-the-badge&logo=github-actions&logoColor=white" />
<img src="https://img.shields.io/badge/License-MIT-blue?style=for-the-badge&logo=open-source-initiative&logoColor=white" />
<img src="https://img.shields.io/badge/Version-1.0.0-orange?style=for-the-badge&logo=semver&logoColor=white" />
<img src="https://img.shields.io/badge/Python-3.10%2B-3776AB?style=for-the-badge&logo=python&logoColor=white" />
<img src="https://img.shields.io/badge/MCP-Compatible-4facfe?style=for-the-badge&logo=data:image/svg%2Bxml;base64,&logoColor=white" />

</div>

<h3 align="center">πŸš€ A powerful open-source alternative to IRCTC, RailYatri, and ixigo Trains β€” built for AI agents</h3>

<p align="center">
For developers building AI assistants, chatbots, and automation tools, the <b>Indian Railways MCP Server</b> exposes live train schedules, PNR status, seat availability, and fare data through the <a href="https://modelcontextprotocol.io">Model Context Protocol</a> β€” so any MCP-compatible client (Claude Desktop, Cursor, Continue.dev) can query Indian Railways in natural language, without you having to write a single scraper.
</p>

<div align="center">

<a href="#-quick-start"><img src="https://img.shields.io/badge/Quick%20Start-β–Ά%20Get%20Running-1488cc?style=for-the-badge" /></a>
<a href="#-mcp-tool-reference"><img src="https://img.shields.io/badge/Tool%20Reference-πŸ“–%20Explore-2b32b2?style=for-the-badge" /></a>
<a href="#-features"><img src="https://img.shields.io/badge/Features-✨%20See%20All-4facfe?style=flat-square&labelColor=1488cc" /></a>

</div>

---

## πŸ“‘ Table of Contents

- [Purpose & Philosophy](#-purpose--philosophy)
- [Architecture](#-architecture)
- [Features](#-features)
- [Tech Stack](#-tech-stack)
- [Quick Start](#-quick-start)
- [Environment Configuration](#-environment-configuration)
- [MCP Tool Reference](#-mcp-tool-reference)
- [Data Sources](#-data-sources)
- [Caching Strategy](#-caching-strategy)
- [Use Cases](#-use-cases)
- [Usage Examples](#-usage-examples)
- [Project Structure](#-project-structure)
- [Client Integrations](#-client-integrations)
- [Docker Deployment](#-docker-deployment)
- [Testing](#-testing)
- [Performance](#-performance)
- [Security Notes](#-security-notes)
- [Troubleshooting](#-troubleshooting)
- [Roadmap](#-roadmap)
- [Contributing](#-contributing)
- [Contributors](#-contributors)
- [Star History](#-star-history)
- [AI-Ready Files](#-ai-ready-files)

---

## 🎯 Purpose & Philosophy

> Indian Railways runs over 13,000 trains a day, but its data lives behind inconsistent HTML pages and rate-limited endpoints β€” making it painful for AI agents to answer a simple question like *"is my train running late?"*

**Indian Railways MCP Server** solves this by normalizing schedules, live status, PNR, fares, and seat data into a single, structured MCP interface that any AI assistant can call directly.

- πŸ” **No auth, no secrets** β€” every data source is public; there's nothing to leak
- 🧩 **Layered architecture** β€” server, client, and parser layers are independently testable and swappable
- πŸ“Š **TTL-aware caching** β€” every tool call respects a data-freshness window instead of hammering upstream sites
- ⚑ **Resilient by default** β€” exponential-backoff retries absorb upstream flakiness so your agent doesn't crash mid-conversation

---

## πŸ— Architecture

```mermaid
graph TD
    Client["πŸ–₯️ MCP Client<br/>(Claude Desktop / Cursor / Continue.dev)"] -->|MCP Protocol Β· stdio| Server

    subgraph Server["πŸš‚ Indian Railways MCP Server"]
        direction TB
        SL["πŸ› οΈ Server Layer<br/>Tool registration (10 tools)<br/>Pydantic input validation"]
        CL["🌐 Client Layer<br/>httpx session mgmt<br/>tenacity retry logic<br/>TTL response cache"]
        PL["πŸ”Ž Parser Layer<br/>BeautifulSoup HTML parsing<br/>Pydantic JSON parsing<br/>Regex extraction"]
        SL --> CL --> PL
    end

    PL -->|HTTP/HTTPS| ERail[("πŸ—„οΈ ERail.in<br/>Schedules Β· Live status<br/>PNR Β· Seats Β· Fares")]
    PL -->|HTTP/HTTPS| IRInfo[("πŸ—„οΈ IndianRailways.info<br/>Coach position<br/>Platform locator")]
```

**Data flow:** MCP client sends a tool call over stdio β†’ Server layer validates input with Pydantic β†’ Client layer issues an HTTP request with retry logic β†’ Parser layer extracts structured data from HTML/JSON β†’ Cache layer stores the result with a TTL β†’ response is formatted and returned to the client.

---

## ✨ Features

| Module | Capability | Real-Time | Cache TTL |
|:---|:---|:---:|:---|
| πŸ” **Station & Train Search** | Search 8,000+ stations and 10,000+ trains by name or code | ❌ | 24 hours |
| πŸš‚ **Train Schedule** | Complete route with all stations, timings, and distances | ❌ | 1 hour |
| πŸ“ **Live Running Status** | Real-time location, delays, and platform info | βœ… | 2 minutes |
| 🎫 **PNR Status** | Passenger details, coach/berth allocation, journey info | βœ… | 30 seconds |
| πŸ’Ί **Seat Availability** | Class-wise availability β€” AVAILABLE / RAC / WL | βœ… | 2 minutes |
| πŸ’° **Fare Enquiry** | Fare breakdown across all travel classes | ❌ | 1 hour |
| πŸ”€ **Trains Between Stations** | Every train connecting two stations | ❌ | 1 hour |
| 🏒 **Station Live** | Upcoming departures from any station | βœ… | 2 minutes |
| πŸšƒ **Coach Position** | Coach layout at any station platform | ❌ | 1 hour |

---

## 🧰 Tech Stack

| Layer | Technology |
|:---|:---|
| **Runtime** | Python 3.10+ |
| **Protocol** | Model Context Protocol (MCP) SDK 1.0+ |
| **HTTP Client** | httpx |
| **HTML Parsing** | BeautifulSoup4 |
| **Validation** | Pydantic 2.0+ |
| **Retry Logic** | tenacity (exponential backoff) |
| **Testing** | pytest, pytest-cov, pytest-mock, pytest-asyncio |
| **Packaging** | pyproject.toml (pip-installable) |
| **Containerization** | Docker (`python:3.11-slim`) |
| **Process Management** | systemd (Linux server deployments) |

---

## πŸš€ Quick Start

### Prerequisites

| Tool | Version | Notes |
|:---|:---|:---|
| Python | 3.10+ | Check with `python --version` |
| pip | Latest | Ships with Python |
| An MCP client | Any | Claude Desktop, Cursor, or Continue.dev |

### Step 1 β€” Clone

```bash
git clone https://github.com/Shadhai/Railway_mcp.git
cd Railway_mcp
```

### Step 2 β€” Configure

```bash
# Create and activate a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate      # Linux/Mac
# .venv\Scripts\activate       # Windows

# Install dependencies
pip install mcp httpx beautifulsoup4 pydantic tenacity
```

> <!-- ADD your vars: this project ships with no required .env file β€” all data sources are public and unauthenticated. -->

### Step 3 β€” Run

```bash
# Run directly
python -m src.indian_railways_mcp.server

# Or install as a package and run the entry point
pip install -e .
indian-railways-mcp
```

**βœ… Success β€” expect this output:**
```
βœ… Available tools: 10
  - search_stations: Search Indian Railways stations by name or code...
  - search_trains: Search Indian Railways trains by number or name...
  - get_train_schedule: Get complete train schedule with all stations...
  ...
```

---

## βš™οΈ Environment Configuration

No credentials are required β€” every upstream source is publicly accessible. The only environment variable in use configures the Python import path:

```env
# ── Runtime ─────────────────────────────────────────────
PYTHONPATH=/path/to/Railway_mcp/src

# <!-- VERIFY: add PORT/NODE_ENV-style vars here only if you front this
#      server with a custom HTTP/SSE transport wrapper. Stdio transport
#      (the default) needs nothing beyond PYTHONPATH. -->
```

---

## πŸ›  MCP Tool Reference

This server communicates over the **MCP stdio protocol**, not a public REST API β€” tools are invoked by your AI client, not by HTTP requests you make yourself. Each tool maps to one or more upstream data-source calls.

#### Discovery Tools

| Tool | Description | Auth |
|:---|:---|:---:|
| `search_stations` | Find station code(s) by name, with fuzzy/case-insensitive matching | ❌ |
| `search_trains` | Find train number(s) by name, with fuzzy/case-insensitive matching | ❌ |
| `get_trains_between` | List all trains connecting two stations | ❌ |

#### Schedule & Status Tools

| Tool | Description | Auth |
|:---|:---|:---:|
| `get_train_schedule` | Full route: every station, arrival/departure time, distance | ❌ |
| `get_live_status` | Real-time location, delay minutes, last station | ❌ |
| `get_station_live` | Upcoming departures at a given station | ❌ |

#### Booking & Fare Tools

| Tool | Description | Auth |
|:---|:---|:---:|
| `check_pnr` | PNR status, passenger list, coach/berth, confirmation state | ❌ |
| `check_seat_availability` | Class-wise seat status (AVAILABLE / RAC / WL) | ❌ |
| `get_fare` | Fare breakdown by class | ❌ |

#### Platform Tools

| Tool | Description | Auth |
|:---|:---|:---:|
| `get_coach_position` | Coach layout at a specific platform | ❌ |
| `get_platform_locator` | Locate which platform a train arrives at | ❌ |

> πŸ“– See `docs/API_REFERENCE.md` in the repo for full parameter schemas.

---

## 🌐 Data Sources

#### ERail.in (Primary)

| Endpoint | Method | Format | Cache TTL |
|:---:|:---|:---|:---|
| `/js5/IRStations.js` | `GET` | JS/JSON array | 24 hours |
| `/js5/IRTrains.js` | `GET` | JS/JSON array | 24 hours |
| `/train-enquiry/{train}` | `GET` | HTML table | 1 hour |
| `/train-running-status/{train}` | `GET` | HTML | 2 minutes |
| `/pnr-status/{pnr}?format=json` | `GET` | JSON | 30 seconds |
| `/train-seats/{train}` | `POST` | HTML table | 2 minutes |
| `/train-fare/{train}` | `POST` | HTML table | 1 hour |
| `/trains-between-stations/{from}/{to}` | `POST` | HTML table | 1 hour |
| `/station-live/{station}` | `GET` | HTML table | 2 minutes |

#### IndianRailways.info (Secondary)

| Endpoint | Method | Format | Cache TTL |
|:---:|:---|:---|:---|
| `/coach_position/` | `POST` | HTML table | 1 hour |
| `/platform_locator/` | `POST` | HTML | 1 hour |

---

## ⏱ Caching Strategy

| Data Type | TTL | Reason |
|:---|:---|:---|
| Station List | 24 hours | Rarely changes |
| Train List | 24 hours | Rarely changes |
| Train Schedule | 1 hour | Occasional updates |
| Live Status | 2 minutes | Real-time data |
| PNR Status | 30 seconds | Real-time data |
| Seat Availability | 2 minutes | Frequent updates |

---

## 🧭 Use Cases

### πŸ—ΊοΈ AI Travel Planning Assistant
A chatbot built on Claude Desktop uses this server to plan an end-to-end journey β€” searching trains between two cities, checking live seat availability, pulling the fare, and confirming the schedule, all from one natural-language conversation.

### πŸ“ Live Train Tracker for Commuters
A commuter-facing IVR or WhatsApp bot polls `get_live_status` every few minutes to tell passengers exactly how delayed their train is and which station it last passed.

### 🎫 PNR Concierge Bot
A support bot integrated with `check_pnr` answers "is my ticket confirmed?" instantly, including per-passenger coach, berth, and waitlist position β€” without a human agent.

### πŸŽ“ Academic / Portfolio Project
A student building an MCP-based AI agent uses this repo as a reference implementation of a layered, cached, retry-safe scraping architecture behind the Model Context Protocol.

---

## πŸ’‘ Usage Examples

**Complete journey planning**

```python
from indian_railways_mcp.client import IndianRailwaysClient

client = IndianRailwaysClient()

trains = client.get_trains_between("NDLS", "BCT")
train = trains['trains'][0]

seats = client.check_seat_availability(
    train['train_number'], "NDLS", "BCT", "20-Jul-2026"
)

if any(c['status'] == 'AVAILABLE' for c in seats['classes']):
    fare = client.get_fare(train['train_number'], "NDLS", "BCT")
    print(f"Fare: β‚Ή{fare['classes'][0]['total_fare']}")

schedule = client.get_train_schedule(train['train_number'])
print(f"Travel time: {schedule['travel_time']} hours")
```

**Live train tracking**

```python
status = client.get_live_status("04815")

if status['status'] == 'RUNNING':
    print(f"{status['train_name']} last seen at {status['last_station']}, "
          f"delayed {status['delay_minutes']} min")
```

**PNR status check**

```python
pnr = client.check_pnr("4553137968")

for p in pnr['passengers']:
    print(f"Passenger {p['serial']}: {p['current_status']} | "
          f"Coach {p['coach']} | Berth {p['berth']} ({p['berth_type']})")
```

---

## πŸ“ Project Structure

```
Railway_mcp/
β”œβ”€β”€ πŸ“„ README.md                     # Main documentation
β”œβ”€β”€ πŸ“„ pyproject.toml                # Package configuration
β”œβ”€β”€ πŸ“„ LICENSE                       # MIT License
β”œβ”€β”€ πŸ“„ .gitignore                    # Git ignore rules
β”œβ”€β”€ πŸ“ docs/
β”‚   β”œβ”€β”€ API_REFERENCE.md             # Complete tool/API documentation
β”‚   β”œβ”€β”€ ARCHITECTURE.md              # System architecture
β”‚   └── EXAMPLES.md                  # Usage examples
β”œβ”€β”€ πŸ“ src/
β”‚   └── πŸ“ indian_railways_mcp/
β”‚       β”œβ”€β”€ __init__.py              # Package init
β”‚       β”œβ”€β”€ server.py                # MCP server (10 tools)
β”‚       β”œβ”€β”€ client.py                # HTTP client (all endpoints)
β”‚       β”œβ”€β”€ parsers.py               # HTML/JSON parsers
β”‚       β”œβ”€β”€ models.py                # Pydantic data models
β”‚       └── utils.py                 # Caching + retry utilities
└── πŸ“ tests/
    β”œβ”€β”€ test_client.py               # Client tests
    └── test_parsers.py              # Parser tests
```

---

## πŸ”Œ Client Integrations

<details>
<summary><b>Claude Desktop</b></summary>

Edit your config file:
- **Mac:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux:** `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "indian-railways": {
      "command": "python",
      "args": ["-m", "src.indian_railways_mcp.server"],
      "cwd": "/path/to/Railway_mcp",
      "env": { "PYTHONPATH": "/path/to/Railway_mcp/src" }
    }
  }
}
```

Restart Claude Desktop β€” you'll see a πŸ”Œ icon with the Indian Railways tools listed.
</details>

<details>
<summary><b>Cursor AI</b></summary>

Add to `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "indian-railways": {
      "command": "python",
      "args": ["-m", "src.indian_railways_mcp.server"],
      "cwd": "/path/to/Railway_mcp"
    }
  }
}
```
</details>

<details>
<summary><b>Continue.dev (VS Code)</b></summary>

Add to `~/.continue/config.json`:

```json
{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "stdio",
          "command": "python",
          "args": ["-m", "src.indian_railways_mcp.server"],
          "cwd": "/path/to/Railway_mcp"
        }
      }
    ]
  }
}
```
</details>

<details>
<summary><b>MCP Inspector (debugging)</b></summary>

```bash
npx @modelcontextprotocol/inspector python -m src.indian_railways_mcp.server
```
</details>

---

## 🐳 Docker Deployment

```dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY src/ ./src/

ENV PYTHONPATH=/app

CMD ["python", "-m", "src.indian_railways_mcp.server"]
```

```bash
# Build
docker build -t indian-railways-mcp .

# Run (stdio requires interactive mode)
docker run -i indian-railways-mcp
```

<details>
<summary><b>Systemd service (Linux server)</b></summary>

`/etc/systemd/system/indian-railways-mcp.service`:

```ini
[Unit]
Description=Indian Railways MCP Server
After=network.target

[Service]
Type=simple
User=mcp
WorkingDirectory=/opt/indian-railways-mcp
Environment=PYTHONPATH=/opt/indian-railways-mcp/src
ExecStart=/usr/bin/python3 -m src.indian_railways_mcp.server
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
```

```bash
sudo systemctl daemon-reload
sudo systemctl enable indian-railways-mcp
sudo systemctl start indian-railways-mcp
sudo systemctl status indian-railways-mcp
```
</details>

---

## πŸ§ͺ Testing

```bash
# Install test dependencies
pip install pytest pytest-cov pytest-mock pytest-asyncio

# Run all tests
pytest tests/ -v

# Run with coverage
pytest tests/ -v --cov=src/indian_railways_mcp --cov-report=html

# Run a specific file / class / test
pytest tests/test_client.py -v
pytest tests/test_client.py::TestPNRStatus -v
pytest tests/test_client.py::TestPNRStatus::test_check_pnr_success -v
```

**Coverage summary**

| Module | Tests | Coverage |
|:---|:---:|:---:|
| `client.py` | 40+ | ~95% |
| `parsers.py` | 25+ | ~95% |
| `utils.py` | 10+ | ~90% |
| `models.py` | 5+ | ~85% |
| **Total** | **80+** | **~92%** |

---

## πŸ“ˆ Performance

**Response times (typical)**

| Operation | Cold (ms) | Cached (ms) |
|:---|:---:|:---:|
| Search Stations | 800 | 5 |
| Search Trains | 1000 | 5 |
| Train Schedule | 1500 | 100 |
| Live Status | 2000 | 200 |
| PNR Status | 1200 | 50 |
| Seat Availability | 2000 | 100 |

**Memory footprint:** ~50MB base (Python + deps) Β· ~65MB with station/train cache warm Β· ~80MB peak during HTML parsing.

---

## πŸ”’ Security Notes

- **No authentication required** β€” every data source is public
- **Rate-limit safe** β€” built-in exponential backoff prevents abusive request patterns
- **Validated inputs** β€” all tool arguments pass through Pydantic models
- **No persistence** β€” PNR and passenger data are never written to disk
- **HTTPS only** β€” every outbound request is encrypted

---

## πŸ”§ Troubleshooting

| Symptom | Likely Cause | Fix |
|:---|:---|:---|
| `Module not found` | `PYTHONPATH` not set | `export PYTHONPATH="/path/to/Railway_mcp/src:$PYTHONPATH"` or `pip install -e .` |
| `Permission denied` on server script | Missing execute bit | `chmod +x src/indian_railways_mcp/server.py` |
| Server silently exits | Docker missing `-i` flag | Always run with `docker run -i indian-railways-mcp` (stdio needs interactive mode) |
| Dependencies missing | Fresh clone, no install | `pip install -r requirements.txt` |
| `Invalid Train` error | Wrong or malformed train number | Verify it's a 5-digit number via `search_trains` |
| `No Data Found` | Train doesn't run that day | Check the train's days of operation |
| `Station Not Found` | Invalid station code | Run `search_stations` first to resolve the code |
| `Connection Timeout` | Upstream network issue | Handled automatically β€” 3x retry with exponential backoff |
| `Parse Error` | Upstream site changed its HTML structure | Requires a manual parser update in `parsers.py` |
| `Rate Limited` | Too many requests in a short window | Backs off automatically; avoid tight polling loops |

---

## πŸ—Ί Roadmap

<!-- Roadmap inferred from current feature set β€” update with real project plans -->

- [x] Core tool set β€” station/train search, schedule, live status
- [x] PNR status, seat availability, and fare enquiry tools
- [x] TTL-based caching layer with retry/backoff
- [x] Docker + systemd deployment paths
- [x] 80+ test suite with ~92% coverage
- [ ] 🚧 Streamable HTTP/SSE transport for remote (non-stdio) deployments
- [ ] 🚧 Multi-language station/train name matching (Hindi, regional scripts)
- [ ] 🚧 Webhook/push alerts for delay and platform changes
- [ ] 🚧 Official `llms.txt`-based tool discovery for broader agent frameworks

---

## 🀝 Contributing

```bash
# 1. Fork the repository
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/Railway_mcp.git
cd Railway_mcp

# 3. Create a feature branch
git checkout -b feature/your-feature-name

# 4. Make your changes and add tests
pytest tests/ -v

# 5. Commit and push
git commit -m "Add: your feature description"
git push origin feature/your-feature-name

# 6. Open a Pull Request against main
```

Please keep parser changes covered by tests in `tests/test_parsers.py` β€” upstream HTML structure changes are the most common source of regressions in this project.

---

## πŸ‘₯ Contributors

<div align="center">
<a href="https://github.com/Shadhai/Railway_mcp/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=Shadhai/Railway_mcp" />
</a>
</div>

---

## ⭐ Star History

<div align="center">

[![Star History Chart](https://api.star-history.com/svg?repos=Shadhai/Railway_mcp&type=Date)](https://star-history.com/#Shadhai/Railway_mcp&Date)

</div>

---

## πŸ€– AI-Ready Files

This repo ships with agent-discovery stubs so AI coding assistants (and MCP-aware crawlers) can understand the project without parsing the full README:

- [`llms.txt`](./llms.txt) β€” machine-readable project summary for LLM tools
- [`AGENTS.md`](./AGENTS.md) β€” instructions for coding agents working in this repo

---

<div align="center">
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:4facfe,50:2b32b2,100:1488cc&height=120&section=footer" width="100%" />
</div>