用 12306 MCP Server 打造自己的火车票查询机器人
“
“不用打开 App,也能查到最新余票”——这可能是开发者最优雅的出行方式。
为什么值得读这篇文章?
如果你经常出差、旅行,或者正在做一个需要火车票信息的自动化项目,你一定遇到过这些尴尬:
-
12306 官方接口文档散落在各处,拼拼凑凑很费劲。 -
想写个脚本定时查票,却被验证码、登录态、反爬策略拦住。 -
老板临时要求“把火车票查询嵌进我们 AI 助手”,只剩两周时间。
这篇文章会告诉你:
如何在一台普通的笔记本上,10 分钟内跑起一个高性能的 12306 查询后端,并通过标准化协议(MCP)与 AI、自动化脚本、甚至微信小程序无缝衔接。
一、12306 MCP Server 是什么?
一句话解释:
12306 MCP Server 是一个帮你把 12306 官方数据“翻译”成标准接口的轻量级后端。
它用 FastAPI 写成,运行在 Python 3.10+ 上,支持官方余票、车站、经停、一次中转等查询,并通过 MCP(Model Context Protocol) 暴露给外部调用。
你可以把它理解成“火车票版的小爱同学底座”:
-
前端(AI、脚本、App)只要会说 MCP,就能查票。 -
后端替你处理 12306 的反爬、数据格式差异、缓存等问题。
二、10 行命令让它跑起来
下面给出两条路径:
-
本地源码——适合想改代码的同学。 -
Docker 镜像——适合“拿来就用”的同学。
“
以下命令都在 macOS、Linux、Windows WSL 中实测通过;如果你用纯 Windows,请把
uv
换成pip
即可。
路径 A:本地源码(推荐开发者)
步骤 | 命令 | 说明 |
---|---|---|
1. 克隆源码 | git clone https://github.com/drfccv/12306-mcp-server.git |
代码不到 3 MB |
2. 进入目录 | cd 12306-mcp-server |
|
3. 安装依赖 | uv sync |
自动创建虚拟环境并锁定版本 |
4. 更新车站库 | uv run python scripts/update_stations.py |
首次必须,后续每周跑一次即可 |
5. 启动服务 | uv run python scripts/start_server.py |
默认端口 8000 |
看到 INFO: Uvicorn running on http://0.0.0.0:8000
就成功了。
路径 B:Docker 一行搞定(推荐运维 / 产品同学)
docker pull drfccv/12306-mcp-server:latest
docker run -d -p 8000:8000 --name 12306-mcp-server drfccv/12306-mcp-server:latest
浏览器打开 http://localhost:8000/docs 就能看到 Swagger 界面,点击即可在线调试。
三、5 个核心工具速览
项目把常见需求拆成 5 个独立工具,每个工具都对应一个 MCP 接口,方便按需组合。
工具名 | 一句话作用 | 典型场景示例 |
---|---|---|
query_tickets | 查余票、车次、座席、时刻 | “明天北京到上海,最早一班高铁” |
search_stations | 车站模糊搜索 | “深圳北是‘SZN’还是‘IZQ’?” |
get_station_info | 车站详情(坐标、拼音) | 在地图上标出车站 |
query_transfer | 一次中转换乘 | “没有直达,如何先到武汉再转长沙?” |
get_train_route_stations | 列车完整时刻表 | “G1 次列车到底停几站?” |
get_current_time | 当前时间与相对日期 | “帮我算三天后的日期,别填错” |
“
每个工具都有独立 Markdown 文档,位于项目
/docs
目录,包含请求示例、返回字段含义、常见报错排查,建议收藏。
四、FAQ:新手最常问的 10 个问题
Q1:我需要登录 12306 账号吗?
A:不需要。项目只调用 12306 公开接口,不触碰任何需要登录的私密数据。
Q2:多久更新一次车站数据?
A:官方偶尔新增或改名车站。建议每周跑一次 update_stations.py
,脚本会自动下载最新版。
Q3:会不会被封 IP?
A:官方公开接口没有严格频率限制,但出于礼貌,建议每秒不超过 3 次请求。项目内部已做指数回退,可放心使用。
Q4:我要在服务器上长期运行,需要 supervisord 吗?
A:Docker 方式已内置健康检查;源码方式可用 systemd/supervisord,示例配置在 /examples
目录。
Q5:如何接入我的 AI 助手?
A:只要你的助手支持 MCP,把下面 JSON 片段写进配置即可:
{
"mcpServers": {
"12306": {
"url": "http://<你的服务器>:8000/mcp"
}
}
}
Q6:支持哪些城市三字码?
A:全国所有客运车站,包括港澳台高铁车站。可用 search_stations
实时查。
Q7:能查学生票、儿童票吗?
A:目前只返回成人票余量。学生、儿童票价计算规则复杂,官方未公开,暂不支持。
Q8:中转方案多久算一次?
A:实时计算,平均 200 ms 内返回。中转城市默认选官方推荐,也可手动指定。
Q9:如何贡献代码?
A:Fork 后提 PR,CI 会自动跑单测。贡献前请阅读 CONTRIBUTING.md
。
Q10:商业项目能用吗?
A:项目采用 MIT 许可证,可商用。但请自行评估 12306 官方政策及法律风险。
五、动手实验:用 curl 查一张票
假设你已经在本地跑起了服务,我们来查一张“明天北京南→上海虹桥”的 G 字头车票。
-
先搜车站代码
curl -s "http://localhost:8000/search_stations?keyword=北京南" | jq
返回:
[{"name":"北京南","code":"VNP"}]
-
再查余票
curl -s "http://localhost:8000/query_tickets?from=VNP&to=AOH&date=2025-07-17" | jq '.[].train_no'
你会看到类似 G1
, G3
, G101
这样的车次列表,附带余票数、座席等级、出发到达时间。
-
想看中转?
把query_tickets
换成query_transfer
,其余参数不变即可。
六、目录结构速读(便于二次开发)
12306-mcp-server/
├─ src/mcp_12306/
│ ├─ server.py # FastAPI 入口,所有路由集中注册
│ ├─ services/ # 真正干活的代码
│ │ ├─ ticket.py # 余票逻辑
│ │ ├─ station.py # 车站逻辑
│ │ └─ transfer.py # 中转换乘
│ ├─ models/ # Pydantic 数据模型,自动校验入参
│ └─ utils/ # 日志、缓存、异常统一处理
├─ scripts/
│ ├─ update_stations.py
│ └─ start_server.py
├─ docs/ # 每个工具的独立文档
└─ tests/ # pytest 单测,覆盖率 90%+
如果你只想改业务逻辑,直接看 services/
目录即可;想加新接口,在 server.py
中新增路由,再写个单测就能提 PR。
七、测试与持续集成
项目内置 pytest 单测,跑一遍不到 10 秒:
uv run pytest
CI 会在每次 push 时自动执行:
-
Python 3.10 与 3.11 双版本测试 -
代码格式(ruff) -
类型检查(mypy)
绿色 ✅ 后才允许合并,保证主干始终可运行。
八、常见集成场景示例
场景 | 技术栈 | 集成要点 |
---|---|---|
企业微信机器人 | Python + Flask | 监听群消息 → 调用 MCP → 返回车次卡片 |
语音助手 | Node.js + MCP SDK | 把自然语言转成参数,再查票 |
小程序 | 云开发 + 云函数 | 云函数内请求 MCP,返回给前端 |
自动化抢票 | cron + curl | 定时查余票,有余票就发邮件 |
所有场景都遵循同一套 MCP 协议,换语言、换平台都不需要改后端。
九、写在最后:如何优雅地遵守规则
12306 的数据属于公开信息,但接口并不对外承诺 SLA。为了长期稳定运行,请记住三条底线:
-
合理频率:每秒 ≤ 3 次,高峰时段再降一半。 -
不存储隐私:不要把乘客姓名、身份证落库。 -
不误导用户:展示数据时注明“来自 12306 公开接口,仅供参考”。
项目作者在免责声明里写得很清楚:
“
“使用本项目造成的任何后果均由使用者本人承担。”
把技术用在让生活更美好的地方,而不是和系统对抗,这才是开发者应有的优雅。
附录:一分钟速查表
任务 | 一条命令 |
---|---|
本地启动 | uv run python scripts/start_server.py |
更新车站 | uv run python scripts/update_stations.py |
Docker 启动 | docker run -d -p 8000:8000 drfccv/12306-mcp-server:latest |
跑测试 | uv run pytest |
查看文档 | 打开 /docs/*.md 或使用 Swagger |
祝你旅途愉快,也祝你的机器人永不宕机。