Skip to content

Commit fa64673

Browse files
committed
fix: allow public_repo for contribution tools
1 parent 64a49f3 commit fa64673

10 files changed

Lines changed: 71 additions & 16 deletions

File tree

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,8 @@ The following sets of tools are available:
892892
<summary><picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/issue-opened-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/issue-opened-light.png"><img src="pkg/octicons/icons/issue-opened-light.png" width="20" height="20" alt="issue-opened"></picture> Issues</summary>
893893

894894
- **add_issue_comment** - Add comment to issue or pull request
895-
- **Required OAuth Scopes**: `repo`
895+
- **Required OAuth Scopes**: `public_repo`
896+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
896897
- `body`: Comment content. Required unless reaction is provided. (string, optional)
897898
- `comment_id`: The numeric ID of the issue or pull request comment to react to. Use this for reactions to comments; omit it to react to the issue or pull request itself. Cannot be combined with body. (integer, optional)
898899
- `issue_number`: Issue or pull request number to comment on or react to. (number, required)
@@ -923,7 +924,8 @@ The following sets of tools are available:
923924
- `repo`: The name of the repository (string, required)
924925

925926
- **issue_write** - Create or update issue/pull request
926-
- **Required OAuth Scopes**: `repo`
927+
- **Required OAuth Scopes**: `public_repo`
928+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
927929
- `assignees`: Usernames to assign to this issue (string[], optional)
928930
- `body`: Issue body content (string, optional)
929931
- `duplicate_of`: Issue number that this issue is a duplicate of. Required when state_reason is 'duplicate'. (number, optional)
@@ -1173,7 +1175,8 @@ The following sets of tools are available:
11731175
- `repo`: Repository name (string, required)
11741176

11751177
- **create_pull_request** - Open new pull request
1176-
- **Required OAuth Scopes**: `repo`
1178+
- **Required OAuth Scopes**: `public_repo`
1179+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
11771180
- `base`: Branch to merge into (string, required)
11781181
- `body`: PR description (string, optional)
11791182
- `draft`: Create as draft PR (boolean, optional)
@@ -1276,7 +1279,8 @@ The following sets of tools are available:
12761279
<summary><picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/repo-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/repo-light.png"><img src="pkg/octicons/icons/repo-light.png" width="20" height="20" alt="repo"></picture> Repositories</summary>
12771280

12781281
- **create_branch** - Create branch
1279-
- **Required OAuth Scopes**: `repo`
1282+
- **Required OAuth Scopes**: `public_repo`
1283+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
12801284
- `branch`: Name for new branch (string, required)
12811285
- `from_branch`: Source branch (defaults to repo default) (string, optional)
12821286
- `owner`: Repository owner (string, required)
@@ -1315,7 +1319,8 @@ The following sets of tools are available:
13151319
- `repo`: Repository name (string, required)
13161320

13171321
- **fork_repository** - Fork repository
1318-
- **Required OAuth Scopes**: `repo`
1322+
- **Required OAuth Scopes**: `public_repo`
1323+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
13191324
- `organization`: Organization to fork to (string, optional)
13201325
- `owner`: Repository owner (string, required)
13211326
- `repo`: Repository name (string, required)
@@ -1399,7 +1404,8 @@ The following sets of tools are available:
13991404
- `repo`: Repository name (string, required)
14001405

14011406
- **push_files** - Push files to repository
1402-
- **Required OAuth Scopes**: `repo`
1407+
- **Required OAuth Scopes**: `public_repo`
1408+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
14031409
- `branch`: Branch to push to (string, required)
14041410
- `files`: Array of file objects to push, each object with path (string) and content (string) (object[], required)
14051411
- `message`: Commit message (string, required)

docs/feature-flags.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ runtime behavior (such as output formatting) won't appear here.
3535
### `remote_mcp_ui_apps`
3636

3737
- **create_pull_request** - Open new pull request
38-
- **Required OAuth Scopes**: `repo`
38+
- **Required OAuth Scopes**: `public_repo`
39+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
3940
- **MCP App UI**: `ui://github-mcp-server/pr-write`
4041
- `base`: Branch to merge into (string, required)
4142
- `body`: PR description (string, optional)
@@ -52,7 +53,8 @@ runtime behavior (such as output formatting) won't appear here.
5253
- No parameters required
5354

5455
- **issue_write** - Create or update issue/pull request
55-
- **Required OAuth Scopes**: `repo`
56+
- **Required OAuth Scopes**: `public_repo`
57+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
5658
- **MCP App UI**: `ui://github-mcp-server/issue-write`
5759
- `assignees`: Usernames to assign to this issue (string[], optional)
5860
- `body`: Issue body content (string, optional)

docs/insiders-features.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ The list below is generated from the Go source. It covers tool **inventory and s
2929
### `remote_mcp_ui_apps`
3030

3131
- **create_pull_request** - Open new pull request
32-
- **Required OAuth Scopes**: `repo`
32+
- **Required OAuth Scopes**: `public_repo`
33+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
3334
- **MCP App UI**: `ui://github-mcp-server/pr-write`
3435
- `base`: Branch to merge into (string, required)
3536
- `body`: PR description (string, optional)
@@ -46,7 +47,8 @@ The list below is generated from the Go source. It covers tool **inventory and s
4647
- No parameters required
4748

4849
- **issue_write** - Create or update issue/pull request
49-
- **Required OAuth Scopes**: `repo`
50+
- **Required OAuth Scopes**: `public_repo`
51+
- **Accepted OAuth Scopes**: `public_repo`, `repo`
5052
- **MCP App UI**: `ui://github-mcp-server/issue-write`
5153
- `assignees`: Usernames to assign to this issue (string[], optional)
5254
- `body`: Issue body content (string, optional)

pkg/github/issues.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,7 +1401,7 @@ func AddIssueComment(t translations.TranslationHelperFunc) inventory.ServerTool
14011401
Required: []string{"owner", "repo", "issue_number"},
14021402
},
14031403
},
1404-
[]scopes.Scope{scopes.Repo},
1404+
[]scopes.Scope{scopes.PublicRepo},
14051405
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
14061406
owner, err := RequiredParam[string](args, "owner")
14071407
if err != nil {
@@ -2511,7 +2511,7 @@ Options are:
25112511
Required: []string{"method", "owner", "repo"},
25122512
},
25132513
},
2514-
[]scopes.Scope{scopes.Repo},
2514+
[]scopes.Scope{scopes.PublicRepo},
25152515
func(ctx context.Context, deps ToolDependencies, req *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
25162516
method, err := RequiredParam[string](args, "method")
25172517
if err != nil {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/github/github-mcp-server/pkg/inventory"
8+
"github.com/github/github-mcp-server/pkg/scopes"
9+
"github.com/github/github-mcp-server/pkg/translations"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestPublicRepoContributionToolsAcceptPublicRepoScope(t *testing.T) {
15+
t.Parallel()
16+
17+
tools := []struct {
18+
name string
19+
tool inventory.ServerTool
20+
}{
21+
{name: "fork_repository", tool: ForkRepository(translations.NullTranslationHelper)},
22+
{name: "create_branch", tool: CreateBranch(translations.NullTranslationHelper)},
23+
{name: "push_files", tool: PushFiles(translations.NullTranslationHelper)},
24+
{name: "create_pull_request", tool: CreatePullRequest(translations.NullTranslationHelper)},
25+
{name: "issue_write", tool: IssueWrite(translations.NullTranslationHelper)},
26+
{name: "add_issue_comment", tool: AddIssueComment(translations.NullTranslationHelper)},
27+
}
28+
29+
filter := CreateToolScopeFilter([]string{string(scopes.PublicRepo)})
30+
for _, tt := range tools {
31+
t.Run(tt.name, func(t *testing.T) {
32+
tool := tt.tool
33+
assert.Equal(t, []string{string(scopes.PublicRepo)}, tool.RequiredScopes)
34+
assert.ElementsMatch(t, []string{string(scopes.PublicRepo), string(scopes.Repo)}, tool.AcceptedScopes)
35+
36+
included, err := filter(context.Background(), &tool)
37+
require.NoError(t, err)
38+
assert.True(t, included)
39+
})
40+
}
41+
}

pkg/github/pullrequests.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ func CreatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo
706706
Required: []string{"owner", "repo", "title", "head", "base"},
707707
},
708708
},
709-
[]scopes.Scope{scopes.Repo},
709+
[]scopes.Scope{scopes.PublicRepo},
710710
func(ctx context.Context, deps ToolDependencies, req *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
711711
owner, err := RequiredParam[string](args, "owner")
712712
if err != nil {

pkg/github/repositories.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,7 @@ func ForkRepository(t translations.TranslationHelperFunc) inventory.ServerTool {
12221222
Required: []string{"owner", "repo"},
12231223
},
12241224
},
1225-
[]scopes.Scope{scopes.Repo},
1225+
[]scopes.Scope{scopes.PublicRepo},
12261226
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
12271227
owner, err := RequiredParam[string](args, "owner")
12281228
if err != nil {
@@ -1509,7 +1509,7 @@ func CreateBranch(t translations.TranslationHelperFunc) inventory.ServerTool {
15091509
Required: []string{"owner", "repo", "branch"},
15101510
},
15111511
},
1512-
[]scopes.Scope{scopes.Repo},
1512+
[]scopes.Scope{scopes.PublicRepo},
15131513
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
15141514
owner, err := RequiredParam[string](args, "owner")
15151515
if err != nil {
@@ -1641,7 +1641,7 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool {
16411641
Required: []string{"owner", "repo", "branch", "files", "message"},
16421642
},
16431643
},
1644-
[]scopes.Scope{scopes.Repo},
1644+
[]scopes.Scope{scopes.PublicRepo},
16451645
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
16461646
owner, err := RequiredParam[string](args, "owner")
16471647
if err != nil {

pkg/http/oauth/oauth_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ func TestSupportedScopes(t *testing.T) {
581581
// Verify all expected scopes are present
582582
expectedScopes := []string{
583583
"repo",
584+
"public_repo",
584585
"delete_repo",
585586
"read:org",
586587
"read:user",

pkg/scopes/scopes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ type oauthScopeDefinition struct {
7676

7777
var oauthScopeDefinitions = []oauthScopeDefinition{
7878
{scope: Repo, byDefault: true},
79+
{scope: PublicRepo},
7980
{scope: DeleteRepo},
8081
{scope: ReadOrg, byDefault: true},
8182
{scope: ReadUser, byDefault: true},

pkg/scopes/scopes_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ func TestOAuthScopeCatalog(t *testing.T) {
125125
defaults := DefaultOAuthScopes()
126126

127127
assert.Subset(t, supported, defaults)
128+
assert.Contains(t, supported, string(PublicRepo))
129+
assert.NotContains(t, defaults, string(PublicRepo))
128130
assert.Contains(t, supported, string(DeleteRepo))
129131
assert.NotContains(t, defaults, string(DeleteRepo))
130132
assert.Contains(t, supported, string(Workflow))

0 commit comments

Comments
 (0)