360 Secure SkillHub
360 安全技能中心

alphaportal-mcp

核心流程为一次性从已登录的AlphaPortal网页提取8天有效期的刷新令牌,即可兑换30分钟访问令牌,通过curl直连平台API,查询关联学生信息、校车站点、实时GPS位置、到离站通知等数据,也支持相关配置修改。适合不想部署MCP服务、需要在脚本或未安装MCP的设备上获取校车数据的用户,提供两种令牌提取方式、调用模板与端点参考,注意写操作无二次确认,直接生效。

chrischall
chrischall
热度 60.09
最近更新 2026-10-10 07:28:28
分类:开发依赖:代码执行 / 第三方 API应用场景:API 集成 / 自动化脚本 / 工作流

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add alphaportal-mcp
Metadata
name
alphaportal-fpx
description
Access AlphaPortal (AlphaRoute) school-bus data — students, stops, live bus GPS location, arrival notifications — from a shell with curl instead of running the alphaportal-mcp server. Capture the signed-in web app's refresh token ONCE (a paste-in-console one-liner, or the fpx browser bridge), then mint access tokens and curl the REST API directly. Use when you want AlphaPortal data without the MCP, in a script, or on a machine where the MCP isn't installed.

AlphaPortal via curl (no MCP, no runtime bridge)

AlphaPortal's app (e.g. cmsnc.alphaportal.app — the cmsnc subdomain is the school district) has no bot wall on its API (api.alpharoute.app): once you hold a token, plain curl does every call — no browser extension at runtime. Login itself is reCAPTCHA-gated and can't be scripted, so the credential is the refresh token the web app stores in your signed-in browser. It's an 8-day, reusable JWT; from it you mint a 30-minute access token with one unauthenticated POST (no reCAPTCHA, no MFA).

So the flow is: capture the refresh token once → mint an access token → curl.

1. Capture the refresh token (once; repeat when it expires after ~8 days)

Option A — paste-in-console (no fpx needed). In a signed-in AlphaPortal tab, open DevTools → Console and run:

JSON.parse(localStorage.user).User.RefreshToken

Copy the value into your shell:

export ALPHAPORTAL_RT='<paste the refresh token>'

Option B — fpx browser bridge (needs the ContextMint Bridge extension — from https://github.com/nullnet-app/contextmint-bridge/releases; Chrome: load the chrome zip unpacked; Safari isn't available yet, so use Chrome for now — plus a signed-in *.alphaportal.app tab). ContextMint Bridge is the fetchproxy extension renamed, same maintainer; source is public at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256:

npm install -g @fetchproxy/cli                              # provides `fpx`
fpx profile add alphaportal --domain alphaportal.app
fpx profile declare alphaportal --local-storage user       # declare scope BEFORE first pairing
fpx local-storage user -p alphaportal                      # first call prints a pair code → approve in ContextMint Bridge
export ALPHAPORTAL_RT=$(fpx local-storage user -p alphaportal | jq -r '.user | fromjson | .User.RefreshToken')

2. Mint an access token (each session, or when the last one is >30 min old)

export ALPHAPORTAL_TOKEN=$(
  curl -s -X POST https://api.alpharoute.app/AlphaCore/v1/public/refresh-token \
    -H 'Content-Type: application/json' \
    -d "{\"refreshToken\":\"$ALPHAPORTAL_RT\"}" | jq -r '.data.token'
)

If ALPHAPORTAL_TOKEN is null, the refresh token is expired/invalid — re-capture it (step 1).

3. Core call pattern

Every read is a GET with the bearer token; the envelope is {success,data,message}, so pipe .data to jq.

alpha() { curl -s "https://api.alpharoute.app/$1" -H "Authorization: Bearer $ALPHAPORTAL_TOKEN"; }

# your students (grab each studentId here first)
alpha AlphaPortal/v1/user-students/list | jq '.data.students[] | {studentId, name, gradeName}'

# live bus GPS for a student's PM run (shift 0=AM, 1=PM)
alpha AlphaPortal/v1/user-students/vehicle-location/218652901/1 | jq '.data.location'

# arrival/departure notifications
alpha AlphaPortal/v1/notifications/list | jq '.data.notifications[] | {title, body, creationDate}'

See references/endpoints.md for the full endpoint list, path variables, and ready-to-run jq recipes.

Status codes

  • 401 — the access token expired (re-run step 2) or the refresh token died (re-capture, step 1).
  • 400 with developerMessage — a required param is missing (e.g. a path studentId, or studentId/radius on a write).
  • success:false in a 200 body — the API rejected the request; read .developerMessage / .message.

Writes

Write endpoints (radius-edit, setnotification) exist and change real transportation records; the alphaportal-mcp server gates them behind a confirmation (a prompt, or a preview plus a one-time confirm token). This shell skill has no preview or confirmation — curl just does it — so treat every write as real and permanent. Request bodies are in references/endpoints.md. The transportation-request submission flow is deliberately undocumented here (its body was not fully verified).