提供西班牙马德里实时公共交通信息的Model Context Protocol (MCP)服务器。
使用TypeScript构建,遵循Clean Architecture原则(DDD + 六边形架构)和函数式编程模式。
git clone <repository-url>
cd mcp-madrid-public-transport
npm install
注意:GTFS数据文件以压缩形式(.txt.zip)存储在仓库中以减少大小。npm install脚本会自动通过postinstall钩子解压它们。如果需要手动解压:
npm run setup:data
在项目根目录创建一个.env文件:
# 仅用于EMT公交车
EMT_CLIENT_ID=your_client_id_here
EMT_PASS_KEY=your_pass_key_here
# 可选:调试日志
DEBUG=false
DEBUG_LEVEL=info # error | warn | info | verbose | debug
# 可选:数据路径
GTFS_DATA_PATH=./transport-data
如何获取EMT凭证(免费):
Client ID和Pass Key复制到.env文件中注意:地铁和火车数据是公开可用的,不需要凭证。
# 构建TypeScript
npm run build
# 启动MCP服务器
npm start
# 开发模式,自动重载
npm run dev
此MCP服务器可以与任何兼容MCP的客户端一起使用。以下是常见客户端的配置说明。
将服务器添加到您的Claude Desktop配置文件中:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%/Claude/claude_desktop_config.json
快速设置:复制并编辑示例配置文件:
# macOS
cp claude_desktop_config.example.json ~/Library/Application\ Support/Claude/claude_desktop_config.json
# Windows (PowerShell)
Copy-Item claude_desktop_config.example.json $env:APPDATA\Claude\claude_desktop_config.json
# 然后编辑文件以添加您的EMT凭证并更新路径
手动配置:
{
"mcpServers": {
"madrid-transport": {
"command": "node",
"args": [
"/absolute/path/to/mcp-madrid-public-transport/dist/index.js"
],
"env": {
"EMT_CLIENT_ID": "your_emt_client_id_here",
"EMT_PASS_KEY": "your_emt_pass_key_here"
}
}
}
}
重要:
/absolute/path/to/mcp-madrid-public-transport为您克隆此仓库的实际路径npm install和npm run build如果您更喜欢使用Docker,请首先构建镜像:
docker build -t mcp-madrid-transport .
然后配置Claude Desktop:
{
"mcpServers": {
"madrid-transport": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e", "EMT_CLIENT_ID=your_emt_client_id_here",
"-e", "EMT_PASS_KEY=your_emt_pass_key_here",
"mcp-madrid-transport"
]
}
}
}
配置后:
get_metro_arrivals,get_bus_arrivals,get_train_arrivals配置完成后,您可以向Claude提问:
对于其他MCP客户端(如mcp-client-cli,自定义实现等),使用stdio传输:
node dist/index.js
服务器通过stdin/stdout使用JSON-RPC 2.0协议通信。
get_metro_arrivals获取地铁站的实时到站信息。
参数:
{
station: string; // 站点名称或代码(例如:"Colombia","par_4_211")
line?: string; // 可选:线路编号(例如:"8","L8")
direction?: string; // 可选:方向/目的地
count?: number; // 到站次数(默认:2,最大:10)
}
示例:
{
"station": "Colombia",
"line": "8",
"count": 3
}
响应:
{
"success": true,
"station": "COLOMBIA",
"stationCode": "par_4_156",
"arrivals": [
{
"line": "8",
"destination": "Nuevos Ministerios",
"estimatedTime": "2 分钟",
"platform": "1"
}
]
}
get_bus_arrivals获取公交站的实时到站信息。
参数:
{
stop: string; // 站点名称或编号(例如:"Plaza de Castilla","3000")
line?: string; // 可选:线路编号(例如:"27")
direction?: string; // 可选:方向/目的地
count?: number; // 到站次数(默认:2)
}
示例:
{
"stop": "3000",
"line": "27",
"count": 2
}
响应:
{
"success": true,
"stop": "Plaza de Castilla",
"arrivals": [
{
"line": "27",
"destination": "Embajadores",
"estimatedTime": "5 分钟",
"distance": 1200
}
]
}
get_train_arrivals获取近郊火车的实时位置和到站信息。
参数:
{
station: string; // 站点名称或代码(例如:"Atocha","10100")
line?: string; // 可选:线路(例如:"C-2")
direction?: string; // 可选:目的地
count?: number; // 到站次数(默认:2)
}
示例:
{
"station": "Atocha",
"line": "C-5",
"count": 3
}
响应:
{
"success": true,
"station": "Atocha",
"arrivals": [
{
"line": "C-5",
"destination": "Fuenlabrada",
"platform": "4",
"departureTime": "14:35",
"status": "准时"
}
]
}
https://serviciosapp.metromadrid.eshttps://openapi.emtmadrid.eshttps://gtfsrt.renfe.com/vehicle_positions.json该项目遵循Clean Architecture原则,采用领域驱动设计(DDD)和六边形架构模式。
src/
├── index.ts # 应用程序入口点及MCP服务器设置
│
├── transport/ # 🚇🚌🚆 交通运输领域(有界上下文)
│ ├── metro/ # 地铁子域
│ │ ├── domain/ # 实体、值对象、接口
│ │ ├── application/ # 用例(GetMetroArrivalsUseCase)
│ │ └── infrastructure/ # API适配器、仓库
│ │
│ ├── bus/ # 公交子域
│ │ ├── domain/
│ │ ├── application/ # 用例(GetBusArrivalsUseCase)
│ │ └── infrastructure/ # EMT API适配器、认证
│ │
│ ├── train/ # 火车子域
│ │ ├── domain/
│ │ ├── application/ # 用例(GetTrainArrivalsUseCase)
│ │ └── infrastructure/ # Renfe GTFS-RT适配器
│ │
│ └── shared/ # 共享领域类型
│ └── domain/ # 坐标、交通运输方式等
│
├── mcp/ # 🔌 MCP工具
│ ├── tools/ # 工具实现
│ │ ├── get-metro-arrivals.ts
│ │ ├── get-bus-arrivals.ts
│ │ └── get-train-arrivals.ts
│ ├── formatters/ # 输出格式化
│ └── validators/ # 输入验证
│
├── gtfs/ # 📊 GTFS数据管理
│ ├── domain/ # GTFS实体(站点、路线、行程)
│ └── infrastructure/ # 文件加载器、SQLite仓库
│
├── cache/ # 💾 缓存层
│ ├── domain/
│ └── infrastructure/ # 内存缓存实现
│
└── common/ # 🔧 共享实用工具
├── http/ # HTTP客户端、重试策略
├── logger/ # 日志记录(控制台、文件、组合)
├── functional/ # Either、Option、管道工具
└── config/ # 环境配置
结果:约1000倍性能提升(端到端3毫秒 vs 之前3750毫秒)
# 类型检查
npx tsc --noEmit
# 代码检查
npm run lint
# 格式化代码
npm run format
启用详细日志:
DEBUG=true DEBUG_LEVEL=debug npm start
日志级别:error | warn | info | verbose | debug
src/ - TypeScript源代码dist/ - 编译后的JavaScript(生成)transport-data/ - GTFS静态数据文件(压缩为.txt.zip)*.db - SQLite数据库(首次运行时生成,约246MB)压缩工作流
为了减少仓库大小,大型GTFS数据文件(>100KB)以压缩形式存储:
# 将所有大型GTFS文件压缩为.txt.zip
npm run compress:data
# 解压所有.txt.zip文件
npm run setup:data
自动解压
postinstall钩子 → 解压GTFS文件和SQLite数据库gtfs-static.db数据库文件大小
.txt.zip):约150MB(存储在Git中)gtfs-static.db.zip):约51MB(存储在Git中)Git配置
.gitignore 排除 *.txt 文件(未压缩的GTFS).gitignore 允许 *.txt.zip 文件(压缩的GTFS).gitignore 排除 *.db 文件(未压缩的SQLite数据库).gitignore 允许 *.db.zip 文件(压缩的数据库).dockerignore 正确配置用于Docker构建| 变量 | 必需 | 默认 | 描述 |
|---|---|---|---|
EMT_CLIENT_ID | 对于公交车 | - | EMT API客户端ID |
EMT_PASS_KEY | 对于公交车 | - | EMT API密钥 |
DEBUG | 不必 | false | 启用调试日志 |
DEBUG_LEVEL | 不必 | info | 日志级别 |
GTFS_DATA_PATH | 不必 | ./transport-data | GTFS数据路径 |
METRO_API_URL | 不必 | 官方URL | 覆盖地铁API URL |
EMT_API_URL | 不必 | 官方URL | 覆盖EMT API URL |
CACHE_TTL_METRO | 不必 | 30 | 地铁缓存TTL(秒) |
CACHE_TTL_BUS | 不必 | 10 | 公交缓存TTL(秒) |
CACHE_TTL_TRAIN | 不必 | 10 | 火车缓存TTL(秒) |
MIT许可证 - 详情见LICENSE文件。