# 12306-MCP 服务 原理

## 1. 启动初始化

### 1.1 车站数据加载

服务启动时通过 `getStations()` 函数从 12306 API 获取全国车站信息，构建四个核心索引：

**具体流程：**
1. 访问 12306 首页 (https://www.12306.cn/index/)
2. 从 HTML 中提取车站名称 JS 文件路径 
3. 下载并解析 JS 文件，获取原始车站数据
4. 补充缺失的车站信息 (MISSING_STATIONS)
5. 基于车站数据得到四个核心数据结构映射表

```typescript
// 1. 车站id -> 车站信息
STATIONS: Record<string, StationData>        

// "AAA": {
// "station_id": "@aaa",
// "station_name": "北京北",
// "station_code": "AAA",
// "station_pinyin": "beijingbei",
// "station_short": "aaa",
// "station_index": "0",
// "code": "1234",
// "city": "北京",
// "r1": "",
// "r2": ""
// }


//  2. 城市名 ->  车站id 和 站名 (可能一个城市多个站)
CITY_STATIONS: Record<string, { station_code: string; station_name: string }> 

// "北京": [{"station_code": "AAA","station_name": "北京北"},{"station_code": "BBB","station_name": "京东"},...]

// 3. 车站名(与城市名相同,只会有一个) -> 车站id 和 站名 
CITY_CODES: Record<string, { station_code: string; station_name: string }>      

// "北京":{"station_code":"CCC","station_name":"北京"}

// 4. 车站名 ->  车站id 和 站名
NAME_STATIONS: Record<string, { station_code: string; station_name: string }>   

// "北京北":{"station_code":"AAA","station_name":"北京北"}

```

## 2. MCP tools

### 2.1 基础tool

- **`get-current-date`**: 获取上海时区当前日期
  - 返回当前上海时区的时间日期字符串("yyyy-MM-dd")
  - 为其他工具提供准确的查询日期基准

- **`get-stations-code-in-city`**: 查询城市内所有车站（使用 `CITY_STATIONS`）
  - 输入：中文城市名
  - 查找：`CITY_STATIONS[city]` 获取该城市所有车站列表
  - 返回：包含 `station_code` 和 `station_name` 的数组
    
- **`get-station-code-of-citys`**: 获取城市代表车站id（使用 `CITY_CODES`）
  - 输入：城市名（支持 "|" 分隔的多个城市）
  - 查找：`CITY_CODES[city]` 获取与城市同名的主要车站
  - 返回：每个城市对应的代表车站信息

- **`get-station-code-by-names`**: 车站名转车站id（使用 `NAME_STATIONS`）
  - 输入：具体车站名（支持 "|" 分隔的多个车站）
  - 查找：`NAME_STATIONS[stationName]` 精确匹配车站名
  - 返回：车站id和车站名

- **`get-station-by-telecode`**: 车站id查车站信息（使用 `STATIONS`）
  - 输入：车站id
  - 查找：`STATIONS[telecode]` 获取完整车站信息
  - 返回：包含拼音、城市等详细信息

### 2.2 核心tool (输入可通过基础tool获取)

- **`get-tickets`**: 查询12306余票信息
  - 输入：出发日期、出发站id、到达站id、车次类型筛选
  - 参数处理：检查日期不早于当前日期，验证车站id存在性, 构造请求入参
  - Cookie 处理：先获取 12306 Cookie 用于身份验证
  - API 调用：访问 `/otn/leftTicket/query` 接口
  - 数据处理, 车次类型筛选
  - 返回格式化数据

- **`get-interline-tickets`**: 中转换乘查询，支持指定中转站
  - 输入：出发站id、到达站id、中转站id、是否显示无座、车次类型筛选
  - 参数处理：检查日期不早于当前日期，验证车站id存在性, 构造请求入参
  - Cookie 处理：先获取 12306 Cookie 用于身份验证
  - API 调用：访问 `/lcquery/queryU` 接口
  - 数据处理, 车次类型筛选
  - 返回格式化数据

- **`get-train-route-stations`**: 列车经停站查询
  - 输入：车次编码(可以调用get-tickets获取)、出发站id、到达站id、出发日期
  - 参数处理：检查日期不早于当前日期，验证车站id存在性, 构造请求入参
  - Cookie 处理：先获取 12306 Cookie 用于身份验证
  - API 调用：访问 `/otn/czxx/queryByTrainNo` 接口
  - 返回格式化数据

## 3. 数据流程与工具关系

### 3.1 车票查询流程

```
用户查询 "后天北京到上海的高铁" - 大模型调用流程：
    ↓
1. get-current-date() → "2024-01-15" (获取当前日期)
2. 大模型理解后天日期 → "2024-01-17"
3. get-station-code-of-citys("北京|上海") → {"北京": {"station_code": "BJP","station_name": "北京"}, "上海": {"station_code": "SHH","station_name": "上海"}}
    ↓
4. get-tickets(date: "2024-01-17", fromStation: "BJP", toStation: "SHH", trainFilterFlags: "G")
    ↓
5. 内部数据处理(参数验证, Cookie获取, API调用, 格式化输出文本)
    ↓
6. 返回格式化的高铁车次信息（车次、时间、价格、余票等）
```

### 3.2 中转查询流程

```
用户查询 "深圳到拉萨，经过西安中转"
    ↓
1. 获取三个城市的车站id
2. get-interline-tickets(from: "SZQ", to: "LSO", transfer: "XAY")
    ↓
3. 内部数据处理(参数验证, Cookie获取, API调用, 格式化输出文本)
    ↓
4. 返回中转方案（第一程 + 第二程）
```

### 3.3 经停站查询流程

```
用户查询 "G1次列车经停哪些站"
    ↓
1. get-train-route-stations(trainNo: "G1", from: "BJP", to: "SHH")
    ↓
2. 数据处理：parseRouteStationsData() → parseRouteStationsInfo()
    ↓
3. 返回经停站列表（站名、到达时间、出发时间、停留时间）
```

### 3.4 工具依赖关系

```
基础工具层：
├── get-current-date 
├── get-stations-code-in-city 
└── get-station-code-of-citys 
└── get-station-code-by-names 
└── get-station-by-telecode 

     ↓ 为核心工具层提供基础数据

核心工具层：
├── get-tickets (依赖车站id)
├── get-interline-tickets (依赖车站id)
└── get-train-route-stations (依赖车站id和车次号)
```

