mcpField
C
Charlotte Area Transit (CATS)

Charlotte Area Transit (CATS)

远程服务
github.com地图与出行05 周前更新

关于 Charlotte Area Transit (CATS)

QueensCoach 是面向出行者和交通信息客户端的 MCP 服务,提供 Charlotte Area Transit System 的公交与轻轨数据。它结合行程规划和实时数据,涵盖时刻表、线路、车辆位置及服务提醒。

主要功能

  1. 01规划含步行和换乘的行程
  2. 02查询实时到站信息和延误
  3. 03查看站点时刻表与线路详情
  4. 04查询服务提醒和交通中断
  5. 05查找站点并追踪车辆
  6. 06提供静态及实时 GTFS 资源

适用场景

  1. 01规划地点之间的公交和铁路路线
  2. 02查询站点的预计到站时间
  3. 03查看指定日期的发车时刻
  4. 04查找附近车站或运营中的车辆

MCP 相关

基于公开时刻表和 GTFS-Realtime 数据,向 MCP 客户端提供 CATS 交通工具和 GTFS 资源。支持 stdio 与 Streamable HTTP;托管 HTTP 服务使用 Google OAuth。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://queenscoach.adamwanninger.com/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

安装包
pypiqueenscoach2.1.1

工具

详细介绍

QueensCoach ♔♘

CI

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 付费方案。

  1. 打开设置 → 连接器。网页版可访问 claude.ai/settings/connectors;桌面应用中,依次打开“设置”和“连接器”。
  2. 点击列表底部的添加自定义连接器。
  3. 将其命名为 QueensCoach,并将上方的 URL 粘贴到远程 MCP 服务 URL 中。OAuth 高级字段留空:此服务会自动注册你的客户端。
  4. 点击添加,然后点击出现的连接器上的连接。浏览器窗口会打开 Google 登录页面;批准后窗口会自动关闭。
  5. 在聊天中打开工具菜单,并确认 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_stopstring出发地点:站点 ID、代码或名称。
origin_latitude、origin_longitudenumber也可以从某个地点出发,步行前往附近站点。
destination_stopstring目的地:站点 ID、代码或名称。
destination_latitude、destination_longitudenumber也可以在某个地点结束行程。
dateYYYY-MM-DD夏洛特当地的服务日期(默认今天)。
depart_atHH:MM不早于此时间出发。默认:现在。
arrive_byHH:MM或不晚于此时间到达。
max_transfersinteger0 到 3(默认 2)。
max_walk_metersinteger前往首站或从末站出发的最长步行距离,100 到 2000 米(默认 800 米)。

最多返回三条行程方案,每条均包含步行和乘车路段:线路、车辆实际终点、上下车地点、时间、每次换乘的等待时间,以及途经站点。只有在换乘次数更多的方案到达更早时,才会提供这类方案(若指定 arrive_by,则需出发更晚)。出发时间在当前时间三小时以内的行程会附带实时延误信息,并标记为 live。如果两地之间的距离在步行限制范围内,则会显示 walkingIsAnOption。

步行距离为估算值:直线距离乘以 1.3,按每小时 4.5 公里计算。数据源不包含街道地图,因此实际步行距离可能更长。换乘时允许步行最多 400 米,并预留两分钟缓冲时间。

get_arrivals
参数类型说明
stopstring站点 ID(02400)、站点代码或站点名称的一部分(CTC Station)。
latitude、longitudenumber不指定 stop 时,使用该地点最近的车站。
routestring可选的线路筛选条件。
modebus | train可选的交通方式筛选条件。
limitinteger最多返回的到站信息数量(默认 10,上限 50)。

指定 stop 或地点其中之一。指定地点时,筛选条件也会影响所选车站:mode: train 会查找最近的火车停靠站,而非距离更近的公交站;响应中还会包含其 metersAway。返回预计到站时间(分钟)、预计和计划时间、时刻表偏差、车辆编号、站台(stopId)以及车辆的实时位置。如果站点名称查询存在歧义,则使用最佳匹配项,并在 otherStopsMatchingQuery 下列出其他匹配项。影响该站点或其线路的当前服务提醒会作为 serviceAlerts 附上,格式与 get_service_alerts 返回的格式相同。若查询下一小时左右之后的时间,请使用 get_schedule。

get_schedule
ArgumentTypeNotes
stopstring站点 ID、代码或名称。
latitude, longitudenumber或选择服务于该路线或交通方式的最近站点。
routestring可选的路线筛选条件。
modebus | train可选的筛选条件。
dateYYYY-MM-DD服务日期(默认为今天)。
after, beforeHH:MM时间范围。after 默认为今天当前时间,或服务开始时间。
limitinteger最多显示的发车次数(默认为 20,上限为 100)。

列出计划发车时间、每趟车次的路线和目的地,以及当天的 firstDeparture 和 lastDeparture。与 GTFS 一样,服务日会延续至午夜之后:周二最后一班列车于周三凌晨 1:31 发车,而在 after 或 before 中,25:30 表示当晚凌晨 1:30。实时预测请使用 get_arrivals。

get_route
ArgumentTypeNotes
routestring必填。 9、501、Blue Line、Airport。
dateYYYY-MM-DD服务日期(默认为今天)。

按方向列出目的地、按顺序排列的站点(遵循大多数车次使用的线路模式,并汇总其他模式)、首末班发车时间,以及清晨、早高峰、午间、晚高峰、傍晚和深夜的典型发车间隔(分钟)。还会列出接下来七天每天的车次数以及有效警报数量。如果查询匹配多个路线,则改为列出这些路线。

get_service_alerts
ArgumentTypeNotes
routestring提及该路线或其任一服务站点的警报。
stopstring提及该站点或服务该站点的任一路线的警报。
latitude, longitudenumber影响 800 m 范围内站点的警报。

最多返回一条;不指定条件时返回所有警报。不包含已结束的警报。每条警报包含其标题、描述、影响和原因,以及 CATS 提供的详细文本;说明警报是 active 还是 upcoming、其时间段(未设结束时间的警报显示为 untilFurtherNotice),以及其中提及的路线和站点。

list_stops
ArgumentTypeNotes
latitude, longitudenumber地点;结果按距离从近到远排列,并包含 metersAway。
querystring站点 ID、站点代码或站点名称的一部分。
routestring仅列出该路线服务的站点。
modebus | train仅列出提供该交通服务的站点,例如用 train 查找最近的铁路车站。
limitinteger站点数量上限(指定地点时默认为 10,不指定时默认为 250;上限为 250)。

每个站点都会列出其 stopIds、坐标、modes 和 routes(ID、编号、全名、交通方式):例如 501 · Light Rail - Lynx Blue Line、510 · CityLYNX Gold Line,或 29 这样的公交路线。没有计划车次停靠的站点不会列出;距离指定地点超过 50 km 的站点也不会返回。

list_vehicles
ArgumentTypeNotes
vehiclestring公交车或列车上显示的车辆编号,例如 2301、LRV307。
routestring路线:9、501、Blue Line、Mt. Holly Road。
modebus | train可选的筛选条件。
limitinteger最多返回的车辆数量(默认值和上限均为 250)。

所有参数均为可选;不指定参数时会返回所有正在运营的车辆。每辆车包含位置、朝向、速度、载客情况(CATS 目前不提供此信息)、车头显示的目的地,以及下一个计划停靠站。即使列表被截断,matches 和 countsByMode 仍会报告总数。

资源

面向需要数据本身的客户端和模型,提供工具背后的数据流。

URI类型内容
gtfs://staticJSON静态 GTFS 存档中的文件、文件大小和 URI,以及抓取时间。
gtfs://static/{file}CSV存档中的任意表格,内容与 CATS 发布的一致。routes.txt、stops.txt、trips.txt 和 stop_times.txt 也会单独列出。
gtfs://realtime/vehicle-positionsJSON解码后的 VehiclePositions 数据流。
gtfs://realtime/trip-updatesJSON解码后的 TripUpdates 数据流。
gtfs://realtime/alertsJSON解码后的 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 地址一律拒绝。

端点。

路径用途
/mcpMCP 端点。需要 Authorization: Bearer <token>。
/.well-known/oauth-protected-resource/mcp将客户端指向授权服务器。
/.well-known/oauth-authorization-server此服务的 OAuth 元数据。
/register动态客户端注册(RFC 7591)。
/authorize、/token、/revokeOAuth 端点。
/auth/google/callbackGoogle 返回用户的地址。

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 中(安装 gcp extra:pip install 'queenscoach[gcp]'),这样登录状态可在重启后保留,并由所有实例共享。请同时设置 QUEENSCOACH_STATELESS_HTTP=true,以便任何实例都能响应任何请求。
  • 访问 token 的有效期为一小时,刷新 token 的有效期为 30 天;每次刷新时,两者都会轮换。

数据源

实时数据(GTFS-Realtime protobuf,每 20s 刷新一次):

  • https://gtfsrealtime.ridetransit.org/GTFSRealTime/Vehicle/VehiclePositions.pb
  • https://gtfsrealtime.ridetransit.org/GTFSRealTime/TripUpdate/TripUpdates.pb
  • https://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_URLCATS 车辆位置 Feed
QUEENSCOACH_TRIP_UPDATES_URLCATS 行程更新 Feed
QUEENSCOACH_ALERTS_URLCATS 告警 Feed
QUEENSCOACH_STATIC_GTFS_URLCATS 静态 GTFS zip
QUEENSCOACH_REALTIME_TTL_MS20000
QUEENSCOACH_STATIC_TTL_MS21600000
QUEENSCOACH_REQUEST_TIMEOUT_MS30000
QUEENSCOACH_MAX_FEED_BYTES33554432
QUEENSCOACH_MAX_STATIC_BYTES268435456

Feed URL 必须使用 http 或 https;否则会在启动时被拒绝。

传输方式
变量CLI默认值
QUEENSCOACH_TRANSPORT--transportstdio
HTTP 传输

仅在选择 --transport http 时读取。

变量CLI默认值说明
QUEENSCOACH_HTTP_HOST--host127.0.0.1绑定地址。
QUEENSCOACH_HTTP_PORT--port8000绑定端口。
QUEENSCOACH_PUBLIC_URL--public-urlhttp://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_ACCOUNTfalse选择允许所有 Google 账号登录。
QUEENSCOACH_TLS_CERT--tls-cert—PEM 证书链,用于直接提供 HTTPS 服务。
QUEENSCOACH_TLS_KEY--tls-key—PEM 私钥。必须与上项一起设置。
QUEENSCOACH_ACCESS_TOKEN_TTL_MS3600000访问令牌有效期。
QUEENSCOACH_REFRESH_TOKEN_TTL_MS2592000000刷新令牌有效期。
QUEENSCOACH_TOKEN_STOREmemorymemory,或 firestore(需要 gcp extra)。
QUEENSCOACH_FIRESTORE_DATABASE(default)用于令牌存储的 Firestore 数据库。
QUEENSCOACH_STATELESS_HTTPfalse在无 MCP 会话的情况下提供服务,适用于重启和多实例部署。

必须设置三个允许列表选项中的一个;见上文。

目录结构

模块作用
config.py环境变量解析和验证
feed_http.py有界、限时的 HTTP 获取
cache.py带 TTL 缓存和 single-flight 刷新的缓存
gtfs_csv.py读取 GTFS 格式的 CSV
static_gtfs.py静态时刻表:线路、站点、行程、时刻表及服务日历
realtime.pyGTFS-Realtime protobuf 解码
transit.py领域层:将实时数据与时刻表关联,解析查询
timetable.py已发布时刻表的领域层:服务日、出发时间、线路模式
planner.py行程规划:在时刻表上执行 Connection Scan,并考虑实时延误
tools.py工具的行为和 JSON 载荷
resources.py作为 MCP 资源提供的 GTFS 数据源
server.pyMCP 工具和资源注册及架构
oauth.pyOAuth 授权服务器,使用 Google 登录
token_store.pyOAuth 状态的存储位置及内存默认实现
token_store_firestore.pyFirestore 令牌存储(仅限 gcp extra)
http.pyStreamable HTTP 传输和 Google 回调路由
main.pyCLI 入口和传输方式选择

此外,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。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。