360 Secure SkillHub
360 安全技能中心

pickuppatrol-mcp

这是校园接送平台PickUp Patrol的纯curl Shell调用方案,无验证码、无需浏览器桥接,适合脚本集成、无对应MCP服务的设备使用。支持账号登录鉴权,可查询学生信息、周默认接送计划、单日安排、学校接送规则与非上学日;可修改单日接送安排、重置为默认计划、调整周默认规则,接口返回JSON可配合jq处理,写入后需回读校验,避免超截止时间被静默忽略。

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

安装技能

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

执行命令安装此 skill: npx secure-skills-cli add pickuppatrol-mcp
Metadata
name
pickuppatrol-api
description
Read and change your children's school dismissal plans on PickUp Patrol (app.pickuppatrol.net) from a shell with curl — students, weekly defaults, day-by-day changes, school cutoff times.

PickUp Patrol from a shell

app.pickuppatrol.net is a ServiceStack JSON API behind an Ionic/Vue SPA. It is reachable server-side with plain curl — no bot wall, no captcha, no browser bridge. Use this when you want PickUp Patrol data in a script or on a machine without the pickuppatrol-mcp server.

Full captured shapes: references/api.md.

Sign in once per shell

export PUP_USER='you@example.com'
read -rs PUP_PASS && export PUP_PASS      # never put the password in a command line
export PUP=https://app.pickuppatrol.net/api/json/reply

pup_login() {
  local jar; jar=$(mktemp -t pupjar)
  curl -sS -c "$jar" -X POST "$PUP/Authenticate" \
    -H 'Content-Type: application/json' \
    -d "$(jq -nc --arg u "$PUP_USER" --arg p "$PUP_PASS" \
          '{provider:"credentials",UserName:$u,Password:$p,RememberMe:true}')" \
    -o /tmp/pup_auth.json -w '%{http_code}' >/tmp/pup_code
  [ "$(cat /tmp/pup_code)" = 200 ] || { jq -r '.ResponseStatus.Message' /tmp/pup_auth.json >&2; return 1; }
  export PUP_JAR="$jar"
  # This deployment returns cookies only — BearerToken comes back null. The
  # JWT path exists server-side, so keep a token if one ever appears.
  PUP_TOKEN=$(jq -r '.BearerToken // empty' /tmp/pup_auth.json); export PUP_TOKEN
}

# Every call goes through this: it sends the session cookies, and the bearer
# token as well when the deployment issued one.
pup() {
  local method=$1 dto=$2; shift 2
  local -a auth=(-b "$PUP_JAR")
  [ -n "$PUP_TOKEN" ] && auth+=(-H "Authorization: Bearer $PUP_TOKEN")
  curl -sS -X "$method" "$PUP/$dto" -H 'Content-Type: application/json' "${auth[@]}" "$@"
}

Never re-run a rejected login. PickUp Patrol answers bad credentials with ResponseStatus.ErrorCode starting LOGIN-ERROR, counts the attempt against the account, and a lockout clears only through their support desk. One failure = stop and fix the credentials.

Reads

pup GET GetSession | jq '{name:.DisplayName, email:.Email, kids:[.Children[].StudentId]}'
pup GET GetChildren | jq -r '.[] | "\(.StudentId)  \(.FirstName) — \(.SchoolName)"'

# Weekly default plan for one student. DayId is 1-based, SUNDAY = 1.
pup GET GetChildren | jq '.[] | select(.StudentId==1050046) | .DefaultPlans
  | sort_by(.DayId) | map({day:.WeekDayName, option:.TransportationName, note:.Note})'

# The dismissal options a school offers, with the rules each imposes.
pup GET "GetTransportations?SchoolId=1703" | jq -r '.[] | select(.IsActive)
  | "\(.TransportationId)\t\(.Name)\tnote=\(.IsNoteRequired)\tcar=\(.UseCarNumbers)\tearly=\(.IsEarlyDismissal)"'

# GetPlanEdit returns the date's OVERRIDE, not the effective plan: a date with
# no specific plan reads back null even when a weekday default exists.
pup GET "GetPlanEdit?PlanDate=2026-08-17&StudentId=1050046" | jq '{TransportationName,Note,IsLocked}'
pup GET "GetInvalidPlanDates?SchoolId=1703" | jq 'length'   # non-school days

Writes

Writes change how a child actually leaves school. Read GetTransportations first and obey the option's rules, or the request is rejected (or worse, silently ignored):

  • IsNoteRequired → Note must be non-empty
  • UseCarNumbers → send CarNumber; otherwise omit the key
  • IsEarlyDismissal → send EarlyDismissalTime as HH:MM:SS; otherwise omit it
  • IsLimited → only usable if the id is in the student's LimitedIds

Change specific dates — Plans is an array, one entry per date:

pup PUT UpdatePlans -d '{"Plans":[{
  "StudentId":1050046,"SchoolId":1703,"PlanDate":"2026-08-17",
  "TransportationId":41246,"TransportationName":"PickUp","Note":"Chris Hall"}]}'

Clear a date back to the weekly default — a null transportation:

pup PUT UpdatePlans -d '{"Plans":[{
  "StudentId":1050046,"SchoolId":1703,"PlanDate":"2026-08-17",
  "TransportationId":null,"TransportationName":"Default plan","Note":null}]}'

Change the weekly defaults — there is no default-plans endpoint. Read the whole student, edit DefaultPlans, PUT the whole record back (references/api.md has the read-modify-write recipe).

Always re-read to verify

A 2xx is not proof. The school silently ignores a change past its cutoff time.

pup GET "GetPlanEdit?PlanDate=2026-08-17&StudentId=1050046" | jq '.TransportationId'

Compare TransportationId and Note — never ModifiedDate, which advances on its own and would make every write look successful. The note matters: every option seen so far is IsNoteRequired, so a note-only edit is ordinary, and an id-only comparison would pass without observing it. After clearing a date, expect null — not the weekday default.