Skip to main content
Glama
dev-in-black

OpenProject MCP Server

by dev-in-black

list_work_packages

Retrieve and filter work packages from OpenProject with pagination options to manage project tasks efficiently.

Instructions

List work packages with optional filtering and pagination.

Args:
    project_id: Optional project ID to filter work packages
    filters: Optional JSON filter string
    page: Page number (default: 1)
    page_size: Items per page (default: 20)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_idNo
filtersNo
pageNo
page_sizeNo

Implementation Reference

  • Core handler implementation that queries the OpenProject API for work packages with optional project filter, JSON filters, and pagination, then formats the results into a markdown list.
    async def list_work_packages(
        project_id: str | None = None,
        filters: str | None = None,
        page: int = 1,
        page_size: int = 20,
    ) -> str:
        """List work packages with optional filtering and pagination.
    
        Args:
            project_id: Optional project ID to filter work packages
            filters: Optional JSON filter string (e.g., '[{"status_id":{"operator":"=","values":["1"]}}]')
            page: Page number (default: 1)
            page_size: Items per page (default: 20)
    
        Returns:
            Formatted markdown string with work packages list
        """
        client = OpenProjectClient()
    
        try:
            params: dict[str, Any] = {
                "pageSize": page_size,
                "offset": (page - 1) * page_size,
            }
    
            if filters:
                params["filters"] = filters
    
            if project_id:
                endpoint = f"projects/{project_id}/work_packages"
                title = f"Work Packages in Project '{project_id}'"
            else:
                endpoint = "work_packages"
                title = "All Work Packages"
    
            result = await client.get(endpoint, params=params)
    
            # Extract metadata
            total = result.get("total", 0)
            count = result.get("count", 0)
    
            # Get work packages
            work_packages = get_embedded_collection(result, "elements")
    
            # Format as markdown
            markdown = f"""# {title}
    
    **Total:** {total} | **Showing:** {count} | **Page:** {page}
    
    ---
    """
    
            if not work_packages:
                markdown += "\n*No work packages found.*\n"
            else:
                for wp in work_packages:
                    markdown += "\n" + _format_work_package_list_item(wp) + "\n"
    
            return markdown
    
        finally:
            await client.close()
  • MCP tool registration via @mcp.tool() decorator on the entry-point function that delegates to the core implementation.
    @mcp.tool()
    async def list_work_packages(
        project_id: str | None = None,
        filters: str | None = None,
        page: int = 1,
        page_size: int = 20,
    ):
        """List work packages with optional filtering and pagination.
    
        Args:
            project_id: Optional project ID to filter work packages
            filters: Optional JSON filter string
            page: Page number (default: 1)
            page_size: Items per page (default: 20)
        """
        return await work_packages.list_work_packages(
            project_id=project_id,
            filters=filters,
            page=page,
            page_size=page_size,
        )
  • Supporting function that formats a single work package dictionary into a detailed markdown list item, extracting embedded entities and links.
    def _format_work_package_list_item(wp: dict[str, Any]) -> str:
        """Format a work package as a concise list item.
    
        Args:
            wp: Work package object from OpenProject API
    
        Returns:
            Formatted markdown string for list display
        """
        wp_id = wp.get("id", "N/A")
        subject = wp.get("subject", "No subject")
    
        # Get embedded resources
        embedded = wp.get("_embedded", {})
        links = wp.get("_links", {})
    
        # Type
        type_obj = embedded.get("type", {})
        type_name = type_obj.get("name", "N/A")
    
        # Status
        status_obj = embedded.get("status", {})
        status_name = status_obj.get("name", "N/A")
    
        # Priority
        priority_obj = embedded.get("priority", {})
        priority_name = priority_obj.get("name", "N/A")
    
        # Project
        project_obj = embedded.get("project", {})
        project_name = project_obj.get("name", "N/A")
    
        # Assignee
        assignee_link = links.get("assignee", {})
        assignee_name = assignee_link.get("title") if assignee_link.get("href") else "Unassigned"
    
        # Parent
        parent_link = links.get("parent", {})
        parent_name = parent_link.get("title") if parent_link.get("href") else None
    
        # Due date
        due_date = wp.get("dueDate", "No due date")
    
        markdown = f"""### #{wp_id}: {subject}
    - **Type:** {type_name} | **Status:** {status_name} | **Priority:** {priority_name}
    - **Project:** {project_name} | **Assignee:** {assignee_name}
    - **Due Date:** {due_date}"""
    
        if parent_name:
            markdown += f" | **Parent:** {parent_name}"
    
        return markdown

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/dev-in-black/openproject-mcp'

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