公交时刻查询服务

基于GTFS数据的DART公交实时到站查询服务,提供站点查询、时刻表检索及智能搜索功能,适用于公共交通出行规划。

  • by brewhouse
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 brewhouse/dart-mcp

使用说明

🚌 DART MCP 服务器(因为您喜欢等公交)

一个承诺会告诉你相关信息的模型上下文协议(MCP)服务器 确切地 当询问下一趟DART公交车何时到达……结果反正也会晚10分钟。使用的是真实的GTFS数据,所以至少这种失望是官方的!

特性(或:“我们为何开发这个产品”)

  • 🚌 公交车 “实时”公交时刻表 - 获取任意两个站点之间的下一班发车信息(实际到达时间可能无限变化)
  • 📍(定位标记,常用于地图或指示位置) 停止查找 - 因为显然64个停靠站太多了,记不住🤷‍♀️
  • 🕐 时钟,表示一个小时的时间单位或提醒时间。 特定时间查询 - 以手术般的精准度规划你的通勤路线,然后看着一切计划崩塌
  • ✨(闪闪发光的符号,常用于表示兴奋、喜悦或特别的时刻) 智能搜索 - 这里大家都很懒,所以输入“dart”缩写而不是全名
  • 📊 表格/数据图表 基于GTFS的 - 我们使用的数据与DART相同,所以当出现问题时,我们可以一起追究它们的责任

设置(有趣的部分🙄)

  1. 安装依赖项 (又名“更多要出问题的东西”):

    # Install uv if you haven't already (because pip is apparently too mainstream now)
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
    # Install dependencies using uv (fingers crossed it actually works)
    uv sync
    
  2. 获取那份甜美、宝贵的GTFS数据: 服务器期望接收DART GTFS数据格式 src/dart_mcp/data/dart-tx-us/ 目录。因为显然我们不能礼貌地问问火车它们在哪里。

    uv run python scripts/fetch_gtfs.py
    

    这个神奇的脚本会下载包含以下内容的文件:

    • stops.txt - 所有火车假装停靠的地方
    • trips.txt - 穿越时空的理论之旅
    • stop_times.txt - 当火车在 理应;据说是 到达(剧透:他们并没有)
    • calendar.txt - 工作日与周末的时刻表(因为火车也需要工作与生活的平衡)

使用方法(祝你好运!)

本地MCP服务器(真家伙)

这台服务器是设计为与MCP客户端(如Claude Desktop)一起使用的,而不是直接由人类运行(因为那样就太简单了)。以下是实际使用方法:

使用 Claude Desktop

将此添加到您的Claude Desktop MCP配置文件中:

{
  "mcpServers": {
    "dart": {
      "command": "uvx",
      "args": ["dart-mcp"]
    }
  }
}

这将自动从PyPI安装并运行最新版本。

然后重启Claude桌面应用,您就可以直接在对话中访问DART时刻表了!

与其他MCP客户端一起

任何兼容MCP的客户端都可以通过以下方式启动此服务器来使用它:

uvx dart-mcp

该服务器通过stdin/stdout使用MCP协议进行通信。直接运行时,它不会执行任何特别的操作——只是静静地等待接收正确的MCP消息。

远程HTTP服务器(用于CustomGPT.ai及Web客户端)

对于像CustomGPT.ai这样的需要远程MCP服务器URL的服务,我们已经提供了一个基于FastAPI的HTTP服务器:

快速入门

# Start the remote server locally
dart-mcp-server
# or
uvicorn dart_mcp.remote_server:app --host 0.0.0.0 --port 8000

部署到云端

# Railway (recommended)
railway init && railway up

# Render
# Push to GitHub and connect to Render

# Fly.io
flyctl launch && flyctl deploy

可用的终端节点

  • GET / - 服务器信息
  • GET /health - 健康检查
  • GET /mcp/tools - 列出可用工具
  • POST /mcp/next_trains - 获取下一班公交车发车时间
  • GET /mcp/stations - 列出所有公交车站
  • GET /mcp/routes - 列出所有公交线路

示例API用法

# Get next buses
curl -X POST http://localhost:8000/mcp/next_trains \
  -H "Content-Type: application/json" \
  -d '{"origin": "DART", "destination": "UNIVERSITY"}'

# List all routes
curl http://localhost:8000/mcp/routes

📋 一个清单或待办事项的符号,可翻译为“清单”或“待办事项”。 看 `DEPLOYMENT.md` 翻译为中文是:“部署指南.md” 或 “部署说明.md”。这里,“DEPLOYMENT”指的是“部署”,而“.md”是Markdown文件格式的后缀,通常用于编写技术文档、说明文件等 以获取详细的部署说明。

测试服务器(用于开发)

你可以通过直接导入它来测试这个东西是否真的有效:

from dart_mcp.server import next_trains, list_stations

# Test next buses functionality (prepare for disappointment)
result = await next_trains('DART Central Station', 'University')
print(result)  # Spoiler: there are no buses

# Test stops list (all 64 of them, because apparently that's manageable)
stations = await list_stations()
print(stations)

可用工具(你的新好伙伴)

next_trains(origin, destination, when_iso=None)

礼貌地询问下一趟火车何时到达。服务员会查看它的“水晶球”(GTFS数据),然后告诉你预计的时间 从技术上讲 准确。

参数:

  • origin (字符串):你现在所在的地方(可能正为自己的人生选择感到后悔)
  • destination (字符串):你想去的地方(可能除了这里,任何地方都行)
  • when_iso (字符串,可选):当你想要出行时(好像在公共交通中时间有什么意义似的)

示例:

# Next buses from current time (aka "right now would be nice")
next_trains('DART Central Station', 'University')

# Buses at a specific time (for the optimists who think schedules matter)
next_trains('University', 'DART Central Station', '2025-05-23T06:00:00')

# Using abbreviations (because typing is hard)
next_trains('dart', 'university')

list_stations()

获取所有64个DART公交站点的列表,因为显然要求记住它们太过困难。

返回值: 一个格式化的列表,会让你意识到这辆公交车到底要去多少个地方。

车站名称识别(我们不是心灵感应者,但我们会尽力)

服务器支持多种方式来简化输入站名的过程:

  • 全名“DART中央车站”(专为追求完美者设计)
  • 简称“大学”(对于稍不那么追求完美主义者而言)
  • 缩写“dart” → “DART中央车站”(为真正懒人准备)
  • 部分匹配“university”与“University”匹配(当你懒得区分大小写时)

可用站点(全部64个辉煌站点)

我们的服务器涵盖了每一个DART公交站点,因为我们追求完美:

DART铁路系统 (主赛事)

  • 红线达拉斯市中心、珍珠/艺术区、城市广场/上城、嘲鸫(Mockingbird,此处为地名,直译保留)、公园大道、胡桃山/登顿、森林大道、林登·B·约翰逊/中央区、春谷、阿拉帕霍中心、加拉廷公园、布什高速公路、帕克路、普兰诺市中心、第15街/普兰诺、卡罗尔顿市中心、三一磨坊、环城公路、春谷(重复项,翻译时可略去或注明重复)、森林大道(重复项,翻译时可略去或注明重复)、胡桃山/登顿(重复项,翻译时可略去或注明重复)、公园大道(重复项,翻译时可略去或注明重复)、嘲鸫(重复项,翻译时可略去或注明重复)、城市广场/上城(重复项,翻译时可略去或注明重复)、珍珠/艺术区(重复项,翻译时可略去或注明重复)、达拉斯市中心(重复项,翻译时可略去或注明重复)

  • 蓝线达拉斯市中心、珍珠/艺术区、城市广场/上城、嘲鸫(Mockingbird,此处可能指达拉斯的一个社区或区域)、公园大道、胡桃山/登顿、森林大道、林登·B·约翰逊/中央区、春谷、阿拉帕霍中心、加拉廷公园、布什高速公路、帕克路、普莱诺市中心、第15街/普莱诺、卡罗尔顿市中心、三一磨坊、环城公路、春谷(重复)、森林大道(重复)、胡桃山/登顿(重复)、公园大道(重复)、嘲鸫(重复)、城市广场/上城(重复)、珍珠/艺术区(重复)、达拉斯市中心(重复)

  • 绿线达拉斯市中心、珍珠/艺术区、城市广场/上城区、嘲鸫大道、公园大道、胡桃山/登顿、森林大道、林登·贝恩斯·约翰逊/中央区、斯普林瓦利、阿拉帕霍中心、加拉廷公园、布什收费公路、帕克路、普莱诺市中心、第15街/普莱诺、卡罗尔顿市中心、特里尼蒂米尔斯、环城大道、斯普林瓦利、森林大道、胡桃山/登顿、公园大道、嘲鸫大道、城市广场/上城区、珍珠/艺术区、达拉斯市中心

  • 橙线达拉斯市中心、珍珠/艺术区、城市广场/上城、嘲鸫区、公园大道、胡桃山/登顿、森林大道、林登·B·约翰逊/中央区、斯普林瓦利、阿拉帕霍中心、加拉廷公园、布什高速公路、帕克路、普兰诺市中心、第15街/普兰诺、卡罗尔顿市中心、三一磨坊、环城路、斯普林瓦利、森林大道、胡桃山/登顿、公园大道、嘲鸫区、城市广场/上城、珍珠/艺术区、达拉斯市中心

样本输出(准备被惊艳到)

🚌 Next DART bus departures from DART Central Station to University on Thursday, May 22, 2025:
• Bus 153: 17:58:00 → 19:16:00 (to University)
• Bus 527: 18:22:00 → 19:22:00 (to University)
• Bus 155: 18:28:00 → 19:46:00 (to University)
• Bus 429: 18:43:00 → 19:53:00 (to University)
• Bus 157: 18:58:00 → 20:16:00 (to University)

实际到达时间可能会有所不同。副作用可能包括对存在的恐惧以及对远程工作的深深喜爱。

技术细节(给技术爱好者看的)

  • GTFS处理我们自动处理车站与其站台之间的关系(因为显然列车系统很复杂)
  • 服务日历遵守工作日/周末时间表(火车也需要休息呢)
  • 数据类型处理GTFS文件中混合整数/字符串格式的混乱情况
  • 时间解析支持24+小时格式,满足那些传奇般的深夜服务需求
  • 错误处理当你输入“Narnia”作为电台名称时,系统会优雅地处理(即不会报错或崩溃)

项目结构(有序的混乱)

dart-mcp/
├── .github/workflows/         # GitHub Actions (the CI/CD overlords)
│   ├── ci.yml                 # Main CI pipeline (linting, testing, the works)
│   └── update-gtfs.yml        # Automated GTFS data updates
├── src/dart_mcp/              # Main package (because modern Python demands structure)
│   ├── data/dart-tx-us/       # GTFS data storage (where CSV files go to retire)
│   ├── __init__.py            # Package initialization (the ceremony of Python)
│   ├── __main__.py            # Entry point for python -m dart_mcp
│   ├── server.py              # MCP server implementation (where the magic happens)
│   └── gtfs.py                # GTFS data processing (aka "CSV wrestling")
├── scripts/                   # Utility scripts (the supporting cast)
│   ├── __init__.py            # Makes scripts a proper Python package
│   ├── fetch_gtfs.py          # Downloads the latest disappointment data
│   └── lint.py                # Run all CI checks locally (before embarrassment)
├── tests/                     # Test suite (because trust but verify)
│   ├── conftest.py            # Shared test fixtures (the common ground)
│   ├── test_gtfs.py           # GTFS functionality tests (8 tests of data wrangling)
│   ├── test_server.py         # Server functionality tests (4 tests of MCP protocol)
│   └── test_fetch_gtfs.py     # Data fetching tests (7 tests of download chaos)
├── .pre-commit-config.yaml    # Pre-commit hooks configuration
├── pyproject.toml             # Modern Python config (because setup.py is so 2020)
└── README.md                  # This literary masterpiece

开发与测试(应对不可避免的故障情况)

代码质量与持续集成/持续交付(CI/CD)

这个项目使用现代的Python工具来保持代码的简洁和可维护性:

  • “Ruff”可以翻译为“粗糙”或“粗犷”,具体含义取决于上下文。在描述物体或表面时,它可能指不光滑、有凹凸不平的质感;在描述人的性格或行为时,它可能指粗鲁、不拘小节的特点闪电般的快速代码检查和格式化(因为生命太短暂,不能浪费在慢工具上)
  • MyPy类型检查(因为猜测类型是业余人士的做法)
  • Pytest带有覆盖率报告的测试框架

发布流程(自动化精彩体验)

这个项目采用自动化版本管理和发布:

  • 语义化版本控制版本号是根据提交信息自动生成的,使用 规范提交(或:约定式提交)
  • 自动标记当你推送至 mainsemantic-release 会自动创建版本标签
  • PyPI 发布带标签的发布版本会通过 GitHub Actions 自动构建并发布到 PyPI
  • 可信出版使用PyPI进行OIDC认证(无需API令牌!)

发布版本

只需使用标准的提交格式进行提交,然后推送到主分支:

# For bug fixes (patch version bump: 1.0.0 → 1.0.1)
git commit -m "fix: correct station name lookup bug"

# For new features (minor version bump: 1.0.0 → 1.1.0)
git commit -m "feat: add support for weekend schedules"

# For breaking changes (major version bump: 1.0.0 → 2.0.0)
git commit -m "feat!: redesign API structure"
# or
git commit -m "feat: major API changes

BREAKING CHANGE: This changes the function signatures"

语义化发布(semantic-release)的工作流程将:

  1. 分析你的提交信息
  2. 确定适当的版本升级
  3. 创建一个 Git 标签(例如。, v1.2.3)
  4. 生成更改日志
  5. 触发发布工作流以发布到PyPI

本地测试

在推送之前,先在本地测试构建过程:

# Build packages locally
uv run python -m build --sdist --wheel

# Validate packages
uv run twine check dist/*

# Test upload to Test PyPI (optional)
uv run twine upload --repository testpypi dist/*

GitHub Actions CI(持续集成)

每次拉取请求(PR)和向主分支的推送都会触发自动检查:

  • ✅ **代码检查(或代码格式化、代码规范检查)**粗略检查代码质量问题
  • ✅ 格式化确保代码风格一致
  • ✅ 类型检查MyPy 验证类型注解
  • ✅ 测试完整的测试套件,附带覆盖率报告
  • ✅ 覆盖范围在CI日志中生成测试覆盖率报告

如果任何检查失败,持续集成(CI)系统将会礼貌地拒绝您的拉取请求(PR),因为标准很重要。

MCP集成(用于AI统治者)

此服务器实现了模型上下文协议(MCP),这意味着它旨在与AI助手和其他MCP客户端无缝协作。一旦配置完成:

  • **Claude Desktop(可译为“Claude桌面版”或保持原样,若“Desktop”在此处作为品牌或产品系列名称,则无需直译)**直接在对话中询问克劳德火车时刻表
  • 其他MCP客户端任何兼容MCP的工具都可以访问DART数据
  • 实时集成您的AI可以查看日程、建议路线,并帮助规划旅行
  • 自然语言无需记住站点名称或命令语法

服务器提供了两个主要工具:

  • next_trains - 获取各站点之间的即将发车信息
  • list_stations - 浏览所有可用的DART站点

所以,你的AI助手现在就像真人一样,可能会让你对火车时刻表感到失望!未来真的已经到来。

许可证(法律条款)

这个项目使用的是官方的DART GTFS数据。如果出现问题,请责怪他们,而不是我们。我们只是传递信息的媒介。


在达拉斯,这里公共交通既是必需品,也是无尽烦恼的源头,我怀着满腔热忱(❤️)并摄入了相当多的咖啡因,完成了这个作品。