Skip to content
Education
Skill

/canvas-bulk-grading

Bulk grading workflows for Canvas LMS assignments using rubrics. Covers single grading, batch grading, and code execution strategies with safety-first dry runs.

BOOST
From plugin
canvas-mcp
2958 skills
Install
$ npx -y skills add vishalsachdev/canvas-mcp --skill canvas-bulk-grading --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/canvas-bulk-grading

Context preview

The summary Claude sees to decide when to auto-load this skill.

Bulk grading workflows for Canvas LMS assignments using rubrics. Covers single grading, batch grading, and code execution strategies with safety-first dry runs.

SKILL.md

canvas-bulk-grading.SKILL.md
name: canvas-bulk-grading
description: Bulk grading workflows for Canvas LMS assignments using rubrics. Covers single grading, batch grading, and code execution strategies with safety-first dry runs.

Canvas Bulk Grading

Grade Canvas LMS assignments efficiently using rubric-based workflows. This skill requires the Canvas MCP server to be running and authenticated with an instructor or TA token.

Prerequisites

  • Canvas MCP server running and connected
  • Authenticated with an **educator** (instructor/TA) Canvas API token
  • Assignment must exist and have submissions to grade
  • Rubric must be created and associated with the assignment with `use_for_grading=true`. Use `create_rubric` for creation and `associate_rubric` for an existing rubric; use `update_rubric` (two-call preview + token) for text/point edits; add or remove criteria in the Canvas UI.

Workflow

Step 1: Gather Assignment and Rubric Information

Before grading, retrieve the assignment details and its rubric criteria.

get_assignment_details(course_identifier, assignment_id)

Then get the rubric. Use `get_rubric` if the rubric is already linked to the assignment, or `list_rubrics` to browse all rubrics in the course:

get_rubric(course_identifier, assignment_id=assignment_id)
list_rubrics(course_identifier)
get_rubric(course_identifier, rubric_id=rubric_id)

Record the **criterion IDs** (often prefixed with underscore, e.g., `_8027`) and **rating IDs** from the rubric response. These are required for rubric-based grading.

Step 2: List Submissions

Retrieve all student submissions to determine how many need grading:

list_submissions(course_identifier, assignment_id)

Note the `user_id` for each submission and the `workflow_state` (submitted, graded, pending_review). Count the submissions that need grading to determine which strategy to use.

Step 3: Choose a Grading Strategy

Use this decision tree based on the number of submissions to grade:

How many submissions need grading?
|
+-- 1-9 submissions
|   Use grade_with_rubric (one call per submission)
|
+-- 10-29 submissions
|   Use bulk_grade_submissions (concurrent batch processing)
|   Set max_concurrent: 5, rate_limit_delay: 1.0
|   Run with dry_run: true first (Safety Rule 1)
|
+-- 30+ submissions OR custom grading logic needed
    Use execute_typescript with bulkGrade function
    Grading logic runs locally; only selected output returns to the model
    Pass dryRun: true on the first run

Strategy A: Single Grading (1-9 submissions)

Call `grade_with_rubric` once per student:

grade_with_rubric(
  course_identifier,
  assignment_id,
  user_id,
  rubric_assessment: {
    "criterion_id": {
      "points": <number>,
      "rating_id": "<string>",    // optional
      "comments": "<string>"      // optional per-criterion feedback
    }
  },
  comment: "Overall feedback"     // optional
)

Strategy B: Bulk Grading (10-29 submissions)

**Always dry run first.** Build the grades dictionary mapping each user ID to their grade data, then validate before submitting:

bulk_grade_submissions(
  course_identifier,
  assignment_id,
  grades: {
    "user_id_1": {
      "rubric_assessment": {
        "criterion_id": {"points": 85, "comments": "Good analysis"}
      },
      "comment": "Overall feedback"
    },
    "user_id_2": {
      "grade": 92,
      "comment": "Excellent work"
    }
  },
  dry_run: true,          // VALIDATE FIRST
  max_concurrent: 5,
  rate_limit_delay: 1.0
)

Review the dry run output. If everything looks correct, re-run with `dry_run: false`.

Strategy C: Code Execution (30+ submissions)

For large classes or custom grading logic, use `execute_typescript` to run grading locally. This avoids loading all submission data into the conversation context.

execute_typescript(code: `
  import { bulkGrade } from './canvas/grading/bulkGrade.js';

  await bulkGrade({
    courseIdentifier: "COURSE_ID",
    assignmentId: "ASSIGNMENT_ID",
    dryRun: true,  // preview first; re-run with false after review
    gradingFunction: (submission) => {
      // Custom grading logic runs locally -- no token cost
      const notebook = submission.attachments?.find(
        f => f.filename.endsWith('.ipynb')
      );

      if (!notebook) return null; // skip ungraded

      return {
        points: 100,
        rubricAssessment: { "_8027": { points: 100 } }
        // No `comment` here on purpose -- see Safety Rule 6. Add one only when
        // the instructor asked for written feedback, and make it feedback.
      };
    }
  });
`)

Use `search_canvas_tools("grading", "signatures")` to discover available TypeScript modules and their function signatures before writing code.

Token Efficiency

The three strategies have very different token costs:

| Strategy | When | Token Cost | Why | |----------|------|------------|-----| | `grade_with_rubric` | 1-9 submissions | Low | Few round-trips, small payloads | | `bulk_grade_submissions` | 10-29 submissions | Medium | One call with batch data | | `execute_typescript` | 30+ submissions | Workload-dependent | Grading logic runs locally; only the code and selected output need to enter model context |

The key insight: as submission count grows, sending grading logic to the server can use less model context than bringing all submission data into the conversation.

Safety Rules

1. **Always dry run first.** For `bulk_grade_submissions`, set `dry_run: true` before the real run. Review the output for correctness. 2. **Verify the rubric before grading.** Confirm criterion IDs, point ranges, and rating IDs match the assignment rubric. Mismatched IDs cause silent failures or incorrect grades. 3. **Spot-check before bulk.** For Strategy B and C, grade 1-2 submissions manually with `grade_with_rubric` first. Verify in Canvas that the grade and rubric feedback appear correctly. 4. **Respect rate limits.** Use `max_concurrent: 5` and `rate_limit_delay: 1.0`

Read more
Ships withcanvas-mcp

MCP server for Canvas LMS with up to 126 tools and 8 agent skills. Designed for Claude Desktop, Cursor, Codex, Windsurf, and 40+ other agents; setup and capabilities vary by client.

Get the whole plugin

Other skills on canvas-mcp.