Coverage for src/mcp_atlassian/jira/config.py: 98%

1"""Configuration module for Jira API interactions."""

2

3 import os

4 from dataclasses import dataclass

5 from typing import Optional, Literal

6

7

8@dataclass

9 class JiraConfig:

10 """Jira API configuration.

11

12 Handles authentication for both Jira Cloud (using username/API token)

13 and Jira Server/Data Center (using personal access token).

14 """

15

16 url: str # Base URL for Jira

17 auth_type: Literal["basic", "token"] # Authentication type

18 username: Optional[str] = None # Email or username (Cloud)

19 api_token: Optional[str] = None # API token (Cloud)

20 personal_token: Optional[str] = None # Personal access token (Server/DC)

21 ssl_verify: bool = True # Whether to verify SSL certificates

22

23 @property

24 def is_cloud(self) -> bool:

25 """Check if this is a cloud instance.

26

27 Returns:

28 True if this is a cloud instance (atlassian.net), False otherwise.

29 """

30 return "atlassian.net" in self.url

31

32 @property

33 def verify_ssl(self) -> bool:

34 """Compatibility property for old code.

35

36 Returns:

37 The ssl_verify value

38 """

39 return self.ssl_verify

40

41 @classmethod

42 def from_env(cls) -> "JiraConfig":

43 """Create configuration from environment variables.

44

45 Returns:

46 JiraConfig with values from environment variables

47

48 Raises:

49 ValueError: If required environment variables are missing or invalid

50 """

51 url = os.getenv("JIRA_URL")

52 if not url:

53 error_msg = "Missing required JIRA_URL environment variable"

54 raise ValueError(error_msg)

55

56 # Determine authentication type based on available environment variables

57 username = os.getenv("JIRA_USERNAME")

58 api_token = os.getenv("JIRA_API_TOKEN")

59 personal_token = os.getenv("JIRA_PERSONAL_TOKEN")

60

61 is_cloud = "atlassian.net" in url

62

63 if is_cloud:

64 if username and api_token:

65 auth_type = "basic"

66 else:

67 error_msg = "Cloud authentication requires JIRA_USERNAME and JIRA_API_TOKEN"

68 raise ValueError(error_msg)

69 else: # Server/Data Center

70 if personal_token:

71 auth_type = "token"

72 elif username and api_token:

73 # Allow basic auth for Server/DC too

74 auth_type = "basic"

75 else:

76 error_msg = "Server/Data Center authentication requires JIRA_PERSONAL_TOKEN"

77 raise ValueError(error_msg)

78

79 # SSL verification (for Server/DC)

80 ssl_verify_env = os.getenv("JIRA_SSL_VERIFY", "true").lower()

81 ssl_verify = ssl_verify_env not in ("false", "0", "no")

82

83 return cls(

84 url=url,

85 auth_type=auth_type,

86 username=username,

87 api_token=api_token,

88 personal_token=personal_token,

89 ssl_verify=ssl_verify

90 )