···11+# Canvas MCP Authentication
22+33+The Canvas MCP Server supports two authentication methods:
44+55+## 1. Personal Access Tokens (Recommended for Students)
66+77+**Best for:** Individual students, anyone without Canvas admin access
88+99+### How it works:
1010+1. Users generate their own Personal Access Token from Canvas
1111+2. Paste it into the web app
1212+3. Get an MCP API key instantly
1313+4. No admin access required
1414+1515+### Setup Instructions:
1616+1717+**For Users:**
1818+1. Log in to your Canvas account
1919+2. Go to **Account → Settings**
2020+3. Scroll to **"Approved Integrations"**
2121+4. Click **"+ New Access Token"**
2222+5. Fill in:
2323+ - **Purpose:** "MCP Server" (or anything you want)
2424+ - **Expires:** (optional - max 120 days, leave blank for 120 days)
2525+6. Click **"Generate Token"**
2626+7. **Copy the token** (you won't see it again!)
2727+8. Paste it into the Canvas MCP login page
2828+2929+**Security Notes:**
3030+- Personal Access Tokens have the same permissions as your Canvas account
3131+- The token is encrypted before being stored in the database
3232+- You can revoke the token anytime from Canvas Settings
3333+- Canvas limits token expiration to a maximum of 120 days
3434+- When your token expires, just generate a new one and update it on the dashboard
3535+3636+---
3737+3838+## 2. OAuth 2.1 (For Institution-Wide Deployment)
3939+4040+**Best for:** Canvas administrators deploying for entire institution
4141+4242+### How it works:
4343+1. Admin registers OAuth application in Canvas
4444+2. Users click "Sign in with Canvas"
4545+3. Canvas OAuth flow handles authentication
4646+4. Server stores encrypted tokens
4747+4848+### Setup Instructions:
4949+5050+**For Canvas Administrators:**
5151+5252+See [SETUP.md](./SETUP.md) for detailed OAuth configuration instructions.
5353+5454+**Quick summary:**
5555+1. Go to Canvas Admin → Developer Keys → "+ API Key"
5656+2. Set redirect URI: `https://canvas.dunkirk.sh/api/auth/callback`
5757+3. Request scopes: courses, assignments, users (read)
5858+4. Copy Client ID and Client Secret
5959+5. Add to server `.env` file
6060+6161+---
6262+6363+## Comparison
6464+6565+| Feature | Personal Access Token | OAuth |
6666+|---------|----------------------|-------|
6767+| **Setup Complexity** | Simple (2 minutes) | Complex (requires admin) |
6868+| **Who Can Use** | Any Canvas user | Requires admin setup |
6969+| **Token Management** | User manages their own | Server manages via refresh tokens |
7070+| **Expiration** | Max 120 days (user sets) | Typically 1 hour (auto-refreshed) |
7171+| **Revocation** | User revokes in Canvas | User revokes in Canvas |
7272+| **Best For** | Individual students | Institution-wide deployment |
7373+7474+---
7575+7676+## Hybrid Deployment
7777+7878+The server supports **both methods simultaneously**:
7979+8080+- Students can use Personal Access Tokens (no admin needed)
8181+- Institutions can set up OAuth for easier onboarding
8282+- Users choose their preferred method on login
8383+8484+This provides maximum flexibility.
8585+8686+---
8787+8888+## Security
8989+9090+Both methods are secure:
9191+9292+**Personal Access Tokens:**
9393+- Encrypted at rest using AES-256-GCM
9494+- Never logged or exposed in API responses
9595+- Only decrypted when making Canvas API calls
9696+9797+**OAuth Tokens:**
9898+- Encrypted at rest using AES-256-GCM
9999+- Automatically refreshed before expiration
100100+- Follow OAuth 2.1 best practices with PKCE
101101+102102+**MCP API Keys:**
103103+- Hashed using Argon2id before storage
104104+- Cannot be recovered (only verified)
105105+- Can be regenerated anytime by user
106106+107107+---
108108+109109+## Which Method Should I Use?
110110+111111+**Use Personal Access Tokens if:**
112112+- You're a student or individual user
113113+- You don't have Canvas admin access
114114+- You want to get started in 2 minutes
115115+- You're okay managing your own token
116116+117117+**Use OAuth if:**
118118+- You're deploying for an entire institution
119119+- You have Canvas admin access
120120+- You want users to have a simpler login flow (just click a button)
121121+- You want tokens to auto-refresh
122122+123123+**Recommendation:** Start with Personal Access Tokens. They're simpler and work for everyone.
+194
MULTI_INSTITUTION.md
···11+# Multi-Institution Support - How It Works
22+33+## Your Question: "Can we make the Canvas thing work at any institution?"
44+55+**Answer: Yes!** ✅
66+77+The server is designed to work with **any Canvas institution**. Here's how:
88+99+---
1010+1111+## How Multi-Institution Support Works
1212+1313+### 1. **User-Provided Domain**
1414+1515+When users visit the login page, they enter their Canvas domain (e.g., `canvas.harvard.edu`, `canvas.mit.edu`, `instructure.university.edu`).
1616+1717+The server:
1818+- Accepts **any valid Canvas domain**
1919+- Uses that domain for the OAuth flow
2020+- Stores the user's specific Canvas instance in the database
2121+- Makes API calls to **their** Canvas instance (not a shared one)
2222+2323+### 2. **OAuth Configuration Options**
2424+2525+You have three ways to configure OAuth:
2626+2727+#### Option A: **Global/Wildcard** (Simplest)
2828+```bash
2929+CANVAS_CLIENT_ID=xxx
3030+CANVAS_CLIENT_SECRET=yyy
3131+```
3232+3333+This uses **one set of OAuth credentials for all institutions**.
3434+3535+✅ **Works if**:
3636+- You have a Canvas Cloud account with inherited developer keys
3737+- Your OAuth app is registered as a "global" developer key
3838+- All institutions in your consortium share OAuth apps
3939+4040+#### Option B: **Per-Institution** (Most Flexible)
4141+```bash
4242+CANVAS_INSTITUTIONS='[
4343+ {"domain":"canvas.harvard.edu","clientId":"aaa","clientSecret":"bbb"},
4444+ {"domain":"canvas.mit.edu","clientId":"ccc","clientSecret":"ddd"}
4545+]'
4646+```
4747+4848+This allows **different OAuth credentials per institution**.
4949+5050+✅ **Use when**:
5151+- Each institution requires separate OAuth app registration
5252+- You want fine-grained control per school
5353+- Supporting multiple independent Canvas instances
5454+5555+#### Option C: **Hybrid** (Recommended)
5656+```bash
5757+# Global fallback
5858+CANVAS_CLIENT_ID=global_id
5959+CANVAS_CLIENT_SECRET=global_secret
6060+6161+# Specific overrides
6262+CANVAS_INSTITUTIONS='[
6363+ {"domain":"canvas.special-school.edu","clientId":"xxx","clientSecret":"yyy"}
6464+]'
6565+```
6666+6767+This supports **most institutions with fallback + specific overrides**.
6868+6969+---
7070+7171+## The OAuth Challenge
7272+7373+The **only requirement** is that each Canvas institution must have your OAuth application registered.
7474+7575+### Who Registers the OAuth App?
7676+7777+**Option 1: Canvas Administrators**
7878+- Each institution's Canvas admin registers your app
7979+- Provides you with Client ID and Client Secret
8080+- You add these to your server config
8181+8282+**Option 2: Canvas Cloud Inherited Keys**
8383+- Some Canvas Cloud consortiums support "inherited" developer keys
8484+- One registration works across multiple institutions
8585+- Ask Canvas support if this is available
8686+8787+**Option 3: User Self-Registration** (Not common)
8888+- Some Canvas instances allow users to create their own OAuth apps
8989+- Users would need to configure their own MCP server instance
9090+- Not practical for a shared service
9191+9292+---
9393+9494+## Practical Deployment Strategy
9595+9696+### For a Public Service (like canvas.dunkirk.sh):
9797+9898+**Phase 1: Start with Major Institutions**
9999+```bash
100100+CANVAS_INSTITUTIONS='[
101101+ {"domain":"canvas.harvard.edu","clientId":"...","clientSecret":"..."},
102102+ {"domain":"canvas.mit.edu","clientId":"...","clientSecret":"..."},
103103+ {"domain":"canvas.stanford.edu","clientId":"...","clientSecret":"..."}
104104+]'
105105+```
106106+107107+**Phase 2: Add Institutions on Request**
108108+- Users request support for their institution
109109+- Contact their Canvas admin to register OAuth app
110110+- Add credentials to `CANVAS_INSTITUTIONS`
111111+112112+**Phase 3: Global Fallback** (if possible)
113113+- Get a Canvas Cloud global developer key
114114+- Set as `CANVAS_CLIENT_ID` + `CANVAS_CLIENT_SECRET`
115115+- All institutions automatically supported
116116+117117+---
118118+119119+## User Experience
120120+121121+1. **User visits** `https://canvas.dunkirk.sh`
122122+2. **Enters domain**: `canvas.myschool.edu`
123123+3. **Server checks**: Is this domain configured?
124124+ - ✅ Yes → Redirect to Canvas OAuth
125125+ - ❌ No → Show error: "Contact admin to add your institution"
126126+4. **After OAuth**: User gets an API key specific to their institution
127127+5. **MCP calls**: Go to **their specific Canvas instance** (not shared)
128128+129129+---
130130+131131+## Technical Flow
132132+133133+```
134134+User (canvas.harvard.edu)
135135+ ↓
136136+Server checks OAuth config for "canvas.harvard.edu"
137137+ ↓
138138+Redirects to https://canvas.harvard.edu/login/oauth2/auth
139139+ ↓
140140+Harvard Canvas authenticates user
141141+ ↓
142142+Redirects back with code
143143+ ↓
144144+Server exchanges code for token (at Harvard's Canvas)
145145+ ↓
146146+Stores Harvard token (encrypted) + generates API key
147147+ ↓
148148+MCP client uses API key
149149+ ↓
150150+Server proxies requests to canvas.harvard.edu with user's token
151151+```
152152+153153+**Key point**: Each user's API calls go to **their own institution's Canvas instance**, using **their own OAuth token**.
154154+155155+---
156156+157157+## What You Need to Support "Any Institution"
158158+159159+### Technically:
160160+✅ **Already built!** The server accepts any domain and handles per-institution OAuth.
161161+162162+### Practically:
163163+You need OAuth credentials for each institution. Options:
164164+165165+1. **Contact Canvas Cloud** → Ask about global developer keys
166166+2. **Start with your institution** → Get it working for one school first
167167+3. **Add institutions incrementally** → As users request support
168168+4. **Open registration** → Allow users to provide their own OAuth credentials (advanced)
169169+170170+---
171171+172172+## Recommendation
173173+174174+**Start with Option A** (Global/Wildcard) if possible:
175175+- Contact Canvas support about Cloud global keys
176176+- Mention you're building a cross-institution MCP service
177177+- Ask if inherited developer keys are available
178178+179179+**If not available**, use **Option B** (Per-Institution):
180180+- Start with your own Canvas instance
181181+- Add others as requested
182182+- Build a self-service OAuth registration flow (future feature)
183183+184184+---
185185+186186+## Summary
187187+188188+✅ **Yes, the server works with any Canvas institution**
189189+✅ **Users can enter any Canvas domain**
190190+✅ **Server handles institution-specific OAuth**
191191+✅ **Each user's API calls go to their own Canvas instance**
192192+193193+❓ **Only requirement**: OAuth app must be registered with each institution
194194+💡 **Solution**: Start with global config, add institutions as needed, or contact Canvas about Cloud global keys
+82-3
README.md
···11-# canvas-mcp
11+# Canvas MCP Server
22+33+A proper MCP (Model Context Protocol) server that connects Canvas LMS to AI assistants like Claude Desktop.
44+55+## Features
66+77+- **Proper MCP Protocol**: Implements Streamable HTTP transport with JSON-RPC
88+- **Personal Access Token Auth**: Students set up in 2 minutes (no admin access needed)
99+- **Multi-Institution Support**: Works with any Canvas instance
1010+- **Encrypted Storage**: Canvas tokens encrypted at rest with AES-256-GCM
1111+- **Session Persistence**: Sessions survive server restarts (stored in SQLite)
1212+- **Built with Bun**: Fast, modern TypeScript using `@modelcontextprotocol/sdk`
1313+1414+## Quick Start
1515+1616+```bash
1717+# Install dependencies
1818+bun install
1919+2020+# Generate encryption key
2121+bun run generate-key
2222+2323+# Copy and configure environment
2424+cp .env.example .env
2525+# Add the generated encryption key to .env
2626+2727+# Run development server
2828+bun dev
2929+```
3030+3131+Visit `http://localhost:3000` to connect your Canvas account.
3232+3333+## How It Works
3434+3535+1. **Web Interface**: Students enter Canvas domain + Personal Access Token
3636+2. **Verification**: Server validates token by calling Canvas API
3737+3. **Token Storage**: Canvas token encrypted and stored server-side
3838+4. **MCP Token**: User receives an MCP connection token for their AI client
3939+5. **MCP Protocol**: AI client connects to `/mcp` endpoint with Bearer token
4040+6. **Canvas Proxy**: Server proxies tool calls to Canvas using stored token
4141+4242+## MCP Tools
4343+4444+- `list_courses`: List Canvas courses with enrollment filtering
4545+- `search_assignments`: Search assignments across courses
4646+- `get_assignment`: Get detailed assignment information
4747+4848+## Client Configuration
24933-a canvas mcp server
5050+After connecting your Canvas account, add this to Claude Desktop config:
45155-The canonical repo for this is hosted on tangled over at [`knot.dunkirk.sh/canvas-mcp`](https://tangled.org/knot.dunkirk.sh/canvas-mcp)
5252+```json
5353+{
5454+ "mcpServers": {
5555+ "canvas": {
5656+ "url": "https://canvas.dunkirk.sh/mcp",
5757+ "headers": {
5858+ "Authorization": "Bearer YOUR_MCP_TOKEN_HERE"
5959+ }
6060+ }
6161+ }
6262+}
6363+```
6464+6565+## Architecture
6666+6767+- **MCP Server**: `@modelcontextprotocol/sdk` with Streamable HTTP transport
6868+- **Web Dashboard**: Bun.serve with HTML/CSS/JS (no frameworks)
6969+- **Database**: SQLite with encrypted Canvas tokens and persistent sessions
7070+- **Transport**: JSON-RPC over HTTP POST at `/mcp` endpoint
7171+7272+## Security
7373+7474+- Canvas tokens encrypted with AES-256-GCM before storage
7575+- MCP tokens hashed with Argon2id (cannot be retrieved after creation)
7676+- Sessions stored in database (survive restarts)
7777+- HTTPS enforced in production
7878+- No Canvas tokens exposed to MCP clients
7979+8080+## Deployment
8181+8282+Deployed at: `https://canvas.dunkirk.sh`
8383+8484+The canonical repo is hosted on tangled at [`knot.dunkirk.sh/canvas-mcp`](https://tangled.org/knot.dunkirk.sh/canvas-mcp)
685786<p align="center">
887 <img src="https://raw.githubusercontent.com/taciturnaxolotl/carriage/main/.github/images/line-break.svg" />
+213
SETUP.md
···11+# Canvas MCP Server Setup
22+33+This guide explains how to set up the Canvas MCP server to work with your Canvas LMS institution(s).
44+55+## Multi-Institution Support
66+77+The server supports three configuration modes:
88+99+### 1. **Global/Wildcard Configuration** (Easiest)
1010+1111+If your Canvas instance supports OAuth applications that work across different domains, or if you're only supporting one institution:
1212+1313+```bash
1414+CANVAS_CLIENT_ID=your_client_id
1515+CANVAS_CLIENT_SECRET=your_client_secret
1616+```
1717+1818+This will accept logins from **any Canvas domain** using the same OAuth credentials.
1919+2020+### 2. **Multiple Specific Institutions**
2121+2222+If you need different OAuth credentials for different institutions:
2323+2424+```bash
2525+CANVAS_INSTITUTIONS='[
2626+ {
2727+ "domain": "canvas.harvard.edu",
2828+ "clientId": "xxx",
2929+ "clientSecret": "yyy",
3030+ "name": "Harvard University"
3131+ },
3232+ {
3333+ "domain": "canvas.mit.edu",
3434+ "clientId": "aaa",
3535+ "clientSecret": "bbb",
3636+ "name": "MIT"
3737+ }
3838+]'
3939+```
4040+4141+---
4242+4343+## How to Get Canvas OAuth Credentials
4444+4545+Each Canvas institution must register your MCP server as an OAuth application. Here's how:
4646+4747+### For Canvas Administrators:
4848+4949+1. **Go to Canvas Admin Panel**
5050+ - Navigate to: Admin → Developer Keys
5151+5252+2. **Create a new Developer Key**
5353+ - Click "+ Developer Key" → "+ API Key"
5454+5555+3. **Fill in the details:**
5656+ - **Key Name**: Canvas MCP Server
5757+ - **Owner Email**: Your email
5858+ - **Redirect URIs**: `https://canvas.dunkirk.sh/api/auth/callback`
5959+ - **Scopes**: Select the following:
6060+ - `url:GET|/api/v1/courses`
6161+ - `url:GET|/api/v1/assignments`
6262+ - `url:GET|/api/v1/users/self`
6363+6464+4. **Save and Enable**
6565+ - Copy the **Client ID** and **Client Secret**
6666+ - Set the key state to "On"
6767+6868+5. **Provide credentials to the server**
6969+ - Add the Client ID and Client Secret to your `.env` file
7070+7171+### For Users (Self-Service):
7272+7373+If you don't have admin access to your Canvas instance:
7474+7575+1. Contact your Canvas LMS administrator
7676+2. Ask them to register an OAuth application with the redirect URI: `https://canvas.dunkirk.sh/api/auth/callback`
7777+3. Request the Client ID and Client Secret
7878+4. Provide these to the Canvas MCP server administrator
7979+8080+---
8181+8282+## Canvas Cloud & Inherited Developer Keys
8383+8484+Some Canvas Cloud institutions support **inherited developer keys** across a consortium. If your institution is part of a Canvas Cloud consortium, a single OAuth application might work across multiple domains.
8585+8686+Ask your Canvas administrator if this is available.
8787+8888+---
8989+9090+## Environment Variables
9191+9292+Copy `.env.example` to `.env` and fill in your values:
9393+9494+```bash
9595+cp .env.example .env
9696+```
9797+9898+### Required Variables:
9999+100100+```bash
101101+# Server
102102+PORT=3000
103103+HOST=localhost
104104+BASE_URL=https://canvas.dunkirk.sh
105105+106106+# Encryption key (generate with: openssl rand -base64 32)
107107+ENCRYPTION_KEY=your_encryption_key_here
108108+109109+# Canvas OAuth (choose one of the options above)
110110+CANVAS_CLIENT_ID=your_client_id
111111+CANVAS_CLIENT_SECRET=your_client_secret
112112+113113+# Database
114114+DATABASE_PATH=./canvas-mcp.db
115115+```
116116+117117+---
118118+119119+## Installation
120120+121121+```bash
122122+# Install dependencies
123123+bun install
124124+125125+# Run development server
126126+bun dev
127127+128128+# Build for production
129129+bun run build
130130+131131+# Run production server
132132+bun start
133133+```
134134+135135+---
136136+137137+## Usage
138138+139139+1. **Users visit**: `https://canvas.dunkirk.sh`
140140+2. **Enter their Canvas domain**: e.g., `canvas.harvard.edu`
141141+3. **Authenticate via Canvas OAuth**
142142+4. **Receive an MCP API key** on their dashboard
143143+5. **Configure their MCP client** with the API key
144144+145145+---
146146+147147+## MCP Client Configuration
148148+149149+After getting an API key, users should add this to their MCP client config:
150150+151151+```json
152152+{
153153+ "mcpServers": {
154154+ "canvas": {
155155+ "command": "bunx",
156156+ "args": ["canvas-mcp-client"],
157157+ "env": {
158158+ "CANVAS_MCP_API_KEY": "cmcp_...",
159159+ "CANVAS_MCP_URL": "https://canvas.dunkirk.sh"
160160+ }
161161+ }
162162+ }
163163+}
164164+```
165165+166166+---
167167+168168+## Security Notes
169169+170170+- **API keys are hashed** before storage using Argon2id
171171+- **Canvas tokens are encrypted** at rest using AES-256-GCM
172172+- **OAuth state parameters** prevent CSRF attacks
173173+- **HTTPS required** in production
174174+- **Session cookies** are HttpOnly and SameSite=Lax
175175+176176+---
177177+178178+## Deployment
179179+180180+Deploy to any platform that supports Bun:
181181+182182+- **Railway**: `railway up`
183183+- **Fly.io**: `fly launch`
184184+- **Docker**: See Dockerfile
185185+- **VPS**: Run with systemd or PM2
186186+187187+Make sure to:
188188+- Set `BASE_URL` to your production domain
189189+- Use HTTPS (required for OAuth)
190190+- Set a strong `ENCRYPTION_KEY`
191191+- Configure Canvas OAuth redirect URI to your production URL
192192+193193+---
194194+195195+## Troubleshooting
196196+197197+### "Canvas domain is not configured"
198198+199199+The server doesn't have OAuth credentials for that Canvas instance. Either:
200200+- Use a global wildcard configuration (`CANVAS_CLIENT_ID` + `CANVAS_CLIENT_SECRET`)
201201+- Add the specific domain to `CANVAS_INSTITUTIONS`
202202+203203+### "OAuth token exchange failed"
204204+205205+- Verify the Client ID and Client Secret are correct
206206+- Check that the redirect URI in Canvas matches exactly: `https://canvas.dunkirk.sh/api/auth/callback`
207207+- Ensure the Canvas domain is correct (no `https://`, just `canvas.university.edu`)
208208+209209+### "Invalid API key"
210210+211211+- The API key might have been regenerated
212212+- Copy the new API key from the dashboard
213213+- Update your MCP client configuration
+156
TEST_MCP.md
···11+# Testing the MCP Server
22+33+## Method 1: Direct JSON-RPC Test (Quick)
44+55+Test the MCP endpoint directly with curl:
66+77+```bash
88+# Set your MCP token (get this from the dashboard)
99+TOKEN="cmcp_your_token_here"
1010+1111+# Test: List available tools
1212+curl -X POST https://canvas.bore.dunkirk.sh/mcp \
1313+ -H "Authorization: Bearer $TOKEN" \
1414+ -H "Content-Type: application/json" \
1515+ -H "Accept: application/json, text/event-stream" \
1616+ -d '{
1717+ "jsonrpc": "2.0",
1818+ "id": 1,
1919+ "method": "tools/list",
2020+ "params": {}
2121+ }'
2222+2323+# Test: List courses
2424+curl -X POST https://canvas.bore.dunkirk.sh/mcp \
2525+ -H "Authorization: Bearer $TOKEN" \
2626+ -H "Content-Type: application/json" \
2727+ -H "Accept: application/json, text/event-stream" \
2828+ -d '{
2929+ "jsonrpc": "2.0",
3030+ "id": 2,
3131+ "method": "tools/call",
3232+ "params": {
3333+ "name": "list_courses",
3434+ "arguments": {
3535+ "enrollment_state": "active"
3636+ }
3737+ }
3838+ }'
3939+```
4040+4141+## Method 2: Claude Desktop (Real Usage)
4242+4343+1. Get your MCP token from the dashboard
4444+2. Open Claude Desktop config:
4545+ - Mac: `~/Library/Application Support/Claude/claude_desktop_config.json`
4646+ - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
4747+4848+3. Add this configuration:
4949+5050+```json
5151+{
5252+ "mcpServers": {
5353+ "canvas": {
5454+ "url": "https://canvas.bore.dunkirk.sh/mcp",
5555+ "headers": {
5656+ "Authorization": "Bearer YOUR_MCP_TOKEN_HERE"
5757+ }
5858+ }
5959+ }
6060+}
6161+```
6262+6363+4. Restart Claude Desktop
6464+6565+5. Test by asking Claude:
6666+ - "What courses am I enrolled in?"
6767+ - "What assignments do I have due this week?"
6868+ - "Show me details about assignment ID 12345 in course 6789"
6969+7070+## Method 3: MCP Inspector (Visual Debugging)
7171+7272+```bash
7373+# Install MCP Inspector
7474+npm install -g @modelcontextprotocol/inspector
7575+7676+# Create a config file
7777+cat > mcp-config.json <<EOF
7878+{
7979+ "mcpServers": {
8080+ "canvas": {
8181+ "url": "https://canvas.bore.dunkirk.sh/mcp",
8282+ "headers": {
8383+ "Authorization": "Bearer YOUR_MCP_TOKEN_HERE"
8484+ }
8585+ }
8686+ }
8787+}
8888+EOF
8989+9090+# Run inspector
9191+mcp-inspector mcp-config.json
9292+```
9393+9494+## Expected Responses
9595+9696+### tools/list
9797+```json
9898+{
9999+ "jsonrpc": "2.0",
100100+ "id": 1,
101101+ "result": {
102102+ "tools": [
103103+ {
104104+ "name": "list_courses",
105105+ "description": "List Canvas courses...",
106106+ "inputSchema": {...}
107107+ },
108108+ {
109109+ "name": "search_assignments",
110110+ ...
111111+ },
112112+ {
113113+ "name": "get_assignment",
114114+ ...
115115+ }
116116+ ]
117117+ }
118118+}
119119+```
120120+121121+### tools/call (list_courses)
122122+```json
123123+{
124124+ "jsonrpc": "2.0",
125125+ "id": 2,
126126+ "result": {
127127+ "content": [
128128+ {
129129+ "type": "text",
130130+ "text": "[{\"id\": 123, \"name\": \"Biology 101\", ...}]"
131131+ }
132132+ ]
133133+ }
134134+}
135135+```
136136+137137+## Troubleshooting
138138+139139+**Error: "Missing session token"**
140140+- Make sure you're including the `Authorization: Bearer YOUR_TOKEN` header
141141+142142+**Error: "Invalid or expired session token"**
143143+- Your MCP token expired or was regenerated
144144+- Get a new token from the dashboard
145145+146146+**Error: "Not authenticated"**
147147+- The MCP token doesn't match any user in the database
148148+- Log in again via the web interface
149149+150150+**Error: "Unknown tool"**
151151+- Check the tool name spelling (case-sensitive)
152152+- Run `tools/list` to see available tools
153153+154154+**Error: Canvas API errors**
155155+- Your Canvas Personal Access Token may have expired (max 120 days)
156156+- Generate a new Canvas token and update via the web interface
···11+#!/usr/bin/env bun
22+// Generate a secure encryption key for the .env file
33+44+import { randomBytes } from "crypto";
55+66+const key = randomBytes(32).toString("base64");
77+88+console.log("\n🔐 Generated Encryption Key:");
99+console.log("\nENCRYPTION_KEY=" + key);
1010+console.log("\nAdd this to your .env file\n");