indian-rail-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., "@indian-rail-mcpWhat trains run between New Delhi and Mumbai?"
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.
indian-rail-mcp
Indian Railways data from official sources, as a typed TypeScript library and an MCP server.
No API key. No third-party data vendor. No npm middleman that can disappear.
NTES — | train schedules, live running status, coach position, trains between stations, live station boards |
IRCTC — | PNR status, coach-by-coach and berth-level seat availability |
Why this exists
The popular irctc-connect package is deprecated. Its author renamed it to railkit and moved it behind a
signup and API key, and the free backends it depended on (bookmytrain.vercel.app, easy-rail.onrender.com)
now return 404 and 500. Anything still working in that ecosystem leans on a scrape of a third-party site using
a credential lifted from that site's own markup.
This library goes straight to the sources Indian Railways actually operates.
Related MCP server: Indian Railway MCP
Install
npm install indian-rail-mcpRequires Node 20+. The only runtime dependency is cheerio.
Library
import {
getTrainInfo,
trackTrain,
searchTrainsBetweenStations,
getLiveStation,
getSeatAvailability,
checkPnrStatus
} from "indian-rail-mcp";
// Full schedule and route
const info = await getTrainInfo("12951");
// -> { trainName: "NDLS TEJAS RAJ", type: "RAJDHANI", runsOn: "Daily",
// classes: ["1A","2A","3A"], route: [ { stationCode: "MMCT", departure: "17:00", ... }, ... ] }
// Where is it right now (defaults to the journey in progress)
const live = await trackTrain("12626");
// -> { journeyDate, summary: "Arrived at BUTI BORI(BTBR) at 13:27 26-Aug",
// stops: [...], coachPosition: [ { position: 0, coach: "ENG", classCode: "ENG" }, ... ] }
// Direct trains between two stations — code or full name
await searchTrainsBetweenStations("CAN", "PAY");
await searchTrainsBetweenStations("NEW DELHI", "MMCT");
// Next couple of hours at a station, with delay and platform
await getLiveStation("NDLS");
// Reservation chart: per-coach vacancy, plus berth detail when a class is given
await getSeatAvailability({ trainNumber: "12951", boardingStation: "MMCT", travelClass: "3A" });Stations accept either a code or a full name — NDLS and NEW DELHI both work, resolved against NTES's own
8,700-station catalogue. Dates accept DD-MM-YYYY, DD-MMM-YYYY or YYYY-MM-DD.
Errors
Every failure is a typed RailError:
Class |
| Meaning |
|
| Bad station, train number or date — caught locally, before any network call |
|
| NTES returned an |
|
| IRCTC returned an |
|
| Network failure or unparseable response |
On
ERR000: NTES returns the same genericERR000page for malformed input as it does for a genuine outage. This library therefore validates station codes against the catalogue before calling NTES, so your own typo can never be reported to you as "the railway service is down".NtesErrordeliberately names both possibilities rather than claiming an outage.
MCP server
Six tools: getTrainInfo, trackTrain, searchTrainBetweenStations, getLiveStation,
getSeatAvailability, checkPnrStatus.
import { createRailMcpServer } from "indian-rail-mcp/mcp";
const server = createRailMcpServer({ allowPnr: true });
await server.connect(yourTransport);Deploy to Vercel
vercel deployvercel.json pins the function to bom1 (Mumbai) — both upstreams are in India, and that is worth far more
than it looks: warm requests run in ~124 ms versus ~885 ms cold, and Indian traffic from Indian egress IPs is much
less likely to trip the F5 WAF in front of NTES.
Environment:
Variable | Purpose |
| Required to enable |
| Per-IP request cap. Default 30. |
Point any MCP client at https://<your-deployment>/api/mcp using Streamable HTTP transport.
PNR and personal data
checkPnrStatus returns passenger personal data — names, ages, gender, coach and berth.
It is disabled unless
RAIL_API_KEYis set and matched. It fails closed.The library never logs, caches or persists PNR responses.
There are deliberately no batch or enumeration helpers. One PNR per call, by design.
If you deploy this publicly, keep it that way. Please don't build a PNR scraper.
Data source and terms
All data is the property of Indian Railways, served by the Centre for Railway Information Systems (CRIS). This project is not affiliated with, endorsed by, or supported by Indian Railways, CRIS or IRCTC.
Read this before deploying:
The NTES Terms and Conditions permit downloading extracts for personal use, and state that you may not use "any software program" to systematically build a database from the site, nor include its pages in "any public or private electronic retrieval system or service", without prior written permission. They also state that railway data "should not be used for commercial purpose".
CRIS grants that permission on request: "Material featured on this Website may be reproduced free of charge after taking proper permission by sending a mail to us." A ready-to-send request is in
PERMISSION-REQUEST.md.Permission status for this project: requested, pending.
IRCTC's terms are stricter, and PNR data is personal data.
Data accuracy is best-effort and not guaranteed — NTES's own disclaimer says the same. Do not rely on it for anything safety-critical; verify with the railways directly.
Be a good citizen: the defaults cache what is stable, rate-limit by IP, and reuse a single upstream session. Please don't remove those.
Development
npm install
npm test # parser regression tests against recorded fixtures — no network
npm run smoke # live end-to-end check against NTES and IRCTC
npm run test:mcp # drives the MCP handler locally: handshake, tools, auth, rate limit
npm run fixtures # re-record fixtures when upstream markup changes
npm run buildFixtures in test/fixtures/ are recorded HTML/JSON. When CRIS changes their markup, npm test fails with a
specific assertion instead of the tools quietly returning empty results.
Licence
MIT — see LICENSE. The licence covers this source code only, not the underlying railway data.
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 Servers
- FlicenseNot gradedqualityBmaintenanceEnables real-time Indian Railways information retrieval, including live train running status, station schedules, and upcoming arrivals/departures.
- FlicenseNot gradedqualityDmaintenanceEnables searching and tracking Indian Railways trains, checking seat availability, live status, delays, and station/train codes.26
- FlicenseNot gradedqualityBmaintenanceProvides transit concierge tools for Indian Railways, including live train status, platform numbers, delay alerts, food options, and cab services, with offline fallback support.
- FlicenseNot gradedqualityDmaintenanceEnables checking railway seat availability, berth types, and pricing for Indian trains through natural language queries.
Related MCP Connectors
iRail MCP — Belgian rail (SNCB/NMBS) real-time via the community iRail API
Real-time BART departures, trip planning, fares, stations, and advisories.
Real-time transit stops, routes, arrivals, vehicle positions, and schedules via OneBusAway APIs.
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/mahi-v-v/indian-rail-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server