get_course_content_overview
Retrieve a structured overview of Canvas course content including pages, modules, and syllabus information to quickly understand course structure and materials.
Instructions
Get a comprehensive overview of course content including pages, modules, and syllabus.
Args:
course_identifier: The Canvas course code (e.g., badm_554_120251_246794) or ID
include_pages: Whether to include pages information
include_modules: Whether to include modules and their items
include_syllabus: Whether to include syllabus content
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| course_identifier | Yes | ||
| include_modules | No | ||
| include_pages | No | ||
| include_syllabus | No |
Implementation Reference
- src/canvas_mcp/tools/courses.py:123-253 (handler)The primary handler function for the 'get_course_content_overview' tool. It resolves the course ID, fetches course details, optionally retrieves pages, modules, and syllabus body via Canvas API calls, processes the data (including HTML stripping for syllabus), and returns a formatted string overview of the course content.@mcp.tool() @validate_params async def get_course_content_overview(course_identifier: str | int, include_pages: bool = True, include_modules: bool = True, include_syllabus: bool = True) -> str: """Get a comprehensive overview of course content including pages, modules, and syllabus. Args: course_identifier: The Canvas course code (e.g., badm_554_120251_246794) or ID include_pages: Whether to include pages information include_modules: Whether to include modules and their items include_syllabus: Whether to include syllabus content """ course_id = await get_course_id(course_identifier) overview_sections = [] # Get course details for context course_response = await make_canvas_request("get", f"/courses/{course_id}") if "error" not in course_response: course_name = course_response.get("name", "Unknown Course") overview_sections.append(f"Course: {course_name}") # Get pages if requested if include_pages: pages = await fetch_all_paginated_results(f"/courses/{course_id}/pages", {"per_page": 100}) if isinstance(pages, list): published_pages = [p for p in pages if p.get("published", False)] unpublished_pages = [p for p in pages if not p.get("published", False)] front_pages = [p for p in pages if p.get("front_page", False)] pages_summary = [ "\nPages Summary:", f" Total Pages: {len(pages)}", f" Published: {len(published_pages)}", f" Unpublished: {len(unpublished_pages)}", f" Front Pages: {len(front_pages)}" ] if published_pages: pages_summary.append("\nRecent Published Pages:") # Sort by updated_at and show first 5 sorted_pages = sorted(published_pages, key=lambda x: x.get("updated_at", ""), reverse=True) for page in sorted_pages[:5]: title = page.get("title", "Untitled") updated = format_date(page.get("updated_at")) pages_summary.append(f" {title} (Updated: {updated})") overview_sections.append("\n".join(pages_summary)) # Get modules if requested if include_modules: modules = await fetch_all_paginated_results(f"/courses/{course_id}/modules", {"per_page": 100}) if isinstance(modules, list): modules_summary = [ "\nModules Summary:", f" Total Modules: {len(modules)}" ] # Count module items by type across all modules item_type_counts = {} total_items = 0 for module in modules[:10]: # Limit to first 10 modules to avoid too many API calls module_id = module.get("id") if module_id: items = await fetch_all_paginated_results( f"/courses/{course_id}/modules/{module_id}/items", {"per_page": 100} ) if isinstance(items, list): total_items += len(items) for item in items: item_type = item.get("type", "Unknown") item_type_counts[item_type] = item_type_counts.get(item_type, 0) + 1 modules_summary.append(f" Total Items Analyzed: {total_items}") if item_type_counts: modules_summary.append(" Item Types:") for item_type, count in sorted(item_type_counts.items()): modules_summary.append(f" {item_type}: {count}") # Show module structure for first few modules if modules: modules_summary.append("\nModule Structure (first 3):") for module in modules[:3]: name = module.get("name", "Unnamed") state = module.get("state", "unknown") modules_summary.append(f" {name} (Status: {state})") overview_sections.append("\n".join(modules_summary)) # Get syllabus content if requested if include_syllabus: # Fetch the course details with syllabus_body included course_with_syllabus = await make_canvas_request( "get", f"/courses/{course_id}", params={"include[]": "syllabus_body"} ) if "error" not in course_with_syllabus: syllabus_body = course_with_syllabus.get('syllabus_body', '') if syllabus_body: # Clean the HTML content clean_syllabus = strip_html_tags(syllabus_body) # For overview, limit to first 1000 characters if len(clean_syllabus) > 1000: clean_syllabus = clean_syllabus[:1000] + "..." syllabus_summary = [ "\nSyllabus Content:", # Indent the content "\n".join([f" {line}" for line in clean_syllabus.split('\n') if line.strip()]) ] overview_sections.append("\n".join(syllabus_summary)) else: overview_sections.append("\nSyllabus Content: No syllabus content found") else: overview_sections.append("\nSyllabus Content: Error fetching syllabus") # Try to get the course code for display course_display = await get_course_code(course_id) or course_identifier result = f"Content Overview for Course {course_display}:" + "\n".join(overview_sections) return result
- src/canvas_mcp/server.py:47-47 (registration)Top-level registration call within register_all_tools that invokes register_course_tools(mcp), which in turn defines and registers the get_course_content_overview tool using FastMCP's @tool decorator.register_course_tools(mcp)
- Helper utility function used within the tool to strip HTML tags and clean syllabus body text for plain text overview.def strip_html_tags(html_content: str) -> str: """Remove HTML tags and clean up text content.""" if not html_content: return "" # Remove HTML tags clean_text = re.sub(r'<[^>]+>', '', html_content) # Replace common HTML entities clean_text = clean_text.replace(' ', ' ') clean_text = clean_text.replace('&', '&') clean_text = clean_text.replace('<', '<') clean_text = clean_text.replace('>', '>') clean_text = clean_text.replace('"', '"') # Clean up whitespace clean_text = re.sub(r'\s+', ' ', clean_text) clean_text = clean_text.strip() return clean_text