Skip to main content
Glama

get_discussion_entry_details

Retrieve detailed information about a specific Canvas discussion entry, including all replies, by providing course, topic, and entry identifiers.

Instructions

Get detailed information about a specific discussion entry including all its replies.

    Args:
        course_identifier: The Canvas course code (e.g., badm_554_120251_246794) or ID
        topic_id: The Canvas discussion topic ID
        entry_id: The Canvas discussion entry ID
        include_replies: Whether to fetch and include replies (default: True)
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
course_identifierYes
topic_idYes
entry_idYes
include_repliesNo

Implementation Reference

  • The core handler function implementing the 'get_discussion_entry_details' tool. It fetches a specific discussion entry's details from Canvas API using multiple endpoints (view, entry_list, entries, replies), handles fallbacks, anonymizes data, and formats a comprehensive response including content and replies.
    @validate_params
    async def get_discussion_entry_details(course_identifier: str | int,
                                         topic_id: str | int,
                                         entry_id: str | int,
                                         include_replies: bool = True) -> str:
        """Get detailed information about a specific discussion entry including all its replies.
    
        Args:
            course_identifier: The Canvas course code (e.g., badm_554_120251_246794) or ID
            topic_id: The Canvas discussion topic ID
            entry_id: The Canvas discussion entry ID
            include_replies: Whether to fetch and include replies (default: True)
        """
        course_id = await get_course_id(course_identifier)
    
        # Method 1: Try to get entry details from the discussion view endpoint
        entry_response = None
        replies = []
    
        try:
            # First try the discussion view endpoint which includes all entries
            view_response = await make_canvas_request(
                "get", f"/courses/{course_id}/discussion_topics/{topic_id}/view"
            )
    
            if "error" not in view_response and "view" in view_response:
                # Find our specific entry in the view
                for entry in view_response.get("view", []):
                    if str(entry.get("id")) == str(entry_id):
                        entry_response = entry
                        if include_replies:
                            replies = entry.get("replies", [])
                        break
        except Exception as e:
            log_warning(
                "Failed to fetch discussion view for entry details",
                exc=e,
                course_id=course_id,
                topic_id=topic_id,
                entry_id=entry_id
            )
    
        # Method 2: If view method failed, try the entry_list endpoint
        if not entry_response:
            try:
                entry_list_response = await make_canvas_request(
                    "get", f"/courses/{course_id}/discussion_topics/{topic_id}/entry_list",
                    params={"ids[]": entry_id}
                )
    
                if "error" not in entry_list_response and isinstance(entry_list_response, list):
                    if entry_list_response:
                        entry_response = entry_list_response[0]
            except Exception as e:
                log_warning(
                    "Failed to fetch entry from entry_list",
                    exc=e,
                    course_id=course_id,
                    topic_id=topic_id,
                    entry_id=entry_id
                )
    
        # Method 3: Fallback to getting all entries and finding our target
        if not entry_response:
            try:
                all_entries = await fetch_all_paginated_results(
                    f"/courses/{course_id}/discussion_topics/{topic_id}/entries",
                    {"per_page": 100}
                )
    
                if not isinstance(all_entries, dict) or "error" not in all_entries:
                    for entry in all_entries:
                        if str(entry.get("id")) == str(entry_id):
                            entry_response = entry
                            # Get recent_replies from this method
                            if include_replies:
                                replies = entry.get("recent_replies", [])
                            break
            except Exception as e:
                log_warning(
                    "Failed to fetch all entries as fallback",
                    exc=e,
                    course_id=course_id,
                    topic_id=topic_id,
                    entry_id=entry_id
                )
    
        # If we still don't have the entry, return error
        if not entry_response:
            return f"Error: Could not find discussion entry {entry_id} in topic {topic_id}. The entry may not exist or you may not have permission to view it."
    
        # Method 4: If we have the entry but no replies yet, try the replies endpoint
        if include_replies and not replies:
            try:
                replies_response = await fetch_all_paginated_results(
                    f"/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies",
                    {"per_page": 100}
                )
    
                if not isinstance(replies_response, dict) or "error" not in replies_response:
                    replies = replies_response
            except Exception as e:
                log_warning(
                    "Failed to fetch entry replies from replies endpoint",
                    exc=e,
                    course_id=course_id,
                    topic_id=topic_id,
                    entry_id=entry_id
                )
    
        # Get topic details for context
        topic_response = await make_canvas_request(
            "get", f"/courses/{course_id}/discussion_topics/{topic_id}"
        )
    
        topic_title = "Unknown Topic"
        if "error" not in topic_response:
            topic_title = topic_response.get("title", "Unknown Topic")
    
        # Format the entry details
        course_display = await get_course_code(course_id) or course_identifier
    
        user_id = entry_response.get("user_id")
        user_name = entry_response.get("user_name", "Unknown user")
        message = entry_response.get("message", "")
        created_at = format_date(entry_response.get("created_at"))
        updated_at = format_date(entry_response.get("updated_at"))
        read_state = entry_response.get("read_state", "unknown")
    
        result = f"Discussion Entry Details for '{topic_title}' in Course {course_display}:\n\n"
        result += f"Topic ID: {topic_id}\n"
        result += f"Entry ID: {entry_id}\n"
        result += f"Author: {user_name} (ID: {user_id})\n"
        result += f"Posted: {created_at}\n"
    
        if updated_at != "N/A" and updated_at != created_at:
            result += f"Updated: {updated_at}\n"
    
        result += f"Read State: {read_state.title()}\n"
        result += f"\nContent:\n{message}\n"
    
        # Format replies
        if include_replies:
            if replies:
                result += f"\nReplies ({len(replies)}):\n"
                result += "=" * 50 + "\n"
    
                for i, reply in enumerate(replies, 1):
                    reply_id = reply.get("id")
                    reply_user_name = reply.get("user_name", "Unknown user")
                    reply_message = reply.get("message", "")
                    reply_created_at = format_date(reply.get("created_at"))
    
                    result += f"\nReply #{i}:\n"
                    result += f"Reply ID: {reply_id}\n"
                    result += f"Author: {reply_user_name}\n"
                    result += f"Posted: {reply_created_at}\n"
                    result += f"Content:\n{reply_message}\n"
            else:
                result += "\nNo replies found for this entry."
        else:
            result += "\n(Replies not included - set include_replies=True to fetch them)"
    
        return result
  • The registration of discussion tools, including 'get_discussion_entry_details', occurs here by calling register_discussion_tools(mcp) during server startup.
    register_discussion_tools(mcp)
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