Skip to main content
Glama
RyK57

canvas-mcp-server

by RyK57

canvas-mcp-server

用于 Canvas LMS REST API 的 MCP 服务器。为 LLM 提供对课程、作业、成绩、提交、公告、讨论、模块、页面和文件的读取访问。

20 个工具,全部只读。

要求

  • Node.js 18+

  • 任何机构的 Canvas 账户

  • 在 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

账户 → 设置 → 新建访问令牌

CANVAS_REQUEST_TIMEOUT_MS

30000

每次请求的超时时间

TRANSPORT

stdio

stdiohttp

PORT / HOST

3000 / 127.0.0.1

HTTP 传输绑定地址

MCP_PATH_SECRET

托管时

/mcp/<secret> 提供端点。当 HOST 不是回环地址时必需

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

如果没有设置 MCP_PATH_SECRET,服务器将拒绝在非回环接口上启动,因为持有你的 Canvas 令牌的公共端点相当于你账户的开放代理。设置后,端点将移至 /mcp/<secret>,所有其他路径都返回 404——包括错误的密钥,因此探测主机不会暴露那里存在 MCP 服务器。

2. 部署

附带的 Dockerfilerailway.json 可直接在 Railway、Render 或 Fly 上使用。该镜像设置 TRANSPORT=httpHOST=0.0.0.0,并以非 root 用户运行。在平台的控制面板中设置三个变量:

变量

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. 自定义 → 连接器 → 添加自定义连接器

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

  3. 在手机上打开聊天,并在 + → 连接器 下启用它。

将该 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 获取 ID,然后一次性使用 canvas_list_announcements 获取所有公告。

“对于项目 2,我实际上需要做什么?” → 使用 canvas_list_assignments 并设置 search_term="project 2" 获取 ID,然后使用 canvas_get_assignment 获取完整说明。

设计说明

构造上只读。 每个工具都带有 readOnlyHint: truedestructiveHint: false,并且客户端没有暴露任何写入路径。Canvas 令牌拥有你账户的全部权限——它们可以提交作业、发布讨论和更改个人资料设置——因此服务器故意不暴露任何这些功能。测试对此进行了断言:如果添加了写入工具,测试套件将失败。

基础 URL 是必需的,而不是默认的。 与单租户 API 不同,Canvas 为每个机构运行一个实例。没有合理的默认值,一个学校 Canvas 颁发的令牌在另一个学校毫无意义,因此服务器在启动时失败,而不是稍后用 401 误导你。

分页信息位于头部。 Canvas 在 RFC 5988 Link 头部中报告“是否有下一页”,并且从不返回总数。这些 URL 被记录为不透明的,因此 has_more 从头部读取,而 page/per_page 仍然是面向调用者的控制项——代理获得一个简单的 next_page 来跟随,而不是需要处理的游标。

ID 以字符串形式请求。 Canvas ID 是 64 位整数,JavaScript 无法精确表示。客户端发送 Accept: application/json+canvas-string-ids,Canvas 会遵守该请求,将所有 ID 作为字符串返回,因此 ID 在 JSON 往返中保持完整。

HTML 在到达模型之前被扁平化。 作业描述、公告、讨论帖子和页面都以 HTML 存储。逐字传递会消耗大量上下文,因此标签变为换行符,实体被解码,长正文被摘录,并保留 html_url 以获取完整版本。

include[] 未暴露。 Canvas 有二十多个 include 选项,它们在列表和单课程端点之间有所不同,并且大多数控制字段对代理没有用处。每个工具只请求它需要的内容,并仅暴露会改变用户所见内容的开关——include_syllabusinclude_gradesinclude_submission

课程 ID 被规范化为上下文代码。 某些 Canvas 端点以 course_1234 而不是 1234 来寻址课程。两种形式在所有地方都被接受并转换,因此代理无需记住哪个端点需要哪种形式。

错误解析为后续操作。 404 会指出为该资源生成有效 ID 的工具。403 区分权限问题和速率限制耗尽,而 Canvas 令人困惑地在同一状态下返回这两者。401 指出一个学校 Canvas 的令牌在另一个学校无法使用。

两个 Canvas 怪癖被处理而不是传递。 课程在 enrollments[].computed_current_score 下报告的成绩与 Enrollments API 所称的 grades.current_score 是同一个数字;两者都会被读取。此外,当没有可提交的内容时,计划器项目的 submissions 字段是布尔值 false——而不是对象——在读取之前会进行检查。

注意事项

  • 公告无法全局列出:Canvas 要求至少一个课程 ID,因此必须先运行 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