Skip to main content
Glama

bb-mcp

License: MIT Platform Python

A Model Context Protocol (MCP) server for the CUHK-SZ Blackboard instance (bb.cuhk.edu.cn, Blackboard Learn Classic 3900). Let your AI assistant download courseware, inspect assignments, read announcements, and submit homework — fully headless, no browser window ever pops up.

一个给 AI 助手用的中大(港中深)Blackboard MCP 工具:课件下载、作业查看与提交、公告阅读。 全程无浏览器窗口,凭据只存本机。中文说明见下方 中文说明

⚠️ For personal productivity only. Use responsibly and follow your institution's IT policies. Don't hammer the server; don't automate anything that violates academic integrity rules.

Tools (9)

Tool

What it does

bb_login()

Headless login using cred.json (template auto-generated on first run)

bb_status()

Session check; auto re-login once with stored credentials if expired

bb_list_courses()

List all your courses

bb_list_course_files(course)

List every file in a course's content area (newest first)

bb_download_courseware(course, keyword, latest)

Download the latest courseware to <output dir>/<course>/

bb_list_assignments(course)

List assignment/test entry links (with visible dates)

bb_assignment_details(course, keyword, download)

Scan all content areas for assignments: summary, due date, submission-entry status, attachment download

bb_announcements(course, limit)

Read announcements (course="all" scans every course)

bb_submit_assignment(course, assignment, file_path, confirm)

Submit homework — two-phase: dry-run by default, confirm=true actually submits

Every tool auto-re-authenticates when the session expires, and tells you explicitly to update cred.json when your password has changed.

Related MCP server: MUSTer MCP Server

Requirements

  • Python 3.10+

  • A Claude Code / MCP-compatible client

  • A bb.cuhk.edu.cn account

Install

git clone https://github.com/changshenhan/bb-mcp.git
cd bb-mcp

python -m venv venv
# Windows
venv\Scripts\pip install -r requirements.txt
# macOS / Linux
venv/bin/pip install -r requirements.txt

# Install Chromium (goes to Playwright's default cache)
venv\Scripts\playwright install chromium

requirements.txt pins mcp<2 (v2 renamed FastMCP and breaks the import) plus playwright.

Configure

1. Credentials — run any tool once and cred.json is generated next to server.py. Fill in your values:

{
  "username": "your_student_id",
  "password": "your_password"
}

The username may include @link.cuhk.edu.cn / @cuhk.edu.cn — the suffix is stripped automatically, same as the site's own login JS. The file stays on your machine and is git-ignored; never commit or share it.

2. Register with your MCP client (Claude Code example, see .mcp.json.example):

{
  "mcpServers": {
    "bb-cuhk": {
      "command": "<absolute path to venv python>",
      "args": ["<absolute path to>/bb-mcp/server.py"],
      "env": {
        "BB_OUTPUT_DIR": "C:\\path\\to\\your\\download\\folder"
      }
    }
  }
}

3. Optional environment variables

Variable

Default

Purpose

BB_OUTPUT_DIR

~/Desktop/BB-Courseware

Download root for courseware & attachments

PLAYWRIGHT_BROWSERS_PATH

Playwright default cache

Custom Chromium install location

BB_BASE_URL

https://bb.cuhk.edu.cn

Point at another Blackboard instance (see below)

Usage examples

Just talk to your assistant:

  • "Download the newest slide from my Computer Networks course"bb_download_courseware(course="Networks", latest=1)

  • "What assignments are due in the Graph Computing course?"bb_assignment_details(course="Graph")

  • "Check announcements for all courses"bb_announcements(course="all")

  • "Submit answer.md to the Topological Sort assignment" → dry-run first, then confirm=true

How the login works (for hackers)

The site's custom login page (a Blackboard bb-SSOIntegrationDemo building block) obfuscates its client-side crypto. Reversed, it is simply:

check():        password field  ← base64(pw)
validate_form(): encoded_pw         = base64(base64(pw))
                 encoded_pw_unicode = base64(utf16le(base64(pw)))   # md5.js chrsz=16
                 password field     ← ""
POST /webapps/bb-SSOIntegrationDemo-BBLEARN/execute/authValidate/customLogin?returnUrl=…
  fields: user_id, tstring (from page), pstring, encoded_pw, encoded_pw_unicode,
          action=login, one_time_token=false, ...

Two quirks worth knowing if you adapt this:

  • The site rejects plain Python OpenSSL TLS handshakes (curl works fine, so it is client-fingerprinting). All HTTP therefore goes through Playwright's APIRequestContext — the browser's own TLS stack — which also shares the cookie jar with the DOM session.

  • The failure page shows no error text at all (302 back to /, clean login form). Login success is therefore decided by a positive check: opening the portal tab and verifying it does not bounce to /webapps/login.

Porting to another school: flip BB_BASE_URL and try. If your instance uses the same custom-login building block it will work as-is; if it redirects to ADFS/Shibboleth you'll need to rewrite _http_login() against your login page's form fields.

Download dedup rules

  • Filename comes from content-disposition; when missing, the content item's display name + a content-type-derived extension is used.

  • A file is skipped when an identical filename (case-insensitive) or an identical byte size (>1 KB) already exists under the output root — manually renamed copies from previous downloads are recognised by size.

Self-test

python _mcp_selftest.py
# → handshake ok, tools: [... 9 tools ...]

Known limits

  • Built for Blackboard Classic (JSP pages). If your school switches to Ultra, _collect_files and the submission selectors need a rewrite.

  • File dates are scraped from YYYY-MM-DD text near the content item; undated items sort last.

  • The submission receipt is a page-text excerpt — always eyeball it after submitting.

Security

  • Credentials live only in ./cred.json (git-ignored), sessions only in ./profile/ (git-ignored). Nothing is sent anywhere except bb.cuhk.edu.cn itself.

  • bb_submit_assignment is two-phase by design: the default confirm=false call only opens the attempt page and returns an excerpt; nothing is submitted until you pass confirm=true.

中文说明

  1. pip install -r requirements.txt 后执行 playwright install chromium

  2. 首次运行任意工具,目录里会自动生成 cred.json,填入学号密码保存 (带不带 @link.cuhk.edu.cn 后缀都行)

  3. .mcp.json.example 抄进你项目根的 .mcp.json,路径改成你的 venv Python 和本目录 server.py 的绝对路径

  4. 之后对 Claude 说人话即可:「把网络课最新课件下下来」「看看有哪些作业待交」

  5. 改了学校密码?工具会明确提示「登录失败」,把新密码填回 cred.json 再跑

下载默认落到 ~/Desktop/BB-Courseware/<课程名>/,作业附件在 <课程名>/assignments/, 可用 BB_OUTPUT_DIR 环境变量改。

License

MIT

Related MCP Connectors

Related MCP Servers