backlog-mcp 1.0.3__py3-none-any.whl → 1.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- app/tools/get_issue_details.py +4 -1
- app/utils/ultils.py +38 -29
- {backlog_mcp-1.0.3.dist-info → backlog_mcp-1.0.4.dist-info}/METADATA +1 -1
- {backlog_mcp-1.0.3.dist-info → backlog_mcp-1.0.4.dist-info}/RECORD +6 -6
- {backlog_mcp-1.0.3.dist-info → backlog_mcp-1.0.4.dist-info}/WHEEL +0 -0
- {backlog_mcp-1.0.3.dist-info → backlog_mcp-1.0.4.dist-info}/entry_points.txt +0 -0
app/tools/get_issue_details.py
CHANGED
|
@@ -4,13 +4,15 @@ from app.utils.ultils import get_issue_detail_handler
|
|
|
4
4
|
|
|
5
5
|
async def get_issue_details(
|
|
6
6
|
issue_key: str,
|
|
7
|
-
|
|
7
|
+
include_comments: bool,
|
|
8
|
+
timezone: str = "UTC",
|
|
8
9
|
):
|
|
9
10
|
"""
|
|
10
11
|
Get details of a Backlog issue by its key.
|
|
11
12
|
|
|
12
13
|
Args:
|
|
13
14
|
issue_key (str): The key of the Backlog issue to retrieve.
|
|
15
|
+
include_comments (bool): Whether to include comments in the response.
|
|
14
16
|
timezone (str, optional): The timezone to format datetime fields. Defaults to "UTC".
|
|
15
17
|
"""
|
|
16
18
|
try:
|
|
@@ -22,6 +24,7 @@ async def get_issue_details(
|
|
|
22
24
|
api_key=ctx.api_key,
|
|
23
25
|
issue_key=issue_key,
|
|
24
26
|
timezone=timezone,
|
|
27
|
+
include_comments=include_comments,
|
|
25
28
|
)
|
|
26
29
|
return result
|
|
27
30
|
except Exception as e:
|
app/utils/ultils.py
CHANGED
|
@@ -46,28 +46,29 @@ def time_in_range(time: str, start_range: str, end_range: str):
|
|
|
46
46
|
return start_range_time <= time_to_be_compared <= end_range_time
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
def process_issue_detail(issue_detail, timezone, issue_key):
|
|
49
|
+
def process_issue_detail(issue_detail, timezone, issue_key, include_comments: bool = True):
|
|
50
50
|
processed_issue = {
|
|
51
51
|
"issue_key": issue_key,
|
|
52
52
|
"summary": issue_detail["summary"],
|
|
53
53
|
"description": issue_detail["description"]
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
if include_comments:
|
|
57
|
+
comments = issue_detail.get("comments", [])
|
|
58
|
+
if comments:
|
|
59
|
+
# Sort comments by created_at (created field)
|
|
60
|
+
sorted_comments = sorted(comments, key=lambda c: convert_to_timezone(timezone, c["created"]))
|
|
61
|
+
# Create list of {content, created_by} where created_by is just the name
|
|
62
|
+
processed_comments = [
|
|
63
|
+
{
|
|
64
|
+
"content": c["content"],
|
|
65
|
+
"created_by": c["createdUser"]["name"] if c.get("createdUser") else None
|
|
66
|
+
}
|
|
67
|
+
for c in sorted_comments if c.get("content")
|
|
68
|
+
]
|
|
69
|
+
# Filter out None created_by if any (though should not happen)
|
|
70
|
+
processed_comments = [c for c in processed_comments if c["created_by"]]
|
|
71
|
+
processed_issue["comments"] = processed_comments
|
|
71
72
|
|
|
72
73
|
return processed_issue
|
|
73
74
|
|
|
@@ -77,6 +78,7 @@ async def get_issue_detail_handler(
|
|
|
77
78
|
api_key: str,
|
|
78
79
|
issue_key: str,
|
|
79
80
|
timezone: str,
|
|
81
|
+
include_comments: bool = True,
|
|
80
82
|
):
|
|
81
83
|
issue_comments_url = f"{backlog_domain}api/v2/issues/{issue_key}/comments"
|
|
82
84
|
issue_detail_url = f"{backlog_domain}api/v2/issues/{issue_key}"
|
|
@@ -85,31 +87,38 @@ async def get_issue_detail_handler(
|
|
|
85
87
|
async with httpx.AsyncClient() as client:
|
|
86
88
|
try:
|
|
87
89
|
issue_detail_response = client.get(issue_detail_url, params=params)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
|
|
91
|
+
if include_comments:
|
|
92
|
+
comments_response = client.get(issue_comments_url, params=params)
|
|
93
|
+
results = await asyncio.gather(issue_detail_response, comments_response)
|
|
94
|
+
issue_detail_result = results[0]
|
|
95
|
+
comments_result = results[1]
|
|
96
|
+
issue_detail = issue_detail_result.json()
|
|
97
|
+
issue_comment = comments_result.json()
|
|
98
|
+
else:
|
|
99
|
+
issue_detail_result = await issue_detail_response
|
|
100
|
+
issue_detail = issue_detail_result.json()
|
|
101
|
+
issue_comment = []
|
|
94
102
|
|
|
95
|
-
if not
|
|
103
|
+
if not issue_detail_result.is_success:
|
|
96
104
|
error_code = issue_detail["errors"][0]["code"]
|
|
97
105
|
return {
|
|
98
106
|
"error_msg": BacklogApiError.get_description_by_code(error_code),
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
if not
|
|
109
|
+
if include_comments and not comments_result.is_success:
|
|
102
110
|
error_code = issue_comment["errors"][0]["code"]
|
|
103
111
|
return {
|
|
104
112
|
"error_msg": BacklogApiError.get_description_by_code(error_code),
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
115
|
+
if include_comments:
|
|
116
|
+
comments_in_time_range = []
|
|
117
|
+
for comment in issue_comment:
|
|
118
|
+
comments_in_time_range.append(comment)
|
|
119
|
+
issue_detail.update({"comments": comments_in_time_range})
|
|
110
120
|
|
|
111
|
-
issue_detail
|
|
112
|
-
processed_detail = process_issue_detail(issue_detail, timezone, issue_key)
|
|
121
|
+
processed_detail = process_issue_detail(issue_detail, timezone, issue_key, include_comments)
|
|
113
122
|
return processed_detail
|
|
114
123
|
|
|
115
124
|
except Exception as e:
|
|
@@ -8,12 +8,12 @@ app/core/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
|
8
8
|
app/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
app/models/models.py,sha256=y3JhziNew3_2bM4Lw3aVjWcTvhmaEbzz0AaCHsdAkbk,4169
|
|
10
10
|
app/tools/__init__.py,sha256=LxxyJiqccPQCNjei_YvtNJgEMs4U7IzKEsAaNKToaKg,68
|
|
11
|
-
app/tools/get_issue_details.py,sha256=
|
|
11
|
+
app/tools/get_issue_details.py,sha256=efixu906oloeIZdf-geTlLxt9nLe-tPDqUlDd9HL6-g,973
|
|
12
12
|
app/tools/get_user_issue_list.py,sha256=soNX0OfvfT1hIyzeDMPaHpAjHeGqavtZdTl0CemCpyo,865
|
|
13
13
|
app/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
app/utils/di.py,sha256=5MmL6efLAX3uzp5WSMi4E_BDCgapzlr_OERZoN5NGnM,408
|
|
15
|
-
app/utils/ultils.py,sha256=
|
|
16
|
-
backlog_mcp-1.0.
|
|
17
|
-
backlog_mcp-1.0.
|
|
18
|
-
backlog_mcp-1.0.
|
|
19
|
-
backlog_mcp-1.0.
|
|
15
|
+
app/utils/ultils.py,sha256=HXa43zAOtyr0VdNHS2Du8CzqseAop2lsjGBPSMZnmb4,11400
|
|
16
|
+
backlog_mcp-1.0.4.dist-info/METADATA,sha256=WWSScaN5867hmnddFdBrbls1dosDjmPLZ7wubzd67TM,3883
|
|
17
|
+
backlog_mcp-1.0.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
18
|
+
backlog_mcp-1.0.4.dist-info/entry_points.txt,sha256=h5JeHYUp_uoaya4FO3QelcsgYOu-VRmh5qWRhPrwjtk,46
|
|
19
|
+
backlog_mcp-1.0.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|