12306-MCP-Python
by DomainTang
README.md
# 12306-MCP-Python
一个可部署到 **ModelScope 魔搭社区自定义 MCP 服务**、并供 **Dify 智能体**调用的 Python MCP Server。项目参考 Joooook/12306-mcp 的公开架构和工具语义,以 Python + 官方 MCP Python SDK/FastMCP 独立实现。
> 仅用于查询公开铁路信息;不登录、不下单、不支付、不绕过验证码、不抢票。12306 网页公开接口可能调整,因此线上使用时应做好接口变化和限流失败的容错。
## 功能
| MCP Tool | 作用 |
|---|---|
| `get-current-date` | 获取 Asia/Shanghai 当前日期 |
| `search-stations` | 按站名/拼音搜索车站和电报码 |
| `get-station-code-by-names` | 精确站名转电报码,支持 `|` 分隔 |
| `get-station-by-telecode` | 电报码反查车站 |
| `get-tickets` | 查询直达余票、时间、席位状态并支持车型过滤 |
| `get-interline-tickets` | 指定中转站组合一次换乘方案 |
| `get-train-route-stations` | 查询某个 `train_no` 的经停站 |
## 项目结构
```text
.
├── src/mcp_12306/
│ ├── server.py # FastMCP 工具注册与服务入口
│ ├── client.py # 12306 HTTP 查询与余票解析
│ ├── stations.py # 车站数据下载、缓存、索引、搜索
│ ├── transfer.py # 中转换乘组合
│ ├── models.py # Pydantic 数据模型
│ └── config.py # 环境变量
├── tests/ # 解析单元测试
├── docs/
│ ├── MODELSCOPE.md # 魔搭部署
│ └── DIFY.md # Dify 接入
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml
└── .env.example
```
## 本地运行
Python 3.10+:
```bash
python -m venv .venv
# Linux/macOS
source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
pip install -e '.[dev]'
12306-mcp-python --transport streamable-http --host 0.0.0.0 --port 8000
```
MCP URL:`http://127.0.0.1:8000/mcp`
stdio:
```bash
12306-mcp-python --transport stdio
```
## Docker
```bash
docker build -t 12306-mcp-python .
docker run --rm -p 8000:8000 12306-mcp-python
```
或:
```bash
docker compose up --build
```
## MCP Inspector 测试
```bash
npx -y @modelcontextprotocol/inspector
```
在 Inspector 中连接:`http://127.0.0.1:8000/mcp`。
推荐测试顺序:
```text
get-current-date
search-stations(keyword="北京南")
get-station-code-by-names(station_names="北京南|上海虹桥")
get-tickets(date="未来有效日期", from_station="VNP", to_station="AOH", train_filter_flags="G")
```
## 工具参数说明
### get-tickets
- `date`: `YYYY-MM-DD`,不能早于上海时区当天。
- `from_station` / `to_station`: 12306 电报码,不是中文站名。
- `train_filter_flags`: `G`、`D`、`ZTK`、`GD` 等首字母组合。
- `only_available`: 过滤明显无可售席位的车次。
- `limit`: 1-100。
返回 JSON 中 `train_no` 是 12306 内部车次编号,查询经停站时应把它传给 `get-train-route-stations`。
### get-interline-tickets
为提高长期可维护性,本实现没有强依赖 12306 可能变化的 `/lcquery/queryU`,而是分别查询“出发→中转”和“中转→目的地”的直达车,再按换乘时间组合。当前仅组合同一天第二程,跨零点方案应对次日第二程再查一次。
## ModelScope 部署
详见 [`docs/MODELSCOPE.md`](docs/MODELSCOPE.md)。核心配置:
```text
Transport: Streamable HTTP
Host: 0.0.0.0
Port: 8000
Path: /mcp
```
启动命令:
```bash
12306-mcp-python --transport streamable-http --host 0.0.0.0 --port 8000
```
## Dify 接入
详见 [`docs/DIFY.md`](docs/DIFY.md)。ModelScope 部署成功后,使用平台提供的 Hosted MCP Remote URL 给 Dify 的 MCP Client;不要把 `localhost` 地址填写到云端 Dify。
## 环境变量
复制 `.env.example` 为 `.env` 可修改:
| 变量 | 默认 | 说明 |
|---|---:|---|
| `MCP_TRANSPORT` | `streamable-http` | 传输方式 |
| `MCP_HOST` | `0.0.0.0` | HTTP 监听地址 |
| `MCP_PORT` | `8000` | HTTP 端口 |
| `MCP_PATH` | `/mcp` | MCP 路径 |
| `HTTP_TIMEOUT` | `15` | 请求超时(秒) |
| `STATION_CACHE_TTL` | `86400` | 车站索引缓存秒数 |
| `MAX_RESULTS` | `20` | 余票默认最大结果数 |
## 已知限制
1. 12306 Web API 属于网页公开接口,可能改变路径、返回字段或访问策略。
2. 本项目没有购票能力,也不应向 Agent 描述为“12306 官方购票接口”。
3. 车站 JS 下载失败时会退化到少量常用站点的 bootstrap 数据;联网恢复后会重新加载完整车站数据。
4. 不建议高频轮询。若用于生产,应在上层增加缓存、并发限制和观测告警,并遵守目标站点服务规则。
5. 余票字段位置源于 12306 当前常见返回格式;如官方格式改变,应更新 `client.py` 中的解析映射。
## 测试
```bash
pytest -q
ruff check src tests
```
## License / Attribution
MIT。架构与工具语义参考开源项目 `Joooook/12306-mcp`(MIT),详见 `NOTICE`。本项目与中国铁路12306、ModelScope、Dify 以及原项目作者均无隶属或背书关系。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing