Skip to main content
Glama
RyK57

canvas-mcp-server

by RyK57

canvas-mcp-server

MCP-сервер для REST API Canvas LMS. Даёт LLM доступ на чтение к вашим курсам, заданиям, оценкам, сдачам, объявлениям, обсуждениям, модулям, страницам и файлам.

20 инструментов, все только для чтения.

Требования

  • Node.js 18+

  • Учётная запись Canvas в любом учебном заведении

  • Токен доступа из Account → Settings → New Access Token в веб-интерфейсе Canvas

Установка

npm install
npm run build

Настройка

У Canvas нет общего API-хоста — каждое учебное заведение запускает свой. Обе переменные ниже обязательны.

{
  "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"
      }
    }
  }
}

Переменная

Обязательна

По умолчанию

Назначение

CANVAS_BASE_URL

да

Хост Canvas вашего учебного заведения, включая схему, без завершающего пути

CANVAS_ACCESS_TOKEN

да

Account → Settings → New Access Token

CANVAS_REQUEST_TIMEOUT_MS

нет

30000

Таймаут на запрос

TRANSPORT

нет

stdio

stdio или http

PORT / HOST

нет

3000 / 127.0.0.1

Адрес привязки HTTP-транспорта

MCP_PATH_SECRET

при хостинге

Обслуживает конечную точку на /mcp/<secret>. Обязателен, когда HOST не является loopback

ALLOWED_ORIGINS

нет

localhost + claude.ai

Разрешённые источники через запятую

Просмотрите инструменты в интерактивном режиме:

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

Развёртывание (для мобильных Claude / коннекторов claude.ai)

Claude подключается к пользовательским коннекторам из облака Anthropic, а не с вашего устройства, поэтому мобильным и claude.ai нужен доступ по публичному HTTPS. Claude Code и Claude Desktop — нет; используйте там stdio.

1. Сгенерируйте секрет пути

openssl rand -hex 32

Сервер отказывается запускаться на не-loopback интерфейсе без установленного MCP_PATH_SECRET, потому что публичная конечная точка, содержащая ваш токен Canvas, является открытым прокси к вашей учётной записи. С установленным секретом конечная точка перемещается на /mcp/<secret>, и любой другой путь возвращает 404 — включая неверный секрет, так что сканирование хоста не раскрывает, что там живёт MCP-сервер.

2. Разверните

Включённые Dockerfile и railway.json работают как есть на Railway, Render или Fly. Образ устанавливает TRANSPORT=http и HOST=0.0.0.0 и запускается от непривилегированного пользователя. Установите три переменные в панели управления платформы:

Переменная

Значение

CANVAS_BASE_URL

хост Canvas вашего учебного заведения

CANVAS_ACCESS_TOKEN

ваш токен

MCP_PATH_SECRET

значение из шага 1

PORT внедряется платформой. /healthz — неаутентифицированный зонд живости.

3. Проверьте

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

4. Добавьте коннектор

На claude.ai в браузере — коннекторы нельзя добавить из мобильного приложения:

  1. Customize → Connectors → Add custom connector

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

  3. На телефоне откройте чат и включите его в разделе + → Connectors

Относитесь к этому URL как к паролю. Если он утёк, смените MCP_PATH_SECRET и добавьте коннектор заново.

Инструменты

Курсыcanvas_list_courses, canvas_get_course, canvas_get_grades, canvas_list_enrollments, canvas_get_profile

Заданияcanvas_list_assignments, canvas_get_assignment, canvas_get_submission, canvas_list_quizzes

Планировщикcanvas_list_planner_items, canvas_list_upcoming, canvas_list_calendar_events

Объявления и обсужденияcanvas_list_announcements, canvas_list_discussions, canvas_get_discussion

Содержимое курсаcanvas_list_modules, canvas_list_module_items, canvas_list_pages, canvas_get_page, canvas_list_files

Каждый инструмент чтения принимает response_format: "markdown" | "json". Markdown используется по умолчанию и оптимизирован для чтения LLM; JSON — это полная структурированная полезная нагрузка. structuredContent всегда заполняется независимо от формата.

Примеры

«Что нужно сдать на этой неделе?»canvas_list_planner_items с end_date на неделю вперёд. Охватывает все курсы одним вызовом и сообщает состояние сдачи. По умолчанию он начинается с сегодняшнего дня, поэтому для «что у меня просрочено» передайте явный более ранний start_date.

«Какие у меня оценки?»canvas_get_grades. Один вызов, все активные курсы, текущий балл и буквенная оценка.

«Что объявили мои преподаватели на этой неделе?»canvas_list_courses для идентификаторов, затем canvas_list_announcements со всеми ними сразу.

«Что мне на самом деле нужно сделать для проекта 2?»canvas_list_assignments с search_term="project 2" для получения идентификатора, затем canvas_get_assignment для полных инструкций.

Замечания по дизайну

Только для чтения по построению. Каждый инструмент несёт readOnlyHint: true и destructiveHint: false, и у клиента нет открытого пути записи. Токены Canvas несут полные полномочия вашей учётной записи — они могут отправлять задания, публиковать сообщения в обсуждениях и изменять настройки профиля — поэтому сервер намеренно отказывается раскрывать что-либо из этого. Тест проверяет это: если когда-либо будет добавлен инструмент записи, набор тестов завершится ошибкой.

Базовый URL обязателен, а не задан по умолчанию. В отличие от однопользовательских API, Canvas запускает один экземпляр на учебное заведение. Разумного значения по умолчанию нет, и токен, выданный Canvas одной школы, бессмысленен в другой, поэтому сервер завершается с ошибкой при запуске, а не вводит вас в заблуждение ошибками 401 позже.

Пагинация живёт в заголовке. Canvas сообщает «есть ли следующая страница» в заголовке Link RFC 5988 и никогда не возвращает общее количество. Эти URL документированы как непрозрачные, поэтому has_more читается из заголовка, а page/per_page остаются элементами управления для вызывающей стороны — агент получает простой next_page для перехода вместо курсора для навигации.

Идентификаторы запрашиваются как строки. Идентификаторы Canvas — 64-битные целые числа, которые JavaScript не может представить точно. Клиент отправляет Accept: application/json+canvas-string-ids, и Canvas выполняет это, возвращая каждый идентификатор строкой, поэтому идентификаторы переживают JSON-кругосветку без изменений.

HTML уплощается до того, как достигает модели. Описания заданий, объявления, сообщения обсуждений и страницы хранятся в HTML. Передача этого дословно сжигает огромный контекст на разметке, поэтому теги превращаются в разрывы строк, сущности декодируются, а длинные тела сокращаются с сохранением html_url для полной версии.

include[] не раскрывается. У Canvas два десятка опций include, они различаются между конечными точками списка и отдельного курса, и большинство управляют полями, которые агенту не нужны. Каждый инструмент запрашивает то, что ему нужно, и показывает только переключатели, меняющие то, что увидит пользователь — include_syllabus, include_grades, include_submission.

Идентификаторы курсов нормализуются в коды контекста. Некоторые конечные точки Canvas обращаются к курсам как course_1234, а не 1234. Обе формы принимаются везде и преобразуются, поэтому агенту не нужно запоминать, какая конечная точка какую хочет.

Ошибки приводят к следующим действиям. Ошибка 404 называет инструмент, который выдаёт допустимые идентификаторы для этого ресурса. Ошибка 403 отличает проблему с правами доступа от исчерпанного лимита запросов, который Canvas сбивающе возвращает под тем же статусом. Ошибка 401 указывает, что токен из Canvas одной школы не будет работать в другой.

Две особенности Canvas обрабатываются, а не передаются дальше. Оценка, которую курс сообщает в enrollments[].computed_current_score, — это то же число, которое API Enrollments называет grades.current_score; читаются оба. А поле submissions элемента планировщика — это логическое false — не объект — когда нечего сдавать, что проверяется перед чтением.

Предостережения

  • Объявления нельзя получить глобально: Canvas требует хотя бы один идентификатор курса, поэтому сначала должен выполняться canvas_list_courses.

  • canvas_list_discussions применяет свой фильтр scope после пагинации, поэтому отфильтрованная страница может вернуться короче, чем per_page, не будучи концом результатов.

  • Canvas опускает элементы модулей из ответа списка для модулей, которые считает большими; canvas_list_module_items получает их.

  • Страницы адресуются по url-слагу (week-1-reading), а не по заголовку. canvas_list_pages возвращает слаг в своём поле url.

  • Конечная точка календаря принимает не более 10 курсов и молча игнорирует остальные; canvas_list_calendar_events сообщает, когда усекает.

  • Оценки отражают только то, что опубликовал преподаватель, и полностью опускаются для курсов, настроенных скрывать итоговые оценки.

Структура проекта

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

Тесты

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

Оба набора тестов запускаются против локального макета, поэтому не нужны ни токен, ни доступ к сети.

-
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