Skip to content

Commit 4a1941c

Browse files
authored
Merge branch 'main' into kelsey/list-issues-field-filtering
2 parents 9d49dbc + 805ad75 commit 4a1941c

20 files changed

Lines changed: 999 additions & 141 deletions

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,8 @@ The following sets of tools are available:
649649
- **Required OAuth Scopes**: `security_events`
650650
- **Accepted OAuth Scopes**: `repo`, `security_events`
651651
- `owner`: The owner of the repository. (string, required)
652+
- `page`: Page number for pagination (min 1) (number, optional)
653+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
652654
- `ref`: The Git reference for the results you want to list. (string, optional)
653655
- `repo`: The name of the repository. (string, required)
654656
- `severity`: Filter code scanning alerts by severity (string, optional)
@@ -712,6 +714,8 @@ The following sets of tools are available:
712714
- **Required OAuth Scopes**: `security_events`
713715
- **Accepted OAuth Scopes**: `repo`, `security_events`
714716
- `owner`: The owner of the repository. (string, required)
717+
- `page`: Page number for pagination (min 1) (number, optional)
718+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
715719
- `repo`: The name of the repository. (string, required)
716720
- `severity`: Filter dependabot alerts by severity (string, optional)
717721
- `state`: Filter dependabot alerts by state. Defaults to open (string, optional)
@@ -1296,9 +1300,17 @@ The following sets of tools are available:
12961300
- `order`: Sort order for results (string, optional)
12971301
- `page`: Page number for pagination (min 1) (number, optional)
12981302
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
1299-
- `query`: Search query using GitHub's powerful code search syntax. Examples: 'content:Skill language:Java org:github', 'NOT is:archived language:Python OR language:go', 'repo:github/github-mcp-server'. Supports exact matching, language filters, path filters, and more. (string, required)
1303+
- `query`: Search query (GitHub code search REST). Implicit AND between terms; supports `OR`, `NOT`, and `"quoted phrase"` for exact match. Qualifiers: `repo:owner/repo`, `org:`, `user:`, `language:`, `path:dir` (prefix match), `filename:exact.ext`, `extension:`, `in:file`, `in:path`, `size:`, `is:archived`, `is:fork`. Max 256 chars. Examples: `WithContext language:go org:github`; `"package main" repo:o/r`; `func extension:go path:cmd repo:o/r`; `NOT TODO language:go repo:o/r`. (string, required)
13001304
- `sort`: Sort field ('indexed' only) (string, optional)
13011305

1306+
- **search_commits** - Search commits
1307+
- **Required OAuth Scopes**: `repo`
1308+
- `order`: Sort order (string, optional)
1309+
- `page`: Page number for pagination (min 1) (number, optional)
1310+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
1311+
- `query`: Commit search query (GitHub commit search REST). Searches commit messages on the default branch only. Scope the search with `repo:owner/repo`, `org:`, or `user:` (queries without a scope qualifier match across all of GitHub and are usually not what you want). Other qualifiers: `author:`, `committer:`, `author-name:`, `committer-name:`, `author-email:`, `committer-email:`, `author-date:`, `committer-date:` (supports `>`, `<`, `>=`, `<=`, and `YYYY-MM-DD..YYYY-MM-DD` ranges), `merge:true|false`, `hash:`, `tree:`, `parent:`, `is:public`. Examples: `repo:owner/repo fix panic`; `org:github author:defunkt committer-date:>=2024-01-01`; `"refactor cache" repo:o/r`; `hash:abc1234 repo:o/r`. (string, required)
1312+
- `sort`: Sort by author or committer date (defaults to best match) (string, optional)
1313+
13021314
- **search_repositories** - Search repositories
13031315
- **Required OAuth Scopes**: `repo`
13041316
- `minimal_output`: Return minimal repository information (default: true). When false, returns full GitHub API repository objects. (boolean, optional)
@@ -1325,6 +1337,8 @@ The following sets of tools are available:
13251337
- **Required OAuth Scopes**: `security_events`
13261338
- **Accepted OAuth Scopes**: `repo`, `security_events`
13271339
- `owner`: The owner of the repository. (string, required)
1340+
- `page`: Page number for pagination (min 1) (number, optional)
1341+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
13281342
- `repo`: The name of the repository. (string, required)
13291343
- `resolution`: Filter by resolution (string, optional)
13301344
- `secret_type`: A comma-separated list of secret types to return. All default secret patterns are returned. To return generic patterns, pass the token name(s) in the parameter. (string, optional)

pkg/github/__toolsnaps__/list_code_scanning_alerts.snap

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@
1010
"description": "The owner of the repository.",
1111
"type": "string"
1212
},
13+
"page": {
14+
"description": "Page number for pagination (min 1)",
15+
"minimum": 1,
16+
"type": "number"
17+
},
18+
"perPage": {
19+
"description": "Results per page for pagination (min 1, max 100)",
20+
"maximum": 100,
21+
"minimum": 1,
22+
"type": "number"
23+
},
1324
"ref": {
1425
"description": "The Git reference for the results you want to list.",
1526
"type": "string"

pkg/github/__toolsnaps__/list_dependabot_alerts.snap

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@
1010
"description": "The owner of the repository.",
1111
"type": "string"
1212
},
13+
"page": {
14+
"description": "Page number for pagination (min 1)",
15+
"minimum": 1,
16+
"type": "number"
17+
},
18+
"perPage": {
19+
"description": "Results per page for pagination (min 1, max 100)",
20+
"maximum": 100,
21+
"minimum": 1,
22+
"type": "number"
23+
},
1324
"repo": {
1425
"description": "The name of the repository.",
1526
"type": "string"

pkg/github/__toolsnaps__/list_secret_scanning_alerts.snap

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@
1010
"description": "The owner of the repository.",
1111
"type": "string"
1212
},
13+
"page": {
14+
"description": "Page number for pagination (min 1)",
15+
"minimum": 1,
16+
"type": "number"
17+
},
18+
"perPage": {
19+
"description": "Results per page for pagination (min 1, max 100)",
20+
"maximum": 100,
21+
"minimum": 1,
22+
"type": "number"
23+
},
1324
"repo": {
1425
"description": "The name of the repository.",
1526
"type": "string"

pkg/github/__toolsnaps__/search_code.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"type": "number"
2727
},
2828
"query": {
29-
"description": "Search query using GitHub's powerful code search syntax. Examples: 'content:Skill language:Java org:github', 'NOT is:archived language:Python OR language:go', 'repo:github/github-mcp-server'. Supports exact matching, language filters, path filters, and more.",
29+
"description": "Search query (GitHub code search REST). Implicit AND between terms; supports `OR`, `NOT`, and `\"quoted phrase\"` for exact match. Qualifiers: `repo:owner/repo`, `org:`, `user:`, `language:`, `path:dir` (prefix match), `filename:exact.ext`, `extension:`, `in:file`, `in:path`, `size:`, `is:archived`, `is:fork`. Max 256 chars. Examples: `WithContext language:go org:github`; `\"package main\" repo:o/r`; `func extension:go path:cmd repo:o/r`; `NOT TODO language:go repo:o/r`.",
3030
"type": "string"
3131
},
3232
"sort": {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"annotations": {
3+
"readOnlyHint": true,
4+
"title": "Search commits"
5+
},
6+
"description": "Search for commits across GitHub repositories using GitHub's commit search syntax. Useful for finding specific changes, authors, or messages across one or many repositories. Searches the default branch only.",
7+
"inputSchema": {
8+
"properties": {
9+
"order": {
10+
"description": "Sort order",
11+
"enum": [
12+
"asc",
13+
"desc"
14+
],
15+
"type": "string"
16+
},
17+
"page": {
18+
"description": "Page number for pagination (min 1)",
19+
"minimum": 1,
20+
"type": "number"
21+
},
22+
"perPage": {
23+
"description": "Results per page for pagination (min 1, max 100)",
24+
"maximum": 100,
25+
"minimum": 1,
26+
"type": "number"
27+
},
28+
"query": {
29+
"description": "Commit search query (GitHub commit search REST). Searches commit messages on the default branch only. Scope the search with `repo:owner/repo`, `org:`, or `user:` (queries without a scope qualifier match across all of GitHub and are usually not what you want). Other qualifiers: `author:`, `committer:`, `author-name:`, `committer-name:`, `author-email:`, `committer-email:`, `author-date:`, `committer-date:` (supports `\u003e`, `\u003c`, `\u003e=`, `\u003c=`, and `YYYY-MM-DD..YYYY-MM-DD` ranges), `merge:true|false`, `hash:`, `tree:`, `parent:`, `is:public`. Examples: `repo:owner/repo fix panic`; `org:github author:defunkt committer-date:\u003e=2024-01-01`; `\"refactor cache\" repo:o/r`; `hash:abc1234 repo:o/r`.",
30+
"type": "string"
31+
},
32+
"sort": {
33+
"description": "Sort by author or committer date (defaults to best match)",
34+
"enum": [
35+
"author-date",
36+
"committer-date"
37+
],
38+
"type": "string"
39+
}
40+
},
41+
"required": [
42+
"query"
43+
],
44+
"type": "object"
45+
},
46+
"name": "search_commits"
47+
}

pkg/github/code_scanning.go

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,41 @@ func GetCodeScanningAlert(t translations.TranslationHelperFunc) inventory.Server
9494
}
9595

9696
func ListCodeScanningAlerts(t translations.TranslationHelperFunc) inventory.ServerTool {
97+
schema := &jsonschema.Schema{
98+
Type: "object",
99+
Properties: map[string]*jsonschema.Schema{
100+
"owner": {
101+
Type: "string",
102+
Description: "The owner of the repository.",
103+
},
104+
"repo": {
105+
Type: "string",
106+
Description: "The name of the repository.",
107+
},
108+
"state": {
109+
Type: "string",
110+
Description: "Filter code scanning alerts by state. Defaults to open",
111+
Enum: []any{"open", "closed", "dismissed", "fixed"},
112+
Default: json.RawMessage(`"open"`),
113+
},
114+
"ref": {
115+
Type: "string",
116+
Description: "The Git reference for the results you want to list.",
117+
},
118+
"severity": {
119+
Type: "string",
120+
Description: "Filter code scanning alerts by severity",
121+
Enum: []any{"critical", "high", "medium", "low", "warning", "note", "error"},
122+
},
123+
"tool_name": {
124+
Type: "string",
125+
Description: "The name of the tool used for code scanning.",
126+
},
127+
},
128+
Required: []string{"owner", "repo"},
129+
}
130+
WithPagination(schema)
131+
97132
return NewTool(
98133
ToolsetMetadataCodeSecurity,
99134
mcp.Tool{
@@ -103,39 +138,7 @@ func ListCodeScanningAlerts(t translations.TranslationHelperFunc) inventory.Serv
103138
Title: t("TOOL_LIST_CODE_SCANNING_ALERTS_USER_TITLE", "List code scanning alerts"),
104139
ReadOnlyHint: true,
105140
},
106-
InputSchema: &jsonschema.Schema{
107-
Type: "object",
108-
Properties: map[string]*jsonschema.Schema{
109-
"owner": {
110-
Type: "string",
111-
Description: "The owner of the repository.",
112-
},
113-
"repo": {
114-
Type: "string",
115-
Description: "The name of the repository.",
116-
},
117-
"state": {
118-
Type: "string",
119-
Description: "Filter code scanning alerts by state. Defaults to open",
120-
Enum: []any{"open", "closed", "dismissed", "fixed"},
121-
Default: json.RawMessage(`"open"`),
122-
},
123-
"ref": {
124-
Type: "string",
125-
Description: "The Git reference for the results you want to list.",
126-
},
127-
"severity": {
128-
Type: "string",
129-
Description: "Filter code scanning alerts by severity",
130-
Enum: []any{"critical", "high", "medium", "low", "warning", "note", "error"},
131-
},
132-
"tool_name": {
133-
Type: "string",
134-
Description: "The name of the tool used for code scanning.",
135-
},
136-
},
137-
Required: []string{"owner", "repo"},
138-
},
141+
InputSchema: schema,
139142
},
140143
[]scopes.Scope{scopes.SecurityEvents},
141144
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
@@ -164,11 +167,25 @@ func ListCodeScanningAlerts(t translations.TranslationHelperFunc) inventory.Serv
164167
return utils.NewToolResultError(err.Error()), nil, nil
165168
}
166169

170+
pagination, err := OptionalPaginationParams(args)
171+
if err != nil {
172+
return utils.NewToolResultError(err.Error()), nil, nil
173+
}
174+
167175
client, err := deps.GetClient(ctx)
168176
if err != nil {
169177
return utils.NewToolResultErrorFromErr("failed to get GitHub client", err), nil, nil
170178
}
171-
alerts, resp, err := client.CodeScanning.ListAlertsForRepo(ctx, owner, repo, &github.AlertListOptions{Ref: ref, State: state, Severity: severity, ToolName: toolName})
179+
alerts, resp, err := client.CodeScanning.ListAlertsForRepo(ctx, owner, repo, &github.AlertListOptions{
180+
Ref: ref,
181+
State: state,
182+
Severity: severity,
183+
ToolName: toolName,
184+
ListOptions: github.ListOptions{
185+
Page: pagination.Page,
186+
PerPage: pagination.PerPage,
187+
},
188+
})
172189
if err != nil {
173190
return ghErrors.NewGitHubAPIErrorResponse(ctx,
174191
"failed to list alerts",

pkg/github/code_scanning_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ func Test_ListCodeScanningAlerts(t *testing.T) {
137137
assert.Contains(t, schema.Properties, "state")
138138
assert.Contains(t, schema.Properties, "severity")
139139
assert.Contains(t, schema.Properties, "tool_name")
140+
assert.Contains(t, schema.Properties, "page")
141+
assert.Contains(t, schema.Properties, "perPage")
140142
assert.ElementsMatch(t, schema.Required, []string{"owner", "repo"})
141143

142144
// Setup mock alerts for success case
@@ -171,6 +173,8 @@ func Test_ListCodeScanningAlerts(t *testing.T) {
171173
"state": "open",
172174
"severity": "high",
173175
"tool_name": "codeql",
176+
"page": "1",
177+
"per_page": "30",
174178
}).andThen(
175179
mockResponse(t, http.StatusOK, mockAlerts),
176180
),
@@ -186,6 +190,25 @@ func Test_ListCodeScanningAlerts(t *testing.T) {
186190
expectError: false,
187191
expectedAlerts: mockAlerts,
188192
},
193+
{
194+
name: "successful alerts listing with custom pagination",
195+
mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
196+
GetReposCodeScanningAlertsByOwnerByRepo: expectQueryParams(t, map[string]string{
197+
"page": "2",
198+
"per_page": "50",
199+
}).andThen(
200+
mockResponse(t, http.StatusOK, mockAlerts),
201+
),
202+
}),
203+
requestArgs: map[string]any{
204+
"owner": "owner",
205+
"repo": "repo",
206+
"page": float64(2),
207+
"perPage": float64(50),
208+
},
209+
expectError: false,
210+
expectedAlerts: mockAlerts,
211+
},
189212
{
190213
name: "alerts listing fails",
191214
mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{

0 commit comments

Comments
 (0)