Skip to main content
Glama

tool_get_grading_progress

Monitor grading progress for an assignment by viewing question-level status, graded submissions count, assigned graders, and completion percentages.

Instructions

Get the grading progress dashboard for an assignment.

Shows each question's grading status: how many submissions have been graded,
assigned graders, and completion percentage. Requires instructor/TA access.

Args:
    course_id: The Gradescope course ID.
    assignment_id: The assignment ID.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
course_idYes
assignment_idYes

Implementation Reference

  • Implementation of the `get_grading_progress` tool, which fetches the grading dashboard for an assignment and returns a markdown summary of grading progress per question.
    def get_grading_progress(course_id: str, assignment_id: str) -> str:
        """Get the grading progress dashboard for an assignment.
    
        Shows each question's grading status: how many submissions have been graded,
        assigned graders, and completion percentage. Requires instructor/TA access.
    
        Args:
            course_id: The Gradescope course ID.
            assignment_id: The assignment ID.
        """
        if not course_id or not assignment_id:
            return "Error: both course_id and assignment_id are required."
    
        try:
            conn = get_connection()
            url = f"{conn.gradescope_base_url}/courses/{course_id}/assignments/{assignment_id}/grade.json"
            resp = conn.session.get(url)
        except AuthError as e:
            return f"Authentication error: {e}"
        except Exception as e:
            return f"Error fetching grading progress: {e}"
    
        if resp.status_code != 200:
            return f"Error: Cannot access grading dashboard (status {resp.status_code})."
    
        try:
            data = resp.json()
        except Exception:
            return "Error: Failed to parse grading dashboard response."
    
        # Extract assignment data
        assignments = data.get("assignments", {})
        if not assignments:
            return f"No grading data found for assignment `{assignment_id}`."
    
        # assignments can be dict or list
        if isinstance(assignments, dict):
            assignment_data = assignments.get(assignment_id, {})
            if not assignment_data:
                # Try first value
                assignment_data = next(iter(assignments.values()), {})
        elif isinstance(assignments, list):
            assignment_data = assignments[0] if assignments else {}
        else:
            assignment_data = {}
    
        questions = assignment_data.get("questions", {})
        if not questions:
            return f"No questions found in grading dashboard for assignment `{assignment_id}`."
    
        lines = [f"## Grading Progress — Assignment {assignment_id}\n"]
    
        # Build question tree for nice formatting
        total_graded = 0
        total_count = 0
    
        lines.append("| Question | Type | Graded | Total | Progress | Graders |")
        lines.append("|----------|------|--------|-------|----------|---------|")
    
        # Group questions — two passes to handle any ordering
        question_groups = {}  # parent_id -> group data with children
        child_map = {}  # parent_id -> list of child questions
        standalone = []
    
        # First pass: identify groups and collect children
        for qid, q in questions.items():
            if q.get("question_group"):
                question_groups[q["id"]] = {**q, "children": []}
            elif q.get("parent_id"):
                child_map.setdefault(q["parent_id"], []).append(q)
            else:
                standalone.append(q)
    
        # Second pass: attach children to their groups
        for parent_id, children in child_map.items():
            if parent_id in question_groups:
                question_groups[parent_id]["children"].extend(children)
            else:
                # Parent not found as a group — treat as standalone
                standalone.extend(children)
    
        group_num = 0
        for gid, group in sorted(question_groups.items(), key=lambda x: x[1].get("index", 0)):
            group_num += 1
            group_title = group.get("title", "")
            children = sorted(group.get("children", []), key=lambda x: x.get("index", 0))
    
            for i, child in enumerate(children, 1):
                graded = child.get("total_graded_count", 0)
                count = child.get("total_count", 0)
                total_graded += graded
                total_count += count
                pct = f"{graded / count * 100:.0f}%" if count > 0 else "N/A"
                graders = ", ".join(g.get("name", "?") for g in child.get("graders", []))
                child_title = child.get("title", "")
                label = f"Q{group_num}.{i}"
                if child_title:
                    label += f" {child_title}"
                qtype = child.get("type", "")
                lines.append(
                    f"| {label} (`{child['id']}`) | {qtype} | {graded} | {count} | {pct} | {graders or 'Unassigned'} |"
                )
    
        for idx, sq in enumerate(sorted(standalone, key=lambda x: x.get("index", 0)), 1):
            graded_count = sq.get("total_graded_count", 0)
            count = sq.get("total_count", 0)
            total_graded += graded_count
            total_count += count
            pct = f"{graded_count / count * 100:.0f}%" if count > 0 else "N/A"
            graders = ", ".join(g.get("name", "?") for g in sq.get("graders", []))
            sq_title = sq.get("title", "")
            label = f"Q{group_num + idx}"
            if sq_title:
                label += f" {sq_title}"
            lines.append(
                f"| {label} (`{sq['id']}`) | {sq.get('type', '')} | {graded_count} | {count} | {pct} | {graders or 'Unassigned'} |"
            )
    
        lines.append("")
    
        # Summary
        if total_count > 0:
            overall_pct = total_graded / total_count * 100
            lines.append(f"**Overall progress:** {total_graded}/{total_count} ({overall_pct:.0f}%)")
    
        # Action button
        action = data.get("action_button", {})
        if action:
            lines.append(f"\n**Next step:** [{action.get('text', 'Continue')}]({action.get('link', '')})")
    
        return "\n".join(lines)
  • Registration of the `tool_get_grading_progress` MCP tool in the server definition.
    @mcp.tool()
    def tool_get_grading_progress(course_id: str, assignment_id: str) -> str:
        """Get the grading progress dashboard for an assignment.
    
        Shows each question's grading status: how many submissions have been graded,
        assigned graders, and completion percentage. Requires instructor/TA access.
    
        Args:
            course_id: The Gradescope course ID.
            assignment_id: The assignment ID.
        """
        return get_grading_progress(course_id, assignment_id)

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/Yuanpeng-Li/gradescope-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server