Skip to content

Commit 9f68a61

Browse files
authored
Merge pull request #24 from natifridman/get-comments
Get Jira comments to issue
2 parents 33bb217 + a7a94d5 commit 9f68a61

File tree

3 files changed

+73
-13
lines changed

3 files changed

+73
-13
lines changed

README.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@ A Model Context Protocol (MCP) server that provides access to JIRA issue data st
66

77
This MCP server connects to Snowflake to query JIRA data and provides three main tools for interacting with the data:
88

9-
- **`list_issues`** - Query and filter JIRA issues with various criteria
10-
- **`get_issue_details`** - Get detailed information for a specific issue by key
11-
- **`get_project_summary`** - Get statistics and summaries for all projects
9+
- **`list_jira_issues`** - Query and filter JIRA issues with various criteria
10+
- **`get_jira_issue_details`** - Get detailed information for a specific issue by key
11+
- **`get_jira_project_summary`** - Get statistics and summaries for all projects
1212

1313
## Features
1414

1515
### Data Sources
1616
The server connects to Snowflake and queries the following tables:
1717
- `JIRA_ISSUE_NON_PII` - Main issue data (non-personally identifiable information)
1818
- `JIRA_LABEL_RHAI` - Issue labels and tags
19+
- `JIRA_COMMENT_NON_PII` - Issue comments (non-personally identifiable information)
1920

2021
**Note**: Table names are expected to exist in your configured Snowflake database and schema.
2122

2223
### Available Tools
2324

24-
#### 1. List Issues (`list_issues`)
25+
#### 1. List Issues (`list_jira_issues`)
2526
Query JIRA issues with optional filtering:
2627
- **Project filtering** - Filter by project key (e.g., 'SMQE', 'OSIM')
2728
- **Issue type filtering** - Filter by issue type ID
@@ -30,15 +31,16 @@ Query JIRA issues with optional filtering:
3031
- **Text search** - Search in summary and description fields
3132
- **Result limiting** - Control number of results returned (default: 50)
3233

33-
#### 2. Get Issue Details (`get_issue_details`)
34+
#### 2. Get Issue Details (`get_jira_issue_details`)
3435
Retrieve comprehensive information for a specific JIRA issue by its key (e.g., 'SMQE-1280'), including:
3536
- Basic issue information (summary, description, status, priority)
3637
- Timestamps (created, updated, due date, resolution date)
3738
- Time tracking (original estimate, current estimate, time spent)
3839
- Metadata (votes, watches, environment, components)
3940
- Associated labels
41+
- Comments (with comment body, creation/update timestamps, and role level)
4042

41-
#### 3. Get Project Summary (`get_project_summary`)
43+
#### 3. Get Project Summary (`get_jira_project_summary`)
4244
Generate statistics across all projects:
4345
- Total issue counts per project
4446
- Status distribution per project
@@ -206,25 +208,25 @@ Example configuration to add to VS Code Continue:
206208
### Query Issues by Project
207209
```python
208210
# List all issues from the SMQE project
209-
result = await list_issues(project="SMQE", limit=10)
211+
result = await list_jira_issues(project="SMQE", limit=10)
210212
```
211213

212214
### Search Issues by Text
213215
```python
214216
# Search for issues containing "authentication" in summary or description
215-
result = await list_issues(search_text="authentication", limit=20)
217+
result = await list_jira_issues(search_text="authentication", limit=20)
216218
```
217219

218220
### Get Specific Issue Details
219221
```python
220222
# Get detailed information for a specific issue
221-
result = await get_issue_details(issue_key="SMQE-1280")
223+
result = await get_jira_issue_details(issue_key="SMQE-1280")
222224
```
223225

224226
### Get Project Overview
225227
```python
226228
# Get statistics for all projects
227-
result = await get_project_summary()
229+
result = await get_jira_project_summary()
228230
```
229231

230232
## Monitoring

src/database.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,57 @@ async def get_issue_labels(issue_ids: List[str], snowflake_token: Optional[str]
171171
except Exception as e:
172172
logger.error(f"Error fetching labels: {str(e)}")
173173

174-
return labels_data
174+
return labels_data
175+
176+
async def get_issue_comments(issue_ids: List[str], snowflake_token: Optional[str] = None) -> Dict[str, List[Dict[str, Any]]]:
177+
"""Get comments for given issue IDs from Snowflake"""
178+
if not issue_ids:
179+
return {}
180+
181+
comments_data = {}
182+
183+
try:
184+
# Sanitize and validate issue IDs (should be numeric)
185+
sanitized_ids = []
186+
for issue_id in issue_ids:
187+
# Ensure issue IDs are numeric to prevent injection
188+
if isinstance(issue_id, (str, int)) and str(issue_id).isdigit():
189+
sanitized_ids.append(str(issue_id))
190+
191+
if not sanitized_ids:
192+
return {}
193+
194+
# Create comma-separated list for IN clause
195+
ids_str = "'" + "','".join(sanitized_ids) + "'"
196+
197+
sql = f"""
198+
SELECT ID, ISSUEID, ROLELEVEL, BODY, CREATED, UPDATED
199+
FROM JIRA_COMMENT_NON_PII
200+
WHERE ISSUEID IN ({ids_str}) AND BODY IS NOT NULL
201+
ORDER BY ISSUEID, CREATED ASC
202+
"""
203+
204+
rows = await execute_snowflake_query(sql, snowflake_token)
205+
columns = ["ID", "ISSUEID", "ROLELEVEL", "BODY", "CREATED", "UPDATED"]
206+
207+
for row in rows:
208+
row_dict = format_snowflake_row(row, columns)
209+
issue_id = str(row_dict.get("ISSUEID"))
210+
211+
if issue_id:
212+
if issue_id not in comments_data:
213+
comments_data[issue_id] = []
214+
215+
comment = {
216+
"id": row_dict.get("ID"),
217+
"role_level": row_dict.get("ROLELEVEL"),
218+
"body": row_dict.get("BODY"),
219+
"created": row_dict.get("CREATED"),
220+
"updated": row_dict.get("UPDATED")
221+
}
222+
comments_data[issue_id].append(comment)
223+
224+
except Exception as e:
225+
logger.error(f"Error fetching comments: {str(e)}")
226+
227+
return comments_data

src/tools.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
execute_snowflake_query,
99
format_snowflake_row,
1010
sanitize_sql_value,
11-
get_issue_labels
11+
get_issue_labels,
12+
get_issue_comments
1213
)
1314
from metrics import track_tool_usage
1415

@@ -183,7 +184,7 @@ async def get_jira_issue_details(issue_key: str) -> Dict[str, Any]:
183184
issue_key: The JIRA issue key (e.g., 'SMQE-1280')
184185
185186
Returns:
186-
Dictionary containing detailed issue information
187+
Dictionary containing detailed issue information including comments
187188
"""
188189
try:
189190
# Get the Snowflake token
@@ -252,6 +253,10 @@ async def get_jira_issue_details(issue_key: str) -> Dict[str, Any]:
252253
labels_data = await get_issue_labels([str(issue['id'])], snowflake_token)
253254
issue['labels'] = labels_data.get(str(issue['id']), [])
254255

256+
# Get comments for this issue
257+
comments_data = await get_issue_comments([str(issue['id'])], snowflake_token)
258+
issue['comments'] = comments_data.get(str(issue['id']), [])
259+
255260
return issue
256261

257262
except Exception as e:

0 commit comments

Comments
 (0)