mcp-server-12306

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

MCP Server 12306

MCP Server 12306

Skill by ara.so — MCP Skills collection.
MCP Server 12306 is a Model Context Protocol server that provides real-time access to China Railway 12306 data including train tickets, station information, transfers, prices, and schedules. Built with FastAPI for high-performance async operations.
ara.so 开发的Skill — MCP Skills 合集。
MCP Server 12306是一个基于Model Context Protocol的服务器,可实时获取中国铁路12306的各类数据,包括火车票、车站信息、中转方案、票价及时刻表。它采用FastAPI构建,支持高性能异步操作。

What It Does

功能介绍

This MCP server exposes tools for:
  • Real-time ticket queries: Search available tickets with seat types, departure/arrival times
  • Station search: Fuzzy search for stations by Chinese name, pinyin, or abbreviation
  • Transfer planning: Find one-transfer routes between cities
  • Price queries: Get real-time ticket prices for trains
  • Route information: Query train stops and schedules
  • Time utilities: Get current time and relative dates for booking
本MCP服务器提供以下工具:
  • 实时车票查询:搜索包含座位类型、出发/到达时间的可用车票
  • 车站搜索:通过中文名称、拼音或简称模糊搜索车站
  • 中转规划:查询城市间的一次中转路线
  • 票价查询:获取列车的实时票价
  • 路线信息:查询列车经停站及时刻表
  • 时间工具:获取当前时间及可用于购票的相对日期

Installation

安装方法

For Claude Desktop (Stdio Mode - Recommended)

适用于Claude Desktop(标准输入输出模式 - 推荐)

Add to your Claude Desktop configuration file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Windows:
%APPDATA%\Claude\claude_desktop_config.json
将以下内容添加到你的Claude Desktop配置文件中:
macOS
~/Library/Application Support/Claude/claude_desktop_config.json
Windows
%APPDATA%\Claude\claude_desktop_config.json

Using uvx (fastest):

使用uvx(最快方式):

json
{
  "mcpServers": {
    "12306": {
      "command": "uvx",
      "args": ["mcp-server-12306"]
    }
  }
}
json
{
  "mcpServers": {
    "12306": {
      "command": "uvx",
      "args": ["mcp-server-12306"]
    }
  }
}

Using pipx:

使用pipx:

json
{
  "mcpServers": {
    "12306": {
      "command": "pipx",
      "args": ["run", "--no-cache", "mcp-server-12306"]
    }
  }
}
json
{
  "mcpServers": {
    "12306": {
      "command": "pipx",
      "args": ["run", "--no-cache", "mcp-server-12306"]
    }
  }
}

From source (for development):

从源码安装(适用于开发):

json
{
  "mcpServers": {
    "12306": {
      "command": "uv",
      "args": ["run", "python", "-m", "mcp_12306.cli"],
      "cwd": "/path/to/mcp-server-12306"
    }
  }
}
json
{
  "mcpServers": {
    "12306": {
      "command": "uv",
      "args": ["run", "python", "-m", "mcp_12306.cli"],
      "cwd": "/path/to/mcp-server-12306"
    }
  }
}

For Remote/HTTP Mode (Streamable HTTP)

远程/HTTP模式(支持流式HTTP)

Local development:

本地开发:

bash
git clone https://github.com/drfccv/mcp-server-12306.git
cd mcp-server-12306
uv sync
uv run python scripts/start_server.py
Then configure your MCP client:
json
{
  "mcpServers": {
    "12306": {
      "url": "http://localhost:8000/mcp"
    }
  }
}
bash
git clone https://github.com/drfccv/mcp-server-12306.git
cd mcp-server-12306
uv sync
uv run python scripts/start_server.py
然后配置你的MCP客户端:
json
{
  "mcpServers": {
    "12306": {
      "url": "http://localhost:8000/mcp"
    }
  }
}

Docker deployment:

Docker部署:

bash
docker run -d -p 8000:8000 --name mcp-server-12306 drfccv/mcp-server-12306:latest
bash
docker run -d -p 8000:8000 --name mcp-server-12306 drfccv/mcp-server-12306:latest

Available Tools

可用工具

1. query_tickets

1. query_tickets

Search for available train tickets between stations.
Parameters:
  • from_station
    (string, required): Departure station name (Chinese or pinyin)
  • to_station
    (string, required): Arrival station name (Chinese or pinyin)
  • train_date
    (string, required): Travel date in YYYY-MM-DD format
  • purpose_codes
    (string, optional): "ADULT" (default) or "0X00" for student tickets
Example usage:
python
undefined
查询两站之间的可用火车票。
参数:
  • from_station
    (字符串,必填):出发站名称(中文或拼音)
  • to_station
    (字符串,必填):到达站名称(中文或拼音)
  • train_date
    (字符串,必填):出行日期,格式为YYYY-MM-DD
  • purpose_codes
    (字符串,可选):"ADULT"(默认)或"0X00"(学生票)
使用示例:
python
undefined

Search tickets from Beijing to Shanghai on a specific date

查询指定日期从北京到上海的车票

result = await mcp_client.call_tool("query_tickets", { "from_station": "北京", "to_station": "上海", "train_date": "2025-06-15", "purpose_codes": "ADULT" })

**Response includes:**
- Train number, type (G/D/K/T/Z)
- Departure/arrival times and duration
- Seat availability and types
- Station codes
result = await mcp_client.call_tool("query_tickets", { "from_station": "北京", "to_station": "上海", "train_date": "2025-06-15", "purpose_codes": "ADULT" })

**返回内容包括:**
- 车次、车型(G/D/K/T/Z)
- 出发/到达时间及行程时长
- 座位可用性及类型
- 车站代码

2. query_ticket_price

2. query_ticket_price

Get real-time ticket prices for a specific train.
Parameters:
  • train_no
    (string, required): Train number (e.g., "G101")
  • from_station_no
    (string, required): Departure station code
  • to_station_no
    (string, required): Arrival station code
  • seat_types
    (string, required): Comma-separated seat type codes
  • train_date
    (string, required): Travel date in YYYY-MM-DD format
Example usage:
python
undefined
获取指定列车的实时票价。
参数:
  • train_no
    (字符串,必填):车次(例如:"G101")
  • from_station_no
    (字符串,必填):出发站代码
  • to_station_no
    (字符串,必填):到达站代码
  • seat_types
    (字符串,必填):逗号分隔的座位类型代码
  • train_date
    (字符串,必填):出行日期,格式为YYYY-MM-DD
使用示例:
python
undefined

Get prices for train G101

获取G101次列车的票价

result = await mcp_client.call_tool("query_ticket_price", { "train_no": "G101", "from_station_no": "BJP", "to_station_no": "SHH", "seat_types": "9,M,O", "train_date": "2025-06-15" })

**Response includes:**
- Price for each seat type
- Seat type codes and names
- Currency (CNY)
result = await mcp_client.call_tool("query_ticket_price", { "train_no": "G101", "from_station_no": "BJP", "to_station_no": "SHH", "seat_types": "9,M,O", "train_date": "2025-06-15" })

**返回内容包括:**
- 各座位类型的票价
- 座位类型代码及名称
- 货币单位(CNY)

3. search_stations

3. search_stations

Search for railway stations by name, pinyin, or abbreviation.
Parameters:
  • keyword
    (string, required): Search term (Chinese, pinyin, or abbreviation)
Example usage:
python
undefined
通过名称、拼音或简称搜索火车站。
参数:
  • keyword
    (字符串,必填):搜索关键词(中文、拼音或简称)
使用示例:
python
undefined

Search stations containing "beijing"

搜索包含"beijing"的车站

result = await mcp_client.call_tool("search_stations", { "keyword": "beijing" })
result = await mcp_client.call_tool("search_stations", { "keyword": "beijing" })

Also works with Chinese

中文关键词同样适用

result = await mcp_client.call_tool("search_stations", { "keyword": "北京" })

**Response includes:**
- Station name (Chinese)
- Station code
- Pinyin and abbreviation
- Match score
result = await mcp_client.call_tool("search_stations", { "keyword": "北京" })

**返回内容包括:**
- 车站名称(中文)
- 车站代码
- 拼音及简称
- 匹配得分

4. get_station_info

4. get_station_info

Get detailed information about a specific station.
Parameters:
  • station_name
    (string, required): Exact station name or code
Example usage:
python
result = await mcp_client.call_tool("get_station_info", {
    "station_name": "北京南"
})
获取指定车站的详细信息。
参数:
  • station_name
    (字符串,必填):准确的车站名称或代码
使用示例:
python
result = await mcp_client.call_tool("get_station_info", {
    "station_name": "北京南"
})

5. query_transfer

5. query_transfer

Find one-transfer routes between cities (when no direct train available).
Parameters:
  • from_station
    (string, required): Departure station
  • to_station
    (string, required): Arrival station
  • train_date
    (string, required): Travel date in YYYY-MM-DD format
  • purpose_codes
    (string, optional): Ticket type
Example usage:
python
undefined
查询城市间的一次中转路线(无直达列车时使用)。
参数:
  • from_station
    (字符串,必填):出发站
  • to_station
    (字符串,必填):到达站
  • train_date
    (字符串,必填):出行日期,格式为YYYY-MM-DD
  • purpose_codes
    (字符串,可选):车票类型
使用示例:
python
undefined

Find transfer routes from Beijing to Guilin

查询从北京到桂林的中转路线

result = await mcp_client.call_tool("query_transfer", { "from_station": "北京", "to_station": "桂林", "train_date": "2025-06-20", "purpose_codes": "ADULT" })

**Response includes:**
- First leg train details
- Transfer station
- Second leg train details
- Total duration
- Layover time at transfer station
result = await mcp_client.call_tool("query_transfer", { "from_station": "北京", "to_station": "桂林", "train_date": "2025-06-20", "purpose_codes": "ADULT" })

**返回内容包括:**
- 第一段列车详情
- 中转车站
- 第二段列车详情
- 总行程时长
- 中转停留时间

6. get_train_route_stations

6. get_train_route_stations

Query all stops and schedule for a specific train.
Parameters:
  • train_no
    (string, required): Train number
  • from_station_telecode
    (string, required): Origin station code
  • to_station_telecode
    (string, required): Destination station code
  • depart_date
    (string, required): Departure date in YYYY-MM-DD format
Example usage:
python
result = await mcp_client.call_tool("get_train_route_stations", {
    "train_no": "G101",
    "from_station_telecode": "BJP",
    "to_station_telecode": "SHH",
    "depart_date": "2025-06-15"
})
Response includes:
  • Station sequence
  • Arrival/departure times
  • Stop duration
  • Running distance
查询指定列车的所有经停站及时刻表。
参数:
  • train_no
    (字符串,必填):车次
  • from_station_telecode
    (字符串,必填):始发站代码
  • to_station_telecode
    (字符串,必填):终点站代码
  • depart_date
    (字符串,必填):出发日期,格式为YYYY-MM-DD
使用示例:
python
result = await mcp_client.call_tool("get_train_route_stations", {
    "train_no": "G101",
    "from_station_telecode": "BJP",
    "to_station_telecode": "SHH",
    "depart_date": "2025-06-15"
})
返回内容包括:
  • 车站顺序
  • 到达/出发时间
  • 停留时长
  • 行驶距离

7. get_current_time

7. get_current_time

Get current time and calculate relative dates for booking.
Parameters:
  • timezone
    (string, optional): Timezone (default: "Asia/Shanghai")
Example usage:
python
result = await mcp_client.call_tool("get_current_time", {
    "timezone": "Asia/Shanghai"
})
Response includes:
  • Current time
  • ISO format timestamp
  • Unix timestamp
  • Formatted date strings
  • Relative dates (today, tomorrow, next week)
获取当前时间并计算可用于购票的相对日期。
参数:
  • timezone
    (字符串,可选):时区(默认:"Asia/Shanghai")
使用示例:
python
result = await mcp_client.call_tool("get_current_time", {
    "timezone": "Asia/Shanghai"
})
返回内容包括:
  • 当前时间
  • ISO格式时间戳
  • Unix时间戳
  • 格式化日期字符串
  • 相对日期(今天、明天、下周)

Common Patterns

常用使用流程

Complete ticket search workflow:

完整车票查询流程:

python
undefined
python
undefined

1. Get current time to determine valid booking dates

1. 获取当前时间以确定有效的购票日期

time_info = await client.call_tool("get_current_time", {}) travel_date = time_info["dates"]["tomorrow"]
time_info = await client.call_tool("get_current_time", {}) travel_date = time_info["dates"]["tomorrow"]

2. Search for station codes if needed

2. 如需车站代码,先搜索车站

stations = await client.call_tool("search_stations", { "keyword": "beijing" }) from_code = stations[0]["code"]
stations = await client.call_tool("search_stations", { "keyword": "shanghai" }) to_code = stations[0]["code"]
stations = await client.call_tool("search_stations", { "keyword": "beijing" }) from_code = stations[0]["code"]
stations = await client.call_tool("search_stations", { "keyword": "shanghai" }) to_code = stations[0]["code"]

3. Query available tickets

3. 查询可用车票

tickets = await client.call_tool("query_tickets", { "from_station": "北京", "to_station": "上海", "train_date": travel_date, "purpose_codes": "ADULT" })
tickets = await client.call_tool("query_tickets", { "from_station": "北京", "to_station": "上海", "train_date": travel_date, "purpose_codes": "ADULT" })

4. Get price for specific train

4. 获取指定列车的票价

if tickets["trains"]: train = tickets["trains"][0] prices = await client.call_tool("query_ticket_price", { "train_no": train["station_train_code"], "from_station_no": train["from_station_telecode"], "to_station_no": train["to_station_telecode"], "seat_types": train["seat_types"], "train_date": travel_date })
undefined
if tickets["trains"]: train = tickets["trains"][0] prices = await client.call_tool("query_ticket_price", { "train_no": train["station_train_code"], "from_station_no": train["from_station_telecode"], "to_station_no": train["to_station_telecode"], "seat_types": train["seat_types"], "train_date": travel_date })
undefined

Finding transfer routes:

查询中转路线:

python
undefined
python
undefined

When no direct trains available, query transfers

无直达列车时,查询中转方案

transfers = await client.call_tool("query_transfer", { "from_station": "拉萨", "to_station": "厦门", "train_date": "2025-07-01", "purpose_codes": "ADULT" })
transfers = await client.call_tool("query_transfer", { "from_station": "拉萨", "to_station": "厦门", "train_date": "2025-07-01", "purpose_codes": "ADULT" })

Each result shows:

每个结果包含:

- First train to transfer city

- 前往中转城市的第一趟列车

- Layover duration

- 中转停留时长

- Second train to final destination

- 前往最终目的地的第二趟列车

for route in transfers["transfer_routes"]: print(f"Transfer at: {route['transfer_station']}") print(f"Layover: {route['layover_minutes']} minutes") print(f"Total duration: {route['total_duration']}")
undefined
for route in transfers["transfer_routes"]: print(f"中转车站: {route['transfer_station']}") print(f"停留时长: {route['layover_minutes']} 分钟") print(f"总行程时长: {route['total_duration']}")
undefined

Checking train route details:

查询列车路线详情:

python
undefined
python
undefined

Get complete route for a train

获取列车的完整路线

route = await client.call_tool("get_train_route_stations", { "train_no": "G7", "from_station_telecode": "BJP", "to_station_telecode": "SHH", "depart_date": "2025-06-15" })
route = await client.call_tool("get_train_route_stations", { "train_no": "G7", "from_station_telecode": "BJP", "to_station_telecode": "SHH", "depart_date": "2025-06-15" })

Shows all stops with arrival/departure times

显示所有经停站的到达/出发时间

for stop in route["stations"]: print(f"{stop['station_name']}: {stop['arrive_time']} - {stop['start_time']}")
undefined
for stop in route["stations"]: print(f"{stop['station_name']}: {stop['arrive_time']} - {stop['start_time']}")
undefined

Configuration

配置说明

Environment Variables

环境变量

The server uses default 12306 public APIs and doesn't require API keys. However, you can configure:
  • Port (HTTP mode only): Set via
    PORT
    environment variable (default: 8000)
  • Timezone: Pass to
    get_current_time
    tool (default: "Asia/Shanghai")
服务器默认使用12306公开API,无需API密钥。不过你可以配置:
  • 端口(仅HTTP模式):通过
    PORT
    环境变量设置(默认:8000)
  • 时区:传递给
    get_current_time
    工具(默认:"Asia/Shanghai")

Station Data

车站数据

The server includes a pre-built station database. To update:
bash
cd scripts
uv run python update_station_data.py
This fetches the latest station list from 12306 and updates
src/mcp_12306/data/station_names.json
.
服务器包含预构建的车站数据库。如需更新:
bash
cd scripts
uv run python update_station_data.py
该脚本会从12306获取最新车站列表并更新
src/mcp_12306/data/station_names.json

Project Structure

项目结构

src/mcp_12306/
├── server.py           # FastAPI main entry point
├── services/
│   ├── ticket_service.py    # Ticket query logic
│   ├── station_service.py   # Station search logic
│   └── http_service.py      # 12306 API client
├── utils/
│   ├── config.py           # Configuration
│   └── logger.py           # Logging
├── data/
│   └── station_names.json  # Station database
scripts/
├── start_server.py         # HTTP mode launcher
└── update_station_data.py  # Station data updater
src/mcp_12306/
├── server.py           # FastAPI主入口
├── services/
│   ├── ticket_service.py    # 车票查询逻辑
│   ├── station_service.py   # 车站搜索逻辑
│   └── http_service.py      # 12306 API客户端
├── utils/
│   ├── config.py           # 配置文件
│   └── logger.py           # 日志工具
├── data/
│   └── station_names.json  # 车站数据库
scripts/
├── start_server.py         # HTTP模式启动脚本
└── update_station_data.py  # 车站数据更新脚本

Troubleshooting

故障排查

"Station not found" errors

"车站未找到"错误

The station database uses exact matching. Use
search_stations
first to find the correct station name:
python
undefined
车站数据库使用精确匹配。请先使用
search_stations
工具找到正确的车站名称:
python
undefined

Search before querying

查询前先搜索

results = await client.call_tool("search_stations", { "keyword": "beijing" })
results = await client.call_tool("search_stations", { "keyword": "beijing" })

Use the exact name from results

使用结果中的准确名称

station_name = results[0]["name"]
undefined
station_name = results[0]["name"]
undefined

No tickets available

无可用车票

  • Check date format is YYYY-MM-DD
  • 12306 typically allows booking 15-30 days in advance
  • Use
    get_current_time
    to get valid booking dates
  • Try different dates or use
    query_transfer
    for indirect routes
  • 检查日期格式是否为YYYY-MM-DD
  • 12306通常允许提前15-30天购票
  • 使用
    get_current_time
    获取有效的购票日期
  • 尝试不同日期或使用
    query_transfer
    查询中转路线

HTTP connection errors

HTTP连接错误

  • Ensure the server is running (
    uv run python scripts/start_server.py
    )
  • Check port 8000 is not in use
  • For Docker, verify port mapping:
    -p 8000:8000
  • In China, direct 12306 API access may require proper network access
  • 确保服务器正在运行(执行
    uv run python scripts/start_server.py
  • 检查8000端口是否被占用
  • 若使用Docker,验证端口映射是否正确:
    -p 8000:8000
  • 在国内,直接访问12306 API可能需要合适的网络环境

Stdio mode not working in Claude Desktop

Claude Desktop标准输入输出模式无法工作

  • Restart Claude Desktop after configuration changes
  • Verify JSON syntax in config file
  • Check
    uvx
    or
    pipx
    is installed:
    uvx --version
  • For source mode, ensure
    cwd
    points to correct directory
  • 修改配置后重启Claude Desktop
  • 验证配置文件的JSON语法是否正确
  • 检查
    uvx
    pipx
    是否已安装:执行
    uvx --version
  • 若使用源码模式,确保
    cwd
    指向正确的目录

Rate limiting

请求频率限制

The 12306 API may rate-limit requests. The server includes basic retry logic, but for production use:
  • Add delays between requests
  • Cache frequently accessed data (stations, routes)
  • Use transfer queries sparingly (they make multiple API calls)
12306 API可能会限制请求频率。服务器已包含基础重试逻辑,但生产环境使用时:
  • 在请求之间添加延迟
  • 缓存频繁访问的数据(车站、路线)
  • 谨慎使用中转查询(会发起多个API请求)

Best Practices

最佳实践

  1. Always get current time first: Use
    get_current_time
    to determine valid booking dates
  2. Search stations before querying: Verify exact station names with
    search_stations
  3. Check direct routes first: Try
    query_tickets
    before
    query_transfer
  4. Cache station data: Station codes rarely change, cache
    get_station_info
    results
  5. Handle no-results gracefully: Not all routes have direct or one-transfer options
  6. Use appropriate date formats: Always use YYYY-MM-DD for dates
  1. 先获取当前时间:使用
    get_current_time
    确定有效的购票日期
  2. 查询前先搜索车站:使用
    search_stations
    验证准确的车站名称
  3. 先查直达路线:先尝试
    query_tickets
    再使用
    query_transfer
  4. 缓存车站数据:车站代码很少变化,缓存
    get_station_info
    的结果
  5. 优雅处理无结果情况:并非所有路线都有直达或一次中转方案
  6. 使用正确的日期格式:日期始终使用YYYY-MM-DD格式

Legal Notice

法律声明

This project is for educational and research purposes only. It queries publicly available 12306 APIs and does not store, modify, or distribute official data. Users must comply with Chinese laws and 12306 terms of service. The authors assume no liability for misuse.
本项目仅用于教育和研究目的。它查询12306公开API,不存储、修改或分发官方数据。用户必须遵守中国法律及12306服务条款。作者对 misuse 不承担任何责任。