diff --git a/src/mcp_atlassian/jira/comments.py b/src/mcp_atlassian/jira/comments.py index 8e7052bf2..ebb1743e4 100644 --- a/src/mcp_atlassian/jira/comments.py +++ b/src/mcp_atlassian/jira/comments.py @@ -52,13 +52,16 @@ def get_issue_comments( logger.error(f"Error getting comments for issue {issue_key}: {str(e)}") raise Exception(f"Error getting comments: {str(e)}") from e - def add_comment(self, issue_key: str, comment: str) -> dict[str, Any]: + def add_comment( + self, issue_key: str, comment: str, visibility: dict[str, str] = None + ) -> dict[str, Any]: """ Add a comment to an issue. Args: issue_key: The issue key (e.g. 'PROJ-123') comment: Comment text to add (in Markdown format) + visibility: (optional) Restrict comment visibility (e.g. {"type":"group","value:"jira-users"}) Returns: The created comment details @@ -70,7 +73,9 @@ def add_comment(self, issue_key: str, comment: str) -> dict[str, Any]: # Convert Markdown to Jira's markup format jira_formatted_comment = self._markdown_to_jira(comment) - result = self.jira.issue_add_comment(issue_key, jira_formatted_comment) + result = self.jira.issue_add_comment( + issue_key, jira_formatted_comment, visibility + ) if not isinstance(result, dict): msg = f"Unexpected return value type from `jira.issue_add_comment`: {type(result)}" logger.error(msg) diff --git a/src/mcp_atlassian/servers/jira.py b/src/mcp_atlassian/servers/jira.py index 7caed34af..bf6f98132 100644 --- a/src/mcp_atlassian/servers/jira.py +++ b/src/mcp_atlassian/servers/jira.py @@ -985,6 +985,12 @@ async def add_comment( ctx: Context, issue_key: Annotated[str, Field(description="Jira issue key (e.g., 'PROJ-123')")], comment: Annotated[str, Field(description="Comment text in Markdown format")], + visibility: Annotated[ + dict[str, str], + Field( + description="""(Optional) Comment visibility (e.g. {"type":"group","value":"jira-users"})""" + ), + ] = None, ) -> str: """Add a comment to a Jira issue. @@ -992,6 +998,7 @@ async def add_comment( ctx: The FastMCP context. issue_key: Jira issue key. comment: Comment text in Markdown. + visibility: (Optional) Comment visibility (e.g. {"type":"group","value":"jira-users"}). Returns: JSON string representing the added comment object. @@ -1001,7 +1008,7 @@ async def add_comment( """ jira = await get_jira_fetcher(ctx) # add_comment returns dict - result = jira.add_comment(issue_key, comment) + result = jira.add_comment(issue_key, comment, visibility) return json.dumps(result, indent=2, ensure_ascii=False) diff --git a/tests/unit/jira/test_comments.py b/tests/unit/jira/test_comments.py index d0fe7845a..86ec74ac8 100644 --- a/tests/unit/jira/test_comments.py +++ b/tests/unit/jira/test_comments.py @@ -171,7 +171,7 @@ def test_add_comment_basic(self, comments_mixin): "Test comment" ) comments_mixin.jira.issue_add_comment.assert_called_once_with( - "TEST-123", "*This* is _Jira_ formatted" + "TEST-123", "*This* is _Jira_ formatted", None ) assert result["id"] == "10001" assert result["body"] == "This is a comment" @@ -211,7 +211,7 @@ def hello(): markdown_comment ) comments_mixin.jira.issue_add_comment.assert_called_once_with( - "TEST-123", "*This* is _Jira_ formatted" + "TEST-123", "*This* is _Jira_ formatted", None ) assert result["body"] == "*This* is _Jira_ formatted" @@ -230,9 +230,40 @@ def test_add_comment_with_empty_comment(self, comments_mixin): # Verify - for empty comments, markdown_to_jira should NOT be called as per implementation comments_mixin.preprocessor.markdown_to_jira.assert_not_called() - comments_mixin.jira.issue_add_comment.assert_called_once_with("TEST-123", "") + comments_mixin.jira.issue_add_comment.assert_called_once_with( + "TEST-123", "", None + ) assert result["body"] == "" + def test_add_comment_with_restricted_visibility(self, comments_mixin): + """Test add_comment with visibility set.""" + # Setup mock response + comments_mixin.jira.issue_add_comment.return_value = { + "id": "10001", + "body": "This is a comment", + "created": "2024-01-01T10:00:00.000+0000", + "author": {"displayName": "John Doe"}, + } + + # Call the method + result = comments_mixin.add_comment( + "TEST-123", "Test comment", {"type": "group", "value": "restricted"} + ) + + # Verify + comments_mixin.preprocessor.markdown_to_jira.assert_called_once_with( + "Test comment" + ) + comments_mixin.jira.issue_add_comment.assert_called_once_with( + "TEST-123", + "*This* is _Jira_ formatted", + {"type": "group", "value": "restricted"}, + ) + assert result["id"] == "10001" + assert result["body"] == "This is a comment" + assert result["created"] == "2024-01-01 10:00:00+00:00" # Parsed date + assert result["author"] == "John Doe" + def test_add_comment_with_error(self, comments_mixin): """Test add_comment with an error response.""" # Setup mock to raise exception