MCP server for Canvas LMS (REST API). Read coursework, deadlines, grades; submit assignments; discussions and messages.
Canvas-mcp demonstrates solid tool design with clear naming conventions (verb_noun pattern), comprehensive parameter descriptions, and well-documented schemas. All 11 tools have descriptions and input schemas with type definitions. Strengths: safety guardrails (dry-run defaults on destructive ops), good parameter constraints (enums, ranges), and clear dependency hints ('Use canvas_list_courses first'). Weaknesses: output schemas are not formally documented in the source code (inferred from eval tests), some parameter descriptions could be more prescriptive about format/constraints, and error handling guidance is minimal. The eval suite demonstrates schema awareness but doesn't substitute for explicit output documentation in tool definitions.
Everything due in the next `days` days across ALL courses, in one call (uses Canvas's planner). Each item shows the course, title, due date with a relative hint, points, and your submission status. This is the tool to answer 'what's due / what do I have coming up'. Read-only.
Search the people enrolled in a course by name to get their numeric user id and role. Use this to resolve recipient ids before calling canvas_send_message. Read-only.
Full detail for one assignment: instructions (HTML stripped to text), accepted submission types, allowed file extensions, rubric, due date, and your current submission status + instructor comments. Read this before submitting so you know what format is required. Read-only.
Without topic_id: list discussion topics in the course. With topic_id: read the topic's prompt and all reply entries (nested). Use this before canvas_post_reply. Read-only.
Without assignment_id: all graded assignments in the course plus your overall current grade. With assignment_id: detailed feedback for that one — score, grade, instructor comments, and rubric assessment. Read-only.
Output schemas not formally documented in tool definitions. Eval suite infers structure (courses, deadlines, assignments arrays) but tool registration lacks explicit return type documentation. LLMs cannot reliably plan downstream calls without seeing what fields are returned.
Parameter descriptions lack prescriptive format constraints. E.g., 'days' parameter says 'Look-ahead window in days' but doesn't explain why min=1, max=90 (API limits? UX best practice?). Format hints help LLMs understand intent and avoid invalid values.
Error handling guidance is minimal. Tools return JSON but no explicit recovery hints. E.g., if canvas_find_person returns no matches, should the LLM retry with a partial name, or is the person not enrolled? Eval suite checks for valid statuses but tool descriptions don't guide error recovery.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
List recent announcements across all courses or in one course. Announcements are read-only. Read-only.
List assignments for one course with due date, points, and your submission status. Use canvas_list_courses first to get the course_id. Read-only.
List the user's currently active courses with course code, term, and current overall grade. Start here to get the numeric course_id needed by every other course-scoped tool. Read-only.
Post a reply to a discussion topic (or to a specific entry for a threaded reply). SAFETY: defaults to a dry run — shows what would be posted but does NOT post. Re-call with confirm=true to post. Replies are visible to the class and the instructor.
Send a Canvas Conversations (inbox) message to one or more people. Resolve recipient_ids with canvas_find_person first. SAFETY: defaults to a dry run — shows what would be sent but does NOT send. Re-call with confirm=true to send. This delivers a real message on your behalf.
Submit work to an assignment as a text entry, a URL, or an uploaded local file. SAFETY: defaults to a dry run — it validates and shows exactly what will be submitted but does NOT submit. Call again with confirm=true to actually submit. Submissions are visible to the instructor and hard to undo. Read canvas_get_assignment first to confirm the accepted submission type.
Dry-run pattern (confirm=false default) is excellent for safety, but descriptions don't explain what 'preview' means operationally. Does it validate permissions? Check file size? Or just echo back the payload? Clarity prevents LLM confusion about what a dry-run guarantees.
canvas_get_grades parameter 'assignment_id' is optional but description doesn't explain the behavioral difference. 'Without assignment_id: course summary. With assignment_id: detailed feedback.' This is clear, but the schema should mark it as optional and explain the two modes explicitly.