canvas — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited canvas (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
MCP 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": "[email protected]",
"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.
#### Advanced alternatives
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": "..."
}#### 1. Install
npm install -g canvas-parent-mcpOr from source:
git clone https://github.com/chrischall/canvas-parent-mcp
cd canvas-parent-mcp
npm install && npm run build#### 2. Configure credentials
cp .env.example .env
# Edit .env: set CANVAS_BASE_URL plus one of CANVAS_TOKEN, CANVAS_USERNAME+CANVAS_PASSWORD, or the OAuth triple.#### 3. Register with mcporter
mcporter config add canvas \
--command "canvas-parent-mcp" \
--env "CANVAS_BASE_URL=https://cms.instructure.com" \
--env "[email protected]" \
--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.)
#### 4. Verify
mcporter list --config ~/.mcporter/mcporter.json
mcporter call canvas.canvas_get_profile --config ~/.mcporter/mcporter.jsonmcporter call canvas.<tool_name> [key=value ...] --config ~/.mcporter/mcporter.jsonAlways 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).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.