brightspace-mcp
v1.1.1
Published
MCP server for D2L Brightspace (multi-auth, opt-in writes, session cache)
Maintainers
Readme
brightspace-mcp
MCP server for D2L Brightspace. Gives Claude (and any MCP-compatible client) access to your courses, grades, assignments, content, calendar, and more — with multi-strategy authentication, full MFA support, and production-grade resilience built in.
Quick start
npx brightspace-mcp@latest setup # interactive wizard (recommended for first time)The interactive wizard handles everything: base URL, auth strategy, MFA, credential storage, and auto-registration with Claude Desktop / Cursor / Windsurf.
For CI pipelines or DevContainers with no TTY, use the non-interactive init command instead:
npx brightspace-mcp@latest init \
--base-url https://yourschool.brightspace.com \
--strategy api_token \
--token-ref env:BRIGHTSPACE_API_TOKENDocumentation
Deep-dive guides live in docs/ — start with docs/README.md.
| Topic | Doc |
|---|---|
| Setup walkthrough | docs/setup-guide.md |
| Auth strategies | docs/auth-strategies.md |
| Known-good presets (Microsoft AAD, etc.) | docs/presets.md |
| Write operations (submit, post, mark) | docs/writes.md |
| MCP tools reference | docs/tools.md |
| MCP Resources + Prompts | docs/tools.md#mcp-resources |
| Troubleshooting | docs/troubleshooting.md |
| Architecture (DDD) | docs/architecture.md |
| Register with MCP clients | docs/clients.md |
For AI assistants and contributors, AGENTS.md is a one-page map of the repo.
Table of contents
- Installation
- Authentication strategies
- MFA strategies
- Configuration reference
- Output: timezone and language
- Redis cache
- Write operations
- Available tools
- MCP Resources
- MCP Prompts
- Web UI dashboard
- Register with an MCP client
- CLI reference
- Docker
Installation
npx (recommended — no install needed)
npx brightspace-mcp@latest setup # first-time wizard
npx brightspace-mcp@latest serve # run the serverGlobal install
npm install -g brightspace-mcp
brightspace-mcp setup
brightspace-mcp serveFrom source
git clone https://github.com/JhostinAleck/brightspace-mcp.git
cd brightspace-mcp
npm install && npm run build
node build/cli/main.js serveRequirements: Node.js ≥ 20.
Authentication strategies
Pick the strategy that matches your Brightspace setup. Run npx brightspace-mcp@latest setup and it will walk you through the right one.
API Token (simplest)
Requires a Valence API token from your Brightspace admin panel.
profiles:
my_school:
base_url: https://school.brightspace.com
auth:
strategy: api_token
api_token:
token_ref: env:BRIGHTSPACE_API_TOKENexport BRIGHTSPACE_API_TOKEN="your-token"
npx brightspace-mcp@latest serveHeadless (username + password)
Automates HTTP-level login — no browser window. Supports all MFA strategies including Duo Push.
profiles:
my_school:
base_url: https://school.brightspace.com
auth:
strategy: headless
headless:
login_url: https://school.brightspace.com/d2l/login
username_ref: env:BRIGHTSPACE_USERNAME
password_ref: env:BRIGHTSPACE_PASSWORD
mfa:
strategy: duo_push # or: totp, manual_prompt, none
duo_push: {} # uses defaults: poll every 1s, timeout 120sBrowser (Playwright)
Launches a headless Chromium instance and automates the login UI. Best for SSO flows (Microsoft Azure AD, SAML) where the login page has complex JavaScript.
npm install playwright && npx playwright install chromiumauth:
strategy: browser
browser:
login_url: https://school.brightspace.com/d2l/login
headless: true
username_ref: env:BRIGHTSPACE_USERNAME
password_ref: env:BRIGHTSPACE_PASSWORD
selectors:
username: "#i0116"
password: "#i0118"
submit: "#idSIButton9"
password_submit: "#idSIButton9"
mfa_input: "#idTxtBx_SAOTCC_OTC"
mfa_submit: "#idSubmit_SAOTCC_Continue"
post_login: "d2l-labs-navigation"
mfa:
strategy: totp
totp:
secret_ref: env:BRIGHTSPACE_TOTP_SECRETThe setup wizard includes a Microsoft SSO preset that fills all selectors automatically.
Session Cookie
Paste the D2L session cookies from your browser's DevTools. Useful when other strategies are blocked.
auth:
strategy: session_cookie
session_cookie:
cookie_ref: env:BRIGHTSPACE_COOKIE
session_ttl_seconds: 3600# Cookie format: "d2lSessionVal=XXX; d2lSecureSessionVal=YYY"
export BRIGHTSPACE_COOKIE="d2lSessionVal=...; d2lSecureSessionVal=..."MFA strategies
| Strategy | When to use |
|---|---|
| none | No MFA on your account |
| totp | Authenticator app (Google Authenticator, Authy, etc.) |
| duo_push | Duo Security — server polls for mobile approval automatically |
| manual_prompt | Any TOTP/OTP — server pauses and asks you to paste the code |
TOTP example
mfa:
strategy: totp
totp:
secret_ref: env:BRIGHTSPACE_TOTP_SECRET # base32 secret from QR code setup
digits: 6 # 6 or 8
period: 30 # seconds
algorithm: SHA1 # SHA1, SHA256, or SHA512Duo Push example
mfa:
strategy: duo_push
duo_push:
poll_interval_ms: 1000 # how often to check (default: 1000)
timeout_ms: 120000 # give up after this many ms (default: 120000)Configuration reference
Full config file (~/.brightspace-mcp/config.yaml):
default_profile: my_school
profiles:
my_school:
base_url: https://school.brightspace.com
auth:
strategy: api_token # api_token | browser | headless | session_cookie | oauth
api_token:
token_ref: env:BRIGHTSPACE_API_TOKEN
session:
cache_backend: memory # memory | file | redis
preemptive_refresh_seconds: 300
output:
tz: America/Bogota # IANA timezone; default: auto-detected from system
locale: es-419 # en-US | es-419 | pt-BR | fr-CA; default: auto-detected
format: markdown # markdown (default) | plain
include_meta_footer: true
logging:
level: info # debug | info | warn | error
writes:
enabled: false
dry_run: false
# Optional — required when session.cache_backend: redis
redis:
url: redis://localhost:6379
key_prefix: "brightspace:"Credential references
Secret values are never stored in plain text. Use ref: notation to point to the actual value:
| Prefix | Example | Description |
|---|---|---|
| env:NAME | env:BRIGHTSPACE_API_TOKEN | Read from environment variable |
| keychain:service/account | keychain:brightspace-mcp/token | OS keychain (macOS Keychain, GNOME Keyring, Windows Credential Manager) |
| file:label | file:api_token | Encrypted file (~/.brightspace-mcp/credentials.enc, AES-256-GCM) |
Output: timezone and language
All tool responses are formatted in your configured timezone and language.
output:
tz: America/Bogota # IANA name; default: auto-detected from system
locale: es-419 # en-US | es-419 | pt-BR | fr-CA; default: auto-detected
format: markdown # markdown (default) | plain
include_meta_footer: trueRun brightspace-mcp setup and choose your timezone and language. Or set it in ~/.brightspace-mcp/config.yaml.
Redis cache
When running multiple instances or want cache persistence across restarts, enable Redis:
1. Add the redis section to config:
redis:
url: redis://localhost:6379
key_prefix: "brightspace:"
profiles:
my_school:
session:
cache_backend: redis2. Install ioredis (optional dependency):
npm install ioredis3. Start Redis and the server:
docker run -d -p 6379:6379 redis:7-alpine
npx brightspace-mcp@latest serveThe domain cache (courses, grades, assignments, etc.) automatically uses Redis as persistent layer when the redis: section is present in config. Session tokens are stored with TTL derived from the token expiry.
Write operations
Write tools (submit_assignment, post_discussion_reply, mark_announcement_read) are disabled by default and require two separate opt-ins:
1. Config file:
writes:
enabled: true
dry_run: false # set true to preview without mutating D2L2. CLI flag:
npx brightspace-mcp@latest serve --enable-writesAll write operations:
- Require a client-supplied
idempotency_key(8–128 chars). Repeat calls with the same key return the cached response without re-executing. - Emit a WARN-level audit log line with correlation ID, tool name, and redacted args.
- Respect
dry_run: trueto return a preview response without touching D2L.
Available tools
Read tools (always available)
| Tool | Description |
|---|---|
| check_auth | Verify authentication and show the active user identity |
| list_my_courses | List all enrolled courses |
| get_my_grades | Get grades for a course |
| get_assignments | List assignments and dropbox folders |
| get_assignment_files | Download and read instructor-posted assignment files |
| get_upcoming_due_dates | List assignments due in the next N days |
| get_feedback | Read instructor feedback on submitted assignments |
| get_syllabus | Fetch the course syllabus |
| get_course_content | Browse modules and topics (includes topic IDs) |
| get_topic_file | Download and read a content topic file (DOCX, PDF, HTML, plain text) |
| get_announcements | List course announcements |
| get_discussions | Browse discussion forums and threads |
| get_calendar_events | List calendar events in a date range |
| get_roster | Get the full course roster |
| get_classlist_emails | Get classmate email addresses |
| get_my_groups | List group enrollments per course with member rosters |
| list_quizzes | List quizzes with attempt counts, time limits, due dates |
| get_quiz_attempts | Your attempts on a quiz with scores and timestamps |
| list_notifications | User activity feed (announcements, due-date reminders, grade releases) |
| search_course | Full-text search across content, announcements, and discussions |
| get_audit_log | Local history of write operations (correlation IDs, redacted args) |
| get_diagnostics | Show cache stats, circuit breaker state, and version info |
| clear_cache | Clear memory and persistent cache backends |
Write tools (require --enable-writes)
| Tool | Description |
|---|---|
| submit_assignment | Upload a file to a Brightspace Dropbox folder |
| post_discussion_reply | Reply to a discussion thread |
| mark_announcement_read | Mark an announcement as read |
MCP Resources
Four stable URIs for Brightspace content (readable by any MCP client via resources/read):
| URI | Content |
|---|---|
| brightspace://{courseId}/syllabus | Course syllabus, HTML stripped |
| brightspace://{courseId}/content/topics/{topicId} | Topic file (text extracted from PDF, or base64 fallback) |
| brightspace://{courseId}/assignments/{assignmentId}/files | All assignment attachments as text |
| brightspace://{courseId}/announcements/{announcementId} | Announcement text |
Obtain IDs from tools like list_my_courses, get_assignments, get_announcements.
MCP Prompts
Four pre-built prompt templates visible in your MCP client's prompt picker:
| Prompt | Arguments | Purpose |
|---|---|---|
| weekly_briefing | none | 7-day overview: due dates, announcements, recent grades |
| grade_audit | course_id? | Grade analysis + what you need to pass |
| study_planner | days_ahead? (default 7) | Study plan from due dates and calendar |
| course_summary | course_id (required) | Full course overview |
Web UI dashboard
brightspace-mcp ui # open at http://localhost:9876
brightspace-mcp ui --open # open browser automatically
brightspace-mcp ui --port 8080 # custom portProvides: auth status, upcoming due dates, grades, announcements, config editor (form + YAML), cache stats, audit logs, diagnostics. Dark/light mode, tooltips on all fields.
Register with an MCP client
See docs/clients.md for Claude Desktop, Cursor, and Windsurf snippets, or run brightspace-mcp setup which auto-detects and registers for you.
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"brightspace": {
"command": "npx",
"args": ["--yes", "brightspace-mcp@latest", "serve"],
"env": {
"BRIGHTSPACE_CONFIG": "/Users/you/.brightspace-mcp/config.yaml"
}
}
}
}CLI reference
npx brightspace-mcp@latest setup Interactive first-time setup wizard (detects system language)
npx brightspace-mcp@latest init [flags] Non-interactive config writer (CI/scripts, no TTY)
npx brightspace-mcp@latest serve Start the MCP server (stdio transport)
npx brightspace-mcp@latest serve --enable-writes Start with write tools enabled
npx brightspace-mcp@latest ui [--port 9876] [--open] Local web dashboard at http://localhost:9876
npx brightspace-mcp@latest auth Re-authenticate and test the config
npx brightspace-mcp@latest record-auth Open browser for manual login, capture session cookies
npx brightspace-mcp@latest doctor End-to-end smoke test: config → auth → API → list_my_courses
npx brightspace-mcp@latest profile list List profiles (* marks the default)
npx brightspace-mcp@latest profile use <name> Switch the default profile
npx brightspace-mcp@latest config show Print config (secrets redacted)
npx brightspace-mcp@latest config show --resolved Show all secret refs as [redacted]
npx brightspace-mcp@latest config validate Validate config schema without running
npx brightspace-mcp@latest config set <path> <value> Edit a nested config value
npx brightspace-mcp@latest cache clear Clear memory + file/Redis cache
npx brightspace-mcp@latest cache clear --context <n> Clear a specific cache context
npx brightspace-mcp@latest upgrade Upgrade brightspace-mcp to the latest versionDocker
Standalone
docker pull ghcr.io/jhostinaleck/brightspace-mcp:latest
docker run --rm -i \
-v "$HOME/.brightspace-mcp:/config:ro" \
-e BRIGHTSPACE_CONFIG=/config/config.yaml \
ghcr.io/jhostinaleck/brightspace-mcp:latest serveWith Redis (docker-compose)
# Start server + Redis
docker compose --profile redis up
# Or standalone (in-memory cache)
docker compose upThe config.yaml inside ~/.brightspace-mcp/ must have the redis: section pointing to redis://redis:6379 when using the compose profile.
Architecture highlights
- Resilience: retry with exponential backoff + jitter, circuit breaker (5 failures → 30s cooldown), request coalescing, bulkhead (max 5 concurrent requests)
- Cache tiers: HTTP response cache (L1, in-memory, 60s TTL) + domain cache (L2, layered memory → file or Redis)
- Security: HTTPS-only transport, secrets redaction in all log output, OS keychain integration, AES-256-GCM encrypted credential file, session tokens expire with the D2L token
- DDD structure: bounded contexts (
assignments,authentication,calendar,communications,content,courses,grades,groups,notifications,quizzes) with clean domain / application / infrastructure separation
License
MIT © Jhostin Aleck
