Skip to main content
Glama

get_comments

Retrieve all comments from projects and tasks with full context including text, author, timestamps, attachments, and discussion threads.

Instructions

Get all comments across projects and tasks with full context.

Returns comprehensive comment data including:

  • Comment text, author, and timestamp

  • Parent entity (project, task, or other) with details

  • Discussion threads and replies

  • Attachments and file references

  • Mentions of team members or clients

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_idNoProductive project ID to filter comments by
task_idNoProductive task ID to filter comments by
page_numberNoPage number for pagination
page_sizeNoOptional number of comments per page (max 200)
extra_filtersNoAdditional Productive query filters using API syntax. Common filters: filter[project_id][eq] (ID), filter[task_id][eq] (ID), filter[discussion_id][eq] (ID).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • Core handler function implementing the get_comments tool logic: builds API parameters for pagination, filtering by project/task, adds sorting, calls the Productive client API, sanitizes response with filter_response, logs via ctx, handles API and general errors.
    async def get_comments(
        ctx: Context,
        project_id: int = None,
        task_id: int = None,
        page_number: int = None,
        page_size: int = config.items_per_page,
        extra_filters: dict = None
    ) -> ToolResult:
        """List comments with optional filters and pagination.
    
        Developer notes:
        - Pass-through for extra_filters (e.g., discussion_id, page_id, task_id).
        - Enforces configurable default page[size] if not provided.
        - Sort defaults to "-created_at" (most recent first).
        - Applies utils.filter_response to sanitize.
        - Uses consistent scalar filters: filter[project_id][eq], filter[task_id][eq]
        """
        try:
            await ctx.info("Fetching comments")
            params = {}
            if page_number is not None:
                params["page[number]"] = page_number
            params["page[size]"] = page_size
            if project_id is not None:
                params["filter[project_id][eq]"] = project_id
            if task_id is not None:
                params["filter[task_id][eq]"] = task_id
            if extra_filters:
                params.update(extra_filters)
    
            # Add default sorting
            params["sort"] = "-created_at"
    
            result = await client.get_comments(params=params if params else None)
            await ctx.info("Successfully retrieved comments")
    
            filtered = filter_response(result)
    
            return filtered
    
        except ProductiveAPIError as e:
            await _handle_productive_api_error(ctx, e, "comments")
        except Exception as e:
            await ctx.error(f"Unexpected error fetching comments: {str(e)}")
            raise e
  • server.py:368-403 (registration)
    MCP tool registration for 'get_comments' using @mcp.tool decorator. Defines input schema via Annotated parameters with descriptions and delegates to the core handler in tools.get_comments.
    async def get_comments(
        ctx: Context,
        project_id: Annotated[
            int, Field(description="Productive project ID to filter comments by")
        ] = None,
        task_id: Annotated[
            int, Field(description="Productive task ID to filter comments by")
        ] = None,
        page_number: Annotated[int, Field(description="Page number for pagination")] = None,
        page_size: Annotated[
            int, Field(description="Optional number of comments per page (max 200)")
        ] = None,
        extra_filters: Annotated[
            dict,
            Field(
                description="Additional Productive query filters using API syntax. Common filters: filter[project_id][eq] (ID), filter[task_id][eq] (ID), filter[discussion_id][eq] (ID)."
            ),
        ] = None,
    ) -> Dict[str, Any]:
        """Get all comments across projects and tasks with full context.
    
        Returns comprehensive comment data including:
        - Comment text, author, and timestamp
        - Parent entity (project, task, or other) with details
        - Discussion threads and replies
        - Attachments and file references
        - Mentions of team members or clients
        """
        return await tools.get_comments(
            ctx,
            project_id=project_id,
            task_id=task_id,
            page_number=page_number,
            page_size=page_size,
            extra_filters=extra_filters,
        )
  • Low-level API client helper that performs the actual HTTP GET request to Productive's /comments endpoint with provided parameters.
    async def get_comments(self, params: Optional[dict] = None) -> Dict[str, Any]:
        """Get all comments
        """
        return await self._request("GET", "/comments", params=params)
  • Input schema definition using Pydantic Annotated fields for tool parameters in the MCP registration.
    async def get_comments(
        ctx: Context,
        project_id: Annotated[
            int, Field(description="Productive project ID to filter comments by")
        ] = None,
        task_id: Annotated[
            int, Field(description="Productive task ID to filter comments by")
        ] = None,
        page_number: Annotated[int, Field(description="Page number for pagination")] = None,
        page_size: Annotated[
            int, Field(description="Optional number of comments per page (max 200)")
        ] = None,
        extra_filters: Annotated[
            dict,
            Field(
                description="Additional Productive query filters using API syntax. Common filters: filter[project_id][eq] (ID), filter[task_id][eq] (ID), filter[discussion_id][eq] (ID)."
            ),
        ] = None,
    ) -> Dict[str, Any]:
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions 'Returns comprehensive comment data' and lists data types, which is helpful, but lacks critical behavioral details: it doesn't specify if this is a read-only operation, potential rate limits, authentication requirements, or pagination behavior beyond the parameters. For a tool with 5 parameters and no annotations, this is insufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded: the first sentence states the core purpose, followed by a bulleted list of return data. Every sentence earns its place by adding value. It could be slightly more concise by integrating the bullet points into prose, but it's well-structured and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, no annotations, but 100% schema coverage and an output schema (implied by 'Has output schema: true'), the description is moderately complete. It explains what data is returned, which complements the output schema, but lacks behavioral context and usage guidelines. For a read operation with good schema support, it's adequate but has clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 5 parameters thoroughly. The description adds no parameter-specific information beyond what's in the schema. It mentions 'full context' and data types, but doesn't explain how parameters affect the output. Baseline 3 is appropriate when the schema does all the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get all comments across projects and tasks with full context.' It specifies the verb ('Get') and resource ('comments'), and distinguishes it from siblings by mentioning 'full context' and comprehensive data. However, it doesn't explicitly differentiate from potential comment-related siblings (none listed), so it's not a perfect 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention any sibling tools or contexts where other tools might be more appropriate. The only implied usage is for retrieving comprehensive comment data, but no explicit when/when-not or alternative recommendations are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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/druellan/Productive-GET-MCP'

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