Skip to main content
Glama
dev-in-black

OpenProject MCP Server

by dev-in-black

get_work_package

Retrieve detailed information about a specific work package from OpenProject, including task details, assignees, and relationships.

Instructions

Get detailed information about a work package.

Args:
    work_package_id: Work package ID

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
work_package_idYes

Implementation Reference

  • The main handler function that fetches a work package by ID from the OpenProject API using OpenProjectClient and formats the response as a markdown string using the helper function.
    async def get_work_package(work_package_id: int) -> str:
        """Get detailed information about a work package.
    
        Args:
            work_package_id: Work package ID
    
        Returns:
            Formatted markdown string with work package details
        """
        client = OpenProjectClient()
    
        try:
            result = await client.get(f"work_packages/{work_package_id}")
            return _format_work_package_markdown(result)
        finally:
            await client.close()
  • Registration of the 'get_work_package' tool using the @mcp.tool() decorator in the FastMCP server. This thin wrapper delegates execution to the implementation in tools/work_packages.py.
    @mcp.tool()
    async def get_work_package(work_package_id: int):
        """Get detailed information about a work package.
    
        Args:
            work_package_id: Work package ID
        """
        return await work_packages.get_work_package(work_package_id=work_package_id)
  • Supporting helper function that takes a raw work package dictionary from the API and formats it into a comprehensive markdown report including all key fields like ID, subject, status, assignee, dates, costs, hierarchy, etc.
    def _format_work_package_markdown(wp: dict[str, Any]) -> str:
        """Format a work package as markdown.
    
        Args:
            wp: Work package object from OpenProject API
    
        Returns:
            Formatted markdown string
        """
        # Basic information
        wp_id = wp.get("id", "N/A")
        subject = wp.get("subject", "No subject")
        lock_version = wp.get("lockVersion", "N/A")
        created_at = wp.get("createdAt", "N/A")
        updated_at = wp.get("updatedAt", "N/A")
    
        # Description
        description_obj = wp.get("description", {})
        description = description_obj.get("raw", "") if description_obj else ""
    
        # Dates
        start_date = wp.get("startDate", "Not set")
        due_date = wp.get("dueDate", "Not set")
        estimated_time = wp.get("estimatedTime", "Not set")
    
        # Costs
        labor_costs = wp.get("laborCosts", "0.00")
        material_costs = wp.get("materialCosts", "0.00")
        overall_costs = wp.get("overallCosts", "0.00")
        spent_time = wp.get("spentTime", "PT0S")
    
        # Get embedded resources
        embedded = wp.get("_embedded", {})
    
        # Type
        type_obj = embedded.get("type", {})
        type_name = type_obj.get("name", "N/A")
        type_color = type_obj.get("color", "")
    
        # Status
        status_obj = embedded.get("status", {})
        status_name = status_obj.get("name", "N/A")
        status_color = status_obj.get("color", "")
    
        # 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")
        project_id = project_obj.get("identifier", "N/A")
    
        # Author
        author_obj = embedded.get("author", {})
        author_name = author_obj.get("name", "Unknown")
    
        # Assignee (from _links)
        links = wp.get("_links", {})
        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_info = parent_link.get("title") if parent_link.get("href") else "None"
    
        # Ancestors
        ancestors = links.get("ancestors", [])
        ancestor_info = []
        for ancestor in ancestors:
            ancestor_info.append(ancestor.get("title", "Unknown"))
    
        # Children
        children = links.get("children", [])
        children_count = len(children) if children else 0
    
        # Attachments
        attachments_obj = embedded.get("attachments", {})
        attachments_count = attachments_obj.get("total", 0)
    
        # Relations
        relations_obj = embedded.get("relations", {})
        relations_count = relations_obj.get("total", 0)
    
        # Build markdown
        markdown = f"""# Work Package #{wp_id}: {subject}
    
    ## Basic Information
    - **Type:** {type_name}
    - **Status:** {status_name}
    - **Priority:** {priority_name}
    - **Project:** {project_name} (`{project_id}`)
    - **Lock Version:** {lock_version}
    
    ## People
    - **Author:** {author_name}
    - **Assignee:** {assignee_name}
    
    ## Dates & Schedule
    - **Start Date:** {start_date}
    - **Due Date:** {due_date}
    - **Estimated Time:** {estimated_time}
    - **Spent Time:** {spent_time}
    
    ## Costs
    - **Labor Costs:** {labor_costs}
    - **Material Costs:** {material_costs}
    - **Overall Costs:** {overall_costs}
    
    ## Hierarchy
    - **Parent:** {parent_info}"""
    
        if ancestor_info:
            markdown += "\n- **Ancestors:** " + " > ".join(ancestor_info)
    
        if children_count > 0:
            markdown += f"\n- **Children:** {children_count} child work package(s)"
    
        markdown += f"""
    
    ## Additional Info
    - **Attachments:** {attachments_count}
    - **Relations:** {relations_count}
    - **Created:** {created_at}
    - **Updated:** {updated_at}
    """
    
        if description:
            markdown += f"""
    ## Description
    ```
    {description}
    ```
    """
    
        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