Install
openclaw skills install canvas-parent-mcpThis skill should be used when the user asks about Canvas LMS (Instructure) data for themselves or any student they observe. Triggers on phrases like "check Canvas", "what's my grade", "Canvas inbox", "what's due", "missing assignments", "Canvas LMS", "Instructure", "course announcements", "syllabus", or any request about courses, assignments, grades, conversations, announcements, planner items, or files.
openclaw skills install canvas-parent-mcpMCP server for Canvas LMS (Instructure) — 18 tools covering profile, observees, courses, assignments, submissions, grades, calendar, planner, announcements, conversations, discussions, and files. Read-only except for one file-download tool.
Pick one auth mode. Username/password is recommended — most schools have disabled personal-access-token creation.
Add to .mcp.json in your project or ~/.claude/mcp.json:
{
"mcpServers": {
"canvas": {
"command": "npx",
"args": ["-y", "canvas-parent-mcp"],
"env": {
"CANVAS_BASE_URL": "https://cms.instructure.com",
"CANVAS_USERNAME": "me@example.com",
"CANVAS_PASSWORD": "your-canvas-password",
"CANVAS_NAME": "CMS"
}
}
}
}
The server logs in lazily on the first request and silently re-mints cookies on 401, so you never have to re-bootstrap. Direct Canvas accounts only — won't work with SAML/Google/Microsoft SSO or 2FA.
If your admin still allows tokens, swap CANVAS_USERNAME/CANVAS_PASSWORD for CANVAS_TOKEN:
"env": {
"CANVAS_BASE_URL": "https://cms.instructure.com",
"CANVAS_TOKEN": "your-personal-access-token"
}
If your account uses SSO (so username/password won't work), mint OAuth credentials by reusing the Canvas mobile-app QR-login flow (canvas-parent-mcp-qr-login), then:
"env": {
"CANVAS_BASE_URL": "https://cms.instructure.com",
"CANVAS_CLIENT_ID": "...",
"CANVAS_CLIENT_SECRET": "...",
"CANVAS_REFRESH_TOKEN": "..."
}
npm install -g canvas-parent-mcp
Or from source:
git clone https://github.com/chrischall/canvas-parent-mcp
cd canvas-parent-mcp
npm install && npm run build
cp .env.example .env
# Edit .env: set CANVAS_BASE_URL plus one of CANVAS_TOKEN, CANVAS_USERNAME+CANVAS_PASSWORD, or the OAuth triple.
mcporter config add canvas \
--command "canvas-parent-mcp" \
--env "CANVAS_BASE_URL=https://cms.instructure.com" \
--env "CANVAS_USERNAME=me@example.com" \
--env "CANVAS_PASSWORD=your-canvas-password" \
--env "CANVAS_NAME=CMS" \
--config ~/.mcporter/mcporter.json
(Or substitute CANVAS_TOKEN / OAuth env vars per the alternatives above.)
mcporter list --config ~/.mcporter/mcporter.json
mcporter call canvas.canvas_get_profile --config ~/.mcporter/mcporter.json
mcporter call canvas.<tool_name> [key=value ...] --config ~/.mcporter/mcporter.json
Always pass --config ~/.mcporter/mcporter.json unless a local config/mcporter.json exists.
Most tools accept an optional observeeId (defaults to self) — set it to a student's user ID when an observer is checking on a linked student. List the candidates with canvas_list_observees.
| Tool | Notes |
|---|---|
canvas_get_profile | Your Canvas profile (id, name, email, login, locale, timezone). Call this first to confirm credentials work. |
canvas_list_observees | Students linked to your observer account. Returns [] for plain student tokens. |
| Tool | Notes |
|---|---|
canvas_list_courses(observeeId?) | Active courses with course-level grades. Includes total scores + current grading period scores. |
canvas_get_course(courseId) | Course detail: syllabus, teachers, term. |
| Tool | Notes |
|---|---|
canvas_list_assignments(courseId, bucket?) | Assignments for a course. bucket can be upcoming, overdue, past, or undated. Includes the user's submission inline. |
canvas_list_missing_submissions(observeeId?, courseIds?) | Past-due unsubmitted assignments. For an observee, courseIds is required. |
canvas_get_submission(courseId, assignmentId, userId?) | A single submission with comments + rubric assessment. userId defaults to self. |
canvas_list_recent_submissions(courseId, since?) | Recently graded submissions in a course. Defaults to a 14-day window. |
| Tool | Notes |
|---|---|
canvas_list_enrollments(observeeId?) | Active student enrollments with grades (current_score, final_score, current_grade, final_grade, current grading period). |
| Tool | Notes |
|---|---|
canvas_list_calendar_events(contextCodes?, type?, startDate?, endDate?) | Calendar events / assignments. contextCodes is an array like ["course_123", "user_456"]. |
canvas_list_upcoming_events | Canvas's curated next-7-days view. |
canvas_list_planner_items(observeeId?, startDate?, endDate?, contextCodes?) | Unified planner: assignments + announcements + planner notes + calendar events. |
| Tool | Notes |
|---|---|
canvas_list_announcements(contextCodes, startDate?, endDate?) | Announcements across one or more courses. contextCodes is required (e.g. ["course_123"]). Defaults to the last 14 days. |
canvas_list_conversations(scope?) | Inbox conversation list. scope ∈ unread / starred / archived. |
canvas_get_conversation(id) | Full conversation thread with messages. |
canvas_list_discussion_topics(courseId) | Discussion topic list for a course (read-only). |
| Tool | Notes |
|---|---|
canvas_list_course_files(courseId, searchTerm?) | File metadata: id, display_name, size, content-type, url. |
canvas_download_file(url, destinationPath, overwrite?) | Writes the file to destinationPath on disk. destinationPath is required — confirm the path with the user before calling. |
Discovery (first time):
canvas_get_profile → confirm credentialscanvas_list_observees → if empty, you're a student; otherwise capture observee IDscanvas_list_courses → capture course IDsIs everything OK at school?
canvas_list_courses (capture IDs)canvas_list_recent_submissions(courseId) for each — last 14 days of gradingcanvas_list_missing_submissions — past-due workcanvas_list_announcements(contextCodes=["course_<id>"]) — recent announcementsWhat got graded this week?
canvas_list_recent_submissions(courseId, since="YYYY-MM-DDTHH:MM:SSZ")What's due soon?
canvas_list_planner_items(startDate=..., endDate=...) — unified plannercanvas_list_assignments(courseId, bucket="upcoming") per courseToday's calendar:
canvas_list_upcoming_eventsRead a syllabus:
canvas_get_course(courseId) — syllabus_body is includedInbox:
canvas_list_conversations — find a threadcanvas_get_conversation(id) — read itDownload a file:
canvas_list_course_files(courseId) → find the file's urlcanvas_download_file(url, destinationPath="/Users/.../file.pdf")canvas_download_file writes to disk at destinationPath — confirm the path with the user; pass overwrite:true to replace..env.Link headers automatically up to 50 pages (5,000 items at the default per_page=100).