{
  "markdown": "# brightspace-mcp\n\n[![CI](https://github.com/JhostinAleck/brightspace-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/JhostinAleck/brightspace-mcp/actions/workflows/ci.yml)\n[![Docs](https://github.com/JhostinAleck/brightspace-mcp/actions/workflows/docs.yml/badge.svg)](https://jhostinaleck.github.io/brightspace-mcp/)\n[![npm version](https://img.shields.io/npm/v/brightspace-mcp.svg)](https://www.npmjs.com/package/brightspace-mcp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE)\n[![Node.js](https://img.shields.io/node/v/brightspace-mcp.svg)](./package.json)\n\n📖 **[Full documentation site →](https://jhostinaleck.github.io/brightspace-mcp/)**\n\nMCP 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.\n\n---\n\n## Quick start\n\n```bash\nnpx brightspace-mcp@latest setup   # interactive wizard (recommended for first time)\n```\n\nThe interactive wizard handles everything: base URL, auth strategy, MFA, credential storage, and auto-registration with Claude Desktop / Cursor / Windsurf.\n\nFor CI pipelines or DevContainers with no TTY, use the non-interactive `init` command instead:\n\n```bash\nnpx brightspace-mcp@latest init \\\n  --base-url https://yourschool.brightspace.com \\\n  --strategy api_token \\\n  --token-ref env:BRIGHTSPACE_API_TOKEN\n```\n\n---\n\n## Documentation\n\nDeep-dive guides live in [`docs/`](./docs/) — start with [`docs/README.md`](./docs/README.md).\n\n| Topic | Doc |\n|---|---|\n| Setup walkthrough | [`docs/setup-guide.md`](./docs/setup-guide.md) |\n| Auth strategies | [`docs/auth-strategies.md`](./docs/auth-strategies.md) |\n| Known-good presets (Microsoft AAD, etc.) | [`docs/presets.md`](./docs/presets.md) |\n| Write operations (submit, post, mark) | [`docs/writes.md`](./docs/writes.md) |\n| MCP tools reference | [`docs/tools.md`](./docs/tools.md) |\n| MCP Resources + Prompts | [`docs/tools.md#mcp-resources`](./docs/tools.md#mcp-resources) |\n| Troubleshooting | [`docs/troubleshooting.md`](./docs/troubleshooting.md) |\n| Architecture (DDD) | [`docs/architecture.md`](./docs/architecture.md) |\n| Register with MCP clients | [`docs/clients.md`](./docs/clients.md) |\n\nFor AI assistants and contributors, [`AGENTS.md`](./AGENTS.md) is a one-page map of the repo.\n\n---\n\n## Table of contents\n\n- [Installation](#installation)\n- [Authentication strategies](#authentication-strategies)\n- [MFA strategies](#mfa-strategies)\n- [Configuration reference](#configuration-reference)\n- [Output: timezone and language](#output-timezone-and-language)\n- [Redis cache](#redis-cache)\n- [Write operations](#write-operations)\n- [Available tools](#available-tools)\n- [MCP Resources](#mcp-resources)\n- [MCP Prompts](#mcp-prompts)\n- [TUI dashboard](#tui-dashboard)\n- [Register with an MCP client](#register-with-an-mcp-client)\n- [CLI reference](#cli-reference)\n- [Docker](#docker)\n\n---\n\n## Installation\n\n### npx (recommended — no install needed)\n\n```bash\nnpx brightspace-mcp@latest setup   # first-time wizard\nnpx brightspace-mcp@latest serve   # run the server\n```\n\n### Global install\n\n```bash\nnpm install -g brightspace-mcp\nbrightspace-mcp setup\nbrightspace-mcp serve\n```\n\n### From source\n\n```bash\ngit clone https://github.com/JhostinAleck/brightspace-mcp.git\ncd brightspace-mcp\nnpm install && npm run build\nnode build/cli/main.js serve\n```\n\n**Requirements**: Node.js ≥ 20.\n\n---\n\n## Authentication strategies\n\nPick the strategy that matches your Brightspace setup. Run `npx brightspace-mcp@latest setup` and it will walk you through the right one.\n\n### API Token (simplest)\n\nRequires a Valence API token from your Brightspace admin panel.\n\n```yaml\nprofiles:\n  my_school:\n    base_url: https://school.brightspace.com\n    auth:\n      strategy: api_token\n      api_token:\n        token_ref: env:BRIGHTSPACE_API_TOKEN\n```\n\n```bash\nexport BRIGHTSPACE_API_TOKEN=\"your-token\"\nnpx brightspace-mcp@latest serve\n```\n\n### Headless (username + password)\n\nAutomates HTTP-level login — no browser window. Supports all MFA strategies including **Duo Push**.\n\n```yaml\nprofiles:\n  my_school:\n    base_url: https://school.brightspace.com\n    auth:\n      strategy: headless\n      headless:\n        login_url: https://school.brightspace.com/d2l/login\n        username_ref: env:BRIGHTSPACE_USERNAME\n        password_ref: env:BRIGHTSPACE_PASSWORD\n        mfa:\n          strategy: duo_push     # or: totp, manual_prompt, none\n          duo_push: {}           # uses defaults: poll every 1s, timeout 120s\n```\n\n### Browser (Playwright)\n\nLaunches a headless Chromium instance and automates the login UI. Best for SSO flows (Microsoft Azure AD, SAML) where the login page has complex JavaScript.\n\n```bash\nnpm install playwright && npx playwright install chromium\n```\n\n```yaml\nauth:\n  strategy: browser\n  browser:\n    login_url: https://school.brightspace.com/d2l/login\n    headless: true\n    username_ref: env:BRIGHTSPACE_USERNAME\n    password_ref: env:BRIGHTSPACE_PASSWORD\n    selectors:\n      username: \"#i0116\"\n      password: \"#i0118\"\n      submit: \"#idSIButton9\"\n      password_submit: \"#idSIButton9\"\n      mfa_input: \"#idTxtBx_SAOTCC_OTC\"\n      mfa_submit: \"#idSubmit_SAOTCC_Continue\"\n      post_login: \"d2l-labs-navigation\"\n    mfa:\n      strategy: totp\n      totp:\n        secret_ref: env:BRIGHTSPACE_TOTP_SECRET\n```\n\nThe setup wizard includes a **Microsoft SSO preset** that fills all selectors automatically.\n\n### Session Cookie\n\nPaste the D2L session cookies from your browser's DevTools. Useful when other strategies are blocked.\n\n```yaml\nauth:\n  strategy: session_cookie\n  session_cookie:\n    cookie_ref: env:BRIGHTSPACE_COOKIE\n    session_ttl_seconds: 3600\n```\n\n```bash\n# Cookie format: \"d2lSessionVal=XXX; d2lSecureSessionVal=YYY\"\nexport BRIGHTSPACE_COOKIE=\"d2lSessionVal=...; d2lSecureSessionVal=...\"\n```\n\n---\n\n## MFA strategies\n\n| Strategy | When to use |\n|---|---|\n| `none` | No MFA on your account |\n| `totp` | Authenticator app (Google Authenticator, Authy, etc.) |\n| `duo_push` | Duo Security — server polls for mobile approval automatically |\n| `manual_prompt` | Any TOTP/OTP — server pauses and asks you to paste the code |\n\n### TOTP example\n\n```yaml\nmfa:\n  strategy: totp\n  totp:\n    secret_ref: env:BRIGHTSPACE_TOTP_SECRET   # base32 secret from QR code setup\n    digits: 6       # 6 or 8\n    period: 30      # seconds\n    algorithm: SHA1 # SHA1, SHA256, or SHA512\n```\n\n### Duo Push example\n\n```yaml\nmfa:\n  strategy: duo_push\n  duo_push:\n    poll_interval_ms: 1000   # how often to check (default: 1000)\n    timeout_ms: 120000       # give up after this many ms (default: 120000)\n```\n\n---\n\n## Configuration reference\n\nFull config file (`~/.brightspace-mcp/config.yaml`):\n\n```yaml\ndefault_profile: my_school\n\nprofiles:\n  my_school:\n    base_url: https://school.brightspace.com\n    auth:\n      strategy: api_token          # api_token | browser | headless | session_cookie | oauth\n      api_token:\n        token_ref: env:BRIGHTSPACE_API_TOKEN\n    session:\n      cache_backend: memory        # memory | file | redis\n      preemptive_refresh_seconds: 300\n\noutput:\n  tz: America/Bogota               # IANA timezone; default: auto-detected from system\n  locale: es-419                   # en-US | es-419 | pt-BR | fr-CA; default: auto-detected\n  format: markdown                 # markdown (default) | plain\n  include_meta_footer: true\n\nlogging:\n  level: info                      # debug | info | warn | error\n\nwrites:\n  enabled: false\n  dry_run: false\n\n# Optional — required when session.cache_backend: redis\nredis:\n  url: redis://localhost:6379\n  key_prefix: \"brightspace:\"\n```\n\n### Credential references\n\nSecret values are never stored in plain text. Use `ref:` notation to point to the actual value:\n\n| Prefix | Example | Description |\n|---|---|---|\n| `env:NAME` | `env:BRIGHTSPACE_API_TOKEN` | Read from environment variable |\n| `keychain:service/account` | `keychain:brightspace-mcp/token` | OS keychain (macOS Keychain, GNOME Keyring, Windows Credential Manager) |\n| `file:label` | `file:api_token` | Encrypted file (`~/.brightspace-mcp/credentials.enc`, AES-256-GCM) |\n\n---\n\n## Output: timezone and language\n\nAll tool responses are formatted in your configured timezone and language.\n\n```yaml\noutput:\n  tz: America/Bogota       # IANA name; default: auto-detected from system\n  locale: es-419           # en-US | es-419 | pt-BR | fr-CA; default: auto-detected\n  format: markdown         # markdown (default) | plain\n  include_meta_footer: true\n```\n\nRun `brightspace-mcp setup` and choose your timezone and language. Or set it in `~/.brightspace-mcp/config.yaml`.\n\n---\n\n## Redis cache\n\nWhen running multiple instances or want cache persistence across restarts, enable Redis:\n\n**1. Add the `redis` section to config:**\n\n```yaml\nredis:\n  url: redis://localhost:6379\n  key_prefix: \"brightspace:\"\n\nprofiles:\n  my_school:\n    session:\n      cache_backend: redis\n```\n\n**2. Install ioredis (optional dependency):**\n\n```bash\nnpm install ioredis\n```\n\n**3. Start Redis and the server:**\n\n```bash\ndocker run -d -p 6379:6379 redis:7-alpine\nnpx brightspace-mcp@latest serve\n```\n\nThe 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.\n\n---\n\n## Write operations\n\nWrite tools (`submit_assignment`, `post_discussion_reply`, `mark_announcement_read`) are disabled by default and require two separate opt-ins:\n\n**1. Config file:**\n\n```yaml\nwrites:\n  enabled: true\n  dry_run: false   # set true to preview without mutating D2L\n```\n\n**2. CLI flag:**\n\n```bash\nnpx brightspace-mcp@latest serve --enable-writes\n```\n\nAll write operations:\n- Require a client-supplied `idempotency_key` (8–128 chars). Repeat calls with the same key return the cached response without re-executing.\n- Emit a WARN-level audit log line with correlation ID, tool name, and redacted args.\n- Respect `dry_run: true` to return a preview response without touching D2L.\n\n---\n\n## Available tools\n\n### Read tools (always available)\n\n| Tool | Description |\n|---|---|\n| `check_auth` | Verify authentication and show the active user identity |\n| `list_my_courses` | List all enrolled courses |\n| `get_my_grades` | Get grades for a course |\n| `get_assignments` | List assignments and dropbox folders |\n| `get_assignment_files` | Download and read instructor-posted assignment files |\n| `get_upcoming_due_dates` | List assignments due in the next N days |\n| `get_feedback` | Read instructor feedback on submitted assignments |\n| `get_syllabus` | Fetch the course syllabus |\n| `get_course_content` | Browse modules and topics (includes topic IDs) |\n| `get_topic_file` | Download and read a content topic file (DOCX, PDF, HTML, plain text) |\n| `get_announcements` | List course announcements |\n| `get_discussions` | Browse discussion forums and threads |\n| `get_calendar_events` | List calendar events in a date range |\n| `get_roster` | Get the full course roster |\n| `get_classlist_emails` | Get classmate email addresses |\n| `get_my_groups` | List group enrollments per course with member rosters |\n| `list_quizzes` | List quizzes with attempt counts, time limits, due dates |\n| `get_quiz_attempts` | Your attempts on a quiz with scores and timestamps |\n| `list_notifications` | User activity feed (announcements, due-date reminders, grade releases) |\n| `search_course` | Full-text search across content, announcements, and discussions |\n| `get_audit_log` | Local history of write operations (correlation IDs, redacted args) |\n| `get_diagnostics` | Show cache stats, circuit breaker state, and version info |\n| `clear_cache` | Clear memory and persistent cache backends |\n\n### Write tools (require `--enable-writes`)\n\n| Tool | Description |\n|---|---|\n| `submit_assignment` | Upload a file to a Brightspace Dropbox folder |\n| `post_discussion_reply` | Reply to a discussion thread |\n| `mark_announcement_read` | Mark an announcement as read |\n\n---\n\n## MCP Resources\n\nFour stable URIs for Brightspace content (readable by any MCP client via `resources/read`):\n\n| URI | Content |\n|---|---|\n| `brightspace://{courseId}/syllabus` | Course syllabus, HTML stripped |\n| `brightspace://{courseId}/content/topics/{topicId}` | Topic file (text extracted from PDF, or base64 fallback) |\n| `brightspace://{courseId}/assignments/{assignmentId}/files` | All assignment attachments as text |\n| `brightspace://{courseId}/announcements/{announcementId}` | Announcement text |\n\nObtain IDs from tools like `list_my_courses`, `get_assignments`, `get_announcements`.\n\n---\n\n## MCP Prompts\n\nFour pre-built prompt templates visible in your MCP client's prompt picker:\n\n| Prompt | Arguments | Purpose |\n|---|---|---|\n| `weekly_briefing` | none | 7-day overview: due dates, announcements, recent grades |\n| `grade_audit` | `course_id?` | Grade analysis + what you need to pass |\n| `study_planner` | `days_ahead?` (default 7) | Study plan from due dates and calendar |\n| `course_summary` | `course_id` (required) | Full course overview |\n\n---\n\n## TUI dashboard\n\n```bash\nbrightspace-mcp tui            # launch full-screen terminal dashboard\nbrightspace-mcp tui --profile work  # use a specific profile\n```\n\nFull-screen interactive terminal UI (Ink + React). Six tabs navigated with `Tab` / `→` / `←`:\n\n| Tab | Contents |\n|-----|----------|\n| **Inicio** | 3-column dashboard: upcoming assignments, 7-day calendar agenda, recent announcements |\n| **Cursos** | Live-search course list → drill into a course → sub-tabs Tareas / Notas / Anuncios |\n| **Calendario** | 30-day event agenda across all active courses |\n| **Config** | Profile summary, field-by-field form editor (dropdowns from schema) or `$EDITOR` |\n| **Caché** | Hit rate, miss count, clear button |\n| **Logs** | Audit log (last 50 entries, `/` to filter by tool name) |\n\nPress `Ctrl+C` to exit.\n\n---\n\n## Register with an MCP client\n\nSee [`docs/clients.md`](./docs/clients.md) for Claude Desktop, Cursor, and Windsurf snippets, or run `brightspace-mcp setup` which auto-detects and registers for you.\n\n**Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"brightspace\": {\n      \"command\": \"npx\",\n      \"args\": [\"--yes\", \"brightspace-mcp@latest\", \"serve\"],\n      \"env\": {\n        \"BRIGHTSPACE_CONFIG\": \"/Users/you/.brightspace-mcp/config.yaml\"\n      }\n    }\n  }\n}\n```\n\n---\n\n## CLI reference\n\n```\nnpx brightspace-mcp@latest setup                      Interactive first-time setup wizard (detects system language)\nnpx brightspace-mcp@latest init [flags]               Non-interactive config writer (CI/scripts, no TTY)\nnpx brightspace-mcp@latest serve                      Start the MCP server (stdio transport)\nnpx brightspace-mcp@latest serve --enable-writes      Start with write tools enabled\nnpx brightspace-mcp@latest tui                        Full-screen terminal dashboard (Ink TUI)\nnpx brightspace-mcp@latest auth                       Re-authenticate and test the config\nnpx brightspace-mcp@latest record-auth                Open browser for manual login, capture session cookies\nnpx brightspace-mcp@latest doctor                     End-to-end smoke test: config → auth → API → list_my_courses\nnpx brightspace-mcp@latest profile list               List profiles (* marks the default)\nnpx brightspace-mcp@latest profile use <name>         Switch the default profile\nnpx brightspace-mcp@latest config show                Print config (secrets redacted)\nnpx brightspace-mcp@latest config show --resolved     Show all secret refs as [redacted]\nnpx brightspace-mcp@latest config validate            Validate config schema without running\nnpx brightspace-mcp@latest config set <path> <value>  Edit a nested config value\nnpx brightspace-mcp@latest cache clear                Clear memory + file/Redis cache\nnpx brightspace-mcp@latest cache clear --context <n>  Clear a specific cache context\nnpx brightspace-mcp@latest upgrade                    Upgrade brightspace-mcp to the latest version\n```\n\n---\n\n## Docker\n\n### Standalone\n\n```bash\ndocker pull ghcr.io/jhostinaleck/brightspace-mcp:latest\ndocker run --rm -i \\\n  -v \"$HOME/.brightspace-mcp:/config:ro\" \\\n  -e BRIGHTSPACE_CONFIG=/config/config.yaml \\\n  ghcr.io/jhostinaleck/brightspace-mcp:latest serve\n```\n\n### With Redis (docker-compose)\n\n```bash\n# Start server + Redis\ndocker compose --profile redis up\n\n# Or standalone (in-memory cache)\ndocker compose up\n```\n\nThe `config.yaml` inside `~/.brightspace-mcp/` must have the `redis:` section pointing to `redis://redis:6379` when using the compose profile.\n\n---\n\n## Architecture highlights\n\n- **Resilience**: retry with exponential backoff + jitter, circuit breaker (5 failures → 30s cooldown), request coalescing, bulkhead (max 5 concurrent requests)\n- **Cache tiers**: HTTP response cache (L1, in-memory, 60s TTL) + domain cache (L2, layered memory → file or Redis)\n- **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\n- **DDD structure**: bounded contexts (`assignments`, `authentication`, `calendar`, `communications`, `content`, `courses`, `grades`, `groups`, `notifications`, `quizzes`) with clean domain / application / infrastructure separation\n\n---\n\n## License\n\n[MIT](./LICENSE) © Jhostin Aleck\n",
  "bytes": 17455,
  "sha": "cbfebe0f182ba86b1557a27cb4be7947f30e82bfc58c78f95ea512f21397e680",
  "repo_slug": "jhostinaleck/brightspace-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_jhostinaleck_brightspace_5815e24c/readme"
}