canvas-mcp-server

canvas-mcp-server

Provides read-only access to Canvas LMS data, enabling an LLM to query courses, assignments, grades, submissions, announcements, discussions, modules, pages, and files via the Canvas REST API.

Category
访问服务器

README

canvas-mcp-server

MCP server for the Canvas LMS REST API. Gives an LLM read access to your courses, assignments, grades, submissions, announcements, discussions, modules, pages and files.

20 tools, all read-only.

Requirements

  • Node.js 18+
  • A Canvas account at any institution
  • An access token from Account → Settings → New Access Token in your Canvas web UI

Install

npm install
npm run build

Configure

Canvas has no shared API host — every institution runs its own. Both variables below are required.

{
  "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 Required Default Purpose
CANVAS_BASE_URL yes — Your institution's Canvas host, scheme included, no trailing path
CANVAS_ACCESS_TOKEN yes — Account → Settings → New Access Token
CANVAS_REQUEST_TIMEOUT_MS no 30000 Per-request timeout
TRANSPORT no stdio stdio or http
PORT / HOST no 3000 / 127.0.0.1 HTTP transport bind address
MCP_PATH_SECRET when hosted — Serves the endpoint at /mcp/<secret>. Required when HOST is not loopback
ALLOWED_ORIGINS no localhost + claude.ai Comma-separated origin allowlist

Inspect the tools interactively:

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

Deploying (for Claude mobile / claude.ai connectors)

Claude connects to custom connectors from Anthropic's cloud, not from your device, so mobile and claude.ai need this reachable over public HTTPS. Claude Code and Claude Desktop don't — use stdio there instead.

1. Generate a path secret

openssl rand -hex 32

The server refuses to start on a non-loopback interface without MCP_PATH_SECRET set, because a public endpoint holding your Canvas token is an open proxy to your account. With it set, the endpoint moves to /mcp/<secret> and every other path returns 404 — including a wrong secret, so probing the host doesn't reveal that an MCP server lives there.

2. Deploy

The included Dockerfile and railway.json work as-is on Railway, Render, or Fly. The image sets TRANSPORT=http and HOST=0.0.0.0 and runs as a non-root user. Set three variables in the platform's dashboard:

Variable Value
CANVAS_BASE_URL your institution's Canvas host
CANVAS_ACCESS_TOKEN your token
MCP_PATH_SECRET the value from step 1

PORT is injected by the platform. /healthz is an unauthenticated liveness probe.

3. Verify

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

4. Add the connector

On claude.ai in a browser — connectors can't be added from the mobile app:

  1. Customize → Connectors → Add custom connector
  2. URL: https://your-app.up.railway.app/mcp/<secret>
  3. On your phone, open a chat and enable it under + → Connectors

Treat that URL like a password. If it leaks, rotate MCP_PATH_SECRET and re-add the connector.

Tools

Courses — canvas_list_courses, canvas_get_course, canvas_get_grades, canvas_list_enrollments, canvas_get_profile

Assignments — canvas_list_assignments, canvas_get_assignment, canvas_get_submission, canvas_list_quizzes

Planner — canvas_list_planner_items, canvas_list_upcoming, canvas_list_calendar_events

Announcements and discussions — canvas_list_announcements, canvas_list_discussions, canvas_get_discussion

Course content — canvas_list_modules, canvas_list_module_items, canvas_list_pages, canvas_get_page, canvas_list_files

Every read tool takes response_format: "markdown" | "json". Markdown is the default and is optimized for an LLM reading it; JSON is the full structured payload. structuredContent is always populated regardless of format.

Examples

"What's due this week?" → canvas_list_planner_items with end_date a week out. Spans every course in one call and reports submission state. It starts from today by default, so for "what am I behind on" pass an explicit earlier start_date.

"What are my grades?" → canvas_get_grades. One call, every active course, current score and letter grade.

"What did my professors announce this week?" → canvas_list_courses for ids, then canvas_list_announcements with all of them at once.

"What do I actually have to do for project 2?" → canvas_list_assignments with search_term="project 2" to get the id, then canvas_get_assignment for the full instructions.

Design notes

Read-only by construction. Every tool carries readOnlyHint: true and destructiveHint: false, and the client has no write path exposed. Canvas tokens carry the full authority of your account — they can submit assignments, post to discussions, and change profile settings — so the server deliberately declines to expose any of that. A test asserts this: if a write tool is ever added, the suite fails.

The base URL is required, not defaulted. Unlike single-tenant APIs, Canvas runs one instance per institution. There is no sensible default, and a token issued by one school's Canvas is meaningless at another, so the server fails at startup rather than misleading you with 401s later.

Pagination lives in a header. Canvas reports "is there a next page" in an RFC 5988 Link header and never returns a total count. Those URLs are documented as opaque, so has_more is read from the header while page/per_page stay the caller-facing controls — an agent gets a simple next_page to follow instead of a cursor to thread.

Ids are requested as strings. Canvas ids are 64-bit integers, which JavaScript cannot represent exactly. The client sends Accept: application/json+canvas-string-ids, which Canvas honours by returning every id as a string, so ids survive a JSON round trip intact.

HTML is flattened before it reaches the model. Assignment descriptions, announcements, discussion posts and pages are all stored as HTML. Passing that through verbatim burns enormous context on markup, so tags become line breaks, entities are decoded, and long bodies are excerpted with the html_url kept for the full version.

include[] is not exposed. Canvas has two dozen include options, they differ between the list and single-course endpoints, and most control fields an agent has no use for. Each tool requests what it needs and surfaces only the toggles that change what a user would see — include_syllabus, include_grades, include_submission.

Course ids are normalised into context codes. Some Canvas endpoints address courses as course_1234 rather than 1234. Both forms are accepted everywhere and converted, so the agent never has to remember which endpoint wants which.

Errors resolve to next actions. A 404 names the tool that produces valid ids for that resource. A 403 distinguishes a permissions problem from an exhausted rate limit, which Canvas confusingly returns under the same status. A 401 points out that a token from one school's Canvas will not work at another.

Two Canvas quirks are handled rather than passed on. The grade a course reports under enrollments[].computed_current_score is the same number the Enrollments API calls grades.current_score; both are read. And a planner item's submissions field is the boolean false — not an object — when nothing is submittable, which is checked before it is read.

Caveats

  • Announcements cannot be listed globally: Canvas requires at least one course id, so canvas_list_courses has to run first.
  • canvas_list_discussions applies its scope filter after paginating, so a filtered page can come back shorter than per_page without being the end of the results.
  • Canvas omits module items from the list response for modules it considers large; canvas_list_module_items fetches them.
  • Pages are addressed by url slug (week-1-reading), not title. canvas_list_pages returns the slug in its url field.
  • The calendar endpoint accepts at most 10 courses and silently ignores the rest; canvas_list_calendar_events reports when it trims.
  • Grades reflect only what an instructor has posted, and are omitted entirely for courses configured to hide final grades.

Project layout

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

Both suites run against a local mock, so no token or network access is needed.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选