Skip to main content
Glama
RyK57

canvas-mcp-server

by RyK57

canvas-mcp-server

MCP-Server für die Canvas LMS REST-API. Gibt einem LLM Lesezugriff auf deine Kurse, Aufgaben, Noten, Abgaben, Ankündigungen, Diskussionen, Module, Seiten und Dateien.

20 Tools, alle schreibgeschützt.

Voraussetzungen

  • Node.js 18+

  • Ein Canvas-Konto an einer beliebigen Einrichtung

  • Ein Zugriffstoken aus Konto → Einstellungen → Neues Zugriffstoken in deiner Canvas-Weboberfläche

Installation

npm install
npm run build

Konfiguration

Canvas hat keinen gemeinsamen API-Host – jede Einrichtung betreibt ihren eigenen. Beide unten aufgeführten Variablen sind erforderlich.

{
  "mcpServers": {
    "canvas": {
      "command": "node",
      "args": ["/absolute/path/to/canvas-mcp-server/dist/index.js"],
      "env": {
        "CANVAS_BASE_URL": "https://bcourses.berkeley.edu",
        "CANVAS_ACCESS_TOKEN": "your-token-here"
      }
    }
  }
}

Variable

Erforderlich

Standard

Zweck

CANVAS_BASE_URL

ja

Der Canvas-Host deiner Einrichtung, inklusive Schema, ohne abschließenden Pfad

CANVAS_ACCESS_TOKEN

ja

Konto → Einstellungen → Neues Zugriffstoken

CANVAS_REQUEST_TIMEOUT_MS

nein

30000

Zeitüberschreitung pro Anfrage

TRANSPORT

nein

stdio

stdio oder http

PORT / HOST

nein

3000 / 127.0.0.1

HTTP-Transport-Bindungsadresse

MCP_PATH_SECRET

bei gehostet

Stellt den Endpunkt unter /mcp/<secret> bereit. Erforderlich, wenn HOST nicht Loopback ist

ALLOWED_ORIGINS

nein

localhost + claude.ai

Durch Kommas getrennte Origin-Whitelist

Untersuche die Tools interaktiv:

CANVAS_BASE_URL=https://your.canvas CANVAS_ACCESS_TOKEN=your-token npm run inspect

Bereitstellung (für Claude Mobile / claude.ai-Connectors)

Claude verbindet sich mit benutzerdefinierten Connectors aus der Cloud von Anthropic, nicht von deinem Gerät. Daher müssen Mobile und claude.ai dies über öffentliches HTTPS erreichen können. Claude Code und Claude Desktop tun das nicht – verwende dort stattdessen stdio.

1. Pfad-Geheimnis generieren

openssl rand -hex 32

Der Server weigert sich, auf einer Nicht-Loopback-Schnittstelle ohne gesetztes MCP_PATH_SECRET zu starten, da ein öffentlicher Endpunkt, der dein Canvas-Token enthält, ein offener Proxy für dein Konto ist. Mit gesetztem Geheimnis wechselt der Endpunkt zu /mcp/<secret> und jeder andere Pfad gibt 404 zurück – auch bei falschem Geheimnis. So verrät das Abtasten des Hosts nicht, dass dort ein MCP-Server lebt.

2. Bereitstellen

Die enthaltenen Dockerfile und railway.json funktionieren unverändert auf Railway, Render oder Fly. Das Image setzt TRANSPORT=http und HOST=0.0.0.0 und läuft als Nicht-Root-Benutzer. Setze drei Variablen im Dashboard der Plattform:

Variable

Wert

CANVAS_BASE_URL

der Canvas-Host deiner Einrichtung

CANVAS_ACCESS_TOKEN

dein Token

MCP_PATH_SECRET

der Wert aus Schritt 1

PORT wird von der Plattform injiziert. /healthz ist ein nicht authentifizierter Liveness-Healthcheck.

3. Überprüfen

curl -s https://your-app.up.railway.app/healthz

4. Connector hinzufügen

Auf claude.ai in einem Browser – Connectors können nicht aus der Mobile-App hinzugefügt werden:

  1. Anpassen → Connectors → Benutzerdefinierten Connector hinzufügen

  2. URL: https://your-app.up.railway.app/mcp/<secret>

  3. Öffne auf deinem Telefon einen Chat und aktiviere ihn unter + → Connectors

Behandle diese URL wie ein Passwort. Wenn sie durchsickert, rotiere MCP_PATH_SECRET und füge den Connector erneut hinzu.

Tools

Kursecanvas_list_courses, canvas_get_course, canvas_get_grades, canvas_list_enrollments, canvas_get_profile

Aufgabencanvas_list_assignments, canvas_get_assignment, canvas_get_submission, canvas_list_quizzes

Planercanvas_list_planner_items, canvas_list_upcoming, canvas_list_calendar_events

Ankündigungen und Diskussionencanvas_list_announcements, canvas_list_discussions, canvas_get_discussion

Kursinhaltecanvas_list_modules, canvas_list_module_items, canvas_list_pages, canvas_get_page, canvas_list_files

Jedes Lesetool akzeptiert response_format: "markdown" | "json". Markdown ist die Standardeinstellung und für das Lesen durch ein LLM optimiert; JSON ist die vollständige strukturierte Nutzlast. structuredContent ist unabhängig vom Format immer gefüllt.

Beispiele

„Was ist diese Woche fällig?"canvas_list_planner_items mit end_date eine Woche voraus. Deckt alle Kurse in einem Aufruf ab und meldet den Abgabestatus. Es beginnt standardmäßig ab heute. Für „Was habe ich verpasst?" übergebe ein explizites früheres start_date.

„Was sind meine Noten?"canvas_get_grades. Ein Aufruf, alle aktiven Kurse, aktueller Punktestand und Notenbuchstabe.

„Was haben meine Professoren diese Woche angekündigt?"canvas_list_courses für IDs, dann canvas_list_announcements mit allen auf einmal.

„Was muss ich eigentlich für Projekt 2 tun?"canvas_list_assignments mit search_term="project 2", um die ID zu erhalten, dann canvas_get_assignment für die vollständigen Anweisungen.

Designhinweise

Von Natur aus schreibgeschützt. Jedes Tool trägt readOnlyHint: true und destructiveHint: false, und der Client hat keinen Schreibpfad. Canvas-Tokens tragen die volle Autorität deines Kontos – sie können Aufgaben einreichen, in Diskussionen posten und Profileinstellungen ändern – daher weigert sich der Server bewusst, all das offenzulegen. Ein Test stellt dies sicher: Wenn jemals ein Schreib-Tool hinzugefügt wird, schlägt die Testsuite fehl.

Die Basis-URL ist erforderlich, nicht standardmäßig gesetzt. Im Gegensatz zu Single-Tenant-APIs betreibt Canvas eine Instanz pro Einrichtung. Es gibt keinen sinnvollen Standard, und ein Token, das von der Canvas einer Schule ausgestellt wurde, ist bei einer anderen bedeutungslos. Daher schlägt der Server beim Start fehl, anstatt dich später mit 401-Fehlern in die Irre zu führen.

Paginierung lebt in einem Header. Canvas meldet „Gibt es eine nächste Seite?" in einem RFC-5988-Link-Header und gibt niemals eine Gesamtzahl zurück. Diese URLs sind als undurchsichtig dokumentiert, daher wird has_more aus dem Header gelesen, während page/per_page die aufruferseitigen Steuerelemente bleiben – ein Agent erhält ein einfaches next_page zum Folgen, anstatt einen Cursor zu verwalten.

IDs werden als Zeichenketten angefordert. Canvas-IDs sind 64-Bit-Ganzzahlen, die JavaScript nicht exakt darstellen kann. Der Client sendet Accept: application/json+canvas-string-ids, was Canvas respektiert, indem es jede ID als Zeichenkette zurückgibt. So überstehen IDs eine JSON-Roundtrip unversehrt.

HTML wird abgeflacht, bevor es das Modell erreicht. Aufgabenbeschreibungen, Ankündigungen, Diskussionsbeiträge und Seiten sind alle als HTML gespeichert. Wenn man das unverändert durchreicht, verbrennt es enorm viel Kontext für Markup. Daher werden Tags zu Zeilenumbrüchen, Entitäten werden dekodiert und lange Texte werden mit der html_url für die vollständige Version auszugsweise dargestellt.

include[] wird nicht offengelegt. Canvas hat zwei Dutzend Include-Optionen, die sich zwischen den Listen- und Einzelkurs-Endpunkten unterscheiden, und die meisten steuern Felder, die ein Agent nicht benötigt. Jedes Tool fordert an, was es braucht, und zeigt nur die Umschalter, die ändern, was ein Benutzer sehen würde – include_syllabus, include_grades, include_submission.

Kurs-IDs werden in Kontextcodes normalisiert. Einige Canvas-Endpunkte adressieren Kurse als course_1234 statt 1234. Beide Formen werden überall akzeptiert und umgewandelt, sodass der Agent sich nie merken muss, welcher Endpunkt welche Form erwartet.

Fehler führen zu nächsten Aktionen. Ein 404 nennt das Tool, das gültige IDs für diese Ressource erzeugt. Ein 403 unterscheidet ein Berechtigungsproblem von einem erschöpften Ratenlimit, das Canvas verwirrenderweise unter demselben Status zurückgibt. Ein 401 weist darauf hin, dass ein Token von der Canvas einer Schule bei einer anderen nicht funktioniert.

Zwei Canvas-Eigenheiten werden behandelt, nicht weitergegeben. Die Note, die ein Kurs unter enrollments[].computed_current_score meldet, ist dieselbe Zahl, die die Enrollments-API grades.current_score nennt; beide werden gelesen. Und das submissions-Feld eines Planer-Elements ist der boolesche Wert false – kein Objekt – wenn nichts einreichbar ist, was vor dem Lesen geprüft wird.

Einschränkungen

  • Ankündigungen können nicht global aufgelistet werden: Canvas erfordert mindestens eine Kurs-ID, daher muss zuerst canvas_list_courses ausgeführt werden.

  • canvas_list_discussions wendet seinen scope-Filter nach der Paginierung an, sodass eine gefilterte Seite kürzer als per_page zurückkommen kann, ohne das Ende der Ergebnisse zu sein.

  • Canvas lässt Modulelemente aus der Listenantwort für Module weg, die es als groß betrachtet; canvas_list_module_items ruft sie ab.

  • Seiten werden über URL-Slug (week-1-reading) adressiert, nicht über den Titel. canvas_list_pages gibt den Slug in seinem url-Feld zurück.

  • Der Kalender-Endpunkt akzeptiert höchstens 10 Kurse und ignoriert den Rest stillschweigend; canvas_list_calendar_events meldet, wenn er kürzt.

  • Noten spiegeln nur das wider, was ein Dozent veröffentlicht hat, und werden für Kurse, die so konfiguriert sind, dass sie Endnoten verbergen, vollständig weggelassen.

Projektstruktur

src/
├── index.ts               # entry point, transport selection
├── constants.ts           # enum values, limits, character limit
├── types.ts               # interfaces for every Canvas entity
├── services/
│   └── canvas-client.ts   # fetch wrapper, auth, Link pagination, error → guidance mapping
├── schemas/
│   ├── inputs.ts          # Zod input schemas
│   └── outputs.ts         # structuredContent schemas
├── formatters/
│   ├── response.ts        # pagination, truncation, HTML flattening, format dispatch
│   └── entities.ts        # per-entity markdown rendering
└── tools/
    ├── courses.ts
    ├── assignments.ts
    ├── planner.ts
    ├── announcements.ts
    └── content.ts

Tests

npm run build
npm test            # 43 checks: MCP handshake, tools, pagination, formatting, errors (mocked API)
npm run test:http   # 19 checks: config validation, path-secret gating, method handling, origins

Beide Test-Suiten laufen gegen einen lokalen Mock, sodass kein Token oder Netzwerkzugriff erforderlich ist.

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.

  • Read-only MCP server for ClassQuill, a tutoring-business-management platform.

  • Read-only MCP server for Muovi, Argentina's trust-first local services marketplace (6 tools).

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/RyK57/canvas-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server