Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc77ea94

Browse files
Add support for retrieving GitHub Issue Comments (#106)
* Add support for retrieving GitHub Issue CommentsAdd new tool 'get_issue_comments' that allows fetching comments associatedwith GitHub issues. This complements the existing issue retrieval functionalityand follows the same patterns as the pull request comments implementation.The implementation includes:- New getIssueComments function in pkg/github/issues.go- Tool registration in server.go- Comprehensive test coverage in issues_test.go* Support pagination for get_issue_comments---------Co-authored-by: Javier Uruen Val <juruen@github.com>
1 parente6b73f7 commitc77ea94

File tree

5 files changed

+217
-0
lines changed

5 files changed

+217
-0
lines changed

‎README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
153153
-`repo`: Repository name (string, required)
154154
-`issue_number`: Issue number (number, required)
155155

156+
-**get_issue_comments** - Get comments for a GitHub issue
157+
158+
-`owner`: Repository owner (string, required)
159+
-`repo`: Repository name (string, required)
160+
-`issue_number`: Issue number (number, required)
161+
156162
-**create_issue** - Create a new issue in a GitHub repository
157163

158164
-`owner`: Repository owner (string, required)

‎cmd/mcpcurl/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Available Commands:
5050
fork_repository Fork a GitHub repository to your account or specified organization
5151
get_file_contents Get the contents of a file or directory from a GitHub repository
5252
get_issue Get details of a specific issuein a GitHub repository.
53+
get_issue_comments Get commentsfor a GitHub issue
5354
list_commits Get list of commits of a branchin a GitHub repository
5455
list_issues List issuesin a GitHub repository with filtering options
5556
push_files Push multiple files to a GitHub repositoryin a single commit

‎pkg/github/issues.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,81 @@ func updateIssue(client *github.Client, t translations.TranslationHelperFunc) (t
597597
}
598598
}
599599

600+
// getIssueComments creates a tool to get comments for a GitHub issue.
601+
funcgetIssueComments(client*github.Client,t translations.TranslationHelperFunc) (tool mcp.Tool,handler server.ToolHandlerFunc) {
602+
returnmcp.NewTool("get_issue_comments",
603+
mcp.WithDescription(t("TOOL_GET_ISSUE_COMMENTS_DESCRIPTION","Get comments for a GitHub issue")),
604+
mcp.WithString("owner",
605+
mcp.Required(),
606+
mcp.Description("Repository owner"),
607+
),
608+
mcp.WithString("repo",
609+
mcp.Required(),
610+
mcp.Description("Repository name"),
611+
),
612+
mcp.WithNumber("issue_number",
613+
mcp.Required(),
614+
mcp.Description("Issue number"),
615+
),
616+
mcp.WithNumber("page",
617+
mcp.Description("Page number"),
618+
),
619+
mcp.WithNumber("per_page",
620+
mcp.Description("Number of records per page"),
621+
),
622+
),
623+
func(ctx context.Context,request mcp.CallToolRequest) (*mcp.CallToolResult,error) {
624+
owner,err:=requiredParam[string](request,"owner")
625+
iferr!=nil {
626+
returnmcp.NewToolResultError(err.Error()),nil
627+
}
628+
repo,err:=requiredParam[string](request,"repo")
629+
iferr!=nil {
630+
returnmcp.NewToolResultError(err.Error()),nil
631+
}
632+
issueNumber,err:=requiredInt(request,"issue_number")
633+
iferr!=nil {
634+
returnmcp.NewToolResultError(err.Error()),nil
635+
}
636+
page,err:=optionalIntParamWithDefault(request,"page",1)
637+
iferr!=nil {
638+
returnmcp.NewToolResultError(err.Error()),nil
639+
}
640+
perPage,err:=optionalIntParamWithDefault(request,"per_page",30)
641+
iferr!=nil {
642+
returnmcp.NewToolResultError(err.Error()),nil
643+
}
644+
645+
opts:=&github.IssueListCommentsOptions{
646+
ListOptions: github.ListOptions{
647+
Page:page,
648+
PerPage:perPage,
649+
},
650+
}
651+
652+
comments,resp,err:=client.Issues.ListComments(ctx,owner,repo,issueNumber,opts)
653+
iferr!=nil {
654+
returnnil,fmt.Errorf("failed to get issue comments: %w",err)
655+
}
656+
deferfunc() {_=resp.Body.Close() }()
657+
658+
ifresp.StatusCode!=http.StatusOK {
659+
body,err:=io.ReadAll(resp.Body)
660+
iferr!=nil {
661+
returnnil,fmt.Errorf("failed to read response body: %w",err)
662+
}
663+
returnmcp.NewToolResultError(fmt.Sprintf("failed to get issue comments: %s",string(body))),nil
664+
}
665+
666+
r,err:=json.Marshal(comments)
667+
iferr!=nil {
668+
returnnil,fmt.Errorf("failed to marshal response: %w",err)
669+
}
670+
671+
returnmcp.NewToolResultText(string(r)),nil
672+
}
673+
}
674+
600675
// parseISOTimestamp parses an ISO 8601 timestamp string into a time.Time object.
601676
// Returns the parsed time or an error if parsing fails.
602677
// Example formats supported: "2023-01-15T14:30:00Z", "2023-01-15"

‎pkg/github/issues_test.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,3 +984,137 @@ func Test_ParseISOTimestamp(t *testing.T) {
984984
})
985985
}
986986
}
987+
988+
funcTest_GetIssueComments(t*testing.T) {
989+
// Verify tool definition once
990+
mockClient:=github.NewClient(nil)
991+
tool,_:=getIssueComments(mockClient,translations.NullTranslationHelper)
992+
993+
assert.Equal(t,"get_issue_comments",tool.Name)
994+
assert.NotEmpty(t,tool.Description)
995+
assert.Contains(t,tool.InputSchema.Properties,"owner")
996+
assert.Contains(t,tool.InputSchema.Properties,"repo")
997+
assert.Contains(t,tool.InputSchema.Properties,"issue_number")
998+
assert.Contains(t,tool.InputSchema.Properties,"page")
999+
assert.Contains(t,tool.InputSchema.Properties,"per_page")
1000+
assert.ElementsMatch(t,tool.InputSchema.Required, []string{"owner","repo","issue_number"})
1001+
1002+
// Setup mock comments for success case
1003+
mockComments:= []*github.IssueComment{
1004+
{
1005+
ID:github.Ptr(int64(123)),
1006+
Body:github.Ptr("This is the first comment"),
1007+
User:&github.User{
1008+
Login:github.Ptr("user1"),
1009+
},
1010+
CreatedAt:&github.Timestamp{Time:time.Now().Add(-time.Hour*24)},
1011+
},
1012+
{
1013+
ID:github.Ptr(int64(456)),
1014+
Body:github.Ptr("This is the second comment"),
1015+
User:&github.User{
1016+
Login:github.Ptr("user2"),
1017+
},
1018+
CreatedAt:&github.Timestamp{Time:time.Now().Add(-time.Hour)},
1019+
},
1020+
}
1021+
1022+
tests:= []struct {
1023+
namestring
1024+
mockedClient*http.Client
1025+
requestArgsmap[string]interface{}
1026+
expectErrorbool
1027+
expectedComments []*github.IssueComment
1028+
expectedErrMsgstring
1029+
}{
1030+
{
1031+
name:"successful comments retrieval",
1032+
mockedClient:mock.NewMockedHTTPClient(
1033+
mock.WithRequestMatch(
1034+
mock.GetReposIssuesCommentsByOwnerByRepoByIssueNumber,
1035+
mockComments,
1036+
),
1037+
),
1038+
requestArgs:map[string]interface{}{
1039+
"owner":"owner",
1040+
"repo":"repo",
1041+
"issue_number":float64(42),
1042+
},
1043+
expectError:false,
1044+
expectedComments:mockComments,
1045+
},
1046+
{
1047+
name:"successful comments retrieval with pagination",
1048+
mockedClient:mock.NewMockedHTTPClient(
1049+
mock.WithRequestMatchHandler(
1050+
mock.GetReposIssuesCommentsByOwnerByRepoByIssueNumber,
1051+
expectQueryParams(t,map[string]string{
1052+
"page":"2",
1053+
"per_page":"10",
1054+
}).andThen(
1055+
mockResponse(t,http.StatusOK,mockComments),
1056+
),
1057+
),
1058+
),
1059+
requestArgs:map[string]interface{}{
1060+
"owner":"owner",
1061+
"repo":"repo",
1062+
"issue_number":float64(42),
1063+
"page":float64(2),
1064+
"per_page":float64(10),
1065+
},
1066+
expectError:false,
1067+
expectedComments:mockComments,
1068+
},
1069+
{
1070+
name:"issue not found",
1071+
mockedClient:mock.NewMockedHTTPClient(
1072+
mock.WithRequestMatchHandler(
1073+
mock.GetReposIssuesCommentsByOwnerByRepoByIssueNumber,
1074+
mockResponse(t,http.StatusNotFound,`{"message": "Issue not found"}`),
1075+
),
1076+
),
1077+
requestArgs:map[string]interface{}{
1078+
"owner":"owner",
1079+
"repo":"repo",
1080+
"issue_number":float64(999),
1081+
},
1082+
expectError:true,
1083+
expectedErrMsg:"failed to get issue comments",
1084+
},
1085+
}
1086+
1087+
for_,tc:=rangetests {
1088+
t.Run(tc.name,func(t*testing.T) {
1089+
// Setup client with mock
1090+
client:=github.NewClient(tc.mockedClient)
1091+
_,handler:=getIssueComments(client,translations.NullTranslationHelper)
1092+
1093+
// Create call request
1094+
request:=createMCPRequest(tc.requestArgs)
1095+
1096+
// Call handler
1097+
result,err:=handler(context.Background(),request)
1098+
1099+
// Verify results
1100+
iftc.expectError {
1101+
require.Error(t,err)
1102+
assert.Contains(t,err.Error(),tc.expectedErrMsg)
1103+
return
1104+
}
1105+
1106+
require.NoError(t,err)
1107+
textContent:=getTextResult(t,result)
1108+
1109+
// Unmarshal and verify the result
1110+
varreturnedComments []*github.IssueComment
1111+
err=json.Unmarshal([]byte(textContent.Text),&returnedComments)
1112+
require.NoError(t,err)
1113+
assert.Equal(t,len(tc.expectedComments),len(returnedComments))
1114+
iflen(returnedComments)>0 {
1115+
assert.Equal(t,*tc.expectedComments[0].Body,*returnedComments[0].Body)
1116+
assert.Equal(t,*tc.expectedComments[0].User.Login,*returnedComments[0].User.Login)
1117+
}
1118+
})
1119+
}
1120+
}

‎pkg/github/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func NewServer(client *github.Client, readOnly bool, t translations.TranslationH
3434
s.AddTool(getIssue(client,t))
3535
s.AddTool(searchIssues(client,t))
3636
s.AddTool(listIssues(client,t))
37+
s.AddTool(getIssueComments(client,t))
3738
if!readOnly {
3839
s.AddTool(createIssue(client,t))
3940
s.AddTool(addIssueComment(client,t))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp