Skip to content

Commit cc6516c

Browse files
authored
Merge pull request github#1 from github/juruen/moar-tools
implement more tools
2 parents 901b16a + 22e58fb commit cc6516c

File tree

6 files changed

+1452
-53
lines changed

6 files changed

+1452
-53
lines changed

README.md

Lines changed: 135 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,141 @@ and set it as the GITHUB_PERSONAL_ACCESS_TOKEN environment variable.
1010

1111
## Tools
1212

13-
1. `get_me`
14-
- Return information about the authenticated user
15-
2. `get_issue`
16-
- Get the contents of an issue within a repository.
17-
- Inputs
18-
- `owner` (string): Repository owner
19-
- `repo` (string): Repository name
20-
- `issue_number` (number): Issue number to retrieve
21-
- Returns: Github Issue object & details
13+
### Users
14+
- **get_me** - Get details of the authenticated user
15+
- No parameters required
16+
17+
### Issues
18+
- **get_issue** - Gets the contents of an issue within a repository
19+
- `owner`: Repository owner (string, required)
20+
- `repo`: Repository name (string, required)
21+
- `issue_number`: Issue number (number, required)
22+
23+
- **add_issue_comment** - Add a comment to an issue
24+
- `owner`: Repository owner (string, required)
25+
- `repo`: Repository name (string, required)
26+
- `issue_number`: Issue number (number, required)
27+
- `body`: Comment text (string, required)
28+
29+
- **search_issues** - Search for issues and pull requests
30+
- `query`: Search query (string, required)
31+
- `sort`: Sort field (string, optional)
32+
- `order`: Sort order (string, optional)
33+
- `page`: Page number (number, optional)
34+
- `per_page`: Results per page (number, optional)
35+
36+
### Pull Requests
37+
- **get_pull_request** - Get details of a specific pull request
38+
- `owner`: Repository owner (string, required)
39+
- `repo`: Repository name (string, required)
40+
- `pull_number`: Pull request number (number, required)
41+
42+
- **list_pull_requests** - List and filter repository pull requests
43+
- `owner`: Repository owner (string, required)
44+
- `repo`: Repository name (string, required)
45+
- `state`: PR state (string, optional)
46+
- `sort`: Sort field (string, optional)
47+
- `direction`: Sort direction (string, optional)
48+
- `per_page`: Results per page (number, optional)
49+
- `page`: Page number (number, optional)
50+
51+
- **merge_pull_request** - Merge a pull request
52+
- `owner`: Repository owner (string, required)
53+
- `repo`: Repository name (string, required)
54+
- `pull_number`: Pull request number (number, required)
55+
- `commit_title`: Title for the merge commit (string, optional)
56+
- `commit_message`: Message for the merge commit (string, optional)
57+
- `merge_method`: Merge method (string, optional)
58+
59+
- **get_pull_request_files** - Get the list of files changed in a pull request
60+
- `owner`: Repository owner (string, required)
61+
- `repo`: Repository name (string, required)
62+
- `pull_number`: Pull request number (number, required)
63+
64+
- **get_pull_request_status** - Get the combined status of all status checks for a pull request
65+
- `owner`: Repository owner (string, required)
66+
- `repo`: Repository name (string, required)
67+
- `pull_number`: Pull request number (number, required)
68+
69+
- **update_pull_request_branch** - Update a pull request branch with the latest changes from the base branch
70+
- `owner`: Repository owner (string, required)
71+
- `repo`: Repository name (string, required)
72+
- `pull_number`: Pull request number (number, required)
73+
- `expected_head_sha`: The expected SHA of the pull request's HEAD ref (string, optional)
74+
75+
- **get_pull_request_comments** - Get the review comments on a pull request
76+
- `owner`: Repository owner (string, required)
77+
- `repo`: Repository name (string, required)
78+
- `pull_number`: Pull request number (number, required)
79+
80+
- **get_pull_request_reviews** - Get the reviews on a pull request
81+
- `owner`: Repository owner (string, required)
82+
- `repo`: Repository name (string, required)
83+
- `pull_number`: Pull request number (number, required)
84+
85+
### Repositories
86+
- **create_or_update_file** - Create or update a single file in a repository
87+
- `owner`: Repository owner (string, required)
88+
- `repo`: Repository name (string, required)
89+
- `path`: File path (string, required)
90+
- `message`: Commit message (string, required)
91+
- `content`: File content (string, required)
92+
- `branch`: Branch name (string, optional)
93+
- `sha`: File SHA if updating (string, optional)
94+
95+
- **search_repositories** - Search for GitHub repositories
96+
- `query`: Search query (string, required)
97+
- `sort`: Sort field (string, optional)
98+
- `order`: Sort order (string, optional)
99+
- `page`: Page number (number, optional)
100+
- `per_page`: Results per page (number, optional)
101+
102+
- **create_repository** - Create a new GitHub repository
103+
- `name`: Repository name (string, required)
104+
- `description`: Repository description (string, optional)
105+
- `private`: Whether the repository is private (boolean, optional)
106+
- `auto_init`: Auto-initialize with README (boolean, optional)
107+
- `gitignore_template`: Gitignore template name (string, optional)
108+
109+
- **get_file_contents** - Get contents of a file or directory
110+
- `owner`: Repository owner (string, required)
111+
- `repo`: Repository name (string, required)
112+
- `path`: File path (string, required)
113+
- `ref`: Git reference (string, optional)
114+
115+
- **fork_repository** - Fork a repository
116+
- `owner`: Repository owner (string, required)
117+
- `repo`: Repository name (string, required)
118+
- `organization`: Target organization name (string, optional)
119+
120+
- **create_branch** - Create a new branch
121+
- `owner`: Repository owner (string, required)
122+
- `repo`: Repository name (string, required)
123+
- `branch`: New branch name (string, required)
124+
- `sha`: SHA to create branch from (string, required)
125+
126+
- **list_commits** - Gets commits of a branch in a repository
127+
- `owner`: Repository owner (string, required)
128+
- `repo`: Repository name (string, required)
129+
- `sha`: Branch name, tag, or commit SHA (string, optional)
130+
- `path`: Only commits containing this file path (string, optional)
131+
- `page`: Page number (number, optional)
132+
- `per_page`: Results per page (number, optional)
133+
134+
### Search
135+
- **search_code** - Search for code across GitHub repositories
136+
- `query`: Search query (string, required)
137+
- `sort`: Sort field (string, optional)
138+
- `order`: Sort order (string, optional)
139+
- `page`: Page number (number, optional)
140+
- `per_page`: Results per page (number, optional)
141+
142+
- **search_users** - Search for GitHub users
143+
- `query`: Search query (string, required)
144+
- `sort`: Sort field (string, optional)
145+
- `order`: Sort order (string, optional)
146+
- `page`: Page number (number, optional)
147+
- `per_page`: Results per page (number, optional)
22148

23149
## Standard input/output server
24150

pkg/github/issues.go

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
9+
"github.com/google/go-github/v69/github"
10+
"github.com/mark3labs/mcp-go/mcp"
11+
"github.com/mark3labs/mcp-go/server"
12+
)
13+
14+
// getIssue creates a tool to get details of a specific issue in a GitHub repository.
15+
func getIssue(client *github.Client) (tool mcp.Tool, handler server.ToolHandlerFunc) {
16+
return mcp.NewTool("get_issue",
17+
mcp.WithDescription("Get details of a specific issue in a GitHub repository."),
18+
mcp.WithString("owner",
19+
mcp.Required(),
20+
mcp.Description("The owner of the repository."),
21+
),
22+
mcp.WithString("repo",
23+
mcp.Required(),
24+
mcp.Description("The name of the repository."),
25+
),
26+
mcp.WithNumber("issue_number",
27+
mcp.Required(),
28+
mcp.Description("The number of the issue."),
29+
),
30+
),
31+
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
32+
owner := request.Params.Arguments["owner"].(string)
33+
repo := request.Params.Arguments["repo"].(string)
34+
issueNumber := int(request.Params.Arguments["issue_number"].(float64))
35+
36+
issue, resp, err := client.Issues.Get(ctx, owner, repo, issueNumber)
37+
if err != nil {
38+
return nil, fmt.Errorf("failed to get issue: %w", err)
39+
}
40+
defer func() { _ = resp.Body.Close() }()
41+
42+
if resp.StatusCode != 200 {
43+
body, err := io.ReadAll(resp.Body)
44+
if err != nil {
45+
return nil, fmt.Errorf("failed to read response body: %w", err)
46+
}
47+
return mcp.NewToolResultError(fmt.Sprintf("failed to get issue: %s", string(body))), nil
48+
}
49+
50+
r, err := json.Marshal(issue)
51+
if err != nil {
52+
return nil, fmt.Errorf("failed to marshal issue: %w", err)
53+
}
54+
55+
return mcp.NewToolResultText(string(r)), nil
56+
}
57+
}
58+
59+
// addIssueComment creates a tool to add a comment to an issue.
60+
func addIssueComment(client *github.Client) (tool mcp.Tool, handler server.ToolHandlerFunc) {
61+
return mcp.NewTool("add_issue_comment",
62+
mcp.WithDescription("Add a comment to an issue"),
63+
mcp.WithString("owner",
64+
mcp.Required(),
65+
mcp.Description("Repository owner"),
66+
),
67+
mcp.WithString("repo",
68+
mcp.Required(),
69+
mcp.Description("Repository name"),
70+
),
71+
mcp.WithNumber("issue_number",
72+
mcp.Required(),
73+
mcp.Description("Issue number to comment on"),
74+
),
75+
mcp.WithString("body",
76+
mcp.Required(),
77+
mcp.Description("Comment text"),
78+
),
79+
),
80+
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
81+
owner := request.Params.Arguments["owner"].(string)
82+
repo := request.Params.Arguments["repo"].(string)
83+
issueNumber := int(request.Params.Arguments["issue_number"].(float64))
84+
body := request.Params.Arguments["body"].(string)
85+
86+
comment := &github.IssueComment{
87+
Body: github.Ptr(body),
88+
}
89+
90+
createdComment, resp, err := client.Issues.CreateComment(ctx, owner, repo, issueNumber, comment)
91+
if err != nil {
92+
return nil, fmt.Errorf("failed to create comment: %w", err)
93+
}
94+
defer func() { _ = resp.Body.Close() }()
95+
96+
if resp.StatusCode != 201 {
97+
body, err := io.ReadAll(resp.Body)
98+
if err != nil {
99+
return nil, fmt.Errorf("failed to read response body: %w", err)
100+
}
101+
return mcp.NewToolResultError(fmt.Sprintf("failed to create comment: %s", string(body))), nil
102+
}
103+
104+
r, err := json.Marshal(createdComment)
105+
if err != nil {
106+
return nil, fmt.Errorf("failed to marshal response: %w", err)
107+
}
108+
109+
return mcp.NewToolResultText(string(r)), nil
110+
}
111+
}
112+
113+
// searchIssues creates a tool to search for issues and pull requests.
114+
func searchIssues(client *github.Client) (tool mcp.Tool, handler server.ToolHandlerFunc) {
115+
return mcp.NewTool("search_issues",
116+
mcp.WithDescription("Search for issues and pull requests"),
117+
mcp.WithString("q",
118+
mcp.Required(),
119+
mcp.Description("Search query using GitHub issues search syntax"),
120+
),
121+
mcp.WithString("sort",
122+
mcp.Description("Sort field (comments, reactions, created, etc.)"),
123+
),
124+
mcp.WithString("order",
125+
mcp.Description("Sort order ('asc' or 'desc')"),
126+
),
127+
mcp.WithNumber("per_page",
128+
mcp.Description("Results per page (max 100)"),
129+
),
130+
mcp.WithNumber("page",
131+
mcp.Description("Page number"),
132+
),
133+
),
134+
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
135+
query := request.Params.Arguments["q"].(string)
136+
sort := ""
137+
if s, ok := request.Params.Arguments["sort"].(string); ok {
138+
sort = s
139+
}
140+
order := ""
141+
if o, ok := request.Params.Arguments["order"].(string); ok {
142+
order = o
143+
}
144+
perPage := 30
145+
if pp, ok := request.Params.Arguments["per_page"].(float64); ok {
146+
perPage = int(pp)
147+
}
148+
page := 1
149+
if p, ok := request.Params.Arguments["page"].(float64); ok {
150+
page = int(p)
151+
}
152+
153+
opts := &github.SearchOptions{
154+
Sort: sort,
155+
Order: order,
156+
ListOptions: github.ListOptions{
157+
PerPage: perPage,
158+
Page: page,
159+
},
160+
}
161+
162+
result, resp, err := client.Search.Issues(ctx, query, opts)
163+
if err != nil {
164+
return nil, fmt.Errorf("failed to search issues: %w", err)
165+
}
166+
defer func() { _ = resp.Body.Close() }()
167+
168+
if resp.StatusCode != 200 {
169+
body, err := io.ReadAll(resp.Body)
170+
if err != nil {
171+
return nil, fmt.Errorf("failed to read response body: %w", err)
172+
}
173+
return mcp.NewToolResultError(fmt.Sprintf("failed to search issues: %s", string(body))), nil
174+
}
175+
176+
r, err := json.Marshal(result)
177+
if err != nil {
178+
return nil, fmt.Errorf("failed to marshal response: %w", err)
179+
}
180+
181+
return mcp.NewToolResultText(string(r)), nil
182+
}
183+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy