Skip to main content
Glama

tool_get_question_rubric

Retrieve grading rubric items for a specific question using course and question IDs, enabling instructors to access rubric data without requiring a submission ID.

Instructions

Get rubric items for a question without needing a submission ID.

Auto-discovers a submission to extract rubric data. Use when you know
the question_id from outline but don't have a submission ID yet.

Args:
    course_id: The Gradescope course ID.
    question_id: The question ID from outline.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
course_idYes
question_idYes

Implementation Reference

  • The handler function `get_question_rubric` fetches and returns the rubric items for a given question ID by auto-discovering a valid submission or by parsing the grading page.
    def get_question_rubric(course_id: str, question_id: str) -> str:
        """Get rubric items for a question without requiring a submission ID.
    
        Useful when you know the question_id from get_assignment_outline but
        don't have a specific submission ID. Auto-discovers a submission to
        extract rubric data.
    
        Args:
            course_id: The Gradescope course ID.
            question_id: The question ID from outline.
        """
        if not course_id or not question_id:
            return "Error: both course_id and question_id are required."
    
        try:
            conn = get_connection()
            ctx = None
    
            # Path 1: submissions page
            url1 = (
                f"{conn.gradescope_base_url}/courses/{course_id}"
                f"/questions/{question_id}/submissions"
            )
            resp = conn.session.get(url1)
            if resp.status_code == 200:
                match = re.search(
                    rf"/courses/{course_id}/questions/{question_id}/submissions/(\d+)/grade",
                    resp.text,
                )
                if match:
                    ctx = _get_grading_context(course_id, question_id, match.group(1))
    
            # Path 2: grade page (may redirect to a specific submission)
            if ctx is None:
                url2 = (
                    f"{conn.gradescope_base_url}/courses/{course_id}"
                    f"/questions/{question_id}/grade"
                )
                resp2 = conn.session.get(url2, allow_redirects=True)
                if resp2.status_code == 200:
                    sub_match = re.search(
                        rf"/questions/{question_id}/submissions/(\d+)",
                        resp2.url,
                    )
                    if sub_match:
                        ctx = _get_grading_context(
                            course_id, question_id, sub_match.group(1)
                        )
                    else:
                        # Check if the page itself has SubmissionGrader props
                        from bs4 import BeautifulSoup
                        soup = BeautifulSoup(resp2.text, "html.parser")
                        grader = soup.find(attrs={"data-react-class": "SubmissionGrader"})
                        if grader:
                            import json as _json
                            props = _json.loads(grader.get("data-react-props", "{}"))
                            rubric_items = props.get("rubric_items", [])
                            if rubric_items:
                                question = props.get("question", {})
                                ctx = {"props": props}
    
            if ctx is None:
                return (
                    f"No submissions found for question `{question_id}`. "
                    "Cannot access rubric. The question may be in a special "
                    "assignment type. Try using `get_submission_grading_context` "
                    "with a known Question Submission ID instead."
                )
        except AuthError as e:
            return f"Authentication error: {e}"
        except ValueError as e:
            return f"Error: {e}"
        except Exception as e:
            return f"Error fetching rubric: {e}"
    
        props = ctx["props"]
        question = props.get("question", {})
        # Use props.rubric_items (same source as grading context), fallback to question.rubric
        rubric_items = props.get("rubric_items", []) or question.get("rubric", [])
    
        if not rubric_items:
            return f"No rubric items found for question `{question_id}`. You can create them with `tool_create_rubric_item`."
    
        weight = question.get("weight", "?")
        scoring_type = question.get("scoring_type", "negative")
    
        lines = [f"## Rubric for Question `{question_id}`\n"]
        lines.append(f"**Weight:** {weight} pts")
        lines.append(f"**Scoring:** {scoring_type}\n")
        lines.append("| ID | Description | Points |")
        lines.append("|----|-------------|--------|")
    
        for item in rubric_items:
            desc = item.get("description", "(no description)")
            # Escape pipes in description
            desc = desc.replace("|", "\\|")
            lines.append(
                f"| `{item['id']}` | {desc} | {item.get('weight', 0)} |"
            )
    
        return "\n".join(lines)
  • Tool registration for `tool_get_question_rubric` in the MCP server.
    def tool_get_question_rubric(
        course_id: str,
        question_id: str,
    ) -> str:
        """Get rubric items for a question without needing a submission ID.
    
        Auto-discovers a submission to extract rubric data. Use when you know
        the question_id from outline but don't have a submission ID yet.
    
        Args:
            course_id: The Gradescope course ID.
            question_id: The question ID from outline.
        """
        return get_question_rubric(course_id, question_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