{"_id":"@canvas-toolchain/canvas-design-studio","_rev":"3-8e1769e99afa988765201270385cc46e","name":"@canvas-toolchain/canvas-design-studio","dist-tags":{"latest":"2.3.0"},"versions":{"2.2.0":{"name":"@canvas-toolchain/canvas-design-studio","version":"2.2.0","license":"MIT","_id":"@canvas-toolchain/canvas-design-studio@2.2.0","maintainers":[{"name":"rifter13","email":"krank13@hotmail.com"}],"homepage":"https://github.com/Ryfter/canvas-toolchain#readme","bugs":{"url":"https://github.com/Ryfter/canvas-toolchain/issues"},"bin":{"canvas-toolchain-design-studio":"dist/index.js"},"dist":{"shasum":"c8d932405faafd6b4ed8584e4f4acdc8641f19d9","tarball":"https://registry.npmjs.org/@canvas-toolchain/canvas-design-studio/-/canvas-design-studio-2.2.0.tgz","fileCount":362,"integrity":"sha512-CTk1HJqwsf+keybMpdu6Fk3lsk4BcCRvt51bLmv4A0p7EgPEUINN6ltHlqZH8W02aUn4O6YMVQ5CZnE/c4cphg==","signatures":[{"sig":"MEQCIGKxrkYi6LzhutHR8wo/pvooh+E7tOnnfYerz2u+D9+MAiBIoLQchkcLo5Onx++aYU5cYTgQ7TcyOGwISiXDhuX41w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":858372},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"gitHead":"e36909b5f008546895553be90f711d3cca69571a","scripts":{"dev":"tsx src/index.ts","test":"vitest run","build":"tsc && node -e \"require('fs').cpSync('src/templates','dist/templates',{recursive:true})\"","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"rifter13","email":"krank13@hotmail.com"},"repository":{"url":"git+https://github.com/Ryfter/canvas-toolchain.git","type":"git","directory":"packages/canvas-design-studio"},"_npmVersion":"11.17.0","description":"Canvas Design Studio — MCP server for generating, validating, and publishing Canvas LMS pages","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.23.0","yaml":"^2.9.0","color":"^4.2.3","jsdom":"^29.1.1","juice":"^11.1.1","cheerio":"^1.2.0","axe-core":"^4.12.1","@anthropic-ai/sdk":"^0.36.0","@inquirer/prompts":"^7.0.0","zod-to-json-schema":"^3.23.0","@modelcontextprotocol/sdk":"^1.10.0","@canvas-toolchain/shared-llm":"2.2.0","@canvas-toolchain/shared-types":"2.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.0.0","vitest":"^3.2.6","typescript":"^5.0.0","@types/node":"^20.0.0","@types/color":"^3.0.6","@types/jsdom":"^28.0.3"},"_npmOperationalInternal":{"tmp":"tmp/canvas-design-studio_2.2.0_1787331933016_0.8552972521443845","host":"s3://npm-registry-packages-npm-production"}},"2.2.1":{"name":"@canvas-toolchain/canvas-design-studio","version":"2.2.1","license":"MIT","_id":"@canvas-toolchain/canvas-design-studio@2.2.1","maintainers":[{"name":"rifter13","email":"krank13@hotmail.com"}],"homepage":"https://github.com/Ryfter/canvas-toolchain#readme","bugs":{"url":"https://github.com/Ryfter/canvas-toolchain/issues"},"bin":{"canvas-toolchain-design-studio":"dist/index.js"},"dist":{"shasum":"3b30248456d544af2241eea553447202b11ba387","tarball":"https://registry.npmjs.org/@canvas-toolchain/canvas-design-studio/-/canvas-design-studio-2.2.1.tgz","fileCount":362,"integrity":"sha512-23GqrrSQERrJfFCI9lrynZw23WQ7D5ngLYXV3K9n8cfKAs3Xu07pmwhaRbqBLONDKzmJfjbqzJNN3sim38wzMA==","signatures":[{"sig":"MEQCIGYeJinbfWDc15a5hpt7Z9zaGah1DV9TVJZEnxOuzuKbAiBNUMPlMW6SguaxOWEbWoYEQNjUaI4fALIi0QWngx2Dpg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@canvas-toolchain%2fcanvas-design-studio@2.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":858372},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"gitHead":"f8b8d54c40fe8d4bbcc6bb6d54ecd1149dd0a855","scripts":{"dev":"tsx src/index.ts","test":"vitest run","build":"tsc && node -e \"require('fs').cpSync('src/templates','dist/templates',{recursive:true})\"","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bab2245d-30bb-4bc9-b524-8c98d18b1327"}},"repository":{"url":"git+https://github.com/Ryfter/canvas-toolchain.git","type":"git","directory":"packages/canvas-design-studio"},"_npmVersion":"11.17.0","description":"Canvas Design Studio — MCP server for generating, validating, and publishing Canvas LMS pages","directories":{},"_nodeVersion":"24.19.0","dependencies":{"zod":"^3.23.0","yaml":"^2.9.0","color":"^4.2.3","jsdom":"^29.1.1","juice":"^11.1.1","cheerio":"^1.2.0","axe-core":"^4.12.1","@anthropic-ai/sdk":"^0.36.0","@inquirer/prompts":"^7.0.0","zod-to-json-schema":"^3.23.0","@modelcontextprotocol/sdk":"^1.10.0","@canvas-toolchain/shared-llm":"2.2.1","@canvas-toolchain/shared-types":"2.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.0.0","vitest":"^3.2.6","typescript":"^5.0.0","@types/node":"^20.0.0","@types/color":"^3.0.6","@types/jsdom":"^28.0.3"},"_npmOperationalInternal":{"tmp":"tmp/canvas-design-studio_2.2.1_1787342253689_0.48435690820683996","host":"s3://npm-registry-packages-npm-production"}},"2.3.0":{"name":"@canvas-toolchain/canvas-design-studio","license":"MIT","version":"2.3.0","description":"Canvas Design Studio — MCP server for generating, validating, and publishing Canvas LMS pages","type":"module","main":"dist/index.js","bin":{"canvas-toolchain-design-studio":"dist/index.js"},"scripts":{"build":"tsc && node -e \"require('fs').cpSync('src/templates','dist/templates',{recursive:true})\"","dev":"tsx src/index.ts","test":"vitest run","test:watch":"vitest","prepublishOnly":"npm run build"},"dependencies":{"@anthropic-ai/sdk":"^0.36.0","@canvas-toolchain/shared-llm":"2.3.0","@canvas-toolchain/shared-types":"2.3.0","@inquirer/prompts":"^7.0.0","@modelcontextprotocol/sdk":"^1.10.0","axe-core":"^4.12.1","cheerio":"^1.2.0","color":"^4.2.3","jsdom":"^29.1.1","juice":"^11.1.1","yaml":"^2.9.0","zod":"^3.23.0","zod-to-json-schema":"^3.23.0"},"devDependencies":{"@types/color":"^3.0.6","@types/jsdom":"^28.0.3","@types/node":"^20.0.0","tsx":"^4.0.0","typescript":"^5.0.0","vitest":"^3.2.6"},"engines":{"node":">=20"},"repository":{"type":"git","url":"git+https://github.com/Ryfter/canvas-toolchain.git","directory":"packages/canvas-design-studio"},"publishConfig":{"access":"public"},"gitHead":"73e54643f8f13130c999a6ed415e10239e16a7d0","types":"./dist/index.d.ts","_id":"@canvas-toolchain/canvas-design-studio@2.3.0","bugs":{"url":"https://github.com/Ryfter/canvas-toolchain/issues"},"homepage":"https://github.com/Ryfter/canvas-toolchain#readme","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-arA387zBSRi1+ME/HTBujUlSlZY1au74QGXtGtfVuBSpF6SVK73H1YHDT3XGBRv8hXBT9EzHE16K3AEA4UbRPA==","shasum":"94a2f4cb84f9625e56c5dd283d0757575fefb93b","tarball":"https://registry.npmjs.org/@canvas-toolchain/canvas-design-studio/-/canvas-design-studio-2.3.0.tgz","fileCount":362,"unpackedSize":858372,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@canvas-toolchain%2fcanvas-design-studio@2.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCBaohctCvkiK9hCI4f1my4qd72sys3nrLwre1EpEaoDAIhAJ7pTMXTU0LcR1bFdrSFyxgxdeCnuG0F3yyjR0YY5+65"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bab2245d-30bb-4bc9-b524-8c98d18b1327"}},"directories":{},"maintainers":[{"name":"rifter13","email":"krank13@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/canvas-design-studio_2.3.0_1788047016660_0.40541042087049584"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-21T17:05:32.787Z","modified":"2026-08-29T23:43:37.133Z","2.2.0":"2026-08-21T17:05:33.186Z","2.2.1":"2026-08-21T19:57:33.871Z","2.3.0":"2026-08-29T23:43:36.817Z"},"bugs":{"url":"https://github.com/Ryfter/canvas-toolchain/issues"},"license":"MIT","homepage":"https://github.com/Ryfter/canvas-toolchain#readme","repository":{"type":"git","url":"git+https://github.com/Ryfter/canvas-toolchain.git","directory":"packages/canvas-design-studio"},"description":"Canvas Design Studio — MCP server for generating, validating, and publishing Canvas LMS pages","maintainers":[{"name":"rifter13","email":"krank13@hotmail.com"}],"readme":"# Canvas Toolchain — Design Studio\n\n**An MCP server that gives AI assistants the power to generate, validate, and maintain beautiful Canvas LMS assignment pages.**\n\nWorks in Claude Code, VS Code, ChatGPT Codex, and any MCP-compatible host. Zero mandatory cloud APIs — your Canvas API token is optional.\n\n---\n\n![Canvas Design Studio — workflow and capabilities overview](docs/Canvas-Design-Studio-Capabilities.png)\n\n---\n\n## What It Does\n\n| Tool | What it does |\n|---|---|\n| `get_started` | Get a tailored orientation based on your current config — what tools are active, what setup unlocks, quick-start prompts, and a Context7 hint. Call this at the start of any session. |\n| `generate_canvas_page` | Turns a raw assignment brief into polished, Canvas-safe HTML with a hero banner, two-column layout, and brand colors |\n| `validate_canvas_html` | Checks HTML against Canvas RCE sanitizer rules and WCAG 2.1 AA accessibility checks |\n| `update_canvas_kb` | Fetches the current Canvas HTML allowlist directly from Canvas LMS source and reports any changes |\n| `setup_institution` | Runs the setup wizard to save brand colors, Canvas URL, API token, brand standards URL, and Panopto config — returns a formatted setup summary when done |\n| `list_canvas_courses` | Lists your Canvas courses with semester filtering, student counts, and favorite pinning to help choose the right one |\n| `publish_to_canvas` | Validates and publishes generated HTML directly to a Canvas course page — with FERPA preflight and title collision protection |\n| `critique_canvas_page` | Scores visual design quality (0–100) with 8 structural checks, strengths, and prioritized findings |\n| `redesign_canvas_page` | Applies mechanical fixes (font floor, hero placeholder) and returns remaining findings for the AI to address |\n| `search_panopto_videos` | Browse or search your Panopto lecture library — titles, durations, captions status (requires Panopto API) |\n| `embed_panopto_video` | Generate Canvas-safe Panopto embed HTML — iframe for whitelisted institutions, accessible fallback link otherwise |\n| `fetch_panopto_captions` | Download Panopto captions, strip timestamps, save as a plain-text Markdown transcript to your local KB |\n| `ingest_assignment_folder` | Read assignment materials from a folder (course config, brief, rubric, shell) and generate a Canvas page in one step |\n| `get_philosophy_kb` | Load your teaching philosophy KB into the AI's context — steers tone, emphasis, and pedagogy across all tools |\n| `update_philosophy_kb` | Add a quote, teaching insight, lecture-sourced statement, or course-specific note to your philosophy KB |\n| `get_student_personas` | Load saved student personas — statistically grounded demographic profiles for realistic audience feedback |\n| `generate_student_personas` | Generate 1–20 student personas using real probability distributions for race, disability, and 21 other dimensions |\n| `load_canvas_page` | Read the most recently generated HTML page from `output/` back into context (or load a named file) |\n| `save_canvas_page` | Write improved HTML back to `output/` — automatically backs up the previous version before overwriting |\n| `setup_course` | Run once per course: choose page types from a checklist, set weeks, get a complete folder scaffold pre-filled with content prompts |\n| `generate_page` | Generate or regenerate a single Canvas page from its `.md` source file |\n| `generate_week` | Generate all pages for one week at once |\n| `generate_course` | Batch generate the entire course in one command |\n| `import_course` | Seed a course folder from a Canvas backup archive — extracts pages, assignments, quizzes, and discussions with `[NEEDS REVIEW]` placeholders for content that can't be auto-extracted |\n\n---\n\n## Quick Start\n\n### Option A — npm global install\n\n```bash\nnpm install -g @canvas-toolchain/canvas-design-studio\n```\n\nThen add to your MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"canvas-toolchain-design-studio\": {\n      \"command\": \"canvas-toolchain-design-studio\"\n    }\n  }\n}\n```\n\n**Claude Desktop** — `%APPDATA%\\Claude\\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)  \n**VS Code** — `.vscode/mcp.json` (use `\"servers\"` key, not `\"mcpServers\"`)  \n**Cursor, Kiro, LM Studio, AnythingLLM, Codex CLI** — see [docs/installation.md](docs/installation.md) for client-specific config\n\n### Option B — Docker (no Node.js required)\n\nDocker has two steps:\n\n1. **Download the image** so it exists on your computer.\n2. **Tell your AI app how to start it** by adding the JSON config below to that app's MCP settings.\n\nThe JSON is not a PowerShell command. It is a configuration snippet for Claude Desktop, Cursor, LM Studio, and other MCP clients.\n\n```bash\n# Pull the image\ndocker pull ghcr.io/ryfter/canvas-design-studio:latest\n```\n\nRun the setup wizard once so Canvas Design Studio can save your school colors, Canvas URL, and optional API token.\n\nWindows PowerShell:\n\n```powershell\ndocker run -it --rm -v \"$HOME\\.canvas-design-mcp:/root/.canvas-design-mcp\" ghcr.io/ryfter/canvas-design-studio:latest\n```\n\nmacOS Terminal:\n\n```bash\ndocker run -it --rm -v \"$HOME/.canvas-design-mcp:/root/.canvas-design-mcp\" ghcr.io/ryfter/canvas-design-studio:latest\n```\n\nLinux terminal:\n\n```bash\ndocker run -it --rm -v \"$HOME/.canvas-design-mcp:/root/.canvas-design-mcp\" ghcr.io/ryfter/canvas-design-studio:latest\n```\n\nAfter the wizard finishes, add this to your MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"canvas-design\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-v\", \"${HOME}/.canvas-design-mcp:/root/.canvas-design-mcp\",\n        \"ghcr.io/ryfter/canvas-design-studio:latest\"\n      ]\n    }\n  }\n}\n```\n\nThat `-v` line is the important part: it lets the temporary Docker container read the saved config from your computer. Without that mount, the container starts fresh every time and will not remember your institution settings.\n\nIf your AI app does not expand `${HOME}` correctly, replace it with your full home folder path:\n\n- Windows: `C:/Users/YOUR-USERNAME/.canvas-design-mcp:/root/.canvas-design-mcp`\n- macOS: `/Users/YOUR-USERNAME/.canvas-design-mcp:/root/.canvas-design-mcp`\n\nCommon config locations:\n\n- **Claude Desktop on Windows:** `%APPDATA%\\Claude\\claude_desktop_config.json`\n- **Claude Desktop on macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Cursor:** `~/.cursor/mcp.json`\n- **LM Studio:** `~/.lmstudio/mcp.json`\n- **Codex CLI:** uses TOML instead of this JSON; see [docs/installation.md](docs/installation.md)\n\nAfter saving the config, fully restart the AI app. The app will run Docker for you whenever it needs the Canvas Design Studio tools.\n\n### What the Setup Wizard Asks\n\nWhether you use npm or Docker, the first setup run asks:\n\n```\n╔═══════════════════════════════════════════════════════════╗\n║          Canvas Design Studio — First Run Setup           ║\n╚═══════════════════════════════════════════════════════════╝\n\nInstitution name (your college or university): (Example University)\nBrand standards URL (optional — your AI fetches this to suggest your colors):\nPrimary brand color (#hex): (#0033A0)\nSecondary / accent color (#hex): (#D64309)\nCanvas base URL (no trailing slash): (https://example.instructure.com)\nCanvas API token — Account → Settings → Approved Integrations (optional):\nProfessor email for FERPA scan allowlist (optional):\nFavorite Canvas course IDs, comma-separated (optional):\n```\n\nWhen the wizard finishes it prints a formatted setup summary showing your settings and what you can do right now. Ask your AI to save it as `my-canvas-setup.md` for reference.\n\nConfig saves to `~/.canvas-design-mcp/institution.json` (legacy data-dir name for Design Studio config; not the npm package name) — survives `npx` reinstalls.\n\n**New to Canvas Design Studio?** See `docs/start_here.md` for a full orientation, or run `get_started` at the beginning of any session for a tailored overview of what's active.\n\n---\n\n## Generating a Page\n\nAsk your AI assistant:\n\n> \"Generate a Canvas assignment page for ITM 370, Assignment 16.06 — AI Augmented Projects, Fall 2026, Dr. Smith. Brief: Students record a 5-minute video demo of their passion project and upload to YouTube.\"\n\nThe tool returns:\n\n- **Canvas-safe HTML** — inline styles only, no `<script>`, no disallowed properties\n- **Hero image prompt** — copy/paste into ChatGPT or Midjourney (1200×400px)\n- **Filename** — `itm-370-16.06-page.html`\n\n---\n\n## Canvas HTML Rules Enforced\n\nThe validator and generator both enforce Canvas RCE constraints:\n\n| Disallowed | Reason |\n|---|---|\n| `<style>` blocks | Canvas strips them — use inline `style=\"\"` |\n| `<script>` | Not permitted in Canvas RCE |\n| `box-shadow` | Stripped by sanitizer |\n| `opacity` | Stripped — use `rgba()` instead |\n| `gap` | Stripped in flex/grid — use `margin` on children |\n| `filter`, `transform`, `transition`, `animation` | All stripped |\n| `<h1>` | Reserved for Canvas page title |\n| `<img>` without `alt` | Accessibility violation |\n\n---\n\n## Accessibility Checks\n\nEvery page is checked against **WCAG 2.1 AA** as it's generated, validated, and\npublished. The `validate_canvas_html`, `generate_*`, `redesign_canvas_page`, and\npublish tools all surface these. There are three layers:\n\n1. **A six-check WCAG content audit** (advisory warnings):\n   - **Contrast ratio** — inline text vs. background colour, against 4.5:1 (body) / 3:1 (large or bold ≥18px) thresholds.\n   - **Meaningful alt text** — content images with an empty `alt=\"\"` that aren't decorative.\n   - **Heading hierarchy** — skipped levels (e.g. H2 → H4) that break screen-reader navigation.\n   - **Descriptive links** — vague link text like \"click here\" / \"read more\".\n   - **Table headers** — data tables with no `<th>` cells.\n   - **Video captions** — Panopto embeds without `captions=true`.\n2. **A blocking rule** — every `<img>` must have an `alt` attribute (a missing `alt` fails validation outright).\n3. **Widget scaffolding** — interactive widgets ship with an `aria-live` status region, 44×44px touch targets, visible focus rings, and `prefers-reduced-motion` support built in.\n\nChecks are **advisory** (they warn, they don't block) — except the missing-`alt` rule.\nThey're fast heuristics over the HTML, not a full engine like axe-core, so a clean\nreport means \"no *detected* issues,\" not \"fully conformant.\"\n\n📖 **Full reference — what each check catches, how it works (with the contrast math),\nwhere it runs, how to fix findings, and its limitations:\n[docs/accessibility.md](../../docs/accessibility.md).**\n\n---\n\n## Ingest Workflow (Professors)\n\nDrop three files in an `ingest/` folder and ask your AI to build the page:\n\n```\ningest/\n├── course-config.md      ← course number, name, professor, semester\n├── assignment-brief.md   ← raw assignment instructions (any format)\n└── style-notes.md        ← optional layout/tone preferences\n```\n\n> \"Read everything in `ingest/`, then generate a Canvas assignment page.\"\n\nThe AI reads all three files, rewrites the brief into student-friendly copy, applies your brand colors, and saves the result to `output/`.\n\n---\n\n## Publishing to Canvas\n\nPublishing directly to Canvas requires a Canvas API token. Professors who prefer the manual workflow can skip this entirely — just paste the generated HTML into Canvas as normal.\n\n### 1. List your courses\n\n> \"List my Canvas courses for this semester\"\n\nThe tool returns each course with its ID, student count, teachers, and term — enough to confirm you have the right one before publishing.\n\n### 2. Publish a page\n\n> \"Publish the generated HTML to course 12345 as 'ITM 310 — Assignment 16.06'\"\n\nBefore writing to Canvas, the tool automatically:\n\n- Scans for obvious FERPA/PII risks (student IDs, grade disclosures)\n- Validates the HTML against Canvas RCE rules\n- Checks for existing pages with similar titles\n\n### 3. Handle a title collision\n\nIf a similar page already exists, the tool stops and asks how to proceed:\n\n```\nA page with a similar title already exists:\n  Existing: \"ITM 310 — Assignment 16.06 AI Projects\"\n  New:      \"ITM 310 — Assignment 16.06\"\n\nRerun publish_to_canvas with one of these options:\n  collisionAction: \"update\"  to replace the existing page content\n  collisionAction: \"create\"  to create a new page with this title\n  collisionAction: \"related\" and relatedPageTitle to create a named variation\n  collisionAction: \"cancel\"  to stop\n```\n\nCanvas keeps full page revision history, so an update is always reversible. Use `skipFerpaCheck: true` or `forcePublish: true` only after reviewing the warning they describe.\n\n---\n\n## Keeping the KB Current\n\nCanvas occasionally updates its HTML allowlist. Run:\n\n> \"Update the Canvas knowledge base\"\n\nThe tool fetches `canvas_sanitize.rb` directly from the Canvas LMS GitHub source and reports additions or removals. Results are cached for 24 hours; pass `force: true` to refresh immediately.\n\n---\n\n## Configuration\n\nConfig file: `~/.canvas-design-mcp/institution.json`\n\n```json\n{\n  \"institution\": \"Example University\",\n  \"colors\": {\n    \"primary\": \"#0033A0\",\n    \"primaryDark\": \"#002277\",\n    \"primaryLight\": \"#E6ECF9\",\n    \"secondary\": \"#D64309\"\n  },\n  \"canvasUrl\": \"https://example.instructure.com\",\n  \"apiToken\": \"\",\n  \"professorEmail\": \"you@university.edu\",\n  \"favoriteCourses\": [12345, 67890],\n  \"kbTipShown\": false\n}\n```\n\n`apiToken`, `professorEmail`, and `favoriteCourses` are optional. The generate and validate tools work without an API token. Run `setup_institution` to update any field interactively.\n\n---\n\n## Requirements\n\n- Node.js 20 or later\n- Any MCP-compatible AI host (Claude Code, VS Code Copilot, ChatGPT Codex, etc.)\n\n---\n\n## Roadmap\n\n- **v0.1** — Core MCP server: generate, validate, KB refresh, institution setup ✓\n- **v0.2** — Direct Canvas publishing: `list_canvas_courses` + `publish_to_canvas` ✓\n- **v0.3** — Accessibility module (WCAG 2.1 AA checks in wizard, validator, and generator) ✓\n- **v0.4** — Design Intelligence Brain (critique + redesign suggestions via host AI) ✓\n- **v0.5** — Panopto video integration (search, embed, caption download) ✓\n- **v0.6** — Assignment folder ingest (drop files in a folder, get a page) ✓\n- **v0.7** — Professor philosophy KB (steering context for every page Claude generates) ✓\n- **v0.8** — Student persona review (statistically grounded audience feedback before publishing) ✓\n- **v0.9** — Assignment improvement loop (load page from output/, apply critique, save back with backup) ✓\n- **v0.9.6** — Course design foundation: `setup_course` wizard, `generate_page/week/course`, 15 page type templates ✓\n- **v0.9.7** — Canvas backup import: `import_course` seeds a full course folder from a previous semester's archive ✓\n- **v0.9.8** — Assignment type customization: `proj-assignment` and `tech-assignment` page types with `team` and `timeline` flags ✓\n- **v1.0.0** — First-professor polish: `get_started` orientation tool, setup summary, brand URL extraction, wizard inline explanations, rich error messages with ChatGPT help links, and three orientation docs (`start_here`, `troubleshooting`, `setup-worksheet`) ✓\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}