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
| Name | Required | Description | Default |
|---|---|---|---|
| course_id | Yes | ||
| question_id | Yes |
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) - src/gradescope_mcp/server.py:439-452 (registration)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)