Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Ccnu Lib

БесплатноНе проверен

封装华中师范大学图书馆空间预约系统(包括登录、查座位、预约、取消、暂离等操作)为一组MCP工具,供LLM调用执行。

GitHubEmbed

Описание

封装华中师范大学图书馆空间预约系统(包括登录、查座位、预约、取消、暂离等操作)为一组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 服务器目录建议

把本仓库克隆到服务器,.envdata/ 都落在仓库目录里,便于备份与迁移:

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_DIRMCP_* 等非机密项,所以 .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
  • 内存中的挂起会话在进程重启后丢失,所有 pending challenge 视为失效,需重新发起。

4. 工具 API(全量)

4.1 通用约定

  • user_key:所有工具都接受可选 user_key,不传则用 default(见 §3.1)。下文各工具不再重复列出此参数。
  • 时间date = YYYY-MM-DDstart_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 否¹ .envCCNU_DEFAULT_USERNAME 学号
password str 否¹ .envCCNU_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_typecaptcha / sms / confirm_send_sms / manual_login(见 §3.2)。 错误码CHALLENGE_PENDING(已有挂起 challenge)、NO_ACCOUNTNAV_FAILEDAUTH_UNSETTLEDLOGIN_FORM_NOT_FOUNDLOGIN_FAILED(账号/验证码错,验证码已刷新需重发起)

submit_challenge

提交验证码/短信码,续跑被挂起的登录流程。

参数 类型 必填 说明
challenge_id str NEED_CHALLENGE 返回的 id
answer str 用户输入;confirm_send_sms 类型传任意值表示确认发短信

成功:返回登录成功结构(同 start_login 成功),或下一个 NEED_CHALLENGE(如确认发短信后转入 sms)。 错误码CHALLENGE_NOT_FOUNDCHALLENGE_NOT_PENDINGSESSION_LOST(挂起会话超时/重启丢失,需重发起)、SUBMIT_FAILEDSTILL_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_TIMENEED_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_TIMENEED_LOCATIONNEED_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 / unknownaway_* 仅暂离/使用中时出现。

  • ended:正常用完 / 主动结束 / 管理员改判完成(后端 raw STOP)。
  • violation已发生的违约(后端 raw MISS 爽约未签到 / LEAVE_EARLY 暂离超时未归)。终态,不算活跃预约。
  • violation_risk:进行中的违约风险(raw BREAK/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(可与 seatsseat_id 关联)。

错误码NEED_LOCATIONNEED_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_recordstotal 做违约次数提醒。

错误码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 按时间倒序(首条最新);directionin(进=raw_direction 0) / out(出=1)。
  • in_building:由首条方向推断当前是否在馆(true=在馆)。
  • 为何需要:实测物理暂离(走闸机出馆)不会实时改预约状态——get_current_reservation 仍是 in_useawayTimeM 仍 0(系统疑似回馆才结算离馆时长)。所以小青团判断"用户在不在馆/是否暂离"要靠这个接口,不能只看预约状态。

错误码NEED_LOGIN


预约类(高风险)

reserve_seat

提交预约。strategy 缺省:传了 seat_idexact_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_id
  • first_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_TIMENEED_LOGINNEED_LOCATIONNO_SEAT(该时段无空闲)、RESERVE_FAILED

cancel_reservation

取消预约。不传 reservation_id 时自动取当前活跃预约。

参数 类型 必填 说明
reservation_id str 缺省取当前活跃预约

成功{ "ok": true, "reservation_id": "...", "status": "cancelled" } 错误码NEED_LOGINNO_ACTIVE(无可取消)、CANCEL_FAILED

start_temporary_leave / return_from_temporary_leave / end_reservation_early

在馆状态操作,均对当前预约生效。

工具 成功 status 成功附加 错误码
start_temporary_leave away away_deadline / away_raw(暂离截止) NEED_LOGINLEAVE_FAILED
return_from_temporary_leave in_use NEED_LOGINRETURN_FAILED
end_reservation_early ended NEED_LOGINEND_FAILED

成功结构:{ "ok": true, "status": "away", "message": "...", "raw": {...} }raw 为后端原始返回,若有)。

重要(真机确认)暂离 / 回座 实际是过闸机自动触发的——走出馆=自动暂离、走回馆=自动回座,用户根本不点按钮。因此:

  • start_temporary_leave / return_from_temporary_leave 只是网页手动按钮的镜像,不是暂离/回座的正常路径,小青团一般不用调;且物理暂离不会实时改预约状态get_current_reservation 仍显示 in_useawayTimeM 仍 0)。
  • 要判断用户是否暂离/已回座,用 get_door_log 轮询(最后一条 out=已出馆暂离,in=在馆),而不是看预约状态。
  • end_reservation_earlymake/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 之间完成签到"——小青团据此设签到提醒。
  • 判断"当前有没有座位"只看 statusnone 即无有效预约(此时不应读 seat_no/receipt,那些字段已被清掉)。
  • seat_no 形如 N1143(馆区前缀 + 4 位),receipt 形如 3533-0072-N1143,每次预约都会变。
  • 取消后该预约 raw_statusCANCELget_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. 数据与安全

  • 第一版按个人自用实现:账号密码明文保存,无加密 / 审计 / 权限系统。
  • .envdata/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

from github.com/cxdpowered/mcp-ccnu-lib

Установка Ccnu Lib

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/cxdpowered/mcp-ccnu-lib

FAQ

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

Compare Ccnu Lib with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории ai