Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 37 additions & 38 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os
import argparse
import types
from dotenv import load_dotenv
from jira import JIRA
from fastmcp import FastMCP
Expand Down Expand Up @@ -57,42 +58,40 @@ def to_markdown(obj):
return "```json\n" + json.dumps(obj, indent=2) + "\n```"
elif hasattr(obj, "raw"):
return "```json\n" + json.dumps(obj.raw, indent=2) + "\n```"
elif isinstance(obj, list):
return "\n".join([to_markdown(o) for o in obj])
elif isinstance(obj, list) or isinstance(obj, types.GeneratorType):
return "\n".join((to_markdown(o) for o in obj))
else:
return str(obj)


@mcp.tool()
def search_issues(jql: str, max_results: int = 100) -> str:
"""Search issues using JQL."""

def simplify_issue(issue):
"""Extract only essential fields to avoid token limit issues"""
return {
"key": issue.key,
"summary": issue.fields.summary,
"status": issue.fields.status.name if issue.fields.status else None,
"assignee": (issue.fields.assignee.displayName if issue.fields.assignee else None),
"qa_contact": (
qa_contact.displayName
if (qa_contact := getattr(issue.fields, QA_CONTACT_FID, None))
else None
),
"reporter": (issue.fields.reporter.displayName if issue.fields.reporter else None),
"priority": (issue.fields.priority.name if issue.fields.priority else None),
"issuetype": (issue.fields.issuetype.name if issue.fields.issuetype else None),
"fixVersion": (issue.fields.fixVersions[0].name if issue.fields.fixVersions else None),
"created": issue.fields.created,
"updated": issue.fields.updated,
"description": issue.fields.description,
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I know this is in draft, but) I think this change needs to be described in the commit message, or split into a separate commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the feedback, what do you think now?

try:
issues = jira_client.search_issues(jql, maxResults=max_results)
# Extract only essential fields to avoid token limit issues
simplified_issues = []
for issue in issues:
simplified = {
"key": issue.key,
"summary": issue.fields.summary,
"status": issue.fields.status.name if issue.fields.status else None,
"assignee": (issue.fields.assignee.displayName if issue.fields.assignee else None),
"qa_contact": (
qa_contact.displayName
if (qa_contact := getattr(issue.fields, QA_CONTACT_FID, None))
else None
),
"reporter": (issue.fields.reporter.displayName if issue.fields.reporter else None),
"priority": (issue.fields.priority.name if issue.fields.priority else None),
"issuetype": (issue.fields.issuetype.name if issue.fields.issuetype else None),
"fixVersion": (
issue.fields.fixVersions[0].name if issue.fields.fixVersions else None
),
"created": issue.fields.created,
"updated": issue.fields.updated,
"description": issue.fields.description,
}
simplified_issues.append(simplified)
return to_markdown(simplified_issues)
return to_markdown((simplify_issue(issue) for issue in issues))
except Exception as e:
raise HTTPException(status_code=400, detail=f"JQL search failed: {e}")

Expand Down Expand Up @@ -353,19 +352,19 @@ def delete_comment(issue_key: str, comment_id: str) -> str:
@mcp.tool()
def get_issue_comments(issue_key: str) -> str:
"""Get all comments for a Jira issue."""

def simplify_comment(comment):
return {
"id": comment.id,
"author": comment.author.displayName if comment.author else "Unknown",
"body": comment.body,
"created": comment.created,
"updated": (comment.updated if hasattr(comment, "updated") else comment.created),
}

try:
issue = jira_client.issue(issue_key)
comments = []
for comment in issue.fields.comment.comments:
comment_data = {
"id": comment.id,
"author": comment.author.displayName if comment.author else "Unknown",
"body": comment.body,
"created": comment.created,
"updated": (comment.updated if hasattr(comment, "updated") else comment.created),
}
comments.append(comment_data)
return to_markdown(comments)
return to_markdown((simplify_comment(c) for c in issue.fields.comment.comments))
except Exception as e:
raise HTTPException(status_code=400, detail=f"Failed to get comments for {issue_key}: {e}")

Expand Down