Claude 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.

LLM Mart · 0 points · 10 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download vishalsachdev-canvas-mcp-skills_canvas-bulk-grading-f098b2c.zip · 3 KB
Part of vishalsachdev/canvas-mcp — 8 skills

Install

skills CLI npx skills add https://github.com/vishalsachdev/canvas-mcp/tree/main/skills/canvas-bulk-grading
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install vishalsachdev-canvas-mcp@llmmart
Git git clone https://github.com/vishalsachdev/canvas-mcp.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole vishalsachdev/canvas-mcp collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

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 the Canvas web UI for editing.

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
|   ALWAYS run with dry_run: true first
|
+-- 30+ submissions OR custom grading logic needed
    Use execute_typescript with bulkGrade function
    Grading logic runs locally; only selected output returns to the model
    ALWAYS run with dry_run: true first

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",
    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 (1 second between batches). Canvas rate limits are approximately 700 requests per 10 minutes.
  5. Do not grade without explicit instructor confirmation. Always present the grading plan (rubric mapping, point values, number of students affected) and wait for approval before submitting grades.
  6. Never attach a comment the instructor did not ask for. A submission comment is visible to the student in SpeedGrader, it appends on every call rather than replacing, and it cannot be un-sent. "Assign grade 8" means the grade only. Never generate a comment that restates the grade or narrates that grading happened (e.g. "Graded via automated review") — that reads to the student as a bot mark on their work and carries no feedback. Include a comment only when the instructor asked for written feedback, and then make it feedback about the work.

Example Prompts

  • "Grade Assignment 5 using the rubric"
  • "Show me the rubric for the midterm project and grade all submissions"
  • "Bulk grade all ungraded submissions for Assignment 3 -- give full marks on criterion 1 and 80% on criterion 2"
  • "How many submissions still need grading for the final paper?"
  • "Dry run bulk grading for Assignment 7 so I can review before submitting"
  • "Use code execution to grade all 150 homework submissions with custom logic"

Error Recovery

Error Cause Action
401 Unauthorized Token expired or invalid Regenerate Canvas API token
403 Forbidden Not an instructor/TA for this course Verify Canvas role
404 Not Found Wrong course, assignment, or rubric ID Re-check IDs with list_assignments or list_rubrics
422 Unprocessable Invalid rubric assessment format Verify criterion IDs and point ranges match the rubric
Partial failures in bulk Some grades submitted, others failed Check each status. Unconfirmed assessments may already be saved: inspect Canvas before retrying to avoid duplicate comments. Retry only confirmed unsaved failures
Files (canvas-mcp)
  • SKILL.md 7.7 KB
    ---
    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 the Canvas web UI for editing.
    
    ## 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
    |   ALWAYS run with dry_run: true first
    |
    +-- 30+ submissions OR custom grading logic needed
        Use execute_typescript with bulkGrade function
        Grading logic runs locally; only selected output returns to the model
        ALWAYS run with dry_run: true first
    ```
    
    ### 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",
        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` (1 second between batches). Canvas rate limits are approximately 700 requests per 10 minutes.
    5. **Do not grade without explicit instructor confirmation.** Always present the grading plan (rubric mapping, point values, number of students affected) and wait for approval before submitting grades.
    6. **Never attach a comment the instructor did not ask for.** A submission comment is visible to the student in SpeedGrader, it *appends* on every call rather than replacing, and it cannot be un-sent. "Assign grade 8" means the grade only. Never generate a comment that restates the grade or narrates that grading happened (e.g. "Graded via automated review") — that reads to the student as a bot mark on their work and carries no feedback. Include a comment only when the instructor asked for written feedback, and then make it feedback about the work.
    
    ## Example Prompts
    
    - "Grade Assignment 5 using the rubric"
    - "Show me the rubric for the midterm project and grade all submissions"
    - "Bulk grade all ungraded submissions for Assignment 3 -- give full marks on criterion 1 and 80% on criterion 2"
    - "How many submissions still need grading for the final paper?"
    - "Dry run bulk grading for Assignment 7 so I can review before submitting"
    - "Use code execution to grade all 150 homework submissions with custom logic"
    
    ## Error Recovery
    
    | Error | Cause | Action |
    |-------|-------|--------|
    | 401 Unauthorized | Token expired or invalid | Regenerate Canvas API token |
    | 403 Forbidden | Not an instructor/TA for this course | Verify Canvas role |
    | 404 Not Found | Wrong course, assignment, or rubric ID | Re-check IDs with `list_assignments` or `list_rubrics` |
    | 422 Unprocessable | Invalid rubric assessment format | Verify criterion IDs and point ranges match the rubric |
    | Partial failures in bulk | Some grades submitted, others failed | Check each status. Unconfirmed assessments may already be saved: inspect Canvas before retrying to avoid duplicate comments. Retry only confirmed unsaved failures |
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related