diff --git a/plane_mcp/tools/__init__.py b/plane_mcp/tools/__init__.py index 457748e..3bedb31 100644 --- a/plane_mcp/tools/__init__.py +++ b/plane_mcp/tools/__init__.py @@ -26,7 +26,14 @@ def register_tools(mcp: FastMCP) -> None: - """Register all tools with the MCP server.""" + """ + Register all Plane MCP tools onto the provided MCP server. + + Registers each feature-specific toolset (unified, project, work items, work item activity, work item comments, work item links, work item relations, work logs, cycles, users, modules, initiatives, intake, labels, pages, work item properties, work item types, states, workspaces, epics, and milestones) in a fixed sequence. Exceptions raised by individual registration functions are not caught and will propagate. + + Parameters: + mcp (FastMCP): The MCP server instance on which to register all tools. + """ register_unified_tools(mcp) register_project_tools(mcp) register_work_item_tools(mcp) diff --git a/plane_mcp/tools/cycles.py b/plane_mcp/tools/cycles.py index c23edb5..6f5be1a 100644 --- a/plane_mcp/tools/cycles.py +++ b/plane_mcp/tools/cycles.py @@ -12,7 +12,92 @@ def register_cycle_tools(mcp: FastMCP) -> None: - """Register all cycle-related tools with the MCP server.""" + """ + Create a new cycle in the specified project. + + Parameters: + project_id (str): UUID of the project to create the cycle in. + name (str): Cycle name. + owned_by (str): UUID of the user who will own the cycle. + description (str | None): Optional cycle description. + start_date (str | None): Optional start date in ISO 8601 format. + end_date (str | None): Optional end date in ISO 8601 format. + external_source (str | None): Optional external system source name. + external_id (str | None): Optional external system identifier. + timezone (str | None): Optional timezone identifier. + + Returns: + Cycle: The created Cycle object. + """ + """ + Update fields of an existing cycle. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to update. + name (str | None): New cycle name, if updating. + description (str | None): New description, if updating. + start_date (str | None): New start date in ISO 8601 format, if updating. + end_date (str | None): New end date in ISO 8601 format, if updating. + owned_by (str | None): UUID of the new owner, if updating. + external_source (str | None): External system source name, if updating. + external_id (str | None): External system identifier, if updating. + timezone (str | None): Timezone identifier, if updating. + + Returns: + Cycle: The updated Cycle object. + """ + """ + Delete a cycle by its ID within the given project. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to delete. + """ + """ + Add one or more work items (issues) to a cycle. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to add work items to. + issue_ids (list[str]): List of work item (issue) UUIDs to add. + """ + """ + Remove a single work item from a cycle. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to remove the work item from. + work_item_id (str): UUID of the work item to remove. + """ + """ + Transfer all work items from a source cycle to another target cycle. + + Parameters: + project_id (str): UUID of the project containing the cycles. + cycle_id (str): UUID of the source cycle whose work items will be transferred. + new_cycle_id (str): UUID of the target cycle to receive the work items. + """ + """ + Archive a cycle. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to archive. + + Returns: + bool: `True` if the cycle was archived successfully, `False` otherwise. + """ + """ + Unarchive a cycle. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to unarchive. + + Returns: + bool: `True` if the cycle was unarchived successfully, `False` otherwise. + """ @mcp.tool() def create_cycle( @@ -27,22 +112,21 @@ def create_cycle( timezone: str | None = None, ) -> Cycle: """ - Create a new cycle. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - name: Cycle name - owned_by: UUID of the user who owns the cycle - description: Cycle description - start_date: Cycle start date (ISO 8601 format) - end_date: Cycle end date (ISO 8601 format) - external_source: External system source name - external_id: External system identifier - timezone: Cycle timezone - + Create a new cycle in the specified project. + + Parameters: + project_id (str): UUID of the project to contain the cycle. + name (str): Cycle name. + owned_by (str): UUID of the user who owns the cycle. + description (str | None): Optional cycle description. + start_date (str | None): Optional cycle start date in ISO 8601 format (e.g., "YYYY-MM-DD" or full timestamp). + end_date (str | None): Optional cycle end date in ISO 8601 format. + external_source (str | None): Optional external system source name. + external_id (str | None): Optional identifier from the external system. + timezone (str | None): Optional IANA timezone name for the cycle (e.g., "UTC", "America/Los_Angeles"). + Returns: - Created Cycle object + Cycle: The created Cycle. """ client, workspace_slug = get_plane_client_context() @@ -74,23 +158,22 @@ def update_cycle( timezone: str | None = None, ) -> Cycle: """ - Update a cycle by ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - cycle_id: UUID of the cycle - name: Cycle name - description: Cycle description - start_date: Cycle start date (ISO 8601 format) - end_date: Cycle end date (ISO 8601 format) - owned_by: UUID of the user who owns the cycle - external_source: External system source name - external_id: External system identifier - timezone: Cycle timezone - + Update a cycle by ID, applying only the fields that are provided. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to update. + name (str | None): New cycle name, or `None` to leave unchanged. + description (str | None): New cycle description, or `None` to leave unchanged. + start_date (str | None): New start date in ISO 8601 format, or `None` to leave unchanged. + end_date (str | None): New end date in ISO 8601 format, or `None` to leave unchanged. + owned_by (str | None): UUID of the user who will own the cycle, or `None` to leave unchanged. + external_source (str | None): External system source name, or `None` to leave unchanged. + external_id (str | None): External system identifier, or `None` to leave unchanged. + timezone (str | None): Cycle timezone, or `None` to leave unchanged. + Returns: - Updated Cycle object + Updated Cycle object """ client, workspace_slug = get_plane_client_context() @@ -110,12 +193,11 @@ def update_cycle( @mcp.tool() def delete_cycle(project_id: str, cycle_id: str) -> None: """ - Delete a cycle by ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - cycle_id: UUID of the cycle + Delete the cycle identified by `cycle_id` within the specified project. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the cycle to delete. """ client, workspace_slug = get_plane_client_context() client.cycles.delete(workspace_slug=workspace_slug, project_id=project_id, cycle_id=cycle_id) @@ -127,13 +209,12 @@ def add_work_items_to_cycle( issue_ids: list[str], ) -> None: """ - Add work items to a cycle. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - cycle_id: UUID of the cycle - issue_ids: List of work item IDs to add to the cycle + Add the specified work items to the given cycle in the project. + + Parameters: + project_id (str): UUID of the project containing the cycle. + cycle_id (str): UUID of the target cycle. + issue_ids (list[str]): List of work item IDs to add to the cycle. """ client, workspace_slug = get_plane_client_context() client.cycles.add_work_items( @@ -150,13 +231,12 @@ def remove_work_item_from_cycle( work_item_id: str, ) -> None: """ - Remove a work item from a cycle. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - cycle_id: UUID of the cycle - work_item_id: UUID of the work item to remove + Remove a work item from the specified cycle in a project. + + Parameters: + project_id (str): UUID of the project. + cycle_id (str): UUID of the cycle. + work_item_id (str): UUID of the work item to remove. """ client, workspace_slug = get_plane_client_context() client.cycles.remove_work_item( @@ -173,13 +253,12 @@ def transfer_cycle_work_items( new_cycle_id: str, ) -> None: """ - Transfer work items from one cycle to another. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - cycle_id: UUID of the source cycle - new_cycle_id: UUID of the target cycle to transfer issues to + Transfer all work items from one cycle to another within a project. + + Parameters: + project_id (str): UUID of the project containing the cycles. + cycle_id (str): UUID of the source cycle whose work items will be moved. + new_cycle_id (str): UUID of the destination cycle that will receive the work items. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/epics.py b/plane_mcp/tools/epics.py index 990ed74..29d3b4d 100644 --- a/plane_mcp/tools/epics.py +++ b/plane_mcp/tools/epics.py @@ -19,7 +19,14 @@ def register_epic_tools(mcp: FastMCP) -> None: """Register all epic-related tools with the MCP server.""" def _get_epic_work_item_type(client: PlaneClient, workspace_slug: str, project_id: str) -> WorkItemType | None: - """Helper function to get the work item type ID for epics.""" + """ + Finds the project's work item type that is marked as an epic. + + Searches the work item types for the given workspace and project and returns the first type whose `is_epic` attribute is truthy. + + Returns: + WorkItemType | None: The work item type designated as an epic if found, `None` otherwise. + """ response = client.work_item_types.list( workspace_slug=workspace_slug, project_id=project_id, @@ -52,31 +59,20 @@ def create_epic( estimate_point: str | None = None, ) -> Epic: """ - Create a new epic. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - name: Epic name (required) - assignees: List of user IDs to assign to the epic - labels: List of label IDs to attach to the epic - type_id: UUID of the epic type - point: Story point value - description_html: HTML description of the epic - description_stripped: Plain text description (stripped of HTML) - priority: Priority level (urgent, high, medium, low, none) - start_date: Start date (ISO 8601 format) - target_date: Target/end date (ISO 8601 format) - sort_order: Sort order value - is_draft: Whether the epic is a draft - external_source: External system source name - external_id: External system identifier - parent: UUID of the parent epic - state: UUID of the state - estimate_point: Estimate point value - + Create a new epic work item in the specified project. + + If `priority` is provided but not one of the allowed PriorityEnum values, it will be ignored (treated as no priority). Raises ValueError if the project has no work item type marked as an epic. + + Parameters: + project_id: UUID of the project where the epic will be created. + name: Title of the epic. + priority: Desired priority value; ignored if not one of the allowed PriorityEnum literals. + Returns: - Created WorkItem object + Epic: The created epic resource. + + Raises: + ValueError: If no work item type with `is_epic=True` exists in the project. """ client, workspace_slug = get_plane_client_context() @@ -208,14 +204,11 @@ def delete_epic( epic_id: str, ) -> None: """ - Delete an epic by ID. - - Args: - project_id: UUID of the project - epic_id: UUID of the epic - - Returns: - None + Delete the epic identified by epic_id from the given project. + + Parameters: + project_id (str): UUID of the project containing the epic. + epic_id (str): UUID of the epic to delete. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/initiatives.py b/plane_mcp/tools/initiatives.py index 70946b7..71360c1 100644 --- a/plane_mcp/tools/initiatives.py +++ b/plane_mcp/tools/initiatives.py @@ -12,7 +12,46 @@ def register_initiative_tools(mcp: FastMCP) -> None: - """Register all initiative-related tools with the MCP server.""" + """ + Register initiative-related MCP tools (create, update, delete) on the provided FastMCP instance. + """ + """ + Create a new initiative in the current workspace. + + Parameters: + name (str): Initiative name. + description_html (str | None): HTML description of the initiative. + start_date (str | None): ISO 8601 start date. + end_date (str | None): ISO 8601 end date. + logo_props (dict | None): Logo properties. + state (InitiativeState | str | None): Initiative state (e.g., "DRAFT", "PLANNED", "ACTIVE", "COMPLETED", "CLOSED"). + lead (str | None): UUID of the user who leads the initiative. + + Returns: + Initiative: The created initiative object. + """ + """ + Update an existing initiative by ID in the current workspace. + + Parameters: + initiative_id (str): UUID of the initiative to update. + name (str | None): New initiative name. + description_html (str | None): New HTML description. + start_date (str | None): New ISO 8601 start date. + end_date (str | None): New ISO 8601 end date. + logo_props (dict | None): New logo properties. + state (InitiativeState | str | None): New initiative state (e.g., "DRAFT", "PLANNED", "ACTIVE", "COMPLETED", "CLOSED"). + lead (str | None): UUID of the user who leads the initiative. + + Returns: + Initiative: The updated initiative object. + """ + """ + Delete an initiative by ID from the current workspace. + + Parameters: + initiative_id (str): UUID of the initiative to delete. + """ @mcp.tool() def create_initiative( @@ -25,20 +64,19 @@ def create_initiative( lead: str | None = None, ) -> Initiative: """ - Create a new initiative in the workspace. - - Args: - workspace_slug: The workspace slug identifier - name: Initiative name - description_html: HTML description of the initiative - start_date: Initiative start date (ISO 8601 format) - end_date: Initiative end date (ISO 8601 format) - logo_props: Logo properties dictionary - state: Initiative state (DRAFT, PLANNED, ACTIVE, COMPLETED, CLOSED) - lead: UUID of the user who leads the initiative - + Create a new initiative in the current Plane workspace. + + Parameters: + name (str): Initiative name. + description_html (str | None): Optional HTML description. + start_date (str | None): Optional start date in ISO 8601 format. + end_date (str | None): Optional end date in ISO 8601 format. + logo_props (dict | None): Optional dictionary of logo properties. + state (InitiativeState | str | None): Optional initiative state, e.g. "DRAFT", "PLANNED", "ACTIVE", "COMPLETED", or "CLOSED". + lead (str | None): Optional UUID string of the user who leads the initiative. + Returns: - Created Initiative object + Initiative: The created Initiative object. """ client, workspace_slug = get_plane_client_context() @@ -66,21 +104,20 @@ def update_initiative( lead: str | None = None, ) -> Initiative: """ - Update an initiative by ID. - - Args: - workspace_slug: The workspace slug identifier - initiative_id: UUID of the initiative - name: Initiative name - description_html: HTML description of the initiative - start_date: Initiative start date (ISO 8601 format) - end_date: Initiative end date (ISO 8601 format) - logo_props: Logo properties dictionary - state: Initiative state (DRAFT, PLANNED, ACTIVE, COMPLETED, CLOSED) - lead: UUID of the user who leads the initiative - + Update an existing initiative's fields by its ID. + + Parameters: + initiative_id (str): UUID of the initiative to update. + name (str | None): New initiative name. + description_html (str | None): HTML description content. + start_date (str | None): Start date in ISO 8601 format (YYYY-MM-DD or full timestamp). + end_date (str | None): End date in ISO 8601 format (YYYY-MM-DD or full timestamp). + logo_props (dict | None): Dictionary of logo properties (e.g., URL, alt text). + state (InitiativeState | str | None): Initiative state (e.g., "DRAFT", "PLANNED", "ACTIVE", "COMPLETED", "CLOSED"). + lead (str | None): UUID of the user who will be the initiative lead. + Returns: - Updated Initiative object + Initiative: The updated Initiative object. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/intake.py b/plane_mcp/tools/intake.py index 81b0b08..c8564e0 100644 --- a/plane_mcp/tools/intake.py +++ b/plane_mcp/tools/intake.py @@ -21,15 +21,14 @@ def create_intake_work_item( data: dict[str, Any], ) -> IntakeWorkItem: """ - Create a new intake work item in a project. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - data: Intake work item data as a dictionary - + Create an intake work item in the specified project. + + Parameters: + project_id (str): UUID of the target project. + data (dict[str, Any]): Mapping of fields for the new intake work item; must conform to the CreateIntakeWorkItem schema. + Returns: - Created IntakeWorkItem object + IntakeWorkItem: The created intake work item. """ client, workspace_slug = get_plane_client_context() @@ -44,17 +43,14 @@ def update_intake_work_item( data: dict[str, Any], ) -> IntakeWorkItem: """ - Update an intake work item by work item ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - work_item_id: UUID of the work item (use the issue field from - IntakeWorkItem response, not the intake work item ID) - data: Updated intake work item data as a dictionary - + Update an existing intake work item for a project. + + Parameters: + work_item_id (str): The work item identifier as exposed in the intake response's `issue` field (use this value rather than any internal intake work item ID). + data (dict[str, Any]): Mapping of intake work item fields to update; the payload will be validated against the intake update schema. + Returns: - Updated IntakeWorkItem object + IntakeWorkItem: The updated intake work item. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/labels.py b/plane_mcp/tools/labels.py index 8882c09..0f61b35 100644 --- a/plane_mcp/tools/labels.py +++ b/plane_mcp/tools/labels.py @@ -67,21 +67,21 @@ def update_label( external_id: str | None = None, ) -> Label: """ - Update a label by ID. - - Args: - project_id: UUID of the project - label_id: UUID of the label - name: Label name - color: Label color (hex color code) - description: Label description - parent: UUID of the parent label (for nested labels) - sort_order: Sort order for the label - external_source: External system source name - external_id: External system identifier - + Update an existing label in the specified project. + + Parameters: + project_id: UUID of the project containing the label. + label_id: UUID of the label to update. + name: New label name, if provided. + color: Hex color code for the label, if provided. + description: New description for the label, if provided. + parent: UUID of the parent label for nesting, if provided. + sort_order: Numeric sort order for label positioning, if provided. + external_source: Name of the external system source, if provided. + external_id: Identifier from the external system, if provided. + Returns: - Updated Label object + Label representing the updated label. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/milestones.py b/plane_mcp/tools/milestones.py index 7824053..54c9a19 100644 --- a/plane_mcp/tools/milestones.py +++ b/plane_mcp/tools/milestones.py @@ -24,17 +24,17 @@ def create_milestone( external_id: str | None = None, ) -> Milestone: """ - Create a new milestone. - - Args: - project_id: UUID of the project - title: Milestone title - target_date: Target date for the milestone (ISO 8601 format) - external_source: External system source name - external_id: External system identifier - + Create a milestone in the specified project. + + Parameters: + project_id (str): UUID of the project to attach the milestone to. + title (str): Milestone title. + target_date (str | None): Target date in ISO 8601 format, or None. + external_source (str | None): Name of the external system that provided this milestone, or None. + external_id (str | None): Identifier from the external system, or None. + Returns: - Created Milestone object + Milestone: The created Milestone object. """ client, workspace_slug = get_plane_client_context() @@ -57,18 +57,18 @@ def update_milestone( external_id: str | None = None, ) -> Milestone: """ - Update a milestone by ID. - - Args: - project_id: UUID of the project - milestone_id: UUID of the milestone - title: Milestone title - target_date: Target date for the milestone (ISO 8601 format) - external_source: External system source name - external_id: External system identifier - + Update a milestone by its ID. + + Parameters: + project_id (str): UUID of the project containing the milestone. + milestone_id (str): UUID of the milestone to update. + title (str | None): New milestone title, or `None` to leave unchanged. + target_date (str | None): New target date in ISO 8601 format, or `None` to leave unchanged. + external_source (str | None): Name of the external system associated with the milestone, or `None`. + external_id (str | None): Identifier in the external system, or `None`. + Returns: - Updated Milestone object + Milestone: The updated Milestone object. """ client, workspace_slug = get_plane_client_context() @@ -128,11 +128,11 @@ def remove_work_items_from_milestone( ) -> None: """ Remove work items from a milestone. - - Args: - project_id: UUID of the project - milestone_id: UUID of the milestone - issue_ids: List of work item IDs to remove from the milestone + + Parameters: + project_id (str): UUID of the project containing the milestone. + milestone_id (str): UUID of the milestone to update. + issue_ids (list[str]): List of work item IDs to remove from the milestone. """ client, workspace_slug = get_plane_client_context() client.milestones.remove_work_items( diff --git a/plane_mcp/tools/modules.py b/plane_mcp/tools/modules.py index 84d4b9a..55dc54a 100644 --- a/plane_mcp/tools/modules.py +++ b/plane_mcp/tools/modules.py @@ -15,6 +15,80 @@ def register_module_tools(mcp: FastMCP) -> None: """Register all module-related tools with the MCP server.""" + """ + Create a new module in the specified project. + + Parameters: + project_id (str): UUID of the project. + name (str): Module name. + description (str | None): Module description. + start_date (str | None): Module start date in ISO 8601 format. + target_date (str | None): Module target/end date in ISO 8601 format. + status (str | None): Module status; allowed values: "backlog", "planned", "in-progress", "paused", "completed", "cancelled". + lead (str | None): UUID of the user who leads the module. + members (list[str] | None): List of user IDs who are members of the module. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + + Returns: + Module: The created module. + """ + """ + Update an existing module by ID. + + Parameters: + project_id (str): UUID of the project. + module_id (str): UUID of the module to update. + name (str | None): New module name. + description (str | None): New module description. + start_date (str | None): Module start date in ISO 8601 format. + target_date (str | None): Module target/end date in ISO 8601 format. + status (str | None): Module status; allowed values: "backlog", "planned", "in-progress", "paused", "completed", "cancelled". + lead (str | None): UUID of the user who leads the module. + members (list[str] | None): List of user IDs who are members of the module. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + + Returns: + Module: The updated module. + """ + """ + Delete a module by ID. + + Parameters: + project_id (str): UUID of the project. + module_id (str): UUID of the module to delete. + """ + """ + Add work items to a module. + + Parameters: + project_id (str): UUID of the project. + module_id (str): UUID of the module. + issue_ids (list[str]): List of work item IDs to add to the module. + """ + """ + Remove a work item from a module. + + Parameters: + project_id (str): UUID of the project. + module_id (str): UUID of the module. + work_item_id (str): UUID of the work item to remove. + """ + """ + Archive a module. + + Parameters: + project_id (str): UUID of the project. + module_id (str): UUID of the module to archive. + """ + """ + Unarchive a module. + + Parameters: + project_id (str): UUID of the project. + module_id (str): UUID of the module to unarchive. + """ @mcp.tool() def create_module( @@ -30,23 +104,24 @@ def create_module( external_id: str | None = None, ) -> Module: """ - Create a new module. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - name: Module name - description: Module description - start_date: Module start date (ISO 8601 format) - target_date: Module target/end date (ISO 8601 format) - status: Module status (backlog, planned, in-progress, paused, completed, cancelled) - lead: UUID of the user who leads the module - members: List of user IDs who are members of the module - external_source: External system source name - external_id: External system identifier - + Create a new module within the specified project. + + If `status` is not one of the allowed ModuleStatusEnum values, the module's status will be left unset. + + Parameters: + project_id (str): UUID of the project to contain the module. + name (str): Module name. + description (str | None): Module description. + start_date (str | None): Module start date in ISO 8601 format. + target_date (str | None): Module target/end date in ISO 8601 format. + status (str | None): Desired module status; valid values are the members of `ModuleStatusEnum`. If invalid, the status will be ignored. + lead (str | None): UUID of the user who leads the module. + members (list[str] | None): List of user UUIDs who are members of the module. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + Returns: - Created Module object + Module: The created Module. """ client, workspace_slug = get_plane_client_context() @@ -84,24 +159,25 @@ def update_module( external_id: str | None = None, ) -> Module: """ - Update a module by ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - module_id: UUID of the module - name: Module name - description: Module description - start_date: Module start date (ISO 8601 format) - target_date: Module target/end date (ISO 8601 format) - status: Module status (backlog, planned, in-progress, paused, completed, cancelled) - lead: UUID of the user who leads the module - members: List of user IDs who are members of the module - external_source: External system source name - external_id: External system identifier - + Update an existing module in the current workspace. + + If `status` is not one of the allowed values ("backlog", "planned", "in-progress", "paused", "completed", "cancelled"), it will be ignored (no status change). Other provided fields will be applied to the module identified by `project_id` and `module_id`. + + Parameters: + project_id (str): UUID of the project containing the module. + module_id (str): UUID of the module to update. + name (str | None): New module name. + description (str | None): New module description. + start_date (str | None): Module start date (ISO 8601). + target_date (str | None): Module target/end date (ISO 8601). + status (str | None): Module status; allowed values are "backlog", "planned", "in-progress", "paused", "completed", "cancelled". + lead (str | None): UUID of the user who leads the module. + members (list[str] | None): List of user UUIDs who are members of the module. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + Returns: - Updated Module object + Module: The updated Module object. """ client, workspace_slug = get_plane_client_context() @@ -129,12 +205,11 @@ def update_module( @mcp.tool() def delete_module(project_id: str, module_id: str) -> None: """ - Delete a module by ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - module_id: UUID of the module + Delete a module from a project in the current workspace. + + Parameters: + project_id (str): UUID of the project containing the module. + module_id (str): UUID of the module to delete. """ client, workspace_slug = get_plane_client_context() client.modules.delete(workspace_slug=workspace_slug, project_id=project_id, module_id=module_id) @@ -146,13 +221,12 @@ def add_work_items_to_module( issue_ids: list[str], ) -> None: """ - Add work items to a module. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - module_id: UUID of the module - issue_ids: List of work item IDs to add to the module + Add the given work items to the specified module within the current workspace. + + Parameters: + project_id (str): UUID of the project containing the module. + module_id (str): UUID of the module to update. + issue_ids (list[str]): List of work item IDs to add to the module. """ client, workspace_slug = get_plane_client_context() client.modules.add_work_items( @@ -169,13 +243,12 @@ def remove_work_item_from_module( work_item_id: str, ) -> None: """ - Remove a work item from a module. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - module_id: UUID of the module - work_item_id: UUID of the work item to remove + Remove a work item from a module in the current workspace. + + Parameters: + project_id (str): UUID of the project containing the module. + module_id (str): UUID of the module to update. + work_item_id (str): UUID of the work item to remove from the module. """ client, workspace_slug = get_plane_client_context() client.modules.remove_work_item( @@ -188,12 +261,11 @@ def remove_work_item_from_module( @mcp.tool() def archive_module(project_id: str, module_id: str) -> None: """ - Archive a module. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - module_id: UUID of the module + Archive a module in the current Plane workspace. + + Parameters: + project_id (str): UUID of the project containing the module. + module_id (str): UUID of the module to archive. """ client, workspace_slug = get_plane_client_context() client.modules.archive(workspace_slug=workspace_slug, project_id=project_id, module_id=module_id) diff --git a/plane_mcp/tools/projects.py b/plane_mcp/tools/projects.py index 106cba7..d6f6710 100644 --- a/plane_mcp/tools/projects.py +++ b/plane_mcp/tools/projects.py @@ -16,7 +16,104 @@ def register_project_tools(mcp: FastMCP) -> None: - """Register all project-related tools with the MCP server.""" + """ + Create a new project in the current workspace. + + Parameters: + name: Project name. + identifier: Project identifier (short string like "MP"). + description: Project description. + project_lead: UUID of the project lead user. + default_assignee: UUID of the default assignee user. + emoji: Emoji for the project. + cover_image: Cover image URL or asset ID. + module_view: Enable module view. + cycle_view: Enable cycle view. + issue_views_view: Enable issue views. + page_view: Enable page view. + intake_view: Enable intake view. + guest_view_all_features: Allow guests to view all features. + archive_in: Days until auto-archive. + close_in: Days until auto-close. + timezone: Timezone string; must match an allowed TimezoneEnum literal or it will be ignored. + external_source: External system source name. + external_id: External system identifier. + is_issue_type_enabled: Enable issue types. + + Returns: + Created Project object. + """ + """ + Update an existing project by ID in the current workspace. + + Parameters: + project_id: UUID of the project to update. + name: New project name. + description: New project description. + project_lead: UUID of the project lead user. + default_assignee: UUID of the default assignee user. + identifier: New project identifier. + emoji: Emoji for the project. + cover_image: Cover image URL or asset ID. + module_view: Enable/disable module view. + cycle_view: Enable/disable cycle view. + issue_views_view: Enable/disable issue views. + page_view: Enable/disable page view. + intake_view: Enable/disable intake view. + guest_view_all_features: Allow guests to view all features. + archive_in: Days until auto-archive. + close_in: Days until auto-close. + timezone: Timezone string; must match an allowed TimezoneEnum literal or it will be ignored. + external_source: External system source name. + external_id: External system identifier. + is_issue_type_enabled: Enable issue types. + is_time_tracking_enabled: Enable time tracking. + default_state: UUID of the default state. + estimate: Estimate configuration. + + Returns: + Updated Project object. + """ + """ + Delete a project by ID from the current workspace. + + Parameters: + project_id: UUID of the project to delete. + """ + """ + Retrieve a worklog summary for a project in the current workspace. + + Parameters: + project_id: UUID of the project. + + Returns: + List of ProjectWorklogSummary objects containing work item IDs and aggregated durations. + """ + """ + Retrieve the feature flags for a project in the current workspace. + + Parameters: + project_id: UUID of the project. + + Returns: + ProjectFeature object describing enabled and disabled features for the project. + """ + """ + Update feature flags for a project in the current workspace. + + Parameters: + project_id: UUID of the project. + epics: Enable/disable epics feature. + modules: Enable/disable modules feature. + cycles: Enable/disable cycles feature. + views: Enable/disable views feature. + pages: Enable/disable pages feature. + intakes: Enable/disable intakes feature. + work_item_types: Enable/disable work item types feature. + + Returns: + Updated ProjectFeature object. + """ @mcp.tool() def create_project( @@ -41,32 +138,31 @@ def create_project( is_issue_type_enabled: bool | None = None, ) -> Project: """ - Create a new project. - - Args: - workspace_slug: The workspace slug identifier - name: Project name - identifier: Project identifier (e.g., "MP" for "My Project") - description: Project description - project_lead: UUID of the project lead user - default_assignee: UUID of the default assignee user - emoji: Emoji for the project - cover_image: Cover image URL or asset ID - module_view: Enable module view - cycle_view: Enable cycle view - issue_views_view: Enable issue views view - page_view: Enable page view - intake_view: Enable intake view - guest_view_all_features: Allow guests to view all features - archive_in: Days until auto-archive - close_in: Days until auto-close - timezone: Project timezone - external_source: External system source name - external_id: External system identifier - is_issue_type_enabled: Enable issue types - + Create a new Plane project in the current workspace. + + Parameters: + name: Project name. + identifier: Project identifier (e.g., "MP" for "My Project"). + description: Project description. + project_lead: UUID of the project lead user. + default_assignee: UUID of the default assignee user. + emoji: Emoji for the project. + cover_image: Cover image URL or asset ID. + module_view: Enable module view. + cycle_view: Enable cycle view. + issue_views_view: Enable issue views view. + page_view: Enable page view. + intake_view: Enable intake view. + guest_view_all_features: Allow guests to view all features. + archive_in: Number of days until the project is auto-archived. + close_in: Number of days until the project is auto-closed. + timezone: Timezone identifier; if the value is not one of the allowed TimezoneEnum literals, it will be treated as `None`. + external_source: External system source name. + external_id: External system identifier. + is_issue_type_enabled: Enable issue types. + Returns: - Created Project object + Project: The created Project object. """ client, workspace_slug = get_plane_client_context() @@ -126,36 +222,16 @@ def update_project( estimate: str | None = None, ) -> Project: """ - Update a project by ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - name: Project name - description: Project description - project_lead: UUID of the project lead user - default_assignee: UUID of the default assignee user - identifier: Project identifier - emoji: Emoji for the project - cover_image: Cover image URL or asset ID - module_view: Enable module view - cycle_view: Enable cycle view - issue_views_view: Enable issue views view - page_view: Enable page view - intake_view: Enable intake view - guest_view_all_features: Allow guests to view all features - archive_in: Days until auto-archive - close_in: Days until auto-close - timezone: Project timezone - external_source: External system source name - external_id: External system identifier - is_issue_type_enabled: Enable issue types - is_time_tracking_enabled: Enable time tracking - default_state: UUID of the default state - estimate: Estimate configuration - + Update fields of an existing project identified by its ID. + + The provided `timezone` string is validated against allowed TimezoneEnum literal values; if it does not match, the timezone is cleared (set to `None`) in the update payload. + + Parameters: + project_id (str): UUID of the project to update. + timezone (str | None): Timezone identifier to set for the project; must match an allowed TimezoneEnum literal or it will be ignored. + Returns: - Updated Project object + Project: The updated Project object returned by the API. """ client, workspace_slug = get_plane_client_context() @@ -206,14 +282,13 @@ def delete_project(project_id: str) -> None: @mcp.tool() def get_project_worklog_summary(project_id: str) -> list[ProjectWorklogSummary]: """ - Get work log summary for a project. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - + Retrieve aggregated worklog summaries for a project. + + Parameters: + project_id (str): UUID of the project to summarize worklogs for. + Returns: - List of ProjectWorklogSummary objects containing work item IDs and durations + list[ProjectWorklogSummary]: A list of ProjectWorklogSummary objects, each summarizing durations and associated work item identifiers. """ client, workspace_slug = get_plane_client_context() return client.projects.get_worklog_summary(workspace_slug=workspace_slug, project_id=project_id) @@ -221,14 +296,13 @@ def get_project_worklog_summary(project_id: str) -> list[ProjectWorklogSummary]: @mcp.tool() def get_project_features(project_id: str) -> ProjectFeature: """ - Get features of a project. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - + Get the feature settings for a project. + + Parameters: + project_id (str): UUID of the project whose features will be retrieved. + Returns: - ProjectFeature object containing enabled/disabled features + ProjectFeature: The project's feature configuration, indicating which features are enabled. """ client, workspace_slug = get_plane_client_context() return client.projects.get_features(workspace_slug=workspace_slug, project_id=project_id) diff --git a/plane_mcp/tools/states.py b/plane_mcp/tools/states.py index 2468c65..dd2afc6 100644 --- a/plane_mcp/tools/states.py +++ b/plane_mcp/tools/states.py @@ -14,7 +14,42 @@ def register_state_tools(mcp: FastMCP) -> None: - """Register all state-related tools with the MCP server.""" + """ + Register state-related MCP tools on the provided FastMCP instance. + """ + """ + Create a new state in the specified project. + + Parameters: + group (str | None): Optional state group; expected values include "backlog", "unstarted", "started", "completed", "cancelled". + description (str | None): Optional human-readable description. + sequence (float | None): Optional ordering value for the state. + is_triage (bool | None): Optional flag indicating a triage state. + default (bool | None): Optional flag indicating the default state. + external_source (str | None): Optional external system source name. + external_id (str | None): Optional external system identifier. + + Returns: + State: The created State object. + """ + """ + Update an existing state by ID in the specified project. + + Parameters: + group (str | None): Optional state group; expected values include "backlog", "unstarted", "started", "completed", "cancelled". + description (str | None): Optional human-readable description. + sequence (float | None): Optional ordering value for the state. + is_triage (bool | None): Optional flag indicating a triage state. + default (bool | None): Optional flag indicating the default state. + external_source (str | None): Optional external system source name. + external_id (str | None): Optional external system identifier. + + Returns: + State: The updated State object. + """ + """ + Delete a state by ID from the specified project. + """ @mcp.tool() def create_state( @@ -30,22 +65,22 @@ def create_state( external_id: str | None = None, ) -> State: """ - Create a new state. - - Args: - project_id: UUID of the project - name: State name - color: State color (hex color code) - description: State description - sequence: State sequence order - group: State group (e.g., backlog, unstarted, started, completed, cancelled) - is_triage: Whether this is a triage state - default: Whether this is the default state - external_source: External system source name - external_id: External system identifier - + Create a new state in the specified project. + + Parameters: + project_id (str): Project identifier. + name (str): State name. + color (str): State color (hex code). + description (str | None): Optional state description. + sequence (float | None): Optional ordering position for the state. + group (str | None): Optional group category; one of "backlog", "unstarted", "started", "completed", "cancelled". + is_triage (bool | None): Whether the state is a triage state. + default (bool | None): Whether the state is the project's default. + external_source (str | None): Optional external system name. + external_id (str | None): Optional identifier in the external system. + Returns: - Created State object + State: The created State object. """ client, workspace_slug = get_plane_client_context() @@ -83,23 +118,15 @@ def update_state( external_id: str | None = None, ) -> State: """ - Update a state by ID. - - Args: - project_id: UUID of the project - state_id: UUID of the state - name: State name - color: State color (hex color code) - description: State description - sequence: State sequence order - group: State group (e.g., backlog, unstarted, started, completed, cancelled) - is_triage: Whether this is a triage state - default: Whether this is the default state - external_source: External system source name - external_id: External system identifier - + Update a state by its identifier. + + If `group` is provided, it is validated against the allowed GroupEnum literal values; an invalid value will be ignored. + + Parameters: + group (str | None): Optional state group (e.g., "backlog", "unstarted", "started", "completed", "cancelled"). If not one of the allowed literals, the group is not applied. + Returns: - Updated State object + State: The updated State object. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/unified.py b/plane_mcp/tools/unified.py index a8b1799..3de8ee5 100644 --- a/plane_mcp/tools/unified.py +++ b/plane_mcp/tools/unified.py @@ -86,7 +86,16 @@ def _resolve_client_attr(client: Any, attr_path: str) -> Any: def register_unified_tools(mcp: FastMCP) -> None: - """Register unified list and retrieve tools with the MCP server.""" + """ + Register unified Plane entity list and retrieve tools on the provided MCP instance. + + This registers two MCP tools: + - `entity_list`: list collections of Plane entities by `entity_type`, enforcing required scope identifiers + (e.g., `project_id`, `cycle_id`, `module_id`, `milestone_id`, `work_item_id`, `type_id`) and accepting optional + query `params`. Returns a list of entity objects. + - `entity_retrieve`: retrieve a single Plane entity by `entity_id` (or by `project_identifier` + `issue_identifier` + for `work_item_by_identifier`), enforcing required scope identifiers depending on `entity_type`. Returns the entity object. + """ @mcp.tool() def entity_list( diff --git a/plane_mcp/tools/work_item_activities.py b/plane_mcp/tools/work_item_activities.py index fba2363..6fe181c 100644 --- a/plane_mcp/tools/work_item_activities.py +++ b/plane_mcp/tools/work_item_activities.py @@ -4,5 +4,9 @@ def register_work_item_activity_tools(mcp: FastMCP) -> None: - """Register all work item activity-related tools with the MCP server.""" + """ + Register work item activity-related tools on the given MCP server. + + Currently no specific tools are registered here because list and retrieve operations for work item activities are handled by the unified `entity_list` and `entity_retrieve` tools. + """ # List and retrieve operations moved to entity_list / entity_retrieve unified tools. diff --git a/plane_mcp/tools/work_item_comments.py b/plane_mcp/tools/work_item_comments.py index d8aa278..3e20b20 100644 --- a/plane_mcp/tools/work_item_comments.py +++ b/plane_mcp/tools/work_item_comments.py @@ -28,18 +28,20 @@ def create_work_item_comment( ) -> WorkItemComment: """ Create a comment for a work item. - - Args: - project_id: UUID of the project - work_item_id: UUID of the work item - comment_html: Comment content in HTML format - comment_json: Comment content in JSON format - access: Access level for the comment (INTERNAL or EXTERNAL) - external_source: External system source name - external_id: External system identifier - + + If `access` is not one of the allowed values in `AccessEnum`, it will be treated as `None` (no access override). + + Parameters: + project_id: UUID of the project containing the work item. + work_item_id: UUID of the target work item. + comment_html: Comment content in HTML format, if provided. + comment_json: Comment content in structured JSON format, if provided. + access: Optional access level for the comment; must match a value from `AccessEnum` (e.g., "INTERNAL" or "EXTERNAL"). + external_source: Optional name of the external system that produced the comment. + external_id: Optional identifier of the comment in the external system. + Returns: - Created WorkItemComment object + The created WorkItemComment object. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/work_item_links.py b/plane_mcp/tools/work_item_links.py index c8f1175..4af848f 100644 --- a/plane_mcp/tools/work_item_links.py +++ b/plane_mcp/tools/work_item_links.py @@ -21,14 +21,14 @@ def create_work_item_link( ) -> WorkItemLink: """ Create a link for a work item. - - Args: - project_id: UUID of the project - work_item_id: UUID of the work item - url: URL of the link - + + Parameters: + project_id (str): UUID of the project. + work_item_id (str): UUID of the work item. + url (str): Target URL for the link. + Returns: - Created WorkItemLink object + WorkItemLink: The created work item link. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/work_item_properties.py b/plane_mcp/tools/work_item_properties.py index 4743d70..a8d7484 100644 --- a/plane_mcp/tools/work_item_properties.py +++ b/plane_mcp/tools/work_item_properties.py @@ -20,7 +20,60 @@ def register_work_item_property_tools(mcp: FastMCP) -> None: - """Register all work item property-related tools with the MCP server.""" + """ + Create a new work item property for the given project and type. + + Parameters: + project_id (str): UUID of the project. + type_id (str): UUID of the work item type. + display_name (str): Display name for the property. + property_type (str): Property type (e.g., "TEXT", "DATETIME", "DECIMAL", "BOOLEAN", "OPTION", "RELATION", "URL", "EMAIL", "FILE"). + relation_type (str | None): Relation type (e.g., "ISSUE", "USER"); required when `property_type` is "RELATION". + description (str | None): Property description. + is_required (bool | None): Whether the property is required. + default_value (list[str] | None): Default value(s) for the property. + settings (dict | None): Typed settings for specific property types; for "TEXT" provide {"display_format": "single-line" | "multi-line" | "readonly"}, for "DATETIME" provide {"display_format": "MMM dd, yyyy" | "dd/MM/yyyy" | "MM/dd/yyyy" | "yyyy/MM/dd"}. + is_active (bool | None): Whether the property is active. + is_multi (bool | None): Whether the property supports multiple values. + validation_rules (dict | None): Validation rules for the property. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + options (list[dict] | None): List of option dicts; required when `property_type` is "OPTION". + + Returns: + WorkItemProperty: The created work item property object. + """ + """ + Update an existing work item property. + + Parameters: + project_id (str): UUID of the project. + type_id (str): UUID of the work item type. + work_item_property_id (str): UUID of the property to update. + display_name (str | None): New display name for the property. + property_type (str | None): New property type (see `create_work_item_property` for allowed values). + relation_type (str | None): Relation type when updating to a relation property (e.g., "ISSUE", "USER"). + description (str | None): New property description. + is_required (bool | None): Whether the property is required. + default_value (list[str] | None): Default value(s) for the property. + settings (dict | None): Typed settings when updating to "TEXT" or "DATETIME" (see `create_work_item_property`). + is_active (bool | None): Whether the property is active. + is_multi (bool | None): Whether the property supports multiple values. + validation_rules (dict | None): Validation rules for the property. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + + Returns: + WorkItemProperty: The updated work item property object. + """ + """ + Delete a work item property by its identifier. + + Parameters: + project_id (str): UUID of the project. + type_id (str): UUID of the work item type. + work_item_property_id (str): UUID of the property to delete. + """ @mcp.tool() def create_work_item_property( @@ -41,32 +94,27 @@ def create_work_item_property( options: list[dict] | None = None, ) -> WorkItemProperty: """ - Create a new work item property. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - type_id: UUID of the work item type - display_name: Display name for the property - property_type: Type of property (TEXT, DATETIME, DECIMAL, BOOLEAN, - OPTION, RELATION, URL, EMAIL, FILE) - relation_type: Relation type (ISSUE, USER) - required for RELATION properties - description: Property description - is_required: Whether the property is required - default_value: Default value(s) for the property - settings: Settings dictionary - required for TEXT and DATETIME properties - For TEXT: {"display_format": "single-line"|"multi-line"|"readonly"} - For DATETIME: {"display_format": - "MMM dd, yyyy"|"dd/MM/yyyy"|"MM/dd/yyyy"|"yyyy/MM/dd"} - is_active: Whether the property is active - is_multi: Whether the property supports multiple values - validation_rules: Validation rules dictionary - external_source: External system source name - external_id: External system identifier - options: List of option dictionaries for OPTION properties - + Create a new work item property in the current workspace and project. + + Parameters: + project_id (str): UUID of the project that will contain the property. + type_id (str): UUID of the work item type to attach the property to. + display_name (str): Human-readable name for the property. + property_type (str): Property type name. One of: "TEXT", "DATETIME", "DECIMAL", "BOOLEAN", "OPTION", "RELATION", "URL", "EMAIL", "FILE". + relation_type (str | None): Relation kind required when `property_type` is "RELATION" (e.g., "ISSUE", "USER"). + description (str | None): Optional description explaining the property's purpose. + is_required (bool | None): Whether the property must have a value. + default_value (list[str] | None): Default value(s) for the property. + settings (dict | None): Type-specific settings. For "TEXT", supply {"display_format": "single-line" | "multi-line" | "readonly"}. For "DATETIME", supply {"display_format": "MMM dd, yyyy" | "dd/MM/yyyy" | "MM/dd/yyyy" | "yyyy/MM/dd"}. + is_active (bool | None): Whether the property is active and available for use. + is_multi (bool | None): Whether the property accepts multiple values. + validation_rules (dict | None): Optional validation rules for the property values. + external_source (str | None): External system source name, if the property is synced from outside. + external_id (str | None): Identifier in the external system. + options (list[dict] | None): For "OPTION" properties, a list of option definitions (each dict will be converted to a CreateWorkItemPropertyOption). + Returns: - Created WorkItemProperty object + WorkItemProperty: The created work item property object. """ client, workspace_slug = get_plane_client_context() @@ -130,32 +178,33 @@ def update_work_item_property( external_id: str | None = None, ) -> WorkItemProperty: """ - Update a work item property by ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - type_id: UUID of the work item type - work_item_property_id: UUID of the property - display_name: Display name for the property - property_type: Type of property (TEXT, DATETIME, DECIMAL, BOOLEAN, - OPTION, RELATION, URL, EMAIL, FILE) - relation_type: Relation type (ISSUE, USER) - required when updating to RELATION - description: Property description - is_required: Whether the property is required - default_value: Default value(s) for the property - settings: Settings dictionary - required when updating to TEXT or DATETIME - For TEXT: {"display_format": "single-line"|"multi-line"|"readonly"} - For DATETIME: {"display_format": - "MMM dd, yyyy"|"dd/MM/yyyy"|"MM/dd/yyyy"|"yyyy/MM/dd"} - is_active: Whether the property is active - is_multi: Whether the property supports multiple values - validation_rules: Validation rules dictionary - external_source: External system source name - external_id: External system identifier - + Update an existing work item property for a work item type within a project. + + Parameters: + project_id: UUID of the project containing the work item type. + type_id: UUID of the work item type that owns the property. + work_item_property_id: UUID of the work item property to update. + display_name: New display name for the property. + property_type: Property type name (e.g., "TEXT", "DATETIME", "DECIMAL", + "BOOLEAN", "OPTION", "RELATION", "URL", "EMAIL", "FILE"). + relation_type: Relation type name (e.g., "ISSUE", "USER"); required when changing + the property to a relation type. + description: New description for the property. + is_required: Whether the property is required. + default_value: Default value or list of default values for the property. + settings: Settings dictionary for the property. When `property_type` is "TEXT", + expected keys include `display_format` with values "single-line", "multi-line", + or "readonly". When `property_type` is "DATETIME", expected key `display_format` + may be a date format string such as "MMM dd, yyyy", "dd/MM/yyyy", "MM/dd/yyyy", + or "yyyy/MM/dd". + is_active: Whether the property is active. + is_multi: Whether the property supports multiple values. + validation_rules: Validation rules dictionary for the property. + external_source: External system source name. + external_id: External system identifier. + Returns: - Updated WorkItemProperty object + Updated WorkItemProperty object. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/work_item_relations.py b/plane_mcp/tools/work_item_relations.py index 70f1f8d..d78a38a 100644 --- a/plane_mcp/tools/work_item_relations.py +++ b/plane_mcp/tools/work_item_relations.py @@ -13,7 +13,16 @@ def register_work_item_relation_tools(mcp: FastMCP) -> None: - """Register all work item relation-related tools with the MCP server.""" + """ + Register work-item relation tools on the given MCP instance. + + Registers two tools on `mcp`: + - `create_work_item_relation`: creates one or more relations from a work item to other issues, validating the relation type. + - `remove_work_item_relation`: removes a relation between a work item and a related issue. + + Parameters: + mcp (FastMCP): MCP server instance to register the tools on. + """ @mcp.tool() def create_work_item_relation( @@ -23,14 +32,16 @@ def create_work_item_relation( issues: list[str], ) -> None: """ - Create relations for a work item. - - Args: - project_id: UUID of the project - work_item_id: UUID of the work item - relation_type: Type of relationship (blocking, blocked_by, duplicate, - relates_to, start_before, start_after, finish_before, finish_after) - issues: List of work item IDs to create relations with + Create relations between a work item and other work items in the given project. + + Parameters: + project_id (str): UUID of the project containing the work item. + work_item_id (str): UUID of the work item to which relations will be added. + relation_type (str): Relation type; must be one of the allowed WorkItemRelationTypeEnum values. + issues (list[str]): List of work item IDs to relate to the target work item. + + Raises: + ValueError: If `relation_type` is not one of the allowed WorkItemRelationTypeEnum values. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/work_item_types.py b/plane_mcp/tools/work_item_types.py index a8f3890..14d6f66 100644 --- a/plane_mcp/tools/work_item_types.py +++ b/plane_mcp/tools/work_item_types.py @@ -27,20 +27,20 @@ def create_work_item_type( external_id: str | None = None, ) -> WorkItemType: """ - Create a new work item type. - - Args: - project_id: UUID of the project - name: Work item type name - description: Work item type description - project_ids: List of project IDs this type applies to - is_epic: Whether this is an epic type - is_active: Whether the type is active - external_source: External system source name - external_id: External system identifier - + Create a new work item type in the current workspace for the given project. + + Parameters: + project_id: Project UUID where the work item type will be created. + name: Name of the work item type. + description: Optional human-readable description. + project_ids: Optional list of project UUIDs this type applies to. + is_epic: Optional flag indicating whether the type represents an epic. + is_active: Optional flag indicating whether the type is active. + external_source: Optional name of an external system providing this type. + external_id: Optional identifier from the external system. + Returns: - Created WorkItemType object + WorkItemType: The newly created work item type. """ client, workspace_slug = get_plane_client_context() @@ -69,21 +69,24 @@ def update_work_item_type( external_id: str | None = None, ) -> WorkItemType: """ - Update a work item type by ID. - - Args: - project_id: UUID of the project - work_item_type_id: UUID of the work item type - name: Work item type name - description: Work item type description - project_ids: List of project IDs this type applies to - is_epic: Whether this is an epic type - is_active: Whether the type is active - external_source: External system source name - external_id: External system identifier - + Updates a work item type identified by its ID in the current Plane workspace. + + Parameters: + project_id (str): UUID of the project containing the work item type. + work_item_type_id (str): UUID of the work item type to update. + name (str | None): New name for the work item type. + description (str | None): New description for the work item type. + project_ids (list[str] | None): List of project UUIDs the type applies to. + is_epic (bool | None): Whether the type should be marked as an epic. + is_active (bool | None): Whether the type should be active. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + Returns: - Updated WorkItemType object + WorkItemType: The updated work item type. + + Notes: + Only parameters provided as non-None are applied; unspecified fields are left unchanged. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/work_items.py b/plane_mcp/tools/work_items.py index 520d140..40b73ec 100644 --- a/plane_mcp/tools/work_items.py +++ b/plane_mcp/tools/work_items.py @@ -60,7 +60,31 @@ def _build_advanced_search_filters( def register_work_item_tools(mcp: FastMCP) -> None: - """Register all work item-related tools with the MCP server.""" + """ + Create a new work item in a project. + + If `priority` is not one of the allowed PriorityEnum literal values it will be ignored (treated as unset). + + Returns: + Created WorkItem object + """ + """ + Update fields of an existing work item. + + If `priority` is not one of the allowed PriorityEnum literal values it will be ignored (treated as unset). + + Returns: + Updated WorkItem object + """ + """ + Delete a work item by ID. + """ + """ + Search work items across the current workspace using a free-form text `query` that matches fields like name and description. + + Returns: + WorkItemSearch object containing matching work items and related metadata + """ @mcp.tool() def create_work_item( @@ -85,32 +109,31 @@ def create_work_item( type: str | None = None, ) -> WorkItem: """ - Create a new work item. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - name: Work item name (required) - assignees: List of user IDs to assign to the work item - labels: List of label IDs to attach to the work item - type_id: UUID of the work item type - point: Story point value - description_html: HTML description of the work item - description_stripped: Plain text description (stripped of HTML) - priority: Priority level (urgent, high, medium, low, none) - start_date: Start date (ISO 8601 format) - target_date: Target/end date (ISO 8601 format) - sort_order: Sort order value - is_draft: Whether the work item is a draft - external_source: External system source name - external_id: External system identifier - parent: UUID of the parent work item - state: UUID of the state - estimate_point: Estimate point value - type: Work item type identifier - + Create a new work item in the specified project. + + Parameters: + project_id (str): UUID of the project. + name (str): Title of the work item. + assignees (list[str] | None): List of user IDs to assign to the work item. + labels (list[str] | None): List of label IDs to attach to the work item. + type_id (str | None): UUID of the work item type. + point (int | None): Story point value. + description_html (str | None): HTML description of the work item. + description_stripped (str | None): Plain-text description. + priority (str | None): Priority level; if not one of the allowed PriorityEnum values, the priority will be ignored. + start_date (str | None): Start date in ISO 8601 format. + target_date (str | None): Target/end date in ISO 8601 format. + sort_order (float | None): Sort order value. + is_draft (bool | None): Whether the work item is a draft. + external_source (str | None): External system source name. + external_id (str | None): External system identifier. + parent (str | None): UUID of the parent work item. + state (str | None): UUID of the state. + estimate_point (str | None): Estimate point value. + type (str | None): Work item type identifier. + Returns: - Created WorkItem object + WorkItem: The created work item. """ client, workspace_slug = get_plane_client_context() @@ -166,33 +189,18 @@ def update_work_item( type: str | None = None, ) -> WorkItem: """ - Update a work item by ID. - - Args: - workspace_slug: The workspace slug identifier - project_id: UUID of the project - work_item_id: UUID of the work item - name: Work item name - assignees: List of user IDs to assign to the work item - labels: List of label IDs to attach to the work item - type_id: UUID of the work item type - point: Story point value - description_html: HTML description of the work item - description_stripped: Plain text description (stripped of HTML) - priority: Priority level (urgent, high, medium, low, none) - start_date: Start date (ISO 8601 format) - target_date: Target/end date (ISO 8601 format) - sort_order: Sort order value - is_draft: Whether the work item is a draft - external_source: External system source name - external_id: External system identifier - parent: UUID of the parent work item - state: UUID of the state - estimate_point: Estimate point value - type: Work item type identifier - + Update fields of an existing work item. + + Parameters: + project_id (str): UUID of the project containing the work item. + work_item_id (str): UUID of the work item to update. + priority (str | None): Priority level, e.g. "urgent", "high", "medium", "low", "none". + start_date (str | None): Start date in ISO 8601 format. + target_date (str | None): Target/end date in ISO 8601 format. + parent (str | None): UUID of the parent work item, if any. + Returns: - Updated WorkItem object + WorkItem: The updated work item object. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/work_logs.py b/plane_mcp/tools/work_logs.py index 12badbd..9a7a4a1 100644 --- a/plane_mcp/tools/work_logs.py +++ b/plane_mcp/tools/work_logs.py @@ -20,15 +20,15 @@ def create_work_log( ) -> WorkItemWorkLog: """ Create a work log for a work item. - - Args: - project_id: UUID of the project - work_item_id: UUID of the work item - duration: Duration of work in minutes - description: Description of the work performed - + + Parameters: + project_id (str): UUID of the project. + work_item_id (str): UUID of the work item. + duration (int | None): Duration of work in minutes; include when known. + description (str | None): Human-readable description of the work. + Returns: - Created WorkItemWorkLog object + WorkItemWorkLog: The created work log object. """ client, workspace_slug = get_plane_client_context() diff --git a/plane_mcp/tools/workspaces.py b/plane_mcp/tools/workspaces.py index 7398910..a96ba9c 100644 --- a/plane_mcp/tools/workspaces.py +++ b/plane_mcp/tools/workspaces.py @@ -12,10 +12,10 @@ def register_workspace_tools(mcp: FastMCP) -> None: @mcp.tool() def get_workspace_features() -> WorkspaceFeature: """ - Get features of the current workspace. - + Fetches the current workspace's feature flags. + Returns: - WorkspaceFeature object containing feature flags + WorkspaceFeature: The workspace's feature flags. """ client, workspace_slug = get_plane_client_context() return client.workspaces.get_features(workspace_slug=workspace_slug)