mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2026-08-29 11:37:44 +00:00
feat(issue): add get_discussion_markdown to issue_read
Adds a new issue_read method that fetches an issue and its comments and renders them as a single Markdown document, instead of a JSON array. Formatting logic lives in a pure, unit-tested helper (formatDiscussionMarkdown) covering comment rendering, empty comment lists, and attachment-inlined bodies. Existing get/get_comments/ get_labels methods are unchanged. Co-Authored-By: Codet <codet@commitgo.dev> (GPT-5-Codex)
This commit is contained in:
@@ -55,9 +55,9 @@ var (
|
||||
|
||||
IssueReadTool = tool.NewDefinition(
|
||||
IssueReadToolName,
|
||||
"Read issue: details, comments, or labels.",
|
||||
"Read issue: details, comments, labels, or the full discussion as Markdown.",
|
||||
annotation.ReadOnly("Read issue details"),
|
||||
tool.String("method", tool.Required(), tool.Enum("get", "get_comments", "get_labels")),
|
||||
tool.String("method", tool.Required(), tool.Enum("get", "get_comments", "get_labels", "get_discussion_markdown")),
|
||||
tool.String("owner", tool.Required(), tool.Description(params.OwnerDesc)),
|
||||
tool.String("repo", tool.Required(), tool.Description(params.RepoDesc)),
|
||||
tool.Number("issue_number", tool.Required()),
|
||||
@@ -112,6 +112,8 @@ func issueReadFn(ctx context.Context, args map[string]any) (*mcp.CallToolResult,
|
||||
return getIssueCommentsByIndexFn(ctx, args)
|
||||
case "get_labels":
|
||||
return getIssueLabelsFn(ctx, args)
|
||||
case "get_discussion_markdown":
|
||||
return getIssueDiscussionMarkdownFn(ctx, args)
|
||||
default:
|
||||
return to.ErrorResult(fmt.Errorf("unknown method: %s", method))
|
||||
}
|
||||
@@ -398,6 +400,54 @@ func getIssueCommentsByIndexFn(ctx context.Context, args map[string]any) (*mcp.C
|
||||
return to.TextResult(out)
|
||||
}
|
||||
|
||||
func getIssueDiscussionMarkdownFn(ctx context.Context, args map[string]any) (*mcp.CallToolResult, error) {
|
||||
owner, err := params.GetString(args, "owner")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
repo, err := params.GetString(args, "repo")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
index, err := params.GetIndex(args, "issue_number")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
|
||||
var issue issueWithAssets
|
||||
issuePath := fmt.Sprintf("repos/%s/%s/issues/%d", url.PathEscape(owner), url.PathEscape(repo), index)
|
||||
if _, err := gitea.DoJSON(ctx, "GET", issuePath, nil, nil, &issue); err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get %v/%v/issue/%v err: %v", owner, repo, index, err))
|
||||
}
|
||||
|
||||
var comments []commentWithAssets
|
||||
commentsPath := fmt.Sprintf("repos/%s/%s/issues/%d/comments", url.PathEscape(owner), url.PathEscape(repo), index)
|
||||
if _, err := gitea.DoJSON(ctx, "GET", commentsPath, nil, nil, &comments); err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get %v/%v/issues/%v/comments err: %v", owner, repo, index, err))
|
||||
}
|
||||
|
||||
discComments := make([]discussionComment, 0, len(comments))
|
||||
for i := range comments {
|
||||
discComments = append(discComments, discussionComment{
|
||||
Author: slim.UserLogin(comments[i].Poster),
|
||||
CreatedAt: comments[i].Created,
|
||||
Body: slim.BodyWithAttachments(comments[i].Body, comments[i].Assets),
|
||||
})
|
||||
}
|
||||
|
||||
md := formatDiscussionMarkdown(discussionIssue{
|
||||
Number: issue.Index,
|
||||
Title: issue.Title,
|
||||
Author: slim.UserLogin(issue.Poster),
|
||||
State: string(issue.State),
|
||||
Labels: slim.LabelNames(issue.Labels),
|
||||
Body: slim.BodyWithAttachments(issue.Body, issue.Assets),
|
||||
CreatedAt: issue.Created,
|
||||
}, discComments)
|
||||
|
||||
return to.RawTextResult(md)
|
||||
}
|
||||
|
||||
func getIssueLabelsFn(ctx context.Context, args map[string]any) (*mcp.CallToolResult, error) {
|
||||
owner, err := params.GetString(args, "owner")
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user