马德里交通MCP服务器🚇🚌🚆
模型上下文协议(MCP)服务器提供 实时的 西班牙马德里的公共交通信息。
使用TypeScript构建,遵循干净架构原则(DDD+六边形架构)和函数式编程模式。
✨ 特性
- 🚇 马德里地铁 -通过官方Metro API实时到达
- 🚌 EMT公交车 -通过EMT OpenAPI实时到达
- 🚆 通勤列车 -通过Renfe GTFS实时馈送实时位置
- 📊 GTFS集成 -来自CRTM的静态进度数据
- ⚡ 优化性能 -SQLite缓存,亚秒级响应时间
- 🔍 智能站分辨率 -车站名称的模糊匹配
🚀 快速开始
先决条件
- Node.js >= 20.0.0
- npm 或纱线
安装
git clone
cd mcp-madrid-public-transport
npm install备注:GTFS数据文件以压缩形式存储(.txt.zip)在存储库中减少大小。这 npm install 脚本通过以下方式自动解压缩它们 postinstall 钩子。如果需要手动解压缩:
npm run setup:data配置
创建一个 .env 项目根目录中的文件:
# Required for EMT buses only
EMT_CLIENT_ID=your_client_id_here
EMT_PASS_KEY=your_pass_key_here
# Optional: Debug logging
DEBUG=false
DEBUG_LEVEL=info # error | warn | info | verbose | debug
# Optional: Data paths
GTFS_DATA_PATH=./transport-data如何获得EMT证书 (免费):
- 访问https://openapi.emtmadrid.es/
- 点击“注册”并创建帐户
- 登录并转到“我的帐户”>“我的应用程序”
- 创建新应用程序
- 复制您的
Client ID和Pass Key到.env文件
备注:地铁和火车数据是公开的,不需要凭证。
构建与运行
# Build TypeScript
npm run build
# Start MCP server
npm start
# Development mode with auto-reload
npm run dev🔧 客户端配置
此MCP服务器可以与任何兼容MCP的客户端一起使用。以下是针对最常见客户的说明。
克劳德桌面
将服务器添加到Claude Desktop配置文件中:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json 视窗: %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
# Then edit the file to add your EMT credentials and update the path手动配置:
{
"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使用克隆此存储库的实际路径 - 添加您的EMT凭据(在以下网址免费获取https://openapi.emtmadrid.es/)
- 确保你已经跑过了
npm install和npm run build第一
Docker选项(备选)
如果你更喜欢使用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:
- “乘地铁到哥伦比亚要多长时间?”
- “什么公共汽车经过3000站?”
- “下一班从阿托查开往丰拉夫拉达的火车什么时候开?”
- “给我看看Sol站接下来的5次地铁到达时间”
- “在接下来的10分钟内,有公共汽车到达卡斯蒂利亚广场吗?”
其他MCP客户端
对于其他MCP客户端(如 mcp-client-cli、自定义实现等),使用stdio传输:
node dist/index.js服务器使用JSON-RPC 2.0协议通过stdin/stdout进行通信。
📡 MCP工具
get_metro_arrivals
在车站实时获取地铁到达时间。
参数:
{
station: string; // Station name or code (e.g., "Colombia", "par_4_211")
line?: string; // Optional: Line number (e.g., "8", "L8")
direction?: string; // Optional: Direction/destination
count?: number; // Number of arrivals (default: 2, max: 10)
}例子:
{
"station": "Colombia",
"line": "8",
"count": 3
}答复:
{
"success": true,
"station": "COLOMBIA",
"stationCode": "par_4_156",
"arrivals": [
{
"line": "8",
"destination": "Nuevos Ministerios",
"estimatedTime": "2 minutos",
"platform": "1"
}
]
}get_bus_arrivals
在车站实时获取公交车到达情况。
参数:
{
stop: string; // Stop name or number (e.g., "Plaza de Castilla", "3000")
line?: string; // Optional: Line number (e.g., "27")
direction?: string; // Optional: Direction/destination
count?: number; // Number of arrivals (default: 2)
}例子:
{
"stop": "3000",
"line": "27",
"count": 2
}答复:
{
"success": true,
"stop": "Plaza de Castilla",
"arrivals": [
{
"line": "27",
"destination": "Embajadores",
"estimatedTime": "5 minutos",
"distance": 1200
}
]
}get_train_arrivals
获取实时Cercanías列车位置和到达时间。
参数:
{
station: string; // Station name or code (e.g., "Atocha", "10100")
line?: string; // Optional: Line (e.g., "C-2")
direction?: string; // Optional: Destination
count?: number; // Number of arrivals (default: 2)
}例子:
{
"station": "Atocha",
"line": "C-5",
"count": 3
}答复:
{
"success": true,
"station": "Atocha",
"arrivals": [
{
"line": "C-5",
"destination": "Fuenlabrada",
"platform": "4",
"departureTime": "14:35",
"status": "on_time"
}
]
}🗂️ 数据源
马德里地铁
- API:官方马德里地铁API
- 端点:
https://serviciosapp.metromadrid.es - 认证:无需✅
- 数据:实时到达、平台、目的地
- 更新频率:约30秒
EMT(市政运输公司)
- API:EMT OpenAPI v2
- 端点:
https://openapi.emtmadrid.es - 认证:OAuth(客户端ID+密钥)🔑
- 数据:实时到达、距离、事件
- 更新频率:约10秒
- 覆盖:马德里市的城市公交车
RENFE附近
- API:Renfe GTFS实时(官方开放数据)
- 端点:
https://gtfsrt.renfe.com/vehicle_positions.json - 认证: ✅ 不需要(公共API)
- 数据:实时车辆位置、行程信息、当前停车
- 更新频率:约30秒
- 许可证:CC-BY-4.0(开放数据)
- 来源: https://data.renfe.com/dataset/ubicacion-vehiculos
- 覆盖:全西班牙(按以“10”开头的行程ID过滤马德里)
CRTM(静态数据)
- 格式:GTFS(通用运输馈电规范)
- 数据:时刻表、路线、站点、车站映射
- 更新频率:每月
🏗️ 建筑
项目如下 清洁建筑 原则与 领域驱动设计(DDD) 和 六边形架构 模式。
src/
├── index.ts # Application entry point & MCP server setup
│
├── transport/ # 🚇🚌🚆 TRANSPORT DOMAIN (Bounded Context)
│ ├── metro/ # Metro subdomain
│ │ ├── domain/ # Entities, value objects, interfaces
│ │ ├── application/ # Use cases (GetMetroArrivalsUseCase)
│ │ └── infrastructure/ # API adapters, repositories
│ │
│ ├── bus/ # Bus subdomain
│ │ ├── domain/
│ │ ├── application/ # Use cases (GetBusArrivalsUseCase)
│ │ └── infrastructure/ # EMT API adapter, auth
│ │
│ ├── train/ # Train subdomain
│ │ ├── domain/
│ │ ├── application/ # Use cases (GetTrainArrivalsUseCase)
│ │ └── infrastructure/ # Renfe GTFS-RT adapter
│ │
│ └── shared/ # Shared domain types
│ └── domain/ # Coordinates, TransportMode, etc.
│
├── mcp/ # 🔌 MCP TOOLS
│ ├── tools/ # Tool implementations
│ │ ├── get-metro-arrivals.ts
│ │ ├── get-bus-arrivals.ts
│ │ └── get-train-arrivals.ts
│ ├── formatters/ # Output formatting
│ └── validators/ # Input validation
│
├── gtfs/ # 📊 GTFS DATA MANAGEMENT
│ ├── domain/ # GTFS entities (Stop, Route, Trip)
│ └── infrastructure/ # File loaders, SQLite repository
│
├── cache/ # 💾 CACHING LAYER
│ ├── domain/
│ └── infrastructure/ # InMemoryCache implementation
│
└── common/ # 🔧 SHARED UTILITIES
├── http/ # HTTP client, retry policies
├── logger/ # Logging (Console, File, Combined)
├── functional/ # Either, Option, pipe utilities
└── config/ # Environment configuration关键设计模式
- 领域驱动设计(DDD):为每种传输类型明确域边界
- 六边形架构:独立于基础设施的域
- 函数式编程:用于错误处理的monad,纯函数
- 坚实的原则:单一责任,依赖倒置
- 存储库模式:抽象数据访问
- 适配器模式:外部API→ 领域模型
⚡ 性能优化
Sprint 1优化(已完成✅)
- SQLite持久数据库:启动时加载一次GTFS数据(约8ms查询,而之前为4500ms)
- GTFS-RT缓存:Renfe提要的全局60秒缓存(每次请求0毫秒vs 200毫秒)
- LRU缓存:缓存行程目的地查询(2ms vs 1000ms)
- 站点映射器:所有111个Cercanías站都已预加载(\100KB)被压缩存储:
# Compress all large GTFS files to .txt.zip
npm run compress:data
# Decompress all .txt.zip files
npm run setup:data自动解压
- npm 安装:自动运行
postinstallhook → 解压缩GTFS文件和SQLite数据库 - Docker构建:Dockerfile在映像构建期间运行解压缩脚本
- 首次运行:应用程序使用解压缩的
gtfs-static.db数据库
文件大小
- 未压缩的GTFS数据:~1.2GB
- 压缩GTFS(
.txt.zip):~150MB(存储在Git中) - 未压缩的SQLite数据库:~246MB
- 压缩数据库(
gtfs-static.db.zip):~51MB(存储在Git中) - Git中压缩总量:约200MB
- 本地未压缩总量:~1.4GB
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 | 覆盖Metro 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许可证-请参阅 许可证 文件以获取详细信息。
🙏 致谢与致谢
数据提供程序
- 马德里地铁 -实时Metro API和静态数据
- 马德里EMT -实时公交车到达API
- Renfe -GTFS实时馈送(开放数据CC-BY-4.0)
- CRTM(马德里地区运输联盟) -所有运输方式的GTFS静态数据
- Xbaak/madrid运输备份 -GTFS数据存储库
发展
- 与克劳德一起建造 🤖 - 该项目是在人工智能助理Claude(Anthropic)的大力协助下开发的,他帮助:
- 建筑设计(DDD+六边形建筑) - TypeScript实现和函数式编程模式 - API集成(Metro、EMT、Renfe GTFS-RT) - 性能优化(1000倍加速) - 代码审查和最佳实践 - 文档
技术
- TypeScript -类型安全的JavaScript
- Node.js -运行时环境
- MCP-SDK (@modelcontextprotocol/sdk)-模型上下文协议
- fp-ts -函数式编程实用程序
- 更好平方3 -快速SQLite3绑定
- csv解析 -GTFS CSV解析
- 黄道带 -运行时类型验证
______________________________________________________________________
由以下材料制成❤️ 在马德里,为马德里
*触手可及的实时公共交通数据*
