Coverage for src/mcp_atlassian/jira/client.py: 89%
28 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-10 03:26 +0900
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-10 03:26 +0900
1"""Base client module for Jira API interactions."""
3import logging
4import re
5from typing import Optional, Dict, Any, cast
7from atlassian import Jira
9from .config import JiraConfig
11# Configure logging
12logger = logging.getLogger("mcp-jira")
15class JiraClient:
16 """Base client for Jira API interactions."""
18 def __init__(self, config: Optional[JiraConfig] = None) -> None:
19 """Initialize the Jira client with configuration options.
21 Args:
22 config: Optional configuration object (will use env vars if not provided)
24 Raises:
25 ValueError: If configuration is invalid or required credentials are missing
26 """
27 from mcp_atlassian.preprocessing import TextPreprocessor
29 # Load configuration from environment variables if not provided
30 self.config = config or JiraConfig.from_env()
32 # Initialize the Jira client based on auth type
33 if self.config.auth_type == "token":
34 self.jira = Jira(
35 url=self.config.url,
36 token=self.config.personal_token,
37 cloud=self.config.is_cloud,
38 verify_ssl=self.config.ssl_verify,
39 )
40 else: # basic auth
41 self.jira = Jira(
42 url=self.config.url,
43 username=self.config.username,
44 password=self.config.api_token,
45 cloud=self.config.is_cloud,
46 verify_ssl=self.config.ssl_verify,
47 )
49 # Initialize the text preprocessor for text processing capabilities
50 self.preprocessor = TextPreprocessor(self.config.url)
52 # Cache for frequently used data
53 self._field_ids: Optional[Dict[str, str]] = None
54 self._current_user_account_id: Optional[str] = None
56 def _clean_text(self, text: str) -> str:
57 """Clean text content by:
58 1. Processing user mentions and links
59 2. Converting HTML/wiki markup to markdown
61 Args:
62 text: Text to clean
64 Returns:
65 Cleaned text
66 """
67 if not text:
68 return ""
70 # Otherwise create a temporary one
71 url = self.config.url if hasattr(self, 'config') else ""
72 return self.preprocessor.clean_jira_text(text)
74 def _markdown_to_jira(self, markdown_text: str) -> str:
75 """
76 Convert Markdown syntax to Jira markup syntax.
78 Args:
79 markdown_text: Text in Markdown format
81 Returns:
82 Text in Jira markup format
83 """
84 if not markdown_text:
85 return ""
87 # Use the shared preprocessor if available
88 if hasattr(self, 'preprocessor'):
89 return self.preprocessor.markdown_to_jira(markdown_text)
91 # Otherwise create a temporary one
92 url = self.config.url if hasattr(self, 'config') else ""
93 return self.preprocessor.markdown_to_jira(markdown_text)