关于 onebusaway-mcp-server
onebusaway-mcp-server 通过 OneBusAway API 提供公共交通线路、站点、实时到站和车辆信息,适用于普吉特海湾地区及兼容的 OneBusAway 实例。它还支持服务提醒和全天时刻表查询。
主要功能
- 01查找站点、线路与所属机构
- 02获取实时到站和车辆位置
- 03查询行程状态与服务提醒
- 04读取站点和线路全天时刻表
- 05提供站点与线路资源
适用场景
- 01查看某站点的实时到站信息
- 02追踪机构或线路上的车辆
- 03查询某线路当天的完整时刻表
MCP 相关
作为 MCP 服务,它通过 16 个工具提供 OneBusAway 的站点、线路、到站、车辆、提醒和时刻表数据,并提供站点与线路资源。支持 STDIO 与 Streamable HTTP。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://onebusaway.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-onebusaway https://onebusaway.caseyjhand.com/mcp{"mcpServers":{"cyanheads-onebusaway":{"type":"http","url":"https://onebusaway.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"cyanheads-onebusaway":{"type":"http","url":"https://onebusaway.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"cyanheads-onebusaway":{"type":"http","url":"https://onebusaway.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-onebusaway":{"serverUrl":"https://onebusaway.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
16此工具无需参数。
详细介绍
@cyanheads/onebusaway-mcp-server
通过 MCP 查询 OneBusAway 公交 API 中的站点、线路、实时到站信息、车辆位置和时刻表。支持 STDIO 或 Streamable HTTP。
概览
OneBusAway 实时公交信息,默认适用于普吉特海湾地区(King County Metro、Sound Transit、Pierce Transit、Community Transit 等),也兼容任何 OneBusAway 实例。查找站点和线路,追踪实时到站信息和车辆位置,并获取时刻表和服务提醒。
工具
| 工具 | 描述 |
|---|---|
onebusaway_list_agencies | 列出此实例上的公交机构,包括 ID、联系方式和服务覆盖区域 |
onebusaway_find_stops | 查找指定经纬度附近的站点,可选按站点代码筛选 |
onebusaway_search_stops | 将站点名称或代码解析为站点 ID |
onebusaway_get_stop | 按 ID 获取一个站点 |
onebusaway_find_routes | 查找指定经纬度附近的线路,可选按名称或编号筛选 |
onebusaway_search_routes | 将线路名称或编号解析为线路 ID |
onebusaway_get_route | 按 ID 获取一条线路 |
onebusaway_list_routes_for_agency | 列出某公交机构运营的所有线路 |
onebusaway_get_arrivals | 获取站点的实时到站和发车信息,包括时刻表偏差、车辆位置和有效提醒 |
onebusaway_get_stop_context | 通过一次上游请求获取站点详情、实时到站信息,以及该站点每条提醒的完整详情 |
onebusaway_get_alert | 按情况 ID 获取完整的服务提醒详情 |
onebusaway_get_trip | 获取一趟行程的实时状态和站点顺序 |
onebusaway_get_block | 按顺序列出一辆车在一个服务日内运行的所有行程及其站点时间 |
onebusaway_get_vehicles | 获取某公交机构正在运营车辆的实时位置,可选指定一条线路 |
onebusaway_get_schedule_for_stop | 按线路和方向获取某站点全天的发车时刻表 |
onebusaway_get_schedule_for_route | 获取某条线路的全天时刻表,包括每趟行程及其站点顺序 |
资源
| 资源 | 描述 |
|---|---|
onebusaway://stop/{stopId} | 站点元数据:名称、坐标、服务线路、轮椅通行情况 |
onebusaway://route/{routeId} | 线路元数据:简称、描述、公交机构、时刻表 URL |
仅支持工具的客户端也可通过 onebusaway_get_stop 和 onebusaway_get_route 获取相同数据。
功能参考
onebusaway_list_agencies tool
- 无需输入;返回所有公交机构及其
id、联系方式、timezone和coverageCenter/coverageSpan limitExceeded表示上游返回的列表已达上限,且没有分页功能可获取剩余内容
onebusaway_find_stops tool
- 必须提供
lat/lon;radius的单位为米,默认值为 300,最大值为 1600;可选的query用于匹配站牌上印制的站点代码 - 每个站点包含
id、code、direction、routeIds和wheelchairBoarding(ACCESSIBLE/NOT_ACCESSIBLE/UNKNOWN);limitExceeded表示该半径范围内还有更多站点
onebusaway_search_stops tool
- 必须提供
query(站点名称片段或站点代码);maxCount最大为 100,默认值为 10 - 返回的站点结构与
onebusaway_find_stops相同;limitExceeded表示匹配的站点数量超过maxCount
onebusaway_get_stop tool
- 提供单个
stopId;返回name、code、坐标、direction、routeIds和wheelchairBoarding - 未知 ID 会返回
stop_not_found错误,可通过onebusaway_find_stops或onebusaway_search_stops进行恢复
onebusaway_find_routes tool
- 必须提供
lat/lon;radius的单位为米,默认值为 500,最大值为 1600;也可改用latSpan+lonSpan矩形框(两者都必须设置);可选的query用于按线路名称或编号搜索 - 每条线路包含
shortName、longName、agencyId、GTFStype(0=有轨电车 … 5=缆车)、color和时刻表url;limitExceeded表示该区域内还有更多线路
onebusaway_search_routes tool
- 必须提供
query(线路名称或编号);maxCount最大为 100,默认值为 10 - 返回
shortName、longName、agencyId和 GTFStype;limitExceeded表示匹配的线路数量超过maxCount - 在线路搜索端点返回 404 的实例上会返回
endpoint_unavailable错误,其中包括 Puget Sound;请改用onebusaway_find_routes或onebusaway_list_routes_for_agency
onebusaway_get_route 工具
- 单个
routeId;返回shortName、longName、description、agency、GTFStype、color和班次url - 未知 ID 会报错
route_not_found,可通过onebusaway_find_routes或onebusaway_search_routes查找
onebusaway_list_routes_for_agency 工具
- 必须提供
agencyId;未知 agency 会报错agency_not_found - 返回所有路线及其
shortName、longName、GTFStype、color和url;limitExceeded表示上游限制了列表且不支持分页
onebusaway_get_arrivals 工具
- 必须提供
stopId;查询时间窗口为minutesBefore(整数,0–60,默认 5)/minutesAfter(整数,0–240,默认 35),更长的时间范围请使用onebusaway_get_schedule_for_stop;未知站点会报错stop_not_found - 每条到站信息包含
predicted(false = 仅按时刻表)、以秒为单位的scheduleDeviation(正值 = 晚点,仅在有预测时有意义)、predictedArrivalTime、vehiclePosition、stopsAway和tripId - 当前有效的警报会出现在
situations[]中:包括该站点上的警报,以及每条到站信息通过situationIds关联的警报,每个警报仅出现一次
onebusaway_get_stop_context 工具
- 输入与
onebusaway_get_arrivals相同,失败类型也相同,为stop_not_found/rate_limited;一次调用只会发出一个上游请求 - 返回
stop(onebusaway_get_stop的字段,但不含routeIds)、符合onebusaway_get_arrivals格式的arrivals,以及符合onebusaway_get_alert格式的alerts——包括查询窗口内站点上的所有警报,以及到站信息上的所有警报;即使窗口内没有到站信息携带某个全站警报,该警报也会包含在内 - 如果上游响应中缺少站点,
stop为 null;如果响应中缺少被引用的警报,则不返回该警报;无论哪种情况,都会通过notice指明用于获取它的工具
onebusaway_get_alert 工具
- 单个
situationId,来自onebusaway_get_arrivals(situations[].id或arrivals[].situationIds);未知 ID 会报错situation_not_found - 返回 TPEG
reason代码、severity、consequenceMessage、affects(agency、路线、站点或行程范围)、包含改道站点 ID 的consequences,以及activeWindows
onebusaway_get_trip 工具
- 必须提供
tripId;serviceDateMs(非负整数,按当地时间午夜计算)仅适用于前一个服务日的行程;includeSchedule(默认 true)会添加包含 GTFS 时间和distanceAlongTripMeters的站点顺序 status包含phase(例如in_progress、layover_before)、predicted、position、scheduleDeviation和nextStop;blockId(行程没有对应区块时为 null)可用于调用onebusaway_get_block- 如果该行程在指定服务日期内未处于活动状态,则报错
trip_not_found;已完成行程的时间信息来自onebusaway_get_schedule_for_route
onebusaway_get_block 工具
- 单个
blockId,来自onebusaway_get_trip;未知 ID 会报错block_not_found - 顶层的
trips、activeServiceIds和inactiveServiceIds描述首个返回的配置;alternateConfigurations按顺序保留其余所有配置。服务 ID 表示日历条件,并不意味着某个配置今天会运行 - 每条行程包含
distanceAlongBlock、accumulatedSlackTime(停站时间,单位为秒)和blockStopTimes。可选的精确tripId或departureFromSec/departureBeforeSec会分别在每个配置中筛选完整行程,并保留空配置项 - 使用筛选条件时,
selection.total/returned统计所有配置中的行程实例;configurationCounts[0]描述顶层配置,之后每项对应一个备选配置
示例:{"blockId":"<blockId from onebusaway_get_trip>","departureFromSec":86400,"departureBeforeSec":90000} 会筛选出发时间在 24:00(含)至 25:00(不含)之间的行程,并保留其完整站点顺序。
onebusaway_get_vehicles 工具
- 必填
agencyId;未知的机构会返回agency_not_found错误。可选的routeId会在获取该机构的所有车辆后由客户端筛选 - 每辆车包含
position、orientation、phase、scheduleDeviation、tripId、nextStop和predicted(表示正在报告实时 GPS 数据);limitExceeded表示上游返回的列表已达上限且不支持分页 tripId优先使用当前行程;路线和目的地标牌元数据仅从该行程解析。orientation保留从东开始逆时针计算的角度(0=东,90=北,180=西,270=南),而非罗盘方位角- 缺少纬度或经度的记录会被跳过:
omittedWithoutPosition统计整个机构中此类记录的数量;按路线筛选时,omittedWithoutPositionOnRoute统计已解析匹配项中的此类记录数量。这些计数不受上游截断影响
onebusaway_get_schedule_for_stop 工具
- 必填
stopId;可选date,须为真实的YYYY-MM-DD日历日期;默认(省略或留空时)为机构时区的当天;未知站点会返回stop_not_found错误 - 按路线和方向对出发班次分组,每项包含
scheduledDepartureTime和tripId serviceDateMs保留上游的时刻表日期标记:省略或留空日期时为查询时间;指定日期时为实例本地午夜;不会取整到服务日边界- 可选的
routeId、departureFromMs和departureBeforeMs条件以 AND 组合;时间边界为非负整数 Unix 毫秒,下限包含,上限不包含。筛选后的结果会省略空方向和路线;selection.total/returned分别统计筛选前后的出发班次数 - 仅提供静态时刻表;实时预测请使用
onebusaway_get_arrivals
示例:{"stopId":"1_75403","routeId":"1_100259","departureFromMs":1792882800000,"departureBeforeMs":1792886400000} 会筛选该路线在给定 Unix 时间区间内的出发班次。
onebusaway_get_schedule_for_route 工具
- 必填
routeId;可选date,须为真实的YYYY-MM-DD日历日期;默认(省略或留空)为今天;未知路线会报错route_not_found - 返回当天的每趟行程,包含
tripId、tripHeadsign、serviceId和停靠站序列 serviceDateMs保留上游路线的scheduleDate,用于标识时刻表对应的服务日期- 路线、停靠站、行程终点标牌和服务元数据优先从引用中解析;引用字段缺失或为空时,保留旧版元数据和分组回退逻辑
- 可选的精确
tripId或departureFromSec/departureBeforeSec,用于选择在时间区间内有任意一次发车的完整行程。边界值必须是非负整数形式的 GTFS 午夜起算秒数,可超过 86400;下界包含在内,上界不包含在内。selection.total/returned分别统计选择前后的行程数 - 仅提供静态时刻表;实时预测请通过停靠站上的
onebusaway_get_arrivals获取
示例:{"routeId":"1_100259","departureFromSec":28800,"departureBeforeSec":32400} 会选出 08:00(含)至 09:00(不含)之间有任意一次发车的行程。
对于路线和区块时刻表,非空白的 tripId 不能与发车时间边界同时使用。空白的可选 ID 视为省略;任一边界都可以省略,但同时提供的两个边界必须递增。未指定选择条件时,三个工具都会返回完整映射结果,不包含选择元数据或默认上限。选择计数仅描述该上游响应,不包括上游服务中未包含的内容;匹配数为零时,结果仍然成功,但会附带提示。
到达信息、停靠站上下文、行程、车辆、时刻表和警报都包含经过验证的 IANA timezone;纪元时间和日期标题会明确标注时区。停靠站工具使用所查询停靠站的机构命名空间,车辆使用所请求的机构,行程/路线时刻表使用所引用路线的机构。每条警报都会解析各自的机构、路线、行程和停靠站范围;只有在所有范围均解析成功且时区一致时,才会使用这些范围的时区。时区缺失、无效、无法解析或互相冲突时,将使用 UTC,不会额外发起请求。纪元数值和 GTFS 秒数保持不变,包括超过 24:00 的时刻表时间。
onebusaway://stop/{stopId} 资源
- 以
application/json格式返回停靠站记录,结构与onebusaway_get_stop返回的相同 stopId来自onebusaway_find_stops或onebusaway_search_stops
onebusaway://route/{routeId} 资源
- 以
application/json格式返回路线记录,结构与onebusaway_get_route返回的相同 routeId来自onebusaway_find_routes或onebusaway_search_routes
功能
基于 @cyanheads/mcp-ts-core 构建:支持 stdio 和 Streamable HTTP 传输、可插拔认证(none / jwt / oauth)、可切换存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及支持可选 OpenTelemetry 跟踪的结构化日志记录。
OneBusAway 专属功能:
- 使用类型化错误分类封装
onebusaway-sdk(NotFound、RateLimited、上游返回 400 时的ValidationError、ServiceUnavailable) - 默认使用 Puget Sound 实例(
api.pugetsound.onebusaway.org),开发时可使用ONEBUSAWAY_API_KEY=TEST;ONEBUSAWAY_BASE_URL可将其指向任意其他 OneBusAway 实例 - 站点和路线 ID 带有机构前缀,格式为
{agencyId}_{localId}(站点为1_75403,路线为1_100259);机构 ID 是不带修饰的前缀(Metro Transit 为1,Sound Transit 为40) - 所有上游请求共用一个限速器,其容量由
ONEBUSAWAY_RATE_LIMIT_*设置;它会根据 API 密钥的配额对请求排队。如果调用在等待时限内未获得请求名额,则会在任何工具上返回可重试的rate_limited错误,并附带data.retryAfter - 仅提供公交数据,不提供行程规划;服务级说明会引导 Agent 了解 ID 格式和常见查询链
便于 Agent 使用的输出:
- 每条到站信息、每个行程和每辆车辆都包含
predicted,用于区分 GPS 跟踪数据和仅基于时刻表的预测 - 机器可读时间:
scheduleDeviation以秒为单位;到站、站点时刻表和更新的时间戳以 Unix 毫秒为单位;行程、路线时刻表和班次的站点时间采用从午夜起算的 GTFS 秒数 - 可串联的 ID:站点工具返回的
stopId可用于查询到站信息,tripId可用于调用onebusaway_get_trip,blockId可用于调用onebusaway_get_block,situationIds可用于调用onebusaway_get_alert,agencyId可用于查询车辆和路线列表 - 类型化错误约定中的恢复提示会指出下一步要调用的工具;结果为空或被截断时会附带
notice
开始使用
公共托管实例
公共实例地址为 https://onebusaway.caseyjhand.com/mcp,无需安装。通过 Streamable HTTP 将任意 MCP 客户端连接到该实例:
{
"mcpServers": {
"onebusaway-mcp-server": {
"type": "streamable-http",
"url": "https://onebusaway.caseyjhand.com/mcp"
}
}
}
自托管 / 本地运行
将以下内容添加到 MCP 客户端配置文件中。在 Puget Sound 实例上,无需注册即可使用 ONEBUSAWAY_API_KEY=TEST。
{
"mcpServers": {
"onebusaway-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/onebusaway-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"ONEBUSAWAY_API_KEY": "TEST"
}
}
}
}
也可以使用 npx(无需 Bun):
{
"mcpServers": {
"onebusaway-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/onebusaway-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"ONEBUSAWAY_API_KEY": "TEST"
}
}
}
}
也可以使用 Docker:
{
"mcpServers": {
"onebusaway-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "ONEBUSAWAY_API_KEY=TEST",
"ghcr.io/cyanheads/onebusaway-mcp-server:latest"
]
}
}
}
使用 Streamable HTTP 时,设置传输方式并启动服务:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 ONEBUSAWAY_API_KEY=TEST bun run start:http
# Server listens at http://localhost:3010/mcp
先决条件
- Bun v1.4.0 或更高版本(或 Node.js v24+)。
- OneBusAway API 密钥。开发时可在 Puget Sound 实例上使用
TEST;用于生产环境或其他实例时,请到相应机构的开发者门户注册。
安装
- 克隆仓库:
git clone https://github.com/cyanheads/onebusaway-mcp-server.git
- 进入目录:
cd onebusaway-mcp-server
- 安装依赖:
bun install
- 配置环境:
cp .env.example .env
# edit .env — set ONEBUSAWAY_API_KEY if needed
配置
| 变量 | 描述 | 默认值 |
|---|---|---|
ONEBUSAWAY_API_KEY | OneBusAway API 密钥。在 Puget Sound 实例上,TEST 可用。 | TEST |
ONEBUSAWAY_BASE_URL | OneBusAway 实例的基础 URL。 | https://api.pugetsound.onebusaway.org |
ONEBUSAWAY_RATE_LIMIT_REQUESTS | 每个时间窗口允许的上游请求数,由所有调用方共享。 | 20 |
ONEBUSAWAY_RATE_LIMIT_WINDOW_MS | 滑动速率限制窗口的时长,单位为毫秒。 | 60000 |
ONEBUSAWAY_RATE_LIMIT_MAX_WAIT_MS | 调用等待可用名额的最长时间,超时后将以 rate_limited 失败,单位为毫秒。请设置为低于 SDK 的 60 秒请求超时时间。 | 45000 |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_HTTP_PORT | HTTP 服务端口。 | 3010 |
MCP_SESSION_MODE | HTTP 会话模式:stateless、stateful 或 auto。 | stateless |
MCP_AUTH_MODE | 身份验证方式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(debug、info、notice、warning、error)。 | info |
LOGS_DIR | 日志文件目录(仅限 Node.js)。 | <project-root>/logs |
STORAGE_PROVIDER_TYPE | 存储后端:in-memory、filesystem、supabase、cloudflare-kv/r2/d1。 | in-memory |
OTEL_ENABLED | 启用 OpenTelemetry。 | false |
完整的可选覆盖项列表请参阅 .env.example。
运行服务
本地开发
-
构建并运行生产版本:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio -
运行检查和测试:
bun run devcheck # Lint, format, typecheck, security, changelog sync bun run test # Vitest test suite bun run test:coverage # Test suite with coverage, held to the framework thresholds bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t onebusaway-mcp-server .
docker run --rm -e ONEBUSAWAY_API_KEY=TEST -p 3010:3010 onebusaway-mcp-server
Dockerfile 默认使用 HTTP 传输、无状态会话模式,并将日志写入 /var/log/onebusaway-mcp-server。默认会安装 OpenTelemetry 对等依赖;构建时使用 --build-arg OTEL_ENABLED=false 可省略这些依赖。
项目结构
| 目录 | 用途 |
|---|---|
src/index.ts | createApp() 入口点:注册工具和资源、设置服务说明,并初始化 OneBusAway 服务。 |
src/config | 使用 Zod 解析和验证服务专属环境变量。 |
src/mcp-server/tools | 工具定义(*.tool.ts)及其共用的架构和格式辅助函数。 |
src/mcp-server/resources | 站点和路线资源定义(*.resource.ts)。 |
src/services/onebusaway | OneBusAway 服务:封装 onebusaway-sdk、控制上游请求频率、对错误分类;包含领域类型。 |
tests/ | 针对工具、资源、服务和配置的 Vitest 测试。 |
开发指南
开发指南和架构规则请参阅 CLAUDE.md。简要说明如下:
- 处理程序抛出异常,框架负责捕获——工具逻辑中不要使用
try/catch - 使用
ctx.log记录请求范围内的日志,使用ctx.state存储租户范围内的数据 - 在
src/index.ts的createApp()数组中注册新工具和资源 - 封装外部 API 调用:验证原始数据 → 规范化为领域类型 → 返回输出架构;绝不伪造缺失字段
贡献
欢迎提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
许可证
Apache-2.0 — 详情请参阅 LICENSE。
来自默认 Puget Sound OneBusAway API 的公交数据由 Sound Transit 和 King County Metro 运营,受 Sound Transit Transit Data Terms of Use 约束;托管端点的用户也需遵守这些条款。主要义务如下:
- 第 2 条:可按要求提供使用指标。
- 第 3 条:数据从 OneBusAway API 实时获取,不会被修改,也不会在请求周期之外缓存。
- 第 4 条:您同意向您提供这些数据的任何用户传递实质上相似的条款。
- 第 7 条:本服务的名称或品牌不得使用 Sound Transit 商标。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。