Skip to main content
Glama

get_rubric_details

Retrieve detailed rubric criteria and scoring information from Canvas courses to understand assessment requirements and grading standards.

Instructions

Get detailed rubric criteria and scoring information.

Args: course_identifier: The Canvas course code (e.g., badm_554_120251_246794) or ID rubric_id: The Canvas rubric ID

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
course_identifierYes
rubric_idYes

Implementation Reference

  • The core handler function for the 'get_rubric_details' MCP tool. Fetches rubric details via Canvas API endpoint /courses/{course_id}/rubrics/{rubric_id}, parses the response, and formats a detailed textual summary of the rubric including criteria, ratings, points, and metadata.
    @validate_params async def get_rubric_details(course_identifier: str | int, rubric_id: str | int) -> str: """Get detailed rubric criteria and scoring information. Args: course_identifier: The Canvas course code (e.g., badm_554_120251_246794) or ID rubric_id: The Canvas rubric ID """ course_id = await get_course_id(course_identifier) rubric_id_str = str(rubric_id) # Get detailed rubric information response = await make_canvas_request( "get", f"/courses/{course_id}/rubrics/{rubric_id_str}", params={"include[]": ["assessments", "associations"]} ) if "error" in response: return f"Error fetching rubric details: {response['error']}" # Extract rubric details title = response.get("title", "Untitled Rubric") context_code = response.get("context_code", "") context_type = response.get("context_type", "") points_possible = response.get("points_possible", 0) reusable = response.get("reusable", False) read_only = response.get("read_only", False) data = response.get("data", []) course_display = await get_course_code(course_id) or course_identifier result = f"Detailed Rubric Information for Course {course_display}:\n\n" result += f"Title: {title}\n" result += f"Rubric ID: {rubric_id}\n" result += f"Context: {context_type} ({context_code})\n" result += f"Total Points: {points_possible}\n" result += f"Reusable: {'Yes' if reusable else 'No'}\n" result += f"Read Only: {'Yes' if read_only else 'No'}\n\n" # Detailed criteria and ratings if data: result += "Detailed Criteria and Ratings:\n" result += "=" * 50 + "\n" for i, criterion in enumerate(data, 1): criterion_id = criterion.get("id", "N/A") description = criterion.get("description", "No description") long_description = criterion.get("long_description", "") points = criterion.get("points", 0) ratings = criterion.get("ratings", []) result += f"\nCriterion #{i}: {description}\n" result += f"ID: {criterion_id}\n" result += f"Points: {points}\n" if long_description: result += f"Description: {truncate_text(long_description, 200)}\n" if ratings: result += f"Rating Levels ({len(ratings)}):\n" for j, rating in enumerate(ratings): rating_description = rating.get("description", "No description") rating_points = rating.get("points", 0) rating_id = rating.get("id", "N/A") result += f" {j+1}. {rating_description} ({rating_points} pts) [ID: {rating_id}]\n" if rating.get("long_description"): result += f" {truncate_text(rating.get('long_description'), 100)}\n" result += "\n" return result
  • Top-level registration call in register_all_tools that invokes register_rubric_tools(mcp), which defines and registers the get_rubric_details tool using @mcp.tool() decorator.
    register_rubric_tools(mcp)
  • Helper function used by rubric tools to validate and parse rubric criteria JSON structure.
    def validate_rubric_criteria(criteria_json: str) -> dict[str, Any]: """Validate and parse rubric criteria JSON structure. Args: criteria_json: JSON string containing rubric criteria Returns: Parsed criteria dictionary Raises: ValueError: If JSON is invalid or structure is incorrect """ # Preprocess the string to handle common issues cleaned_json = preprocess_criteria_string(criteria_json) try: criteria = json.loads(cleaned_json) except json.JSONDecodeError as e: # Try alternative parsing methods if JSON fails try: # Maybe it's a Python literal string representation import ast criteria = ast.literal_eval(cleaned_json) if isinstance(criteria, dict): # Successfully parsed as Python literal, continue with validation pass else: raise ValueError("Parsed result is not a dictionary") except (ValueError, SyntaxError): # Both JSON and literal_eval failed, provide detailed error error_msg = f"Invalid JSON format: {str(e)}\n" error_msg += f"Original string length: {len(criteria_json)}\n" error_msg += f"Cleaned string length: {len(cleaned_json)}\n" error_msg += f"First 200 characters of original: {repr(criteria_json[:200])}\n" error_msg += f"First 200 characters of cleaned: {repr(cleaned_json[:200])}\n" if len(cleaned_json) > 200: error_msg += f"Last 100 characters of cleaned: {repr(cleaned_json[-100:])}" error_msg += "\nAlso failed to parse as Python literal. Please ensure the criteria is valid JSON." raise ValueError(error_msg) from e if not isinstance(criteria, dict): raise ValueError("Criteria must be a JSON object (dictionary)") # Validate each criterion for criterion_key, criterion_data in criteria.items(): if not isinstance(criterion_data, dict): raise ValueError(f"Criterion {criterion_key} must be an object") if "description" not in criterion_data: raise ValueError(f"Criterion {criterion_key} must have a 'description' field") if "points" not in criterion_data: raise ValueError(f"Criterion {criterion_key} must have a 'points' field") try: points = float(criterion_data["points"]) if points < 0: raise ValueError(f"Criterion {criterion_key} points must be non-negative") except (ValueError, TypeError) as err: raise ValueError(f"Criterion {criterion_key} points must be a valid number") from err # Validate ratings if present - handle both object and array formats if "ratings" in criterion_data: ratings = criterion_data["ratings"] # Handle both object and array formats if isinstance(ratings, dict): # Object format: {"1": {...}, "2": {...}} for rating_key, rating_data in ratings.items(): if not isinstance(rating_data, dict): raise ValueError(f"Rating {rating_key} in criterion {criterion_key} must be an object") if "description" not in rating_data: raise ValueError(f"Rating {rating_key} in criterion {criterion_key} must have a 'description' field") if "points" not in rating_data: raise ValueError(f"Rating {rating_key} in criterion {criterion_key} must have a 'points' field") try: rating_points = float(rating_data["points"]) if rating_points < 0: raise ValueError(f"Rating {rating_key} points must be non-negative") except (ValueError, TypeError) as err: raise ValueError(f"Rating {rating_key} points must be a valid number") from err elif isinstance(ratings, list): # Array format: [{"description": ..., "points": ...}, ...] for i, rating_data in enumerate(ratings): if not isinstance(rating_data, dict): raise ValueError(f"Rating {i} in criterion {criterion_key} must be an object") if "description" not in rating_data: raise ValueError(f"Rating {i} in criterion {criterion_key} must have a 'description' field") if "points" not in rating_data: raise ValueError(f"Rating {i} in criterion {criterion_key} must have a 'points' field") try: rating_points = float(rating_data["points"]) if rating_points < 0: raise ValueError(f"Rating {i} points must be non-negative") except (ValueError, TypeError) as err: raise ValueError(f"Rating {i} points must be a valid number") from err else: raise ValueError(f"Criterion {criterion_key} ratings must be an object or array") return criteria
  • Imports the register_rubric_tools function, enabling its use in server.py for tool registration.
    from .rubrics import register_rubric_tools
Install Server

Other Tools

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/vishalsachdev/canvas-mcp'

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