Skip to main content
Glama
cdmx-in
by cdmx-in

get_task_messages

Retrieve all messages and comments for a specific task in Goodday project management, using the task ID and optional project name for identification.

Instructions

Retrieve all messages/comments for a specific task.

Args: task_short_id: The short ID of the task (e.g., RAD-434) project_name: Optional project name for disambiguation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
task_short_idYes
project_nameNo

Implementation Reference

  • The primary handler function implementing the 'get_task_messages' MCP tool. It finds the task by short ID (across projects or in specified project), fetches messages via Goodday API, formats them with user names and timestamps, and returns a formatted string.
    async def get_task_messages(task_short_id: str, project_name: Optional[str] = None) -> str:
        """Retrieve all messages/comments for a specific task.
    
        Args:
            task_short_id: The short ID of the task (e.g., RAD-434)
            project_name: Optional project name for disambiguation
        """
        task_id = None
        found_in_project = None
        
        # If project name is provided, use it to find the project
        if project_name:
            matched_project, available_projects = await find_project_by_name(project_name)
            if not matched_project:
                return f"Project '{project_name}' not found. Available projects: {', '.join(available_projects[:10])}{'...' if len(available_projects) > 10 else ''}"
            project_id = matched_project.get("id")
            found_in_project = matched_project.get("name")
            
            # Find the task in the specified project
            tasks_data = await make_goodday_request(f"project/{project_id}/tasks")
            if isinstance(tasks_data, list):
                for task in tasks_data:
                    if isinstance(task, dict) and task.get("shortId") == task_short_id:
                        task_id = task.get("id")
                        break
            
            if not task_id:
                return f"Task with short ID '{task_short_id}' not found in project '{found_in_project}'."
        else:
            # Search across all projects
            projects_data = await make_goodday_request("projects")
            if not projects_data or not isinstance(projects_data, list):
                return "Unable to fetch projects."
            
            for proj in projects_data:
                if isinstance(proj, dict):
                    proj_id = proj.get("id")
                    tasks_data = await make_goodday_request(f"project/{proj_id}/tasks")
                    if isinstance(tasks_data, list):
                        for task in tasks_data:
                            if isinstance(task, dict) and task.get("shortId") == task_short_id:
                                task_id = task.get("id")
                                found_in_project = proj.get("name")
                                break
                if task_id:
                    break
            
            if not task_id:
                return f"Task with short ID '{task_short_id}' not found in any project."
    
        # Get task messages
        messages_data = await make_goodday_request(f"task/{task_id}/messages")
        if not messages_data:
            return f"No messages found for task '{task_short_id}'."
        
        if isinstance(messages_data, dict) and "error" in messages_data:
            return f"Unable to fetch messages: {messages_data.get('error', 'Unknown error')}"
        
        if not isinstance(messages_data, list):
            return f"Unexpected response format: {str(messages_data)}"
    
        # Get user mapping
        user_id_to_name = await get_user_mapping()
        
        def user_display(user_id):
            if not user_id:
                return "N/A"
            name = user_id_to_name.get(user_id)
            return f"{name} ({user_id})" if name else user_id
    
        # Format messages
        formatted_messages = []
        for msg in messages_data:
            if not isinstance(msg, dict):
                continue
    
            formatted_msg = f"""
    **Message ID:** {msg.get('id', 'N/A')}
    **Date Created:** {format_timestamp_ist(msg.get('dateCreated', 'N/A'))}
    **From User:** {user_display(msg.get('fromUserId'))}
    **To User:** {user_display(msg.get('toUserId'))}
    **Message:** {msg.get('message', 'No message content')}
    **Task Status ID:** {msg.get('taskStatusId', 'N/A')}
    """.strip()
            formatted_messages.append(formatted_msg)
    
        result = "\n---\n".join(formatted_messages)
        return f"**Messages for Task '{task_short_id}' in project '{found_in_project}' - {len(messages_data)} messages:**\n\n{result}"
  • The @mcp.tool() decorator registers this function as the MCP tool named 'get_task_messages'.
    async def get_task_messages(task_short_id: str, project_name: Optional[str] = None) -> str:
  • Helper function to get user ID to name mapping, used in get_task_messages for displaying user names in messages.
    async def get_user_mapping() -> dict:
        """Get mapping of user IDs to names."""
        data = await make_goodday_request("users")
        user_id_to_name = {}
        if isinstance(data, list):
            for u in data:
                if isinstance(u, dict):
                    user_id_to_name[u.get("id")] = u.get("name", "Unknown")
        return user_id_to_name
  • Helper to format timestamps to IST, used in message formatting.
    def format_timestamp_ist(timestamp_str: str) -> str:
        """Format timestamp to IST timezone."""
        if not timestamp_str or timestamp_str == 'N/A':
            return 'N/A'
        try:
            # Parse the timestamp (assuming it's in ISO format)
            dt = datetime.fromisoformat(timestamp_str.replace('Z', '+00:00'))
            # Convert to IST (UTC+5:30)
            ist_offset = timedelta(hours=5, minutes=30)
            ist_time = dt + ist_offset
            return ist_time.strftime('%Y-%m-%d %H:%M:%S IST')
        except Exception:
            return timestamp_str
  • Helper to resolve project by name, used when project_name is provided.
    async def find_project_by_name(project_name: str) -> tuple[Optional[dict], List[str]]:
        """Find project by name (case-insensitive)."""
        projects_data = await make_goodday_request("projects")
        if not projects_data or not isinstance(projects_data, list):
            return None, []
        
        # Filter out system projects (like sprints) to avoid overwhelming the AI
        filtered_projects = [
            proj for proj in projects_data 
            if isinstance(proj, dict) and proj.get("systemType") != "PROJECT"
        ]
        
        project_name_lower = project_name.lower().strip()
        matched_project = None
        for proj in filtered_projects:
            if not isinstance(proj, dict):
                continue
            current_project_name = proj.get("name", "").lower().strip()
            if current_project_name == project_name_lower:
                matched_project = proj
                break
            if (
                project_name_lower in current_project_name
                or current_project_name in project_name_lower
            ):
                matched_project = proj
                break
        
        available_projects = [
            p.get("name", "Unknown")
            for p in projects_data
            if isinstance(p, dict)
        ]
        return matched_project, available_projects

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/cdmx-in/goodday-mcp'

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