公交线路查询工具

MCP Buses Coruña是一个封装了iTranvias API的公交线路查询工具,提供完整的线路、站点目录和实时到站信息查询功能。

  • by cjescudero
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 cjescudero/mcp-buses-coruna

使用说明

MCP巴士Coruña

A Corunia有轨电车公司使用的Itranvias API的MCP包装。它在不优先考虑或隐藏站点或行的情况下暴露:

  • 来自本地版本快照的完整线路、路线和站点目录;
  • 由其标识符指示的站点的实时到达(func=0).

它包括一个嵌入式应用程序,可以通过 stdio 或HTTP流媒体。它不会保留它来自的应用程序的功能配置:没有主要站点、兴趣线或业务默认值。

在正常执行中, list_bus_lines y search_stops 不要访问iTransvias。服务器在启动时从磁盘加载目录,并为 show_bus_arrivals。因此,避免了整个结构的重复下载,减轻了供应商的负担,即使API暂时降级,搜索也仍然可用。

要求和调试

  • Node.js 20.19后版本。
  • 对于可复制的安装,请使用 npm ci (没有 npm install).
npm ci
npm test
npm run build
npm run serve

默认传输是 stdio,适用于在本地运行流程的MCP客户。只有到达查询需要网络访问。

工具

  • list_bus_lines:返回本地目录中的所有行。每一行包括 line_id, line_name, origin, destination, color_hex 以及他们的旅程 routes (route_id, origin, destination y stop_ids).
  • search_stops:返回站点目录或按名称或标识符筛选。 query 它是可选的,并且 limit 支持1到400之间的值。
  • show_bus_arrivals:返回指定站点的到达人数。 stopId 这是强制性的。

答案包括文本和 structuredContent。这三种工具都包含 structuredContent.catalog,骗子 schema_version, generated_at, line_count y stop_count;这样就可以准确地确定支持结果的快照。不存在的停止或提供程序故障作为工具错误返回(isError: true).

本地目录

分布式目录 data/transit-catalog.json 包含线路、路线和站点的标准副本。它与代码一起进行版本控制,在启动时进行验证,在执行过程中不会修改。传输网络的更改需要更新该文件并部署新版本,但不需要更改MCP的代码或结构。

要使用另一个兼容的快照而不重新编译:

CATALOG_PATH=/ruta/al/transit-catalog.json npm run serve

CATALOG_PATH 它必须指向具有相同规范化架构的文件。日期 generated_at 南非 structuredContent.catalog.generated_at 在工具和 generated_at en /health,允许检测过时的部署。

手动更新

更新是一个显式的维护操作,而不是服务器的自动任务:

npm run update:catalog
npm test

更新程序通过 func=7,验证并规范响应,并以原子方式替换快照。如果下载或验证失败,则保留以前的目录不变。在确认和部署文件之前,应检查差异-线路、路线和站点的高低。

不透明值 dato=20160101T000000_gl_0_20160101T000000 de la URL func=7 这是iTransvias请求完整快照所需的参数。实际API回答说,如果省略参数,则这些参数无效。因此,该值是供应商协议的一部分,不表示MCP的日期、停止、行或业务偏好。

更新程序的独占变量:

变量 默认 描述
CATALOG_SOURCE_URL URL itranvias func=7 使用的HTTP源 npm run update:catalog
CATALOG_PATH data/transit-catalog.json 快照的目的地;它还用作运行时的覆盖
CATALOG_TIMEOUT_SECONDS 20 最大下载时间,在1到120秒之间

CATALOG_SOURCE_URL y CATALOG_TIMEOUT_SECONDS 它们不会在运行时读取。不要在MCP的每个实例上配置定期更新:只进行一次,检查结果并分发经过验证的快照。

到达和运行时设置

在运行时,唯一的远程操作是 func=0。您可以通过 ARRIVALS_URL_TEMPLATE标记 {stop_id} 这是强制性的。

Itranvias目前将查询限制在每秒1次和每分钟4次。服务器对每个进程应用这些限制,重复同一停止的同时请求,并将新鲜读取保存15秒。如果供应商暂时被阻止,它最多可以提供120秒的最后一次有效读取,标记为 source: "stale" 你知道吗 fetched_at 原创。他从不重新计算或编造分钟。

变量 默认 限制
CATALOG_PATH data/transit-catalog.json 标准化和可读的本地快照
ARRIVALS_URL_TEMPLATE https://itranvias.com/queryitr_v3.php?func=0&dato={stop_id} URL HTTP(S)连接 {stop_id}
HTTP_TIMEOUT_SECONDS 8 1至120之间的数字
ARRIVALS_CACHE_TTL_SECONDS 15 重复使用有效读取的时间,介于0到300之间
ARRIVALS_STALE_TTL_SECONDS 120 最后一次可用读取的最长时间,最多3600秒
ITRANVIAS_MIN_INTERVAL_MS 1100 外部请求之间的最小间隔
ITRANVIAS_MAX_REQUESTS_PER_MINUTE 4 每个进程节点的全局最大值

该小部件不会自动更新:当您选择一个站点时以及当您按下时进行查询 更新。这可以防止多个对话本身耗尽供应商的限制。如果在同一IP下部署多个进程或副本,则在代理或共享存储上协调边界。

作为ChatGPT应用程序的集成

该模板使用版本化的URI来防止ChatGPT保留以前的包。 search_stops 它是一个公共工具,不会打开小部件;独自一人 show_bus_arrivals 它链接到交互式模板。

资源声明没有直接连接的CSP(connectDomains y resourceDomains 空),因为该包是自我拥有的,仅通过MCP桥访问服务器。该小部件的域被配置为源,没有路径:

变量 默认 描述
WIDGET_DOMAIN https://escudero.gtec.udc.es ChatGPT分配给小部件的专用源

要发布多个应用程序,请使用不同的子域,例如每个子域都有DNS/TLS https://buses-coruna.escudero.gtec.udc.es。更改HTML、CSS或JavaScript后,会增加 APP_RESOURCE_URI en server.ts 在ChatGPT中重新创建应用程序版本之前。

传输HTTP

MCP_TRANSPORT=http npm run serve
  • MCP: http://127.0.0.1:3001/mcp
  • 健康检查: http://127.0.0.1:3001/health

HTTP配置:

变量 默认 描述
HOST 127.0.0.1 听力界面;美国 0.0.0.0 只有在适当的代理或隔离之后
PORT 3001 有效TCP端口
MCP_ALLOWED_ORIGINS 环回起源 允许起源的CSV列表
MCP_ALLOWED_HOSTS 主机环回y HOST CSV值列表 Host 允许的
MCP_AUTH_TOKEN sin令牌 定义如下, /mcp 要求 Authorization: Bearer …
MCP_RATE_LIMIT_PER_MINUTE 120 IP限制; 0 禁用它

服务器验证 Origin y Host 降低DNS重新绑定的风险。不要在生产中使用开放的CORS。如果您在团队外暴露MCP,请在代理上配置TLS、强令牌、确切的起源和主机,并保留速率限制。

烟雾测试HTTP

启动HTTP服务器:

./scripts/test-mcp-connection.sh

脚本检查 /health 并发送MCP请求 initialize 真正的a /mcp。对于另一个目的地或受保护的服务器:

BASE_URL=https://mcp.example.org \
ORIGIN=https://cliente.example.org \
MCP_AUTH_TOKEN='token-secreto' \
./scripts/test-mcp-connection.sh

使用SystemD和Nginx部署

安装和编译应用程序,例如,在 /opt/mcp-buses-coruna:

cd /opt/mcp-buses-coruna
npm ci
npm test
npm run build

文件 /etc/mcp-buses-coruna.env:

MCP_TRANSPORT=http
HOST=127.0.0.1
PORT=3001
CATALOG_PATH=/opt/mcp-buses-coruna/data/transit-catalog.json
HTTP_TIMEOUT_SECONDS=8
WIDGET_DOMAIN=https://escudero.gtec.udc.es
MCP_ALLOWED_ORIGINS=https://cliente.example.org
MCP_ALLOWED_HOSTS=mcp.example.org
MCP_AUTH_TOKEN=cambia-este-token
MCP_RATE_LIMIT_PER_MINUTE=120

保护该文件,因为它包含令牌:

sudo chown root:root /etc/mcp-buses-coruna.env
sudo chmod 600 /etc/mcp-buses-coruna.env

单元 /etc/systemd/system/mcp-buses-coruna.service:

[Unit]
Description=MCP Buses Coruña
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/mcp-buses-coruna
EnvironmentFile=/etc/mcp-buses-coruna.env
ExecStart=/usr/bin/npm run serve
Restart=on-failure
RestartSec=3
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

已配置TLS的Nginx代理:

server {
    listen 443 ssl http2;
    server_name mcp.example.org;

    location = /mcp {
        proxy_pass http://127.0.0.1:3001/mcp;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_read_timeout 300s;
    }

    location = /health {
        proxy_pass http://127.0.0.1:3001/health;
        proxy_set_header Host $host;
    }
}

安装或更新后:

sudo systemctl daemon-reload
sudo systemctl enable --now mcp-buses-coruna
sudo systemctl status mcp-buses-coruna
journalctl -u mcp-buses-coruna -f

远程客户端必须使用的URL是 https://mcp.example.org/mcp.没有用 localhost 从服务器以外的机器。

开发和验证

npm run build:app       # bundle único de la app MCP
npm run build:server    # TypeScript del servidor
npm run build           # ambos
npm test                # build y pruebas sin depender de la red pública

集成测试使用临时目录和模拟到达API来通过 stdio:发现,UI资源,快照元数据,没有优先级的目录,搜索,到达顺序和错误。他们还验证没有正常通话试图下载 func=7.