Skip to content

Commit 53e2708

Browse files
authored
Merge branch 'main' into feat/259/assign-reviewers
2 parents b09f589 + 45d0270 commit 53e2708

File tree

15 files changed

+819
-160
lines changed

15 files changed

+819
-160
lines changed

.github/workflows/docker-publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ on:
99
schedule:
1010
- cron: "27 0 * * *"
1111
push:
12-
branches: ["main"]
12+
branches: ["main", "next"]
1313
# Publish semver tags as releases.
1414
tags: ["v*.*.*"]
1515
pull_request:
16-
branches: ["main"]
16+
branches: ["main", "next"]
1717

1818
env:
1919
# Use docker.io for Docker Hub if empty

CONTRIBUTING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ These are one time installations required to be able to test your changes locall
1919

2020
## Submitting a pull request
2121

22+
> **Important**: Please open your pull request against the `next` branch, not `main`. The `next` branch is where we integrate new features and changes before they are merged to `main`.
23+
2224
1. [Fork][fork] and clone the repository
2325
1. Make sure the tests pass on your machine: `go test -v ./...`
2426
1. Make sure linter passes on your machine: `golangci-lint run`
2527
1. Create a new branch: `git checkout -b my-branch-name`
2628
1. Make your change, add tests, and make sure the tests and linter still pass
27-
1. Push to your fork and [submit a pull request][pr]
29+
1. Push to your fork and [submit a pull request][pr] targeting the `next` branch
2830
1. Pat yourself on the back and wait for your pull request to be reviewed and merged.
2931

3032
Here are a few things you can do that will increase the likelihood of your pull request being accepted:

cmd/github-mcp-server/main.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import (
44
"errors"
55
"fmt"
66
"os"
7+
"strings"
78

89
"github.com/github/github-mcp-server/internal/ghmcp"
910
"github.com/github/github-mcp-server/pkg/github"
1011
"github.com/spf13/cobra"
12+
"github.com/spf13/pflag"
1113
"github.com/spf13/viper"
1214
)
1315

@@ -54,14 +56,14 @@ var (
5456
EnableCommandLogging: viper.GetBool("enable-command-logging"),
5557
LogFilePath: viper.GetString("log-file"),
5658
}
57-
5859
return ghmcp.RunStdioServer(stdioServerConfig)
5960
},
6061
}
6162
)
6263

6364
func init() {
6465
cobra.OnInitialize(initConfig)
66+
rootCmd.SetGlobalNormalizationFunc(wordSepNormalizeFunc)
6567

6668
rootCmd.SetVersionTemplate("{{.Short}}\n{{.Version}}\n")
6769

@@ -91,6 +93,7 @@ func initConfig() {
9193
// Initialize Viper configuration
9294
viper.SetEnvPrefix("github")
9395
viper.AutomaticEnv()
96+
9497
}
9598

9699
func main() {
@@ -99,3 +102,12 @@ func main() {
99102
os.Exit(1)
100103
}
101104
}
105+
106+
func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
107+
from := []string{"_"}
108+
to := "-"
109+
for _, sep := range from {
110+
name = strings.ReplaceAll(name, sep, to)
111+
}
112+
return pflag.NormalizedName(name)
113+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ require (
4141
github.com/sourcegraph/conc v0.3.0 // indirect
4242
github.com/spf13/afero v1.14.0 // indirect
4343
github.com/spf13/cast v1.7.1 // indirect
44-
github.com/spf13/pflag v1.0.6 // indirect
44+
github.com/spf13/pflag v1.0.6
4545
github.com/subosito/gotenv v1.6.0 // indirect
4646
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
4747
go.uber.org/multierr v1.11.0 // indirect

pkg/github/__toolsnaps__/search_issues.snap

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"title": "Search issues",
44
"readOnlyHint": true
55
},
6-
"description": "Search for issues in GitHub repositories.",
6+
"description": "Search for issues in GitHub repositories using issues search syntax already scoped to is:issue",
77
"inputSchema": {
88
"properties": {
99
"order": {
@@ -14,6 +14,10 @@
1414
],
1515
"type": "string"
1616
},
17+
"owner": {
18+
"description": "Optional repository owner. If provided with repo, only notifications for this repository are listed.",
19+
"type": "string"
20+
},
1721
"page": {
1822
"description": "Page number for pagination (min 1)",
1923
"minimum": 1,
@@ -25,10 +29,14 @@
2529
"minimum": 1,
2630
"type": "number"
2731
},
28-
"q": {
32+
"query": {
2933
"description": "Search query using GitHub issues search syntax",
3034
"type": "string"
3135
},
36+
"repo": {
37+
"description": "Optional repository name. If provided with owner, only notifications for this repository are listed.",
38+
"type": "string"
39+
},
3240
"sort": {
3341
"description": "Sort field by number of matches of categories, defaults to best match",
3442
"enum": [
@@ -48,7 +56,7 @@
4856
}
4957
},
5058
"required": [
51-
"q"
59+
"query"
5260
],
5361
"type": "object"
5462
},
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"annotations": {
3+
"title": "Search pull requests",
4+
"readOnlyHint": true
5+
},
6+
"description": "Search for pull requests in GitHub repositories using issues search syntax already scoped to is:pr",
7+
"inputSchema": {
8+
"properties": {
9+
"order": {
10+
"description": "Sort order",
11+
"enum": [
12+
"asc",
13+
"desc"
14+
],
15+
"type": "string"
16+
},
17+
"owner": {
18+
"description": "Optional repository owner. If provided with repo, only notifications for this repository are listed.",
19+
"type": "string"
20+
},
21+
"page": {
22+
"description": "Page number for pagination (min 1)",
23+
"minimum": 1,
24+
"type": "number"
25+
},
26+
"perPage": {
27+
"description": "Results per page for pagination (min 1, max 100)",
28+
"maximum": 100,
29+
"minimum": 1,
30+
"type": "number"
31+
},
32+
"query": {
33+
"description": "Search query using GitHub pull request search syntax",
34+
"type": "string"
35+
},
36+
"repo": {
37+
"description": "Optional repository name. If provided with owner, only notifications for this repository are listed.",
38+
"type": "string"
39+
},
40+
"sort": {
41+
"description": "Sort field by number of matches of categories, defaults to best match",
42+
"enum": [
43+
"comments",
44+
"reactions",
45+
"reactions-+1",
46+
"reactions--1",
47+
"reactions-smile",
48+
"reactions-thinking_face",
49+
"reactions-heart",
50+
"reactions-tada",
51+
"interactions",
52+
"created",
53+
"updated"
54+
],
55+
"type": "string"
56+
}
57+
},
58+
"required": [
59+
"query"
60+
],
61+
"type": "object"
62+
},
63+
"name": "search_pull_requests"
64+
}

pkg/github/__toolsnaps__/search_users.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"title": "Search users",
44
"readOnlyHint": true
55
},
6-
"description": "Search for GitHub users",
6+
"description": "Search for GitHub users exclusively",
77
"inputSchema": {
88
"properties": {
99
"order": {
@@ -25,8 +25,8 @@
2525
"minimum": 1,
2626
"type": "number"
2727
},
28-
"q": {
29-
"description": "Search query using GitHub users search syntax",
28+
"query": {
29+
"description": "Search query using GitHub users search syntax scoped to type:user",
3030
"type": "string"
3131
},
3232
"sort": {
@@ -40,7 +40,7 @@
4040
}
4141
},
4242
"required": [
43-
"q"
43+
"query"
4444
],
4545
"type": "object"
4646
},

pkg/github/issues.go

Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,24 @@ func AddIssueComment(getClient GetClientFn, t translations.TranslationHelperFunc
153153
}
154154
}
155155

156-
// SearchIssues creates a tool to search for issues and pull requests.
156+
// SearchIssues creates a tool to search for issues.
157157
func SearchIssues(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
158158
return mcp.NewTool("search_issues",
159-
mcp.WithDescription(t("TOOL_SEARCH_ISSUES_DESCRIPTION", "Search for issues in GitHub repositories.")),
159+
mcp.WithDescription(t("TOOL_SEARCH_ISSUES_DESCRIPTION", "Search for issues in GitHub repositories using issues search syntax already scoped to is:issue")),
160160
mcp.WithToolAnnotation(mcp.ToolAnnotation{
161161
Title: t("TOOL_SEARCH_ISSUES_USER_TITLE", "Search issues"),
162162
ReadOnlyHint: ToBoolPtr(true),
163163
}),
164-
mcp.WithString("q",
164+
mcp.WithString("query",
165165
mcp.Required(),
166166
mcp.Description("Search query using GitHub issues search syntax"),
167167
),
168+
mcp.WithString("owner",
169+
mcp.Description("Optional repository owner. If provided with repo, only notifications for this repository are listed."),
170+
),
171+
mcp.WithString("repo",
172+
mcp.Description("Optional repository name. If provided with owner, only notifications for this repository are listed."),
173+
),
168174
mcp.WithString("sort",
169175
mcp.Description("Sort field by number of matches of categories, defaults to best match"),
170176
mcp.Enum(
@@ -188,56 +194,7 @@ func SearchIssues(getClient GetClientFn, t translations.TranslationHelperFunc) (
188194
WithPagination(),
189195
),
190196
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
191-
query, err := RequiredParam[string](request, "q")
192-
if err != nil {
193-
return mcp.NewToolResultError(err.Error()), nil
194-
}
195-
sort, err := OptionalParam[string](request, "sort")
196-
if err != nil {
197-
return mcp.NewToolResultError(err.Error()), nil
198-
}
199-
order, err := OptionalParam[string](request, "order")
200-
if err != nil {
201-
return mcp.NewToolResultError(err.Error()), nil
202-
}
203-
pagination, err := OptionalPaginationParams(request)
204-
if err != nil {
205-
return mcp.NewToolResultError(err.Error()), nil
206-
}
207-
208-
opts := &github.SearchOptions{
209-
Sort: sort,
210-
Order: order,
211-
ListOptions: github.ListOptions{
212-
PerPage: pagination.perPage,
213-
Page: pagination.page,
214-
},
215-
}
216-
217-
client, err := getClient(ctx)
218-
if err != nil {
219-
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
220-
}
221-
result, resp, err := client.Search.Issues(ctx, query, opts)
222-
if err != nil {
223-
return nil, fmt.Errorf("failed to search issues: %w", err)
224-
}
225-
defer func() { _ = resp.Body.Close() }()
226-
227-
if resp.StatusCode != http.StatusOK {
228-
body, err := io.ReadAll(resp.Body)
229-
if err != nil {
230-
return nil, fmt.Errorf("failed to read response body: %w", err)
231-
}
232-
return mcp.NewToolResultError(fmt.Sprintf("failed to search issues: %s", string(body))), nil
233-
}
234-
235-
r, err := json.Marshal(result)
236-
if err != nil {
237-
return nil, fmt.Errorf("failed to marshal response: %w", err)
238-
}
239-
240-
return mcp.NewToolResultText(string(r)), nil
197+
return searchHandler(ctx, getClient, request, "issue", "failed to search issues")
241198
}
242199
}
243200

0 commit comments

Comments
 (0)