画布mcp
一位老师面对 模型上下文协议(MCP) 包装Canvas LMS REST API的服务器。专为希望使用AI助手(例如Claude)在多个Canvas课程中创建和管理课程内容的讲师而设计。
安全与隐私: 正确安装后(遵循 逐步设置),此MCP服务器会自动从AI助手中屏蔽个人身份信息(PII),并根据FERPA和机构政策(包括UC/CSU)为您的数据提供强大的安全性。看 FERPA.md 和 安全_建筑.md 了解详情。
注: Canvas API集成是通用的。模块模板是用户可编辑的JSON/Handlebars文件,存储在 ~/.config/mcp/canvas-mcp/templates/ --默认设置在第一次运行时播种,可以针对任何课程结构进行自定义或替换。目录
1. 1. 安装 Git 1. 下载项目 1. 安装依赖项并构建 1. 获取Canvas API代币 1. 创建配置文件 1. 连接到您的AI助手 1. 开始使用它
- 克劳德桌面版 - 克劳德代码 - Gemini CLI - Codex CLI
它做什么
将此服务器连接到AI助手(如Claude Desktop),并要求它:
- 在课程之间切换(
"switch to my algorithms course") - 列出你的课程,看看哪一门是活动的
- 列出模块,获取成绩摘要,报告错过和迟到的作业
- 创建作业、测验、页面、讨论、公告和文件
- 创建量规并将其与作业相关联
- 在一次调用中从模板构建一周的模块
- 重置带有确认门的沙盒课程
- 在页面、作业、测验、模块、讨论和公告中按名称查找任何项目
- 使用Canvas Smart Search(测试版)从语义上搜索课程内容
- 通过模糊名称匹配从Zoom参与者CSV导入出勤情况
需求
- Node.js 20+()
- Git(git-scm.com)
- Canvas LMS帐户,具有至少一门课程的教师级访问权限
- Canvas API令牌(配置文件→ 设置→ 新访问令牌)
逐步设置(第一次)
这些说明假定没有开发人员经验。按顺序执行每个步骤。
1.安装Node.js
首选 并下载 长期支持 版本(左侧按钮)。运行安装程序并接受所有默认设置。要确认它有效,请打开终端(macOS:按⌘+空格键,键入“终端”)并运行:
node --version你应该看看这样的东西 v22.0.0任何版本20或更高都可以。
2.安装Git
在macOS上,Git通常已经安装。跑 git --version 在终端进行检查。如果您看到版本号,请跳到步骤3。如果没有,请从下载Git git-scm.com 并安装它。
3.下载项目
在终端中,运行:
git clone https://github.com/you/canvas-mcp
cd canvas-mcp这将创建一个名为的文件夹 canvas-mcp 在您的主目录中,并将您放入其中。
4.安装依赖项并构建
仍在航站楼内 canvas-mcp 文件夹:
npm install
npm run buildnpm install 下载所需的软件包(约1分钟,需要互联网)。 npm run build 将TypeScript源代码编译为可运行的JavaScript packages/teacher/dist/。你应该看不到任何错误。
5.获取Canvas API代币
- 登录您所在机构的Canvas(例如。,
https://yourschool.instructure.com) - 点击您的个人资料图片→ 账户 → 设置
- 向下滚动至 已批准的集成 然后单击 新访问令牌
- 为其命名(例如“Claude MCP”)并设置到期日期
- 点击 生成令牌 然后复制令牌——你不会再看到它了
6.创建配置文件
创建服务器启动时读取的目录和文件。在终端:
macOS/Linux:
mkdir -p ~/.config/mcp/canvas-mcp然后打开文本编辑器并创建文件 ~/.config/mcp/canvas-mcp/config.json 使用此内容(替换您的真实值):
{
"canvas": {
"instanceUrl": "https://yourschool.instructure.com",
"apiToken": "YOUR_CANVAS_API_TOKEN_HERE"
},
"program": {
"activeCourseId": null,
"courseCodes": ["ENG101", "ENG102"],
"courseCache": {}
},
"defaults": {
"assignmentGroup": "Assignments",
"submissionType": "online_url",
"pointsPossible": 100
},
"attendance": {
"hostName": "Your Name",
"defaultPoints": 10,
"defaultMinDuration": 0
}
}替换 yourschool.instructure.com 使用您学校的Canvas域名 YOUR_CANVAS_API_TOKEN_HERE 使用步骤5中的令牌。更新 courseCodes 根据您的实际课程代码(或将数组留空以查看您的所有课程)。
attendance.hostName --您的Zoom显示名称(无 (Host) 后缀)。匹配此名称的行在匹配之前会从Zoom CSV中筛选出来。不区分大小写
attendance.defaultPoints --出勤奖励的默认分数(默认值:10)。
attendance.defaultMinDuration --计数为存在的最小分钟数(默认值:0,表示没有过滤器)。
canvas.instanceUrl 和 canvas.apiToken 如果缺少任何一个,服务器将立即退出并显示明确的错误。
program.courseCodes 过滤器 list_courses 仅显示匹配的课程(例如。, "ENG101" 火柴 "ENG101-003").让它空着([])查看所有教师注册的课程。
program.activeCourseId 和 program.courseCache 由自动管理 set_active_course --不要手工编辑它们。
7.连接到您的AI助手
服务器可与任何兼容MCP的AI客户端配合使用。选择您喜欢的助手以获取设置说明:
- 克劳德桌面版 (macOS)
- 克劳德代码 (CLI)
- Gemini CLI (CLI)
- Codex CLI (CLI)
8.开始使用它
在助手的聊天窗口中,尝试:
“列出我的Canvas课程”
助理会打电话来 list_courses 并展示你的课程。然后设置活动课程:
“切换到我的ENG101课程”
______________________________________________________________________
配置参考
服务器读取 ~/.config/mcp/canvas-mcp/config.json 默认启动时。上述步骤6中的设置说明使用此默认路径。
使用自定义配置位置
如果您需要将配置文件存储在默认位置之外的其他位置,例如,为不同的学校或环境维护单独的配置,您可以使用 --config 服务器中的标志 args:
"args": ["--secure-heap=65536", "/path/to/canvas-mcp/packages/teacher/dist/index.js", "--config", "/your/custom/path/config.json"]如果使用自定义位置,请替换 ~/.config/mcp/canvas-mcp 在安装说明中,您选择的目录路径无处不在,包括 mkdir 步骤6中的命令和您在那里创建的配置文件路径。
平台特定设置
这 ~/.config/mcp/canvas-mcp/config.json 在步骤6中创建的文件在所有客户端之间共享——您只需配置一次。
注: Gemini CLI是目前首选的客户端,因为它是为数不多的允许对LLM进行无缝PII屏蔽和对控制台窗口进行解锁的客户端之一。如果有其他客户端支持此功能,我不知道他们。
Gemini CLI (Google's gemini CLI)
编辑 ~/.gemini/settings.json (如果它不存在,请创建它):
{
"mcpServers": {
"canvas-mcp": {
"command": "node",
"args": ["--secure-heap=65536", "/path/to/canvas-mcp/packages/teacher/dist/index.js"]
}
}
}如果您已经配置了其他服务器,请添加 "canvas-mcp" 进入现有 "mcpServers" 对象。保存后重新启动Gemini CLI。
要将服务器限制为单个项目而不是所有会话,请将相同的JSON放入 .gemini/settings.json 在该项目的文件夹中。
挂钩(PII致盲): 为了在Gemini CLI中启用自动学生姓名屏蔽功能——这样真实姓名就永远不会到达模型——设置canvas mcp挂钩。看 clients/gemini/docs/SETUP.md 获取分步说明。 注: 目前需要Gemini CLI的本地补丁,以便钩子能够正确处理学生特定的查询——安装指南涵盖了这一点。
Claude Desktop
- 下载并安装 克劳德桌面版 如果你还没有
- 打开Finder(macOS),按⌘+Shift+G,然后粘贴:
~/Library/Application Support/Claude/
- 打开(或创建)文件
claude_desktop_config.json在文本编辑器中 - 添加以下内容,替换
/path/to/canvas-mcp使用您在步骤3中克隆的文件夹的实际路径(例如。,/Users/yourname/canvas-mcp):
{
"mcpServers": {
"canvas-mcp": {
"command": "node",
"args": ["--secure-heap=65536", "/path/to/canvas-mcp/packages/teacher/dist/index.js"]
}
}
}- 保存文件并 重新启动克劳德桌面 (完全退出并重新打开)
- 寻找锤子图标(🔨) 在Claude Desktop聊天窗口中,这确认MCP工具已连接。单击它以查看工具列表。
如果Claude Desktop已打开并配置了其他MCP服务器,请合并 "canvas-mcp" 进入你现有的 "mcpServers" 对象,而不是替换它。
Claude Code (Anthropic's claude CLI)
使用单个命令将服务器添加到用户级MCP配置中:
claude mcp add canvas-mcp -- node --secure-heap=65536 /path/to/canvas-mcp/packages/teacher/dist/index.js替换 /path/to/canvas-mcp 使用步骤3中的实际文件夹路径。这封信是写给 ~/.claude.json (用户范围),并使服务器在所有Claude Code会话中可用。
要仅将其添加到特定项目中(因此它不能全局使用),请从该项目的文件夹中运行命令并添加 --scope project:
claude mcp add --scope project canvas-mcp -- node --secure-heap=65536 /path/to/canvas-mcp/packages/teacher/dist/index.js验证服务器是否已添加:
claude mcp listCodex CLI (OpenAI's codex CLI)
编辑 ~/.codex/config.toml (如果它不存在,请创建它):
[mcp_servers.canvas-mcp]
command = "node"
args = ["--secure-heap=65536", "/path/to/canvas-mcp/packages/teacher/dist/index.js"]要将其限制为单个项目,请将相同的TOML放入 .codex/config.toml 在该项目的文件夹中(必须信任该项目)。
工具
总共19个工具。所有工具都接受可选 course_id 以覆盖活动课程。
课程背景
| 工具 | 说明 |
|---|---|
list_courses | 列出您的Canvas课程。筛选到 program.courseCodes 默认情况下;通过 all: true 看到一切。 |
set_active_course | 通过模糊匹配查询字符串来设置活动课程(例如。 "ENG101", "english spring"). |
get_active_course | 从本地配置返回当前活动的课程。没有Canvas API调用。 |
报告
报告工具响应中的学生姓名和画布ID会自动替换为会话令牌([STUDENT_001], [STUDENT_002],…)在它们到达AI之前。看 隐私 在......下面
| 工具 | 说明 |
|---|---|
get_module_summary | 模块的完整结构:项目类型、标题、分数、截止日期。接受 module_id 或 module_name (部分匹配)。 |
get_grades | 等级数据范围如下 scope: "class" (每个学生的分数+缺课/迟到数,支持 sort_by), "assignment" (每项作业按学生细分),或 "student" (一名学生的所有作业通过 student_token).学生姓名被会话令牌替换。 |
get_submission_status | 学生错过或迟交作业。 type: "missing" 支持可选 since_date 过滤器。学生姓名被会话令牌替换。 |
student_pii | PII查找。 action: "resolve" 显示会话令牌的真实姓名和Canvas ID(仅显示给您)。 action: "list" 返回当前会话中注册的所有令牌。 |
创建并列出
| 工具 | 说明 |
|---|---|
create_item | 创建课程项目。 type: page, assignment, quiz, discussion, announcement, module,或 module_item.支持可选 template_name/template_data 用于模板渲染页面。通过 dry_run: true 在不调用Canvas的情况下预览已解析的输入。 |
list_items | 按类型列出课程项目: modules, assignments, quizzes, pages, discussions, announcements, rubrics, assignment_groups, module_items (要求 module_name),或 templates (列出可用的模块模板)。 |
查找、更新和删除
| 工具 | 说明 |
|---|---|
find_item | 按部分名称查找任何课程项目,并返回其全部详细信息。类型: page (身体), assignment (附描述), quiz (有问题), module, module_item, discussion, announcement, syllabus.返回第一个不区分大小写的部分匹配,如果多个项目匹配,则返回警告。 |
update_item | 按名称查找课程项目,然后更新它。类型: page, assignment, quiz, module, module_item, syllabus。只提供要更改的字段。 |
delete_item | 按名称查找课程项目,然后将其删除或移除。类型: page, assignment, quiz, module, module_item, discussion, announcement.删除 module_item 只将其从模块中删除——底层内容不会被删除。 |
文件和量规
| 工具 | 说明 |
|---|---|
upload_file | 通过Canvas的3步上传协议将本地文件上传到课程文件部分。 |
delete_file | 永久删除文件。不可逆-不通过API回收站。 |
create_rubric | 创建一个量规并将其与作业相关联。看 量规注释 在......下面 |
模块创建(高级)
| 工具 | 说明 |
|---|---|
build_module | 通过以下方式构建模块 mode: "blueprint" (从以下位置渲染命名模板 ~/.config/mcp/canvas-mcp/templates/), "manual" (明确的项目列表), "solution" (与课程模块链接的解决方案模块),或 "clone" (从任何课程中复制一个模块,并替换可选的周数)。 |
破坏性行动
| 工具 | 说明 |
|---|---|
reset_course | 预览或执行完整课程内容重置。 |
注释
dry_run: 默认为 dry_run=false。您将获得一个5分钟后到期的令牌。您必须向LLM提供令牌以确认重置。如果 dry_run=true,无需确认;返回要删除的内容的计数。
替代确认: 用户可以改为提供 confirmation_text 与Canvas课程名称完全匹配(区分大小写),完全跳过令牌流。
始终保存: 注册、课程设置和导航选项卡永远不会被触摸。
出席
| 工具 | 说明 |
|---|---|
import_attendance | 从Zoom参与者CSV导入考勤。两步工作流程: action="parse" 读取CSV,通过4步流水线(持久映射)将Zoom名称与Canvas花名册进行匹配→ 精确→ Levenshtein部分模糊→ 不匹配),并返回标记化结果以供审查。 action="submit" 为匹配的学生发布成绩。支持 min_duration 过滤, dry_run 预览和持久 zoom-name-map.json 用于记忆名称映射。结果为FERPA盲法。 |
智能搜索(Canvas测试版功能)
| 工具 | 说明 |
|---|---|
search_course | 使用Canvas Smart Search(人工智能语义搜索)搜索课程内容。返回带有距离分数的结果——lower=更接近匹配。支持内容类型过滤、距离阈值、结果限制和可选的正文包含。通过 save_threshold: true 将阈值作为新的默认值保留到config中。需要在您的实例上启用Canvas Smart Search测试版。 |
______________________________________________________________________
隐私/FERA
学生姓名和Canvas数字ID是受FERPA保护的PII。当此服务器与云托管的AI助手(如Claude Desktop)一起使用时,每个工具响应都会通过助手的基础设施。为了防止学生数据离开您的机器,所有报告工具在响应到达AI之前都会自动用不透明的会话令牌替换学生身份信息:
[STUDENT_001],[STUDENT_002],…按照首先看到学生的顺序分配,并在每次服务器重启时重置。- 人工智能只考虑令牌——它永远看不到真实姓名或Canvas ID。
- 人类可读的查找表(
[STUDENT_001] → Jane Smith)如图所示 给你 在助手的用户界面和人工智能的响应旁边,这样你就可以随时知道谁是谁,而不需要问。 - 要显式查找令牌,请调用
student_pii(action='resolve', student_token='[STUDENT_001]')--结果仅显示给您,不会添加到AI的上下文中。 - 百叶窗始终打开,不能禁用。
用于保护内存令牌映射的会话密钥是:
- 启动时新生成(从未存储到磁盘)
- 通过以下方式固定在RAM中
mlock在操作系统允许的情况下(防止交换文件暴露) - 已将进程退出归零(
SIGINT,SIGTERM,SIGHUP)
这 --secure-heap=65536 AI助手配置中的标志为加密操作中间体分配了一个锁定的内存区域。将其包含在配置中,如所示 平台特定设置.
有关威胁模型和合规态势的完整详细信息,请参阅 docs/FERPA.md, 文档/安全_建筑.md,以及 docs/PII_ARCHITECTURE.md.
______________________________________________________________________
画布API注释
- 分页 是自动处理的--所有列表操作如下
Link: rel="next"标题。 - 速率限制 --客户观看
X-Rate-Limit-Remaining当其降至10以下时,会增加500ms的延迟。 - 重试 --HTTP 429响应触发指数回退,最多3次尝试。
- 仅限经典测验 -新测验(Canvas测验引擎)有一个不同的API,并且超出了范围。
- 测验创建返回200,而不是201-一个已知的Canvas API异常,客户端可以正确处理。
Rubrics需要赋值(画布限制)
Canvas不支持独立的量规。一个量规 必须 与至少一个作业相关联,或者它进入了一个坏的“僵尸”状态:它出现在课程评价标准列表中,但返回 404 关于个人GET和 500 删除。
为了防止这种情况, create_rubric 总是需要一个 assignment_id 并在单个API调用中创建标题及其关联。如果不将量规链接到作业,则无法创建量规。
在...期间 reset_course,量规清理步骤(步骤8)通过创建临时分配、将僵尸量规与其关联、删除量规(现在可删除),然后删除临时分配来处理任何预先存在的僵尸量规(例如,通过Canvas UI手动创建)。无法恢复的Rubrics在以下回复中报告 rubrics_failed.
其他注意事项:
- 删除页面之前,首页会自动取消设置。
- 文件删除是不可逆的——预览会明确显示文件计数。
______________________________________________________________________
发展
运行测试
# Unit tests (no credentials required)
npm run test:unit
# Integration tests (requires .env.test — see below)
npm run test:integration单元测试模拟所有HTTP 马绍尔语集成测试针对真实的Canvas实例运行。
设置集成测试
创建 .env.test 在项目根目录中:
# Core Canvas configuration
CANVAS_INSTANCE_URL=https://canvas.instructure.com
CANVAS_API_TOKEN=your_test_teacher_token
CANVAS_TEST_COURSE_ID=12345
# Student tokens for the seed script (requires 5 students)
STUDENT0_API_TOKEN=token_0
STUDENT1_API_TOKEN=token_1
STUDENT2_API_TOKEN=token_2
STUDENT3_API_TOKEN=token_3
STUDENT4_API_TOKEN=token_4使用免费 canvas.instructure.com 名为的课程帐户 TEST SANDBOX --把它和你的生产课程完全分开。
- 创建
.env.test包含核心和学生令牌的文件。 - 运行种子脚本以建立测试状态:
npm run seed - 该脚本会自动将剩余的ID(模块、作业等)填充到您的
.env.test文件。 - 运行集成测试:
npm run test:integration
令牌开销分析
npm run count-tokens # exact (requires ANTHROPIC_API_KEY)
npm run count-tokens -- --no-api # estimate without API key
npm run count-tokens -- --dump # also writes raw payloads to tmp/token-dump/构建
npm run build # compiles packages/core and packages/teacher → their dist/ folders项目结构
clients/
└── gemini/ # Gemini CLI hooks for PII blinding (see clients/gemini/docs/SETUP.md)
├── src/
│ ├── before_model.ts # BeforeModel hook — 3-phase fuzzy name matching (case-insensitive, partial, Levenshtein)
│ ├── after_model.ts # AfterModel hook — unblinds tokens in model response
│ └── after_tool.ts # AfterTool hook — progress indicator for canvas-mcp tool calls
├── docs/
│ ├── SETUP.md # Step-by-step hook installation guide
│ ├── HOOK_REFERENCE.md # Hook API reference & behavioral findings
│ ├── FUZZY_MATCHING_REQUIREMENTS.md # 3-phase fuzzy matching specification
│ └── TESTING.md # Hook testing strategy
└── patches/
└── gemini-cli-hookTranslator.patch.md # Required local patch for Gemini CLI (see SETUP.md Step 2b)
packages/
├── core/ # @canvas-mcp/core — shared Canvas API layer
│ ├── src/
│ │ ├── canvas/
│ │ │ ├── client.ts # HTTP client (auth, pagination, rate limiting, retry)
│ │ │ ├── courses.ts # Course & enrollment API calls
│ │ │ ├── modules.ts # Module & module item API calls
│ │ │ ├── assignments.ts # Assignment & assignment-group API calls
│ │ │ ├── quizzes.ts # Classic Quiz API calls
│ │ │ ├── pages.ts # Page API calls (CRUD + front page handling)
│ │ │ ├── discussions.ts # Discussion topic & announcement API calls
│ │ │ ├── files.ts # File upload (3-step Canvas/S3 flow) & delete
│ │ │ ├── rubrics.ts # Rubric CRUD + association API calls
│ │ │ ├── submissions.ts # Grade & submission API calls
│ │ │ └── search.ts # Canvas Smart Search API
│ │ ├── config/
│ │ │ ├── schema.ts # Config types and DEFAULT_CONFIG
│ │ │ └── manager.ts # Read/write ~/.config/mcp/canvas-mcp/config.json
│ │ ├── security/
│ │ │ ├── secure-store.ts # AES-256-GCM in-memory PII store (session tokens, mlock)
│ │ │ └── sidecar-manager.ts# Writes/deletes the PII sidecar file for Gemini CLI hooks
│ │ ├── attendance/
│ │ │ ├── zoom-csv-parser.ts# Parse Zoom participant CSV (column filtering, pronoun/host stripping)
│ │ │ ├── name-matcher.ts # 4-step name matching pipeline (map → exact → fuzzy → unmatched)
│ │ │ ├── zoom-name-map.ts # Persistent JSON map from Zoom names to Canvas user IDs
│ │ │ ├── review-file.ts # Writes ambiguous/unmatched entries for human review
│ │ │ └── types.ts # ZoomParticipant, RosterEntry, MatchResult, ReviewEntry
│ │ ├── matching/
│ │ │ └── levenshtein.ts # Levenshtein edit distance (shared by attendance + Gemini hooks)
│ │ ├── templates/
│ │ │ ├── index.ts # Re-exports from service.ts
│ │ │ ├── service.ts # TemplateService — manifest parsing, Handlebars rendering
│ │ │ ├── seed.ts # Seeds default templates to user config dir on first run
│ │ │ └── defaults/ # Bundled default templates (later-standard, later-review, etc.)
│ │ └── tools/
│ │ └── context.ts # list_courses, set_active_course, get_active_course
│ └── tests/
│ ├── fixtures/
│ │ └── zoom-report-sample.csv # Real Zoom export for parser tests
│ ├── setup/
│ │ └── msw-server.ts # Shared MSW server setup for core unit tests
│ └── unit/
│ ├── attendance/ # name-matcher, zoom-csv-parser, zoom-name-map, review-file tests
│ ├── canvas/ # submissions tests
│ ├── config/ # schema, manager tests
│ ├── matching/ # levenshtein tests
│ ├── templates/ # service tests
│ └── tools/
│ └── context.test.ts
└── teacher/ # @canvas-mcp/teacher — MCP server entry point
├── src/
│ ├── index.ts # MCP server wiring and startup
│ └── tools/
│ ├── attendance.ts # import_attendance (parse + submit, per-server WeakMap state)
│ ├── content.ts # upload_file, create_rubric, delete_file
│ ├── modules.ts # build_module (blueprint / manual / solution / clone)
│ ├── reporting.ts # get_module_summary, get_grades, get_submission_status, student_pii
│ ├── reset.ts # reset_course (dry_run + confirmation gate)
│ └── find.ts # create_item, list_items, find_item, update_item, delete_item, search_course
└── tests/
├── setup/
│ ├── msw-server.ts # Shared MSW server setup for unit tests
│ └── integration-env.ts# Integration test environment loader
├── unit/tools/
│ ├── attendance.test.ts
│ ├── content.test.ts
│ ├── find.test.ts
│ ├── modules.test.ts
│ ├── reporting.test.ts
│ └── reset.test.ts
└── integration/ # Real Canvas API tests, requires .env.test