Ccnu Lib
БесплатноНе проверен封装华中师范大学图书馆空间预约系统(包括登录、查座位、预约、取消、暂离等操作)为一组MCP工具,供LLM调用执行。
Описание
封装华中师范大学图书馆空间预约系统(包括登录、查座位、预约、取消、暂离等操作)为一组MCP工具,供LLM调用执行。
README
华中师范大学图书馆空间预约 MCP 服务。它把"登录图书馆 → 查座位 → 约/取消 → 暂离/回座/退座"这一整套网页操作,封装成一组可被 LLM 调用的 MCP 工具。
技术上:纯 HTTP 实现,无浏览器——直接复刻 CAS SSO 登录链拿到会话,再直连后端 JSON API(Python 现算 HMAC 签名)完成查询与预约。登录态靠持久化 cookie(CASTGC)静默续登保活。
关键约束
- 真实预约系统:
https://kjyy.ccnu.edu.cn/jsq-v/(Vue SPA,统一身份认证 CAS 登录)。 - 仅校园网内可访问 —— 部署机器必须在校园网内,否则页面不可达。
- 验证码 / 短信验证走人工输入(截图 base64 回传给用户看),不做自动识别。
1. 职责边界
本服务只是预约执行器,不理解自然语言、不主动提醒用户、不做定时调度。那些由调用方(小青团)负责。
| 小青团(MCP client) | mcp-ccnu-lib(本服务) | |
|---|---|---|
| 理解用户意图、管理身份映射 | ✅ | ❌ |
| 保存预约计划 / 偏好 / 提醒策略 | ✅ | ❌ |
| 定时触发预约、签到前提醒、超时自动退座 | ✅ | ❌ |
| 判断哪些动作需要确认 / 预授权 | ✅ | ❌ |
| 保存图书馆登录态(cookie+token)、账号 | ❌ | ✅ |
| 处理验证码 / 短信挑战 | ❌ | ✅ |
| 查座位、提交预约、取消、暂离/回座/退座 | ❌ | ✅ |
一句话:小青团决策,本服务执行。高风险动作(约/取消/退座等)由小青团做确认与预授权,本服务只负责把动作真实落到网站上。
2. 部署(Docker,推荐)
镜像基于轻量 python:3.12-slim(纯 HTTP,无 Chromium,体积小),本地 docker compose 一键构建运行。
2.1 服务器目录建议
把本仓库克隆到服务器,.env 与 data/ 都落在仓库目录里,便于备份与迁移:
ccnu-library-mcp/ # 克隆下来的本仓库
├── docker-compose.yml
├── Dockerfile
├── pyproject.toml
├── src/ # 服务代码
├── .env # 你创建:账号等机密(不入库)
└── data/ # 首次启动自动生成,持久化登录态
├── ccnu_lib.sqlite # accounts / sessions / challenges
└── users/<user_key>/
├── session.json # cookie(含 CASTGC) + app token,跨重启静默 SSO 保活
└── screenshots/ # 验证码图
2.2 初始化
git clone <本仓库地址> ccnu-library-mcp
cd ccnu-library-mcp
cp .env.example .env
# 按下方模板编辑 .env(账号可选;也可启动后用 save_account 工具传入)
2.3 生产 .env 最小模板
MCP_HOST=0.0.0.0
MCP_PORT=8010
DATA_DIR=/data
DEFAULT_USER_KEY=default
# 验证码人工输入超时秒数
CHALLENGE_TTL_SECONDS=240
# 可选:default 测试用户的默认账号(留空则用 save_account 工具传入)
CCNU_DEFAULT_USERNAME=你的学号
CCNU_DEFAULT_PASSWORD=你的密码
docker-compose.yml会用environment覆盖DATA_DIR、MCP_*等非机密项,所以.env里真正必须填的只有账号。登录入口(CAS/VUE 地址)运行时从后端getSysSet取,无需在.env配。
2.4 启动
docker compose up -d --build
docker compose logs -f # 看启动日志
docker compose ps # 确认容器 healthy
服务监听 http://<服务器IP>:8010/mcp(传输 streamable-http)。
data/ 已挂载为 volume,重启容器免重新登录(session.json 里的 CASTGC 支持静默 SSO)。升级代码后重新 docker compose up -d --build 即可,登录态保留。
2.5 本地开发(不走 Docker)
pip install -e . # httpx + cryptography + mcp,无浏览器
cp .env.example .env
python -m ccnu_lib.server # 监听 0.0.0.0:8010/mcp
本地用 MCP client 连
127.0.0.1时若设了系统代理,需NO_PROXY=127.0.0.1,localhost,否则 502。
3. MCP 接入(小青团侧)
传输为 streamable-http,端点 http://<host>:8010/mcp。
{
"mcpServers": {
"ccnu_library": {
"transport": "http",
"url": "http://ccnu-library-mcp:8010/mcp",
"tool_prefix": "ccnu_",
"high_risk_tools": [
"save_account", "reserve_seat", "cancel_reservation",
"start_temporary_leave", "return_from_temporary_leave",
"end_reservation_early"
]
}
}
}
3.1 user_key(多用户隔离)
所有工具都接受可选 user_key。小青团应传 user_key = person_id,这样一个人的 QQ / 微信 / CLI 共用同一份图书馆登录态与偏好。不传则用 default(仅测试)。每个 user_key 独立保存 session.json(cookie+token)与账号。
3.2 challenge 交互(关键机制)
challenge 不是登录专属,而是贯穿所有工具的通用中断模型:任何动作执行到一半遇到图形验证码时,工具不阻塞,而是挂起当前登录流程并返回:
{
"ok": false, "code": "NEED_CHALLENGE",
"challenge_id": "ch_xxx", "challenge_type": "captcha",
"prompt": "请输入图形验证码",
"image_base64": "data:image/jpeg;base64,....", // captcha 才有(CAS 验证码 jpg)
"phone_hint": "尾号1234", // sms 才有(纯 HTTP 下短信暂未实现)
"expires_at": "2026-06-25T12:30:00+08:00"
}
小青团应:把 image_base64 原样发给用户看 → 收集用户输入 → 调 submit_challenge(challenge_id, answer) 续跑同一个流程,直到 logged_in:true 或原动作完成。
challenge_type取值:captcha(图形)/sms(短信)/confirm_send_sms(提交任意值确认发短信)/manual_login。- challenge 有超时(默认 240s),过期需重新发起原动作。
- 同一
user_key同一时刻只应有一个挂起 challenge;存在挂起时再发起新动作会返回CHALLENGE_PENDING。 - 内存中的挂起会话在进程重启后丢失,所有
pendingchallenge 视为失效,需重新发起。
4. 工具 API(全量)
4.1 通用约定
user_key:所有工具都接受可选user_key,不传则用default(见 §3.1)。下文各工具不再重复列出此参数。- 时间:
date=YYYY-MM-DD,start_time/end_time=HH:MM(步长 30 分钟,范围约 07:30–22:00,start_time必须早于end_time)。 - 返回:所有工具返回一个对象,必含
ok(bool)。失败时ok:false且含code(机器可判)+message(人读)。下文"错误码"列的是该工具特有的code。 - 登录前置:除登录类工具外,所有工具内部会先确保登录态(有 token 直接用,否则尝试 SSO 复登);仍未登录则返回
NEED_LOGIN,调用方应转去start_login。
4.2 速查表
| 工具 | 主要参数 | 说明 | 高风险 |
|---|---|---|---|
save_account |
username, password, phone_hint?, login_now? | 保存账号(明文,个人自用),覆盖旧值 | ✅ |
get_login_status |
— | 实地探测登录态(含自动 SSO 复登) | |
start_login |
username?, password? | 发起登录,可能返回 NEED_CHALLENGE |
|
submit_challenge |
challenge_id, answer | 提交验证码/短信,续跑挂起流程 | |
get_availability_distribution |
date, start_time, end_time, library?, area_filter? | 各区域可用座位分布(按空闲降序) | |
list_available_seats |
date, start_time, end_time, location_id, area_filter?, limit? | 某区域具体可用座位 | |
get_seat_layout |
location_id | 区域座位平面图(网页版布局透传 + 扁平座位表) | |
reserve_seat |
date, start_time, end_time, seat_id?, location_id?, strategy? | 提交预约 | ✅ |
cancel_reservation |
reservation_id? | 取消未开始预约(缺省取当前有效) | ✅ |
get_current_reservation |
— | 当前预约 + 状态 + 暂离详情 | |
start_temporary_leave |
reservation_id? | 暂离(网页按钮镜像;正常暂离过闸机自动,见下) | ✅ |
return_from_temporary_leave |
reservation_id? | 回座(同上,正常回座过闸机自动) | ✅ |
end_reservation_early |
reservation_id? | 提前结束/退座(区别于取消未开始) | ✅ |
get_site_favorite_locations |
— | 网站常用/收藏座位 | |
get_violation_records |
page?, page_size? | 违约记录(爽约/暂离超时等),分页 | |
get_reservation_history |
page?, page_size? | 历史预约记录(过往全部),分页 | |
get_door_log |
date | 某天闸机进出记录(可靠判断在馆/暂离) |
登录类
save_account
保存图书馆账号密码(明文,个人自用),同 user_key 已存在则覆盖。
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
username |
str | 否¹ | .env 的 CCNU_DEFAULT_USERNAME |
学号 |
password |
str | 否¹ | .env 的 CCNU_DEFAULT_PASSWORD |
密码 |
phone_hint |
str | 否 | — | 手机号尾号提示,仅留存 |
login_now |
bool | 否 | false |
为 true 时保存后立即触发 start_login,返回其结果 |
¹
username/password入参缺省时回落到.env默认账号;两边都没有则报错。
成功:{ "ok": true, "user_key": "...", "message": "账号已保存" }(login_now:true 时返回 start_login 的结果)
错误码:MISSING_CREDENTIALS(无账号且无 .env 默认)
get_login_status
打开预约页实地探测登录态(被打回 CAS 即未登录),并刷新落盘 cookie。
成功:
{ "ok": true, "user_key": "...", "logged_in": true,
"status": "logged_in", "needs_challenge": false, "message": "当前登录态可用" }
status 取值:no_account / logged_in / logged_out / error。
start_login
发起登录。可带账号密码(会先保存)。遇验证码/短信时不阻塞,返回 NEED_CHALLENGE 挂起。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
username |
str | 否 | 传入则先保存再登录 |
password |
str | 否 | 同上 |
成功:{ "ok": true, "user_key": "...", "status": "logged_in", "logged_in": true, "message": "登录成功" }
挂起(需人工):
{ "ok": false, "code": "NEED_CHALLENGE",
"challenge_id": "ch_xxx", "challenge_type": "captcha",
"prompt": "请输入图形验证码",
"image_base64": "data:image/png;base64,....",
"phone_hint": "尾号1234",
"expires_at": "2026-06-25T12:30:00+08:00" }
challenge_type:captcha / sms / confirm_send_sms / manual_login(见 §3.2)。
错误码:CHALLENGE_PENDING(已有挂起 challenge)、NO_ACCOUNT、NAV_FAILED、AUTH_UNSETTLED、LOGIN_FORM_NOT_FOUND、LOGIN_FAILED(账号/验证码错,验证码已刷新需重发起)
submit_challenge
提交验证码/短信码,续跑被挂起的登录流程。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
challenge_id |
str | 是 | NEED_CHALLENGE 返回的 id |
answer |
str | 是 | 用户输入;confirm_send_sms 类型传任意值表示确认发短信 |
成功:返回登录成功结构(同 start_login 成功),或下一个 NEED_CHALLENGE(如确认发短信后转入 sms)。
错误码:CHALLENGE_NOT_FOUND、CHALLENGE_NOT_PENDING、SESSION_LOST(挂起会话超时/重启丢失,需重发起)、SUBMIT_FAILED、STILL_NOT_LOGGED_IN(manual_login 仍未完成)、LOGIN_FAILED
查询类
get_availability_distribution
返回各区域可用座位分布,按 available 降序。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
date / start_time / end_time |
str | 是 | 见通用约定 |
library |
str | 否 | 按建筑名包含过滤 |
area_filter |
str | 否 | 按区域名包含过滤 |
成功:
{ "ok": true, "date": "2026-06-25", "start_time": "08:00", "end_time": "12:00",
"locations": [
{ "location_id": "...", "path": ["逸夫图书馆","2F","安静区"],
"total": 120, "available": 34, "max_minute": 240 }
] }
错误码:BAD_TIME、NEED_LOGIN
list_available_seats
列出某区域指定时段的具体可用座位。
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
date / start_time / end_time |
str | 是 | — | 见通用约定 |
location_id |
str | 是 | — | 由 get_availability_distribution 取得 |
area_filter |
str | 否 | — | 按座位 label 包含过滤 |
limit |
int | 否 | 50 | 返回上限 |
成功:
{ "ok": true, "date": "2026-06-25", "location_id": "...",
"seats": [ { "seat_id": "...", "seat_no": "312", "name": "...",
"location_id": "...", "available": true } ] }
错误码:BAD_TIME、NEED_LOCATION、NEED_LOGIN
get_current_reservation
查询当前有效预约及状态。只在存在活跃预约(reserved / waiting_sign_in / in_use / away / violation_risk)时返回座位明细;否则返回干净的 none,不会回显已取消/已结束那条的座位信息——调用方判断"有没有座位"一律看 status,不要看 seat_no。
成功(无有效预约):{ "ok": true, "status": "none", "message": "当前无有效预约", "last_raw_status": "CANCEL" }(last_raw_status 仅排查用,为最近一条记录的后端原始状态,可能不存在)
成功(有预约):
{ "ok": true, "reservation_id": "...", "status": "away", "raw_status": "AWAY",
"seat_no": "312", "path": ["逸夫图书馆","2F","安静区"],
"date": "2026-06-25", "start_time": "08:00", "end_time": "12:00",
"receipt": "...", "raw_text": "...",
"away_deadline": "2026-06-25T10:15:00+08:00",
"away_raw": { "...": "..." },
"actual_begin": "...", "actual_end": null }
status 枚举:none / reserved / waiting_sign_in / in_use / away / ended / cancelled / violation / violation_risk / unknown。away_* 仅暂离/使用中时出现。
ended:正常用完 / 主动结束 / 管理员改判完成(后端 rawSTOP)。violation:已发生的违约(后端 rawMISS爽约未签到 /LEAVE_EARLY暂离超时未归)。终态,不算活跃预约。violation_risk:进行中的违约风险(rawBREAK/VIOLATION等),仍算活跃。
错误码:NEED_LOGIN
get_site_favorite_locations
返回网站里的常用/收藏座位(原始结构,含 roomId/label/buildName/floorName/roomName 等)。成功:{ "ok": true, "favorites": [...] };错误码:NEED_LOGIN
get_seat_layout
透传网页版某区域的座位平面布局(Fabric.js 画布数据),并附一份扁平座位表方便辅助选座。参数 location_id(必填,取自 get_availability_distribution)。
{ "ok": true, "location_id": "1995338594917990400", "layout_version": "15",
"seat_count": 172,
"seats": [ { "seat_id": "2003722571020177408", "seat_no": "N1167",
"name": "1行1列", "direction": "top", "power": true,
"x": 33.0, "y": 148.0 } ],
"layout": { "version": "5.2.1", "objects": [...], "backgroundImage": {...} } }
seats:从画布抽出的扁平座位表(seat_id/seat_no/name行列/direction/power是否有电源/x,y画布坐标)——小青团可直接据此辅助选座,无需解析画布。layout:网页版原始 Fabric 画布对象(已剥掉后端尾部_updVersion_N标记并解析成对象),需要在前端渲染座位图时用;纯文字场景用seats即可。- 注意:该布局是静态座位表,不含实时空闲状态;查空闲仍用
list_available_seats(可与seats按seat_id关联)。
错误码:NEED_LOCATION、NEED_LOGIN
get_violation_records / get_reservation_history
分页拉取违约记录 / 历史预约记录。参数 page(默认 1)、page_size(默认 20)。
{ "ok": true, "page": 1, "page_size": 20, "total": 15, "count": 15,
"records": [ { /* 同 get_current_reservation 的记录结构:reservation_id/status/raw_status/seat_no/path/date/start_time/end_time/receipt/raw_text */ } ] }
total= 后端总条数(用于分页),count= 本页返回条数。- 每条
record复用统一映射:违约记录里raw_text常带原因(如"用户暂离超时未归, 预约释放"),status映射为violation;历史里正常完成的为ended、取消的为cancelled。 - 小青团可用
get_violation_records的total做违约次数提醒。
错误码:NEED_LOGIN
get_door_log
某天(date=yyyy-MM-dd,必填)的闸机进出记录。
{ "ok": true, "date": "2026-07-01", "count": 2, "in_building": false,
"events": [ { "time": "2026-07-01 15:17:14", "gate": "南湖二楼中出", "direction": "out", "raw_direction": 1 },
{ "time": "2026-07-01 15:12:44", "gate": "南湖二楼右入", "direction": "in", "raw_direction": 0 } ] }
events按时间倒序(首条最新);direction:in(进=raw_direction 0) /out(出=1)。in_building:由首条方向推断当前是否在馆(true=在馆)。- 为何需要:实测物理暂离(走闸机出馆)不会实时改预约状态——
get_current_reservation仍是in_use、awayTimeM仍 0(系统疑似回馆才结算离馆时长)。所以小青团判断"用户在不在馆/是否暂离"要靠这个接口,不能只看预约状态。
错误码:NEED_LOGIN
预约类(高风险)
reserve_seat
提交预约。strategy 缺省:传了 seat_id 则 exact_seat,否则 first_available。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
date / start_time / end_time |
str | 是 | 见通用约定 |
seat_id |
str | 否 | exact_seat 必填 |
location_id |
str | 否 | 非 exact_seat 策略必填(用于自动选座) |
strategy |
str | 否 | 见下 |
strategy 取值:
exact_seat—— 必须约指定seat_idfirst_available—— 区域内第一个可用(需location_id,默认)random_available—— 可用中随机(需location_id)favorite_first—— 收藏座位优先,无收藏命中则退回第一个可用(需location_id)
成功:
{ "ok": true, "reservation_id": "...", "status": "reserved", "raw_status": "RESERVE",
"seat_no": "312", "path": ["逸夫图书馆","2F","安静区"],
"date": "2026-06-25", "start_time": "08:00", "end_time": "12:00",
"receipt": "...", "raw_text": "..." }
错误码:BAD_TIME、NEED_LOGIN、NEED_LOCATION、NO_SEAT(该时段无空闲)、RESERVE_FAILED
cancel_reservation
取消预约。不传 reservation_id 时自动取当前活跃预约。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
reservation_id |
str | 否 | 缺省取当前活跃预约 |
成功:{ "ok": true, "reservation_id": "...", "status": "cancelled" }
错误码:NEED_LOGIN、NO_ACTIVE(无可取消)、CANCEL_FAILED
start_temporary_leave / return_from_temporary_leave / end_reservation_early
在馆状态操作,均对当前预约生效。
| 工具 | 成功 status |
成功附加 | 错误码 |
|---|---|---|---|
start_temporary_leave |
away |
away_deadline / away_raw(暂离截止) |
NEED_LOGIN、LEAVE_FAILED |
return_from_temporary_leave |
in_use |
— | NEED_LOGIN、RETURN_FAILED |
end_reservation_early |
ended |
— | NEED_LOGIN、END_FAILED |
成功结构:{ "ok": true, "status": "away", "message": "...", "raw": {...} }(raw 为后端原始返回,若有)。
重要(真机确认):暂离 / 回座 实际是过闸机自动触发的——走出馆=自动暂离、走回馆=自动回座,用户根本不点按钮。因此:
start_temporary_leave/return_from_temporary_leave只是网页手动按钮的镜像,不是暂离/回座的正常路径,小青团一般不用调;且物理暂离不会实时改预约状态(get_current_reservation仍显示in_use、awayTimeM仍 0)。- 要判断用户是否暂离/已回座,用
get_door_log轮询(最后一条out=已出馆暂离,in=在馆),而不是看预约状态。end_reservation_early(make/stop提前退座)已真机验证可用:在馆外in_use时调用会正常结束(终态ended,不产生违约)。三个工具与
cancel_reservation都接受可选reservation_id,但当前实现以"当前预约"为准操作,reservation_id主要用于调用方自查比对。
对接交互流程(小青团侧,已真机实测 2026-06-30)
下面是把本服务真正驱动起来的完整交互方式。两条闭环都已在校园网真机跑通(登录含图形验证码、预约 / 取消 / 重订)。
A. 登录闭环(带 challenge 的通用模式)
登录态会过期;任何业务工具内部会先尝试静默 SSO 复登,复登失败才返回 NEED_LOGIN,此时转登录闭环:
start_login
└─ ok:true → 已登录,继续业务
└─ NEED_CHALLENGE(captcha/sms) → 把 image_base64 发给用户看,收用户输入
└─ submit_challenge(challenge_id, answer)
└─ ok:true → 登录成功
└─ NEED_CHALLENGE(...) → 还有下一步挑战(如确认发短信→输短信码),循环
└─ LOGIN_FAILED → 账号/验证码错;验证码已刷新,需重新 start_login
要点(实测结论):
- 挑战图就是验证码那一小张(已裁剪,非整页),
image_base64原样转发用户即可。 - 同一
user_key同一时刻只允许一个挂起 challenge;存在挂起时其它动作返回CHALLENGE_PENDING。 - 挂起态在内存,服务进程重启即失效,需重新发起;challenge 也有
CHALLENGE_TTL_SECONDS超时。 - 刚登录过、cookie 新鲜时,下次通常能静默 SSO 免验证码。
B. 预约 / 取消闭环
get_availability_distribution(date,start,end, library?/area_filter?) → 选区域 location_id
list_available_seats(location_id) → 选 seat_id(或交给 strategy 自动选)
reserve_seat(seat_id 或 location_id+strategy) → 返回 reservation_id / seat_no / receipt
get_current_reservation() → 轮询状态、读签到窗口、暂离提醒
cancel_reservation() # 不传 id 自动取当前活跃预约(已实测)
或 end_reservation_early() # 使用中提前退座
关键字段语义(供小青团做提醒/判断):
reserve_seat/get_current_reservation成功结构里的raw_text携带签到窗口,如"请在 07:30 至 08:30 之间完成签到"——小青团据此设签到提醒。- 判断"当前有没有座位"只看
status:none即无有效预约(此时不应读seat_no/receipt,那些字段已被清掉)。 seat_no形如N1143(馆区前缀 + 4 位),receipt形如3533-0072-N1143,每次预约都会变。- 取消后该预约
raw_status变CANCEL,get_current_reservation即回status:none。
5. 环境变量(.env)
| 变量 | 默认 | 说明 |
|---|---|---|
MCP_HOST / MCP_PORT |
0.0.0.0 / 8010 | 服务监听 |
DATA_DIR |
./data | 数据目录(容器内为 /data) |
DEFAULT_USER_KEY |
default | 不传 user_key 时的兜底键 |
CHALLENGE_TTL_SECONDS |
240 | 验证码人工输入超时 |
CCNU_DEFAULT_USERNAME / _PASSWORD |
— | 可选:default 用户默认账号 |
6. 数据与安全
- 第一版按个人自用实现:账号密码明文保存,无加密 / 审计 / 权限系统。
.env、data/、scripts/_probe_out/已在.gitignore与.dockerignore,不入库、不进镜像。- 同一
user_key同一时刻只允许一个活动任务(Session.lock串行化),避免两个定时任务同时操作同一登录态。 - 数据目录结构见 §2.1。
7. 已知边界
- 仅校园网内可用;登录态靠持久化 cookie(CASTGC) 静默 SSO 保活,失效时重新触发图形验证码登录。异地登录风控的短信验证在纯 HTTP 下尚未实现(真机触发后再补)。
- 签到 / 暂离 / 回座物理上由进出馆闸机自动触发(真机确认):进馆自动签到、出馆自动暂离、再进馆自动回座,用户不点按钮。且物理暂离不实时改预约状态——判断在馆/暂离用
get_door_log轮询,别看get_current_reservation状态。网页手动按钮的镜像start_temporary_leave/return_from_temporary_leave仅备用,正常流程用不到;end_reservation_early(提前退座)已真机验证可用。 - 续约官方要求到现场预约终端刷卡,网页端无入口,本服务不提供。
- 违约红线:每月 3 次违约进黑名单一周。自动取消 / 退座的预授权与确认由小青团控制,本服务只执行,不判断。
8. 验证脚本(scripts/)
| 脚本 | 用途 |
|---|---|
smoke_mcp.py |
通过 MCP 协议冒烟(连服务、列工具、跑只读流程) |
try_login.py / try_api.py / try_reserve.py / probe_*.py / dump_signing.py |
⚠️ Playwright 时代的登录/鉴权/接口反推脚本,纯 HTTP 重构后已失效,仅作历史参考 |
重构后真机验证改用临时脚本直接调
login.start_login/submit_challenge/reservations.*(走文件握手输验证码)。
9. 免责声明
- 本项目仅供个人学习与自用,用于自动化操作本人在华中师范大学图书馆的合法预约权限,不提供任何绕过学校系统规则的能力(不做验证码自动识别、不做虚假签到、不做位置伪造)。
- 使用者须对自己的账号行为负责,遵守学校图书馆的预约与违约规则。因使用本项目导致的违约、封禁或其他后果,由使用者自行承担,作者不承担任何责任。
- 本项目与华中师范大学及其图书馆无任何隶属或合作关系,所涉站点与接口的所有权归校方所有。学校系统若调整,本项目可能随时失效。
10. 许可证
MIT © 2026 mcp-ccnu-lib contributors
Установка Ccnu Lib
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/cxdpowered/mcp-ccnu-libFAQ
Ccnu Lib MCP бесплатный?
Да, Ccnu Lib MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Ccnu Lib?
Нет, Ccnu Lib работает без API-ключей и переменных окружения.
Ccnu Lib — hosted или self-hosted?
Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.
Как установить Ccnu Lib в Claude Desktop, Claude Code или Cursor?
Открой Ccnu Lib на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
автор: modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
автор: xuzexin-hzCompare Ccnu Lib with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории ai
