Skip to content

feat(resources): return issue resource as single markdown document#2031

Open
SamMorrowDrums wants to merge 1 commit intomainfrom
sammorrowdrums/issue-resource-template
Open

feat(resources): return issue resource as single markdown document#2031
SamMorrowDrums wants to merge 1 commit intomainfrom
sammorrowdrums/issue-resource-template

Conversation

@SamMorrowDrums
Copy link
Collaborator

Summary

Prototype of issues as an MCP resource. Consolidates the issue resource into a single ResourceContents item — one markdown file with the issue body, frontmatter metadata, and all comments separated by --- delimiters.

Changes

  • Return one markdown file instead of multiple content items (VS Code doesn't support multi-file resource responses)
  • Use .md extension in URI template for editor preview support
  • Convert HTML <img> tags to markdown image syntax
  • Keep original image URLs rather than fetching/embedding them

Caveats

  • Private image resources won't render in markdown preview (they require session-based auth that can't be forwarded)
  • This is a prototype — not sure if we want this, but lots of GitHub content could be resources

Testing

  • All existing tests updated and passing
  • Added tests for HTML img tag conversion
  • script/lint and script/test pass

Consolidate the issue resource into a single ResourceContents item
containing the issue body, frontmatter metadata, and all comments
separated by --- delimiters.

- Return one markdown file instead of multiple content items
- Use .md extension in URI template for editor preview support
- Convert HTML <img> tags to markdown image syntax
- Keep original image URLs (private images won't render in preview)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 18, 2026 09:31
@SamMorrowDrums SamMorrowDrums requested a review from a team as a code owner February 18, 2026 09:31
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

pkg/github/issue_resource.go:261

  • The response body from client.Search.Issues is not being closed, which can lead to resource leaks. The response should be captured and its body should be closed with a defer statement.

Similar to the pattern used in other parts of the codebase, the response body should be closed:

issues, resp, err := client.Search.Issues(ctx, fmt.Sprintf("repo:%s/%s is:issue", owner, repo), &github.SearchOptions{
    ListOptions: github.ListOptions{PerPage: 100},
})
if err != nil {
    return nil, err
}
defer func() { _ = resp.Body.Close() }()

Note: This same issue exists in completePRNumber in repository_resource_completions.go line 218, but that's outside the scope of this PR.

	issues, _, err := client.Search.Issues(ctx, fmt.Sprintf("repo:%s/%s is:issue", owner, repo), &github.SearchOptions{

Comment on lines +82 to +85
issue, _, err := client.Issues.Get(ctx, owner, repo, issueNumber)
if err != nil {
return nil, fmt.Errorf("failed to get issue: %w", err)
}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

The response body from client.Issues.Get is not being closed, which can lead to resource leaks. The response should be captured and its body should be closed with a defer statement, similar to the pattern used in GetIssue function in issues.go.

The response body should be closed even when the blank identifier is used for the response variable, following the pattern:

issue, resp, err := client.Issues.Get(ctx, owner, repo, issueNumber)
if err != nil {
    return nil, fmt.Errorf("failed to get issue: %w", err)
}
defer func() { _ = resp.Body.Close() }()

This issue also appears on line 261 of the same file.

Suggested change
issue, _, err := client.Issues.Get(ctx, owner, repo, issueNumber)
if err != nil {
return nil, fmt.Errorf("failed to get issue: %w", err)
}
issue, resp, err := client.Issues.Get(ctx, owner, repo, issueNumber)
if err != nil {
return nil, fmt.Errorf("failed to get issue: %w", err)
}
defer func() { _ = resp.Body.Close() }()

Copilot uses AI. Check for mistakes.
Comment on lines +127 to +155
b.WriteString(fmt.Sprintf("state: %s\n", issue.GetState()))
if user := issue.GetUser(); user != nil {
b.WriteString(fmt.Sprintf("author: %s\n", user.GetLogin()))
}
if issue.CreatedAt != nil {
b.WriteString(fmt.Sprintf("created_at: %s\n", issue.CreatedAt.Format("2006-01-02T15:04:05Z")))
}
if len(issue.Labels) > 0 {
b.WriteString("labels:\n")
for _, label := range issue.Labels {
if label != nil {
b.WriteString(fmt.Sprintf(" - %s\n", label.GetName()))
}
}
}
if issue.GetMilestone() != nil {
b.WriteString(fmt.Sprintf("milestone: %s\n", issue.GetMilestone().GetTitle()))
}
b.WriteString("---\n\n")
return b.String()
}

func buildCommentFrontmatter(comment *github.IssueComment) string {
var b strings.Builder
b.WriteString("---\n")
if user := comment.GetUser(); user != nil {
b.WriteString(fmt.Sprintf("author: %s\n", user.GetLogin()))
}
b.WriteString(fmt.Sprintf("author_association: %s\n", comment.GetAuthorAssociation()))
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

Several frontmatter fields are not quoted or escaped, which could potentially cause YAML parsing issues if they contain special characters like colons, quotes, or hash symbols. While unlikely in practice (GitHub usernames are alphanumeric, states are enums, etc.), consider quoting these values for robustness:

  • author (lines 129, 153)
  • state (line 127)
  • milestone (line 143)
  • author_association (line 155)
  • labels array items (line 138)

For example:

b.WriteString(fmt.Sprintf("author: %q\n", user.GetLogin()))
b.WriteString(fmt.Sprintf("  - %s\n", label.GetName())) // Labels can be handled with %q as well

This would make the YAML more robust against edge cases and align with how the title field is handled.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant