Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

A remote MCP server for querying Canvas LMS courses, assignments, and grades. Enables natural language interaction with Canvas data via MCP clients like Claude Desktop.

README.md

Canvas MCP Server

Read-only Remote MCP server (Streamable HTTP transport) for querying Canvas LMS courses, assignments, and grades.

Setup

  1. Install dependencies:
   npm install
  1. Configure Canvas credentials:
   cp .env.example .env

Edit .env and add:

  • CANVAS_BASE_URL: Your Canvas instance URL (e.g., https://yourschool.instructure.com)
  • CANVAS_API_TOKEN: Your Canvas personal access token
  • CANVAS_TIMEOUT_MS (optional, default 15000): Timeout in milliseconds for outbound Canvas API requests (connect + read)
  • PORT (optional, default 8080): HTTP server port
  • BASE_PATH (optional, default /mcp): MCP endpoint path
  • ALLOWED_ORIGINS (optional): Comma-separated list of allowed origins for Origin validation (default: http://localhost:,http://127.0.0.1:)
  • MCP_AUTH_TOKEN (optional): If set, require Authorization: Bearer <token> on all /mcp requests (both GET and POST)

To get your API token:

  • Log into Canvas
  • Go to Account → Settings
  • Scroll to "Approved Integrations"
  • Click "+ New Access Token"
  • Set purpose (e.g., "MCP Server"), leave expiry blank
  • Copy the token (you won't see it again!)
  1. Build the project:
   npm run build

Running the Server

Start the HTTP server: ``bash npm run dev ``

The server will start on http://0.0.0.0:8080 (or your configured PORT) with:

  • MCP endpoint: http://localhost:8080/mcp
  • Health check: http://localhost:8080/healthz

Test health check: ``bash curl http://localhost:8080/healthz ``

Expected response: OK

Note: The MCP endpoint (/mcp) uses Streamable HTTP transport (Server-Sent Events) and should be accessed by MCP clients (like Claude Desktop), not directly via curl.

Security & Ops Features:

  • Origin validation protects against unauthorized cross-origin requests
  • DNS rebinding protection validates the Host header
  • Supports localhost, private IP ranges (192.168.x.x, 10.x.x.x, 172.16-31.x.x), and .local domains (mDNS)
  • Configure allowed origins via ALLOWED_ORIGINS environment variable
  • Outbound Canvas API timeouts via CANVAS_TIMEOUT_MS (default 15000ms)
  • Structured per-request logging for every MCP tool call (never logs secrets)
  • Optional Bearer auth for /mcp endpoint using MCP_AUTH_TOKEN

MCP Auth (optional):

  • If MCP_AUTH_TOKEN is set, all /mcp requests must include header: Authorization: Bearer <token>
  • Auth is enforced after Host/Origin validation
  • On missing/invalid token, server returns 401 with { "error": "unauthorized" }
  • The token is never logged

Docker Deployment (Raspberry Pi / Production)

This project includes Docker support for production deployment on Raspberry Pi or any ARM/x64 system.

Prerequisites

  • Docker installed on your system
  • Docker Compose installed

Deployment Steps

  1. Clone the repository to your Raspberry Pi:
   git clone <your-repo-url>
   cd Canvas_MCP
  1. Create .env file with your Canvas credentials:
   cp .env.example .env
   nano .env

Set your Canvas credentials: ```env CANVAS_BASE_URL=https://yourschool.instructure.com CANVAS_API_TOKEN=your_canvas_api_token_here

Optional: outbound Canvas API timeout (ms)

CANVAS_TIMEOUT_MS=15000

Optional: require Bearer token auth for /mcp

MCP_AUTH_TOKEN=choose-a-strong-token ```

  1. Build and start the container:
   docker-compose up -d
  1. Verify the container is running:
   docker-compose ps
  1. Check logs:
   docker-compose logs -f
  1. Test the server:
   curl http://localhost:8080/healthz

Docker Compose Commands

Start the server: ``bash docker-compose up -d ``

Stop the server: ``bash docker-compose down ``

Restart the server: ``bash docker-compose restart ``

View logs: ``bash docker-compose logs -f canvas-mcp ``

Rebuild after code changes: ``bash docker-compose down docker-compose build --no-cache docker-compose up -d ``

Configuration

The container automatically:

  • Restarts unless explicitly stopped (restart: unless-stopped)
  • Exposes port 8080
  • Includes health checks
  • Runs as non-root user for security

To change the port, edit docker-compose.yml: ```yaml ports:

  • "3000:8080" # External:Internal

## Connecting to Claude Desktop

This is a **remote MCP server** using Streamable HTTP transport. Configure Claude Desktop to connect to the running server.

Add to Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

{ "mcpServers": { "canvas": { "url": "http://localhost:8080/mcp" } } } ```

For Raspberry Pi or remote servers: ``json { "mcpServers": { "canvas": { "url": "http://raspberrypi.local:8080/mcp" } } } ``

Or use the IP address: ``json { "mcpServers": { "canvas": { "url": "http://192.168.1.100:8080/mcp" } } } ``

Important:

  1. The server must be running before starting Claude Desktop
  2. Start with Docker: docker-compose up -d or locally: npm run dev
  3. Verify the server is running: curl http://localhost:8080/healthz
  4. For remote connections, ensure port 8080 is accessible (firewall rules, etc.)

Restart Claude Desktop, then try:

  • "What Canvas courses am I enrolled in?"
  • "Show me assignments for [course name]"
  • "What assignments am I missing?"
  • "Check my submission status for [assignment name]"
  • "What's my current grade in [course name]?"
  • "What's due this week?"
  • "Show me all overdue assignments"

Current Features (v0.5)

list_courses

List all active Canvas courses with course ID, name, and course code.

list_assignments

List assignments for a specific course with details including:

  • Assignment ID, name, due date
  • Points possible, submission types
  • Submission status (workflow state, submitted date, missing/late flags)

Parameters:

  • course_id (required): The Canvas course ID
  • include_future (optional, default true): Include locked/future assignments. Best-effort filter based on unlock_at field; assignments without unlock_at are always included.
  • status_filter (optional, default "all"): Filter by submission status:
  • "all": No filtering (returns all assignments)
  • "missing": submission.missing === true OR (due date passed AND no submitted_at)
  • "unsubmitted": No submission object OR no submitted_at exists (regardless of due date)
  • "submitted": submitted_at exists OR workflow_state is submitted/graded

Supports pagination via Canvas Link headers.

get_submission_status

Get detailed submission status for a specific assignment with a single API request.

Returns:

  • assignment_id: The assignment ID
  • name: Assignment name
  • workflow_state: Current submission state (e.g., "unsubmitted", "submitted", "graded")
  • submitted_at: Submission timestamp (ISO 8601, null if not submitted)
  • graded_at: Grading timestamp (ISO 8601, null if not graded)
  • score: Numeric score (null if not graded)
  • late: Boolean flag indicating late submission
  • missing: Boolean flag indicating missing assignment
  • excused: Boolean flag indicating excused assignment

Parameters:

  • course_id (required): The Canvas course ID
  • assignment_id (required): The Canvas assignment ID

get_course_grades

Get grade summary for a course with graceful degradation. Single API request, read-only, never throws. Handles multiple enrollments by preferring active, most current enrollment.

Returns when grades are available: ``json { "course_id": 123456, "available": true, "current_score": 87.5, "current_grade": "B+", "final_score": 85.0, "final_grade": "B", "enrollment_state": "active", "term_id": 5678, "course_start_at": "2025-01-15T00:00:00Z", "course_end_at": "2025-05-15T00:00:00Z", "last_updated": null } ``

Returns when grades not yet posted: ``json { "course_id": 123456, "available": false, "reason": "no_grades_yet", "enrollment_state": "active", "term_id": 5678, "course_start_at": "2025-01-15T00:00:00Z", "course_end_at": "2025-05-15T00:00:00Z" } ``

Returns when grades are hidden or course not found: ``json { "course_id": 123456, "available": false, "reason": "hidden_or_unavailable" } ``

Parameters:

  • course_id (required): The Canvas course ID

Behavior:

  • Handles multiple enrollments (e.g., retaking a course) by preferring enrollment_state="active" and the most current enrollment (by course end date or enrollment ID)
  • Distinguishes between grades not yet posted (no_grades_yet) and grades hidden/unavailable (hidden_or_unavailable)
  • Includes metadata for sanity-checking: enrollment_state, term_id, and course date range
  • All grade fields (scores, grades) may be null if not provided by Canvas
  • Never throws errors

list_upcoming

List upcoming and/or overdue assignments across all active courses in a single consolidated view. Reuses existing list_courses and list_assignments logic.

Example response: ``json [ { "course_id": 123456, "course_name": "Introduction to Computer Science", "assignment_id": 789012, "name": "Homework 5", "due_at": "2025-01-12T23:59:00Z", "status": "unsubmitted", "points_possible": 100 }, { "course_id": 123456, "course_name": "Introduction to Computer Science", "assignment_id": 789013, "name": "Final Project", "due_at": "2025-01-20T23:59:00Z", "status": "submitted", "points_possible": 200 } ] ``

Parameters:

  • days (optional, default 14): Number of days to look ahead for upcoming assignments
  • include_overdue (optional, default true): Include overdue assignments
  • course_ids (optional): Array of course IDs to filter. If not provided, checks all active courses.

Behavior:

  • Returns assignments due within the next N days and optionally overdue assignments
  • Sorted by due date ascending (overdue items appear first)
  • Status is one of: "submitted", "unsubmitted", "missing"
  • Skips assignments without due dates
  • Gracefully handles errors on individual courses (continues with remaining courses)

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Other servers.