关于 Charlotte Area Transit (CATS)
QueensCoach 是面向出行者和交通信息客户端的 MCP 服务,提供 Charlotte Area Transit System 的公交与轻轨数据。它结合行程规划和实时数据,涵盖时刻表、线路、车辆位置及服务提醒。
主要功能
- 01规划含步行和换乘的行程
- 02查询实时到站信息和延误
- 03查看站点时刻表与线路详情
- 04查询服务提醒和交通中断
- 05查找站点并追踪车辆
- 06提供静态及实时 GTFS 资源
适用场景
- 01规划地点之间的公交和铁路路线
- 02查询站点的预计到站时间
- 03查看指定日期的发车时刻
- 04查找附近车站或运营中的车辆
MCP 相关
基于公开时刻表和 GTFS-Realtime 数据,向 MCP 客户端提供 CATS 交通工具和 GTFS 资源。支持 stdio 与 Streamable HTTP;托管 HTTP 服务使用 Google OAuth。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://queenscoach.adamwanninger.com/mcpclaude mcp add --transport http ajwann-queenscoach https://queenscoach.adamwanninger.com/mcp{"mcpServers":{"ajwann-queenscoach":{"type":"http","url":"https://queenscoach.adamwanninger.com/mcp"}}}在 Cursor 中打开{"servers":{"ajwann-queenscoach":{"type":"http","url":"https://queenscoach.adamwanninger.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"ajwann-queenscoach":{"type":"http","url":"https://queenscoach.adamwanninger.com/mcp"}}}{"mcpServers":{"ajwann-queenscoach":{"serverUrl":"https://queenscoach.adamwanninger.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
QueensCoach ♔♘
QueensCoach 是一款面向 Charlotte Area Transit System (CATS) 公交和轻轨的 MCP 服务,基于该机构公开的 GTFS 时刻表和 GTFS-Realtime 数据源构建。它可以规划行程、预测到站时间、查询时刻表、介绍线路并报告服务提醒。它可以通过 stdio 运行,由使用它的 MCP 客户端启动;也可以通过前置 Google OAuth 的 HTTP 运行,作为托管服务。两种传输方式提供相同的工具和资源。
托管服务
Google Cloud Run 上运行着一个公开实例。使用任意 Google 账号登录:
https://queenscoach.adamwanninger.com/mcp
我们无法保证服务持续可用。 托管服务按现状提供。它可能运行缓慢、无法访问、因达到支出上限而关闭,或在未通知的情况下退役。对于需要依赖的用途,请运行自己的实例:通过 stdio,或在自己的 Google Cloud 项目中使用 deploy/GCP.md。
登录会向服务提供你的 Google 账号邮箱地址,该地址仅用于判断是否允许你访问,绝不会被存储。服务签发的令牌只会记录你在 Google 的不透明 ID,不包含其他个人信息。你分享给工具的位置会作为该调用的参数传入,用于回答问题,不会被存储。托管服务适用隐私政策和服务条款。
添加到 Claude
Claude 将远程 MCP 服务称为连接器。自定义连接器适用于 Claude 付费方案。
- 打开设置 → 连接器。网页版可访问 claude.ai/settings/connectors;桌面应用中,依次打开“设置”和“连接器”。
- 点击列表底部的添加自定义连接器。
- 将其命名为
QueensCoach,并将上方的 URL 粘贴到远程 MCP 服务 URL 中。OAuth 高级字段留空:此服务会自动注册你的客户端。 - 点击添加,然后点击出现的连接器上的连接。浏览器窗口会打开 Google 登录页面;批准后窗口会自动关闭。
- 在聊天中打开工具菜单,并确认 QueensCoach 已启用。随后会显示它的七个工具。
该连接器属于你的 Claude 账号,因此在网页版、桌面版和移动版上都可使用。要断开连接,请在同一“连接器”页面移除它;这会撤销此服务签发的令牌。
添加到 Claude Code
claude mcp add --transport http queenscoach https://queenscoach.adamwanninger.com/mcp
然后运行 /mcp,选择 queenscoach,再选择身份验证,这会打开相同的 Google 登录页面。之后,/mcp 会显示连接状态。通过此方式添加的服务会在 Claude Code 下次启动时加载。
其他客户端
任何支持通过带 OAuth 的流式 HTTP 连接远程服务的 MCP 客户端都可以使用:将相同的 URL 提供给它,它就会自动发现其余信息。
工具
| 工具 | 用途 |
|---|---|
plan_trip | 查询两地之间的公交和火车行程,包括步行和换乘,并根据实时延误进行调整。 |
get_arrivals | 查询指定站点或某地点附近车站的实时预计到站信息。 |
get_schedule | 查询任意日期某站点公布的时刻表:发车时间、首班车和末班车。 |
get_route | 查询某条线路在指定日期的信息:目的地、按顺序排列的站点、运营时间和发车频率。 |
get_service_alerts | 查询当前和即将发生的绕行与服务中断,可按全系统、线路、站点或地点筛选。 |
list_stops | 查询站点和车站,以及服务各站的线路;按距某地点由近到远排列。 |
list_vehicles | 查询运营中公交车和火车的 GPS 位置:按编号查询单辆车、某条线路的车辆,或全部车辆。 |
询问 Claude“离我最近的火车站在哪里?”、“我所在的站下一班火车什么时候到?”或“从这里怎么去机场?”,它就会将设备的位置传递给工具。服务端不会看到未传给它的位置,因此需要使用会向模型共享设备位置的客户端。
plan_trip
| 参数 | 类型 | 说明 |
|---|---|---|
origin_stop | string | 出发地点:站点 ID、代码或名称。 |
origin_latitude、origin_longitude | number | 也可以从某个地点出发,步行前往附近站点。 |
destination_stop | string | 目的地:站点 ID、代码或名称。 |
destination_latitude、destination_longitude | number | 也可以在某个地点结束行程。 |
date | YYYY-MM-DD | 夏洛特当地的服务日期(默认今天)。 |
depart_at | HH:MM | 不早于此时间出发。默认:现在。 |
arrive_by | HH:MM | 或不晚于此时间到达。 |
max_transfers | integer | 0 到 3(默认 2)。 |
max_walk_meters | integer | 前往首站或从末站出发的最长步行距离,100 到 2000 米(默认 800 米)。 |
最多返回三条行程方案,每条均包含步行和乘车路段:线路、车辆实际终点、上下车地点、时间、每次换乘的等待时间,以及途经站点。只有在换乘次数更多的方案到达更早时,才会提供这类方案(若指定 arrive_by,则需出发更晚)。出发时间在当前时间三小时以内的行程会附带实时延误信息,并标记为 live。如果两地之间的距离在步行限制范围内,则会显示 walkingIsAnOption。
步行距离为估算值:直线距离乘以 1.3,按每小时 4.5 公里计算。数据源不包含街道地图,因此实际步行距离可能更长。换乘时允许步行最多 400 米,并预留两分钟缓冲时间。
get_arrivals
| 参数 | 类型 | 说明 |
|---|---|---|
stop | string | 站点 ID(02400)、站点代码或站点名称的一部分(CTC Station)。 |
latitude、longitude | number | 不指定 stop 时,使用该地点最近的车站。 |
route | string | 可选的线路筛选条件。 |
mode | bus | train | 可选的交通方式筛选条件。 |
limit | integer | 最多返回的到站信息数量(默认 10,上限 50)。 |
指定 stop 或地点其中之一。指定地点时,筛选条件也会影响所选车站:mode: train 会查找最近的火车停靠站,而非距离更近的公交站;响应中还会包含其 metersAway。返回预计到站时间(分钟)、预计和计划时间、时刻表偏差、车辆编号、站台(stopId)以及车辆的实时位置。如果站点名称查询存在歧义,则使用最佳匹配项,并在 otherStopsMatchingQuery 下列出其他匹配项。影响该站点或其线路的当前服务提醒会作为 serviceAlerts 附上,格式与 get_service_alerts 返回的格式相同。若查询下一小时左右之后的时间,请使用 get_schedule。
get_schedule
| Argument | Type | Notes |
|---|---|---|
stop | string | 站点 ID、代码或名称。 |
latitude, longitude | number | 或选择服务于该路线或交通方式的最近站点。 |
route | string | 可选的路线筛选条件。 |
mode | bus | train | 可选的筛选条件。 |
date | YYYY-MM-DD | 服务日期(默认为今天)。 |
after, before | HH:MM | 时间范围。after 默认为今天当前时间,或服务开始时间。 |
limit | integer | 最多显示的发车次数(默认为 20,上限为 100)。 |
列出计划发车时间、每趟车次的路线和目的地,以及当天的 firstDeparture
和 lastDeparture。与 GTFS 一样,服务日会延续至午夜之后:周二最后一班列车于周三凌晨 1:31 发车,而在 after 或 before 中,25:30 表示当晚凌晨 1:30。实时预测请使用 get_arrivals。
get_route
| Argument | Type | Notes |
|---|---|---|
route | string | 必填。 9、501、Blue Line、Airport。 |
date | YYYY-MM-DD | 服务日期(默认为今天)。 |
按方向列出目的地、按顺序排列的站点(遵循大多数车次使用的线路模式,并汇总其他模式)、首末班发车时间,以及清晨、早高峰、午间、晚高峰、傍晚和深夜的典型发车间隔(分钟)。还会列出接下来七天每天的车次数以及有效警报数量。如果查询匹配多个路线,则改为列出这些路线。
get_service_alerts
| Argument | Type | Notes |
|---|---|---|
route | string | 提及该路线或其任一服务站点的警报。 |
stop | string | 提及该站点或服务该站点的任一路线的警报。 |
latitude, longitude | number | 影响 800 m 范围内站点的警报。 |
最多返回一条;不指定条件时返回所有警报。不包含已结束的警报。每条警报包含其标题、描述、影响和原因,以及 CATS 提供的详细文本;说明警报是 active 还是 upcoming、其时间段(未设结束时间的警报显示为 untilFurtherNotice),以及其中提及的路线和站点。
list_stops
| Argument | Type | Notes |
|---|---|---|
latitude, longitude | number | 地点;结果按距离从近到远排列,并包含 metersAway。 |
query | string | 站点 ID、站点代码或站点名称的一部分。 |
route | string | 仅列出该路线服务的站点。 |
mode | bus | train | 仅列出提供该交通服务的站点,例如用 train 查找最近的铁路车站。 |
limit | integer | 站点数量上限(指定地点时默认为 10,不指定时默认为 250;上限为 250)。 |
每个站点都会列出其 stopIds、坐标、modes 和 routes(ID、编号、全名、交通方式):例如 501 · Light Rail - Lynx Blue Line、510 · CityLYNX Gold Line,或 29 这样的公交路线。没有计划车次停靠的站点不会列出;距离指定地点超过 50 km 的站点也不会返回。
list_vehicles
| Argument | Type | Notes |
|---|---|---|
vehicle | string | 公交车或列车上显示的车辆编号,例如 2301、LRV307。 |
route | string | 路线:9、501、Blue Line、Mt. Holly Road。 |
mode | bus | train | 可选的筛选条件。 |
limit | integer | 最多返回的车辆数量(默认值和上限均为 250)。 |
所有参数均为可选;不指定参数时会返回所有正在运营的车辆。每辆车包含位置、朝向、速度、载客情况(CATS 目前不提供此信息)、车头显示的目的地,以及下一个计划停靠站。即使列表被截断,matches 和 countsByMode 仍会报告总数。
资源
面向需要数据本身的客户端和模型,提供工具背后的数据流。
| URI | 类型 | 内容 |
|---|---|---|
gtfs://static | JSON | 静态 GTFS 存档中的文件、文件大小和 URI,以及抓取时间。 |
gtfs://static/{file} | CSV | 存档中的任意表格,内容与 CATS 发布的一致。routes.txt、stops.txt、trips.txt 和 stop_times.txt 也会单独列出。 |
gtfs://realtime/vehicle-positions | JSON | 解码后的 VehiclePositions 数据流。 |
gtfs://realtime/trip-updates | JSON | 解码后的 TripUpdates 数据流。 |
gtfs://realtime/alerts | JSON | 解码后的 Alerts 数据流。 |
静态表格来自工具使用的同一份缓存下载文件。实时资源是解码后的数据流实体,包含 GTFS-Realtime 字段名、原始 ID 和 Unix 时间戳,不包含工具添加的时刻表关联信息。每个资源的 fetchedAt 均使用东部时间,与工具一致。stop_times.txt 文件较大(实时数据流中约为 12 MB)。
安装
需要 Python 3.11+。
pip install queenscoach
也可以不安装直接运行;大多数 MCP 客户端都以这种方式启动它:
uvx queenscoach
也可以从克隆的代码库运行,以便修改代码或从源代码运行 HTTP 传输:
python3 -m venv .venv
.venv/bin/pip install . # '.[gcp]' adds the Firestore token store
传输方式
使用 --transport 或 QUEENSCOACH_TRANSPORT 选择传输方式;默认值为 stdio。
queenscoach # stdio (default)
queenscoach --transport http --port 8000 # streamable HTTP + Google OAuth
stdio
适用于由客户端自行启动的服务。无需身份验证:客户端已拥有该进程。
在 Claude Code 中注册:
claude mcp add queenscoach -- uvx queenscoach
或者在 MCP 客户端配置文件中注册:
{
"mcpServers": {
"queenscoach": {
"command": "uvx",
"args": ["queenscoach"]
}
}
}
如果提供绝对路径(/absolute/path/to/.venv/bin/queenscoach),已安装的副本同样可用:MCP 客户端很少与当前 Shell 共用 PATH。python -m queenscoach 会运行同一服务,因此只要安装了该软件包,任何解释器都可以用作命令。
stdout 仅承载 MCP 协议流量;所有诊断信息均发送到 stderr。
使用 Google OAuth 的 HTTP
适用于任何知道 URL 的人都能访问的托管服务。每个发往 /mcp 的请求都需要 bearer token,而获取 token 的唯一方式是使用位于允许列表中的 Google 账号登录。
登录方式。 MCP 客户端会动态注册,并期望 MCP 服务自己的源站上有一个授权服务器。Google 既不支持动态注册,也不提供受众限制为第三方资源的 token,因此此服务本身就是 OAuth 2.1 授权服务器,只将登录委托给 Google:
MCP client <--OAuth--> queenscoach <--OAuth--> Google
Google 的响应只使用一次,用于确认登录的账号。系统会检查该邮箱是否在允许列表中,只有通过检查后,此服务才会签发自己的 token。Google 的 token 绝不会交给客户端。
在 Google Cloud 中进行一次性设置。 在 console.cloud.google.com/auth/clients 中,创建一个类型为 Web application 的 OAuth client,并添加一个已获授权的重定向 URI:
https://your-public-url/auth/google/callback
它必须与 QUEENSCOACH_PUBLIC_URL 完全一致。服务启动时会在日志中输出预期的 URI。
将客户端 ID 和密钥复制到下面的环境变量中。
运行。 .env.example 列出了所有设置;Shell 格式如下:
export QUEENSCOACH_GOOGLE_CLIENT_ID=...apps.googleusercontent.com
export QUEENSCOACH_GOOGLE_CLIENT_SECRET=...
export [email protected]
export QUEENSCOACH_PUBLIC_URL=https://queenscoach.example.com
queenscoach --transport http --port 8000
然后将客户端指向 https://queenscoach.example.com/mcp;客户端会发现其余配置,并打开浏览器以使用 Google 登录。在 Claude Code 中:
claude mcp add --transport http queenscoach https://queenscoach.example.com/mcp
默认拒绝访问。 除非 QUEENSCOACH_ALLOWED_EMAILS、QUEENSCOACH_ALLOWED_DOMAINS 或明确设置的 QUEENSCOACH_ALLOW_ANY_GOOGLE_ACCOUNT=true 指定了允许访问的用户,否则服务启动会失败。因此,配置错误的部署无法访问,而不会向互联网上的所有 Google 账号开放。未经验证的 Google 地址一律拒绝。
端点。
| 路径 | 用途 |
|---|---|
/mcp | MCP 端点。需要 Authorization: Bearer <token>。 |
/.well-known/oauth-protected-resource/mcp | 将客户端指向授权服务器。 |
/.well-known/oauth-authorization-server | 此服务的 OAuth 元数据。 |
/register | 动态客户端注册(RFC 7591)。 |
/authorize、/token、/revoke | OAuth 端点。 |
/auth/google/callback | Google 返回用户的地址。 |
scripts/install.sh 会完成整个部署:在 /opt 下创建系统用户,通过 API 创建 Cloudflare 隧道及其 DNS 记录,配置两个 systemd 单元,并执行验证。无需端口转发,因此在 CGNAT 或受限路由器后也能运行。参见 deploy/。
scripts/deploy-gcp.sh 会在你自己的 GCP 项目中的 Google Cloud
Run 上执行相同的操作:创建项目本身、用于登录的 Firestore、存放客户端密钥的 Secret Manager、由 Cloud Build 构建的容器、每月预算(可选设置硬性支出上限),并执行相同的验证。它会缩容至零,因此个人服务的成本几乎为零。参见
deploy/GCP.md。
部署说明。
- 默认情况下,服务使用普通 HTTP,并期望由隧道或代理终止 TLS;安装脚本会进行相应配置。改为设置
QUEENSCOACH_TLS_CERT和QUEENSCOACH_TLS_KEY后,服务会自行提供 HTTPS,适用于前方没有任何代理的部署。 QUEENSCOACH_PUBLIC_URL是客户端连接的地址,也是此服务的 OAuth issuer 标识符,因此必须填写外部 URL,而不是绑定地址。- 默认情况下,token 状态保存在内存中,因此按进程隔离:重启会使尚未过期的 token 失效。设置
QUEENSCOACH_TOKEN_STORE=firestore可将其改为保存在 Firestore 中(安装gcpextra:pip install 'queenscoach[gcp]'),这样登录状态可在重启后保留,并由所有实例共享。请同时设置QUEENSCOACH_STATELESS_HTTP=true,以便任何实例都能响应任何请求。 - 访问 token 的有效期为一小时,刷新 token 的有效期为 30 天;每次刷新时,两者都会轮换。
数据源
实时数据(GTFS-Realtime protobuf,每 20s 刷新一次):
https://gtfsrealtime.ridetransit.org/GTFSRealTime/Vehicle/VehiclePositions.pbhttps://gtfsrealtime.ridetransit.org/GTFSRealTime/TripUpdate/TripUpdates.pbhttps://gtfsrealtime.ridetransit.org/GTFSRealTime/Alert/Alerts.pb
静态时刻表(缓存 6h),用于将 feed 标识符转换为线路名称、站点名称和坐标,也是时刻表和规划工具读取的时刻表:
https://gtfsrealtime.ridetransit.org/GTFSStatic/api/GTFSDownload/GTFS.zip
服务会读取 agency.txt(用于获取时区)、routes.txt、stops.txt、
trips.txt、stop_times.txt,以及存在时的 calendar.txt 和
calendar_dates.txt。stop_times.txt 会以流式方式读取,并按行程打包到数组中;完整的 CATS feed 在内存中约占 15 MB。不会读取 shapes.txt。压缩包中的每个文件仍可作为资源使用。
此服务会处理的 feed 特殊情况
根据实时 feed 捕获数据验证:
VehiclePosition.stop_id和current_stop_sequence不可用。 在一份样本捕获数据中,158 个车辆站点 ID 均与已发布时刻表中的任何站点不匹配;报告的序号还超出了行程自身的站点数(例如,52 个站点的行程报告了序号 192)。此服务不会展示这些数据;下一站信息来自 TripUpdates feed,其中的站点 ID 均可解析。StopTimeEvent.delay从未填充。 时刻偏差根据time减去scheduled_time计算,这两个字段都有值。- TripUpdates 覆盖了约 83% 的在运营车辆,因此对于其余车辆,服务会省略
nextStop,而不是猜测。 - 线路匹配优先精确匹配,因此查询
5会返回线路 5,而不是 501 或 510。 - 大多数目的地标识只标明方向。 64 条线路中有 61 条的行程只标注为 “Inbound” 或 “Outbound”,因此时刻表和规划工具会将每趟行程的终点站报告为其
destination。 - 不会报告载客量。 每辆车的
occupancy_status都是NO_DATA_AVAILABLE。 - 时刻表只覆盖未来几周。 CATS 只发布
calendar_dates.txt,覆盖约四周(所检查的 feed 覆盖 2026 年 9 月 8 日至 10 月 4 日)。时刻表查询会通过scheduleCovers报告覆盖范围,并拒绝范围之外的日期。 - 未设定结束时间的提醒会在 3000 年结束。 如果提醒的结束时间超过五年后,服务会将其报告为
untilFurtherNotice。 parent_station的范围过宽,不适合用于归并站台。 CATS 将其用于覆盖相距最多 900 m、彼此无关站点的行程规划地点,因此服务会按名称和距离对车站进行分组。
行为说明
- 已经过去的到站预测会被过滤掉;不会出现负数 ETA。
- 200 m 范围内名称相同的站点会被视为同一站点:例如 Gold Line 站点的两个站台,或马路两侧相对的公交站。
list_stops、get_arrivals、get_schedule和plan_trip都会将它们视为同一地点。 - Feed 响应大小有限,且有时间限制;单个缓慢的 Feed 不会导致调用一直挂起。
- 并发调用会共享每个 Feed 的单个进行中请求;即使一个调用放弃等待,也不会中止其他调用正在等待的请求。
- 如果刷新失败但存在缓存数据,则会返回最近一次成功获取的数据,而不是报错。每个响应中的
feedAgeSeconds会显示数据有多陈旧。 - 对于
get_arrivals和get_route,告警 Feed 是补充信息:如果获取失败,它们仍会返回结果,只是不包含告警。实时预测不可用时,plan_trip同样会回退到时刻表,并说明这一点。 - 参数中的日期和时刻均采用 Charlotte 当地时间。服务日会延续到午夜之后,与 GTFS 一致;其时刻以服务日期当天的中午减去 12 小时为起点,因此在夏令时切换时也能保持准确。
- 时刻表解析、行程规划和时刻表扫描都在线程中运行,因此某项操作缓慢时不会阻塞其他请求。时刻表下载完成后的首次调用需要等待约一秒完成解析;之后搜索行程的耗时远低于一秒。
- 工具响应中的所有时间均为东部时间(
America/New_York),采用 ISO 8601 格式,并带有该日期生效的时区偏移:夏令时期间为2026-09-08T17:59:48-04:00,其他时间为2026-12-21T19:00:00-05:00。时钟回拨当晚的两个凌晨 1:30 会通过时区偏移加以区分。坐标采用 WGS84 十进制度数。
配置
Feeds(两种传输方式均适用)
所有配置项均为可选;默认值指向上述 CATS Feeds。时长单位为毫秒。
| 变量 | 默认值 |
|---|---|
QUEENSCOACH_VEHICLE_POSITIONS_URL | CATS 车辆位置 Feed |
QUEENSCOACH_TRIP_UPDATES_URL | CATS 行程更新 Feed |
QUEENSCOACH_ALERTS_URL | CATS 告警 Feed |
QUEENSCOACH_STATIC_GTFS_URL | CATS 静态 GTFS zip |
QUEENSCOACH_REALTIME_TTL_MS | 20000 |
QUEENSCOACH_STATIC_TTL_MS | 21600000 |
QUEENSCOACH_REQUEST_TIMEOUT_MS | 30000 |
QUEENSCOACH_MAX_FEED_BYTES | 33554432 |
QUEENSCOACH_MAX_STATIC_BYTES | 268435456 |
Feed URL 必须使用 http 或 https;否则会在启动时被拒绝。
传输方式
| 变量 | CLI | 默认值 |
|---|---|---|
QUEENSCOACH_TRANSPORT | --transport | stdio |
HTTP 传输
仅在选择 --transport http 时读取。
| 变量 | CLI | 默认值 | 说明 |
|---|---|---|---|
QUEENSCOACH_HTTP_HOST | --host | 127.0.0.1 | 绑定地址。 |
QUEENSCOACH_HTTP_PORT | --port | 8000 | 绑定端口。 |
QUEENSCOACH_PUBLIC_URL | --public-url | http://localhost:<port> | 外部源;OAuth 发行者。 |
QUEENSCOACH_GOOGLE_CLIENT_ID | 必需 | 来自 Google Cloud 凭据。 | |
QUEENSCOACH_GOOGLE_CLIENT_SECRET | 必需 | 来自 Google Cloud 凭据。 | |
QUEENSCOACH_ALLOWED_EMAILS | — | 允许的地址,以逗号或空格分隔。 | |
QUEENSCOACH_ALLOWED_DOMAINS | — | 允许的裸域名,例如 example.com。 | |
QUEENSCOACH_ALLOW_ANY_GOOGLE_ACCOUNT | false | 选择允许所有 Google 账号登录。 | |
QUEENSCOACH_TLS_CERT | --tls-cert | — | PEM 证书链,用于直接提供 HTTPS 服务。 |
QUEENSCOACH_TLS_KEY | --tls-key | — | PEM 私钥。必须与上项一起设置。 |
QUEENSCOACH_ACCESS_TOKEN_TTL_MS | 3600000 | 访问令牌有效期。 | |
QUEENSCOACH_REFRESH_TOKEN_TTL_MS | 2592000000 | 刷新令牌有效期。 | |
QUEENSCOACH_TOKEN_STORE | memory | memory,或 firestore(需要 gcp extra)。 | |
QUEENSCOACH_FIRESTORE_DATABASE | (default) | 用于令牌存储的 Firestore 数据库。 | |
QUEENSCOACH_STATELESS_HTTP | false | 在无 MCP 会话的情况下提供服务,适用于重启和多实例部署。 |
必须设置三个允许列表选项中的一个;见上文。
目录结构
| 模块 | 作用 |
|---|---|
config.py | 环境变量解析和验证 |
feed_http.py | 有界、限时的 HTTP 获取 |
cache.py | 带 TTL 缓存和 single-flight 刷新的缓存 |
gtfs_csv.py | 读取 GTFS 格式的 CSV |
static_gtfs.py | 静态时刻表:线路、站点、行程、时刻表及服务日历 |
realtime.py | GTFS-Realtime protobuf 解码 |
transit.py | 领域层:将实时数据与时刻表关联,解析查询 |
timetable.py | 已发布时刻表的领域层:服务日、出发时间、线路模式 |
planner.py | 行程规划:在时刻表上执行 Connection Scan,并考虑实时延误 |
tools.py | 工具的行为和 JSON 载荷 |
resources.py | 作为 MCP 资源提供的 GTFS 数据源 |
server.py | MCP 工具和资源注册及架构 |
oauth.py | OAuth 授权服务器,使用 Google 登录 |
token_store.py | OAuth 状态的存储位置及内存默认实现 |
token_store_firestore.py | Firestore 令牌存储(仅限 gcp extra) |
http.py | Streamable HTTP 传输和 Google 回调路由 |
main.py | CLI 入口和传输方式选择 |
此外,scripts/install.sh 可将 HTTP
传输部署到 Debian 主机;scripts/deploy-gcp.sh
与 Dockerfile 可将其部署到 Google Cloud Run。
开发
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest # offline, against recorded feed fixtures
.venv/bin/mypy # strict
.venv/bin/ruff check .
.venv/bin/ruff format .
测试使用从实时数据源捕获的 protobuf 和 GTFS 测试数据,因此结果确定且不会发起网络请求。GTFS 测试数据是从真实归档中截取的精简内容:29 路公交、蓝线和金线的行程、这些线路停靠的站点,以及完整的服务日历。实时数据捕获于工作日傍晚,因此可以据此规划从蓝线换乘金线的路线。例外是 tests/test_feed_http.py:它通过本地回环套接字提供预设响应,以真实测试字节数上限和超时。
tests/test_http.py 会通过真实的 ASGI 应用完成整个 OAuth 握手流程——注册、/authorize、Google 回调、/token,然后进行经过身份验证的 tools/list 调用;Google 的令牌端点由存根替代,因此无需账号或网络。
tests/test_token_store.py 会使用两种存储运行每项令牌存储测试。Firestore 部分需要模拟器(运行 gcloud emulators firestore start,然后设置 FIRESTORE_EMULATOR_HOST),未启用模拟器时会跳过。tests/test_stdio.py 会在子进程中启动真正的 stdio 服务;CI 还会使用普通的 pip install . 运行该测试,以证明 stdio 无需任何可选依赖。
许可证
MIT——详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。