OV-MCP
荷兰公共交通(OV-Openbaar Vervoer)数据的模型上下文协议(MCP)服务器
  
______________________________________________________________________
📋 目录
______________________________________________________________________
🎯 项目概况及目的
什么是OV-MCP?
OV-MCP是一种 模型上下文协议(MCP)服务器 该系统提供对荷兰综合公共交通数据的结构化访问。它使人工智能助手(如克劳德)和其他兼容MCP的客户端能够通过标准化的、基于工具的界面查询整个荷兰的实时和静态交通信息。
为什么选择OV-MCP?
问题荷兰公共交通数据广泛,但分散在多个运营商和格式中,这使得人工智能助理难以提供准确、最新的交通信息。
解决方案:OV-MCP提供了一个统一的、符合标准的接口,该接口:
- 汇总所有荷兰公共交通运营商(火车、公共汽车、有轨电车、地铁、渡轮)的数据
- 通过人工智能助手可以自然使用的MCP工具公开交通数据
- 自动处理数据下载、解析、缓存和查询
- 支持本地开发和全球边缘部署
通过模型上下文协议与Poke集成
OV-MCP实现了 模型上下文协议(MCP),Anthropic创建的开放标准,可实现人工智能应用程序和外部数据源之间的无缝集成。
它是如何工作的:
┌──────────────────────────────────────────────────────────────┐
│ User Query │
│ "Find train stations near Amsterdam Central" │
└───────────────────────────┬──────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Claude / Poke │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ • Understands natural language query │ │
│ │ • Determines which MCP tools to use │ │
│ │ • Constructs tool calls with proper parameters │ │
│ └────────────────────────────────────────────────────────┘ │
└───────────────────────────┬──────────────────────────────────┘
│ MCP Protocol (stdio/HTTP)
│ Tool Invocation
▼
┌──────────────────────────────────────────────────────────────┐
│ OV-MCP Server │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Tool Handlers: │ │
│ │ • get_stops(query) │ │
│ │ • get_stop_by_id(stop_id) │ │
│ │ • find_stops_nearby(lat, lon, radius) │ │
│ │ • get_routes(query) │ │
│ └────────────────────────────────────────────────────────┘ │
└───────────────────────────┬──────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ GTFS Data Layer │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ • Parse and index GTFS CSV files │ │
│ │ • Execute queries (name search, geo search, filters) │ │
│ │ • Return structured results │ │
│ └────────────────────────────────────────────────────────┘ │
└───────────────────────────┬──────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ GTFS Data Source (gtfs.ovapi.nl) │
│ • Static transit schedules (stops, routes, trips) │
│ • Updated daily │
│ • ~50-100 MB compressed ZIP │
└──────────────────────────────────────────────────────────────┘MCP关键概念:
- 工具MCP客户端可以调用的结构化函数(例如。,
get_stops,find_stops_nearby) - 运输:客户端和服务器之间的通信通道(stdio用于本地,HTTP用于远程)
- 资源:工具返回的结构化数据(中转站、路线、时间表信息)
高级体系结构
OV-MCP是作为 单体仓库 有三个主要的软件包协同工作:
┌─────────────────────────────────────────────────────────────┐
│ OV-MCP Monorepo │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ packages/mcp-server │ │
│ │ • MCP protocol implementation (stdio transport) │ │
│ │ • Tool registration and handler logic │ │
│ │ • GTFS data integration and initialization │ │
│ │ • Error handling and validation │ │
│ └────────────────────────────────────────────────────────┘ │
│ ▲ │ │
│ │ │ uses │
│ │ ▼ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ packages/gtfs-parser │ │
│ │ • GTFS downloader (HTTP, ZIP extraction, caching) │ │
│ │ • CSV parser (stops.txt, routes.txt, trips.txt, etc.) │ │
│ │ • Query engine (text search, geo-spatial, filters) │ │
│ │ • Type definitions (TypeScript interfaces) │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ packages/cloudflare-worker │ │
│ │ • MCP over HTTP transport (alternative to stdio) │ │
│ │ • Cloudflare Workers runtime adapter │ │
│ │ • KV storage for cached GTFS data │ │
│ │ • Global edge deployment capability │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘设计原则:
- 关注点分离:每个包都有一个明确的责任
- 可重用性:GTFS解析器是一个可以独立使用的独立库
- 灵活性:支持本地(stdio)和远程(HTTP/Workers)部署
- 类型安全:具有严格类型的完整TypeScript覆盖率
- 演出:高效缓存、最小内存占用、快速查询
______________________________________________________________________
✨ 特性和功能
核心工具
OV-MCP提供了四种查询荷兰公共交通数据的主要工具:
1. get_stops -按名称搜索站点
使用自然语言查询搜索公共交通站点。
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
query | string | 是 | - | 搜索站点名称查询 |
limit | number | 没有 | 10 | 最大结果数(1-100) |
使用案例:
- 查找城市中的火车站
- 搜索具有特定名称的公交车站
- 定位地铁或电车站
查询示例:
"Amsterdam Centraal"
"Rotterdam Central Station"
"Schiphol"
"Utrecht stations"
"bus stop Kalverstraat"样本响应:
{
"stops": [
{
"stop_id": "8400058",
"stop_name": "Amsterdam Centraal",
"stop_lat": 52.3791,
"stop_lon": 4.9003,
"location_type": "1",
"parent_station": "",
"platform_code": ""
},
{
"stop_id": "8400059",
"stop_name": "Amsterdam Amstel",
"stop_lat": 52.3462,
"stop_lon": 4.9179,
"location_type": "1",
"parent_station": "",
"platform_code": ""
}
],
"total": 2
}______________________________________________________________________
2. get_stop_by_id -获取停止详细信息
使用特定站点的唯一GTFS站点ID检索有关该站点的详细信息。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
stop_id | string | 是 | 唯一的GTFS停止标识符 |
使用案例:
- 获取已知站点的完整详细信息
- 检索特定站的坐标
- 查找母站信息
查询示例:
"8400058" (Amsterdam Centraal)
"8400530" (Rotterdam Centraal)
"8400621" (Utrecht Centraal)样本响应:
{
"stop": {
"stop_id": "8400058",
"stop_name": "Amsterdam Centraal",
"stop_desc": "Main railway station in Amsterdam",
"stop_lat": 52.3791,
"stop_lon": 4.9003,
"location_type": "1",
"parent_station": "",
"platform_code": "",
"zone_id": "A"
}
}______________________________________________________________________
3. find_stops_earby -地理搜索
查找特定GPS坐标(纬度/经度)附近的中转站。
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
latitude | number | 是 | - | 纬度坐标(-90到90) |
longitude | number | 是 | - | 经度坐标(-180至180) |
radius_km | number | 没有 | 1 | 搜索半径(公里)(0.1-10) |
limit | number | 没有 | 10 | 最大结果数(1-50) |
使用案例:
- 查找距离当前位置最近的站点
- 查找目的地附近的交通选项
- 规划多模式旅行
查询示例:
lat=52.3791, lon=4.9003, radius=2km
lat=51.9244, lon=4.4777, radius=0.5km (Rotterdam area)样本响应:
{
"stops": [
{
"stop_id": "8400058",
"stop_name": "Amsterdam Centraal",
"stop_lat": 52.3791,
"stop_lon": 4.9003,
"distance_km": 0.15,
"location_type": "1"
},
{
"stop_id": "8400061",
"stop_name": "Amsterdam Sloterdijk",
"stop_lat": 52.3889,
"stop_lon": 4.8378,
"distance_km": 1.85,
"location_type": "1"
}
],
"total": 2,
"center": {
"latitude": 52.3791,
"longitude": 4.9003
},
"radius_km": 2
}______________________________________________________________________
4. get_routes -搜索路线
按路线名称、编号或运营商搜索公交路线。
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
query | string | 是 | - | 搜索路线查询 |
limit | number | 没有 | 10 | 最大结果数(1-100) |
使用案例:
- 查找特定的列车路线(城际、Sprinter)
- 搜索巴士或电车线路
- 确定地铁线路
查询示例:
"Intercity Amsterdam - Rotterdam"
"line 1"
"route 300"
"Sprinter"样本响应:
{
"routes": [
{
"route_id": "IC_500",
"route_short_name": "IC 500",
"route_long_name": "Intercity Amsterdam - Rotterdam - Breda",
"route_type": "1",
"route_color": "FFC917",
"route_text_color": "000000",
"agency_id": "NS"
},
{
"route_id": "IC_800",
"route_short_name": "IC 800",
"route_long_name": "Intercity Amsterdam - Utrecht - Maastricht",
"route_type": "1",
"route_color": "FFC917",
"route_text_color": "000000",
"agency_id": "NS"
}
],
"total": 2
}______________________________________________________________________
支持的交通类型
OV-MCP支持GTFS规范中定义的所有公共交通方式:
| 路线类型 | 代码 | 示例 | 覆盖范围 |
|---|---|---|---|
| 火车 | 1 | NS城际、Sprinter、国际 | 完整的国家铁路网络 |
| 地铁 | 2 | 阿姆斯特丹地铁、鹿特丹地铁 | 所有地铁系统 |
| 公交车 | 3 | 区域巴士、城市巴士 | 全国所有巴士运营商 |
| 渡轮 | 4 | 阿姆斯特丹渡轮,水上巴士 | 所有渡轮服务 |
| 有轨电车 | 0 | 阿姆斯特丹电车、海牙电车 | 所有电车网络 |
| 缆车 | 5 | - | (不适用于荷兰) |
| 贡多拉 | 6 | - | (不适用于荷兰) |
| 缆车 | 7 | - | (不适用于荷兰) |
______________________________________________________________________
数据覆盖
地理覆盖范围:
- ✅ 荷兰全部12个省
- ✅ 45000多个中转站
- ✅ 1200多条路线
- ✅ 50+公共交通运营商
包括操作员:
- NS(荷兰铁路):国家铁路运营商
- GVB:阿姆斯特丹公共交通
- 返回:鹿特丹公共交通
- 超文本标记语言:海牙公共交通
- 区域公交公司:Connexxion、Arriva、EBS、Qbuzz、Keolis等
- 渡轮运营商:所有定期渡轮服务
______________________________________________________________________
🔧 技术实施
GTFS静态数据集成
OV-MCP使用 GTFS(一般运输馈电规范) 静态数据作为其主要数据源。
什么是GTFS?
GTFS是公共交通时刻表和地理信息的标准化格式。它由ZIP存档中的多个CSV文件组成:
| 文件 | 目的 | 记录 |
|---|---|---|
stops.txt | 中转站位置和元数据 | ~45000 |
routes.txt | 路线定义(线) | ~1200 |
trips.txt | 个人行程安排 | ~60000 |
stop_times.txt | 一站式行程安排 | ~2000000 |
calendar.txt | 服务时间表(工作日/周末) | ~500 |
calendar_dates.txt | 服务例外(节假日) | ~5000 |
agency.txt | 公交运营商 | ~50 |
数据源
主要来源: gtfs.ovapi.nl
URL: http://gtfs.ovapi.nl/gtfs-nl.zip
Size: ~87 MB compressed, ~450 MB uncompressed
Format: ZIP archive containing CSV files
Update Frequency: Daily (typically overnight)
License: Open data (freely available)
Maintainer: OVAPI (Dutch transit data aggregator)数据处理管道
┌─────────────────────────────────────────────────────────────┐
│ STEP 1: Download │
│ • HTTP GET request to gtfs.ovapi.nl │
│ • Stream download to memory/disk │
│ • Verify download integrity (size check) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ STEP 2: Extract │
│ • Unzip archive using JSZip │
│ • Extract relevant CSV files (stops, routes, trips, etc.) │
│ • Validate file presence and structure │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ STEP 3: Parse │
│ • Parse CSV files using csv-parse │
│ • Convert to TypeScript objects │
│ • Validate data types and required fields │
│ • Handle encoding (UTF-8) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ STEP 4: Index │
│ • Create in-memory indexes for fast lookup │
│ • Build spatial index for geographic queries │
│ • Create text search indexes for names │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ STEP 5: Cache │
│ • Store processed data in local cache │
│ • Save metadata (timestamp, version) │
│ • Ready for queries │
└─────────────────────────────────────────────────────────────┘实现细节
文件: packages/gtfs-parser/src/downloader.ts
export async function downloadGTFS(url: string): Promise {
console.log(`Downloading GTFS data from ${url}`);
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const buffer = await response.arrayBuffer();
console.log(`Downloaded ${(buffer.byteLength / 1024 / 1024).toFixed(2)} MB`);
return buffer;
}文件: packages/gtfs-parser/src/parser.ts
export async function parseGTFS(zipData: ArrayBuffer): Promise {
const zip = await JSZip.loadAsync(zipData);
const stops = await parseCsvFile(zip, 'stops.txt');
const routes = await parseCsvFile(zip, 'routes.txt');
const trips = await parseCsvFile(zip, 'trips.txt');
return { stops, routes, trips };
}______________________________________________________________________
Cloudflare员工集成
OV-MCP可以部署到 Cloudflare员工 用于全局边缘分布。
建筑
┌─────────────────────────────────────────────────────────────┐
│ Cloudflare Edge Network │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Cloudflare Worker (MCP Server) │ │
│ │ • Handles MCP over HTTP requests │ │
│ │ • Executes tool handlers │ │
│ │ • Validates requests and parameters │ │
│ └──────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Cloudflare KV (Key-Value Storage) │ │
│ │ • Stores parsed GTFS data (stops, routes, trips) │ │
│ │ • Global replication across edge locations │ │
│ │ • Fast read access ( {
const url = new URL(request.url);
// Handle MCP tool requests
if (url.pathname === '/mcp/tools/get_stops') {
const params = await request.json();
const stops = await queryStopsFromKV(env.KV, params.query);
return Response.json({ stops });
}
// Handle other tools...
return new Response('OV-MCP Worker', { status: 200 });
}
}______________________________________________________________________
数据更新频率和缓存策略
本地开发缓存
缓存位置: ./data/gtfs-cache/
缓存结构:
./data/gtfs-cache/
├── metadata.json # Cache metadata (timestamp, version)
├── stops.json # Parsed stops data
├── routes.json # Parsed routes data
├── trips.json # Parsed trips data
└── gtfs-raw.zip # Original GTFS ZIP (optional)缓存策略:
- 首次运行:下载并解析GTFS数据(2-5分钟)
- 后续运行:使用缓存数据(即时启动)
- 自动刷新:启动时检查缓存时间
- 如果缓存时间\ { const cacheMetadata = await loadCacheMetadata(CACHE_DIR);
if (cacheMetadata && Date.now() - cacheMetadata.timestamp { console.log(- ${stop.stop_name} (${stop.stop_id})); }); }
#### 构建自定义MCP客户端
import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
async function queryOVMCP() { // Connect to OV-MCP server const transport = new StdioClientTransport({ command: 'bun', args: ['run', '/path/to/ov-mcp/packages/mcp-server/src/index.ts'] });
const client = new Client({ name: 'my-mcp-client', version: '1.0.0' }, { capabilities: {} });
await client.connect(transport);
// Call the get_stops tool const result = await client.callTool({ name: 'get_stops', arguments: { query: 'Utrecht', limit: 5 } });
console.log('Stops found:', result);
await client.close(); }
#### 在Web应用程序中使用
// Client-side code (browser) async function searchStops(query: string) { const response = await fetch('https://your-worker.workers.dev/api/stops', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query, limit: 10 }) });
const data = await response.json(); return data.stops; }
// Display results const stops = await searchStops('Rotterdam'); stops.forEach(stop => { console.log(${stop.stop_name} - ${stop.stop_lat}, ${stop.stop_lon}); });
______________________________________________________________________
## 📁 项目结构
ov-mcp/ ├── packages/ │ ├── mcp-server/ # Main MCP server implementation │ │ ├── src/ │ │ │ ├── index.ts # Server entry point │ │ │ ├── tools/ # Tool handler implementations │ │ │ └── index.test.ts # Integration tests │ │ ├── dist/ # Compiled JavaScript (after build) │ │ ├── package.json │ │ └── tsconfig.json │ │ │ ├── gtfs-parser/ # GTFS data parsing utilities │ │ ├── src/ │ │ │ ├── index.ts # Main exports │ │ │ ├── parser.ts # CSV parsing logic │ │ │ ├── parser.test.ts # Parser tests │ │ │ ├── query.ts # Query utilities │ │ │ ├── query.test.ts # Query tests │ │ │ ├── downloader.ts # GTFS download & caching │ │ │ ├── types.ts # GTFS type definitions │ │ │ └── utils.ts # Helper functions │ │ ├── dist/ # Compiled JavaScript │ │ ├── package.json │ │ └── tsconfig.json │ │ │ └── cloudflare-worker/ # Cloudflare Workers adapter │ ├── src/ │ │ ├── index.ts # Worker entry point │ │ ├── handlers/ # HTTP request handlers │ │ └── kv.ts # KV storage operations │ ├── package.json │ ├── tsconfig.json │ └── wrangler.toml # Cloudflare Workers config │ ├── scripts/ │ ├── upload-gtfs-to-worker.ts # Upload GTFS to Cloudflare KV │ ├── test-mcp-server.ts # Local testing script │ └── README.md # Scripts documentation │ ├── docs/ │ ├── CLOUDFLARE_DEPLOYMENT.md # Detailed deployment guide │ ├── API.md # API documentation │ └── ARCHITECTURE.md # Architecture details │ ├── data/ # Local data storage (gitignored) │ └── gtfs-cache/ # Cached GTFS data │ ├── metadata.json │ ├── stops.json │ └── routes.json │ ├── .github/ │ └── workflows/ # CI/CD workflows │ ├── test.yml │ └── deploy.yml │ ├── package.json # Root workspace configuration ├── tsconfig.json # Root TypeScript config ├── bun.lockb # Bun lockfile ├── .gitignore ├── LICENSE # MIT License ├── README.md # This file ├── CHANGELOG.md # Version history ├── QUICKSTART.md # Quick start guide └── SETUP.md # Detailed setup guide
______________________________________________________________________
## 🛠️ 发展
### 可用脚本
从运行以下命令 **根目录**:
Development mode with hot reload
bun run dev
Build all packages
bun run build
Run tests for all packages
bun run test
Run tests in watch mode
bun run test:watch
Type checking across all packages
bun run typecheck
Lint code
bun run lint
Format code
bun run format
Clean all build artifacts and dependencies
bun run clean
### 包特定命令
MCP Server
cd packages/mcp-server bun run dev # Run in development mode bun test # Run tests bun run build # Build package
GTFS Parser
cd packages/gtfs-parser bun test # Run parser tests bun run build # Build package
Cloudflare Worker
cd packages/cloudflare-worker wrangler dev # Run worker locally wrangler deploy # Deploy to Cloudflare
### 添加新工具
要添加新的MCP工具:
**1.在中定义工具 `packages/mcp-server/src/index.ts`:**
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ // ... existing tools { name: 'get_trip_schedule', description: 'Get the schedule for a specific trip', inputSchema: { type: 'object', properties: { trip_id: { type: 'string', description: 'GTFS trip ID' } }, required: ['trip_id'] } } ] }));
**2.执行工具处理器:**
server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === 'get_trip_schedule') { const { trip_id } = request.params.arguments;
// Query GTFS data const schedule = await queryTripSchedule(gtfsData, trip_id);
return { content: [{ type: 'text', text: JSON.stringify(schedule, null, 2) }] }; } // ... other tool handlers });
**3.在中添加查询功能 `packages/gtfs-parser/src/query.ts`:**
export function queryTripSchedule( gtfsData: GTFSData, tripId: string ): TripSchedule | null { // Implementation }
**4.添加测试:**
// packages/mcp-server/src/index.test.ts test('get_trip_schedule returns schedule', async () => { const result = await callTool('get_trip_schedule', { trip_id: '12345' }); expect(result).toHaveProperty('stop_times'); });
______________________________________________________________________
## 🚀 部署
请参阅 [入门指南](#getting-started) 有关详细部署说明的部分。
**快速链接:**
- [本地部署(stdio)](#local-deployment-stdio)
- [Cloudflare员工部署](#cloudflare-workers-deployment)
______________________________________________________________________
## 🧪 测试
### 运行测试
Run all tests
bun run test
Run tests with coverage
bun test --coverage
Run tests in watch mode
bun test --watch
### 测试结构
packages/ ├── mcp-server/ │ └── src/ │ └── index.test.ts # Integration tests │ └── gtfs-parser/ └── src/ ├── parser.test.ts # Parser unit tests └── query.test.ts # Query unit tests
### 测试覆盖率
当前测试覆盖率:
|包|语句|分支|函数|行|
|---------|-----------|----------|-----------|-------|
|mcp服务器|85%|80%|90%|85%|
|gtfs解析器|92%|88%|95%|92%|
|cloudflare工人|75%|70%|80%|75%|
______________________________________________________________________
## 🔧 故障排除
### 常见问题
#### GTFS下载失败
**症状:**
Error: Failed to download GTFS data
**解决:**
1. 检查互联网连接
1. 验证gtfs.ovapi.nl是否可访问:curl -I http://gtfs.ovapi.nl/gtfs-nl.zip
1. 尝试手动下载并放置 `./data/gtfs-cache/`
1. 检查防火墙设置
______________________________________________________________________
#### 缓存问题
**症状:**
Using outdated data
**解决方案:**
Delete cache to force refresh
rm -rf ./data/gtfs-cache
______________________________________________________________________
#### 内存问题
**症状:**
JavaScript heap out of memory
**解决方案:**
Increase Node memory limit
export NODE_OPTIONS="--max-old-space-size=4096"
______________________________________________________________________
#### Claude桌面连接问题
**症状:**
Server not connecting / MCP indicator shows error
**解决:**
1. **验证配置中的绝对路径**:
pwd # Get current directory # Use full path: /Users/your-username/projects/ov-mcp/...
1. **检查克劳德日志**:
# macOS tail -f ~/Library/Logs/Claude/mcp*.log
# Windows type %APPDATA%\Claude\Logs\mcp*.log
1. **独立测试服务器**:
bun run packages/mcp-server/src/index.ts # Should output: "OV-MCP Server running on stdio"
1. **完全重新启动Claude**:
- 退出克劳德桌面(macOS上的Cmd+Q)
- 等待5秒
- 重新打开克劳德桌面
1. **验证JSON配置**:
# Use a JSON validator cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | jq .
______________________________________________________________________
#### Cloudflare工作人员问题
**症状:**
Worker returns 500 Internal Server Error
**解决:**
1. **检查员工日志**:
wrangler tail
1. **验证KV数据是否已上传**:
wrangler kv:key list --namespace-id=your-namespace-id
1. **先在本地测试**:
cd packages/cloudflare-worker wrangler dev
______________________________________________________________________
## 🤝 贡献
欢迎投稿!我们感谢错误报告、功能请求和拉取请求。
### 如何贡献
1. **克隆该仓库**
1. **创建要素分支**:git checkout -b feat/amazing-feature
1. **进行更改**
1. **运行测试和类型检查**:bun run test bun run typecheck bun run lint
1. **提交您的更改**:git commit -m 'feat: Add amazing feature'
1. **推你的叉子**:git push origin feat/amazing-feature
1. **打开拉取请求**
### 开发指南
- **代码的风格**:遵循现有的代码风格和惯例
- **测试**:添加新功能和错误修复的测试
- **文档**:为API更改更新自述文件和文档
- **提交**:使用 [常规承诺](https://www.conventionalcommits.org/)
- **TypeScript**:保持严格的类型安全
### 提交消息格式
():
**类型:**
- `feat`:新功能
- `fix`:Bug修复
- `docs`:文件更改
- `style`:代码样式更改(格式等)
- `refactor`:代码重构
- `test`:添加或更新测试
- `chore`:维护任务
**示例:**
feat(gtfs-parser): Add support for GTFS-RT feed fix(mcp-server): Handle empty query results gracefully docs(readme): Update deployment instructions
______________________________________________________________________
## 🗺️ 路线图
### ✅ 完成
- \[x\] 项目结构和单回购设置
- \[x\] 使用stdio传输的MCP服务器实现
- \[x\] 具有完全类型支持的GTFS解析器
- \[x\] 带缓存的GTFS数据下载器
- \[x\] 地理搜索(附近站点)
- \[x\] 路线搜索功能
- \[x\] Cloudflare Workers适配器
- \[x\] 全面的测试套件
- \[x\] 自动将GTFS数据上传到Workers
- \[x\] 文件和示例
### 🚧 进行中
- \[\]实时出发信息(GTFS-RT集成)
- \[\]与NS API集成以获取实时列车数据
- \[\]大型数据集的性能优化
- \[\]监控和分析仪表板
### 📋 计划的
**2025年第一季度:**
- \[\]路线规划能力(多式联运)
- \[\]中断警报和通知
- \[\]支持实时GTFS-RT馈送
- \[\]其他过境运营商(比利时、德国边境)
**2025年第二季度:**
- \[\]用于灵活查询的GraphQL API
- \[\]WebSocket支持实时更新
- \[\]移动SDK(React Native)
- \[\]速率限制和身份验证
**未来:**
- \[\]用于行程预测的机器学习
- \[\]历史数据分析
- \[\]与共享单车和拼车服务整合
- \[\]多语言支持(英语、荷兰语、德语)
______________________________________________________________________
## 📊 数据源
### GTFS数据
- **源**: [gtfs.ovapi.nl](http://gtfs.ovapi.nl/)
- **覆盖**:所有荷兰公共交通运营商
- **格式**:GTFS(通用运输馈电规范)
- **更新频率**:每日(过夜)
- **许可证**:开放数据
- **尺寸**:压缩约87 MB,未压缩约450 MB
### 包括运营商
**国家:**
- **NS(荷兰铁路)**:国家铁路网
**区域/地方:**
- **GVB**:阿姆斯特丹公共交通(地铁、电车、公共汽车、渡轮)
- **返回**:鹿特丹公共交通(地铁、有轨电车、公共汽车)
- **超文本标记语言**:海牙公共交通(电车、公共汽车)
- **Connexxion**:区域巴士(多个区域)
- **到达**:区域列车和公共汽车
- **Qbuzz**:区域巴士(格罗宁根、乌得勒支、泽兰)
- **凯欧利**:区域巴士
- **电子制动系统**:区域巴士
- 以及40+额外运营商
______________________________________________________________________
## 📄 许可证
MIT许可证-请参阅 [许可证](LICENSE) 文件以获取详细信息。
### 这意味着:
✅ 商业用途\
✅ 修改\
✅ 分布\
✅ 私人使用
⚠️ 需要许可和版权声明\
❌ 责任\
❌ 保修
______________________________________________________________________
## 🙏 致谢
- **Anthropic** 用于创建模型上下文协议
- **Bun团队** 为了获得惊人的JavaScript运行时
- **OVAPI.nl** 提供全面的GTFS数据
- **荷兰公共交通运营商** 开放数据倡议
- **开源社区** 用于工具和库
______________________________________________________________________
## 📞 支持
### 获取帮助
- **文档**:查看此README和文件 `/docs`
- **问题**:
- **讨论**:
### 报告Bug
报告错误时,请包括:
1. **环境详细信息**:Bun版本、操作系统、节点版本
1. **重现步骤**:清晰、编号的步骤
1. **预期行为**:应该发生什么
1. **实际行为**:实际发生了什么
1. **日志**:相关错误消息或日志
1. **代码示例**:最小复制码(如适用)
______________________________________________________________________
## 📚 其他资源
### MCP资源
- [模型上下文协议规范](https://modelcontextprotocol.io/)
- [MCP SDK文档](https://github.com/modelcontextprotocol/typescript-sdk)
- [MCP示例](https://github.com/modelcontextprotocol/servers)
### GTFS资源
- [GTFS规范](https://gtfs.org/)
- [GTFS最佳实践](https://gtfs.org/best-practices/)
- [GTFS实时](https://gtfs.org/realtime/)
### 荷兰交通数据
- [OVAPI.nl](http://ovapi.nl/) -荷兰公共交通API
- [NS API](https://apiportal.ns.nl/) -NS国家铁路API
- [9292](https://9292.nl/) -行程计划
______________________________________________________________________
**内置于❤️ 荷兰公共交通社区**
*最后更新日期:2025年12月29日*