MCP server exposing Canvas classes and concept vaults to an LLM client (Claude Desktop / Claude Code / Gemini CLI). Syncs coursework, builds a concept graph, and serves it over stdio.
Canvas Obsidian demonstrates solid tool design with clear naming (verb_noun pattern), comprehensive descriptions (avg 180 chars), and well-structured schemas. All 8 tools have input schemas with typed parameters and descriptions. Strengths: deterministic tool semantics (upcoming_assignments), thoughtful defaults (k=10 for search_notes), and explicit error guidance (grades tool documents hidden-grade behavior). Weaknesses: no output schemas documented, missing error recovery guidance for most tools, no pagination support despite search_notes returning up to 10 results, and no tool annotations (readOnlyHint/destructiveHint). The refresh tool is marked WRITE but lacks confirmation/dry-run pattern. search_notes lacks result count/total fields for pagination planning.
Recent Canvas announcements for one class (cancellations, exam logistics, study guides, posted solutions), newest first.
Look up one concept in a class's knowledge graph: definition, linked concepts, and which lectures it appears in. None if not found.
The student's current grades, live from Canvas — ALL classes unless `course` is given. Never computed here, only reported. Each class returns `current_score` (graded work only) and `final_score` (ungraded counted as zero). `items` adds per-assignment scores, including work submitted but not marked yet. A class whose instructor hides grades comes back with an `error` field and no scores.
The student's current classes this term (slug, canvas id, full name). Call this first when a question is class-specific but the class is unclear.
Check Canvas for anything new: announcements, assignments, and newly posted files. Takes a few seconds. Use it when the student asks whether anything was posted recently, or when an answer might be stale. New lecture FILES are detected and named, but not transcribed — reading a slide deck needs a vision model and takes minutes, which would exceed this request's timeout.
No output schemas documented. LLMs cannot plan downstream tool calls or extract fields without knowing return structure. search_notes returns list[dict] with course/source/section/text, but this is inferred from code, not declared in schema.
refresh tool is destructive (WRITE) but lacks confirmation/dry-run pattern. Agents may trigger unintended syncs. No guidance on what 'new' means or how to handle partial failures.
search_notes accepts k parameter but returns no total_count or next_cursor. Agents cannot determine if results are truncated or plan pagination. Baseline pattern requires pagination support for list tools.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | <=2025-11-25 | v2 |
Semantic search over the student's own course material — lecture slides, homework prompts, and code notebooks. Searches ALL classes unless `course` is given. Each hit carries its course, source file and section for citation. k defaults to 10, not 5. The consumer here is a model that reads every result and picks, not a human scanning a list, so the cost of a lower-ranked hit is a few hundred tokens rather than a wasted click.
One class's syllabus as plain text (dates, schedule, grading, policies).
Assignments due within `days`, live from Canvas — across ALL classes unless `course` is given. Deterministic: use for any deadline question.
No tool annotations (readOnlyHint/destructiveHint/idempotentHint). Agents cannot infer safety properties without reading descriptions. refresh should be marked destructiveHint=true; others readOnlyHint=true.
Error handling lacks recovery guidance. grades documents hidden-grade behavior well, but other tools (announcements, concept, search_notes) do not explain what happens on 404, permission denied, or service unavailable.