Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,8 @@ The following sets of tools are available:
<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>

- **add_issue_comment** - Add comment to issue or pull request
- **Required OAuth Scopes**: `repo`
- **Required OAuth Scopes**: `public_repo`
- **Accepted OAuth Scopes**: `public_repo`, `repo`
- `body`: Comment content. Required unless reaction is provided. (string, optional)
- `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)
- `issue_number`: Issue or pull request number to comment on or react to. (number, required)
Expand Down Expand Up @@ -923,7 +924,8 @@ The following sets of tools are available:
- `repo`: The name of the repository (string, required)

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

- **create_pull_request** - Open new pull request
- **Required OAuth Scopes**: `repo`
- **Required OAuth Scopes**: `public_repo`
- **Accepted OAuth Scopes**: `public_repo`, `repo`
- `base`: Branch to merge into (string, required)
- `body`: PR description (string, optional)
- `draft`: Create as draft PR (boolean, optional)
Expand Down Expand Up @@ -1276,7 +1279,8 @@ The following sets of tools are available:
<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>

- **create_branch** - Create branch
- **Required OAuth Scopes**: `repo`
- **Required OAuth Scopes**: `public_repo`
- **Accepted OAuth Scopes**: `public_repo`, `repo`
- `branch`: Name for new branch (string, required)
- `from_branch`: Source branch (defaults to repo default) (string, optional)
- `owner`: Repository owner (string, required)
Expand Down Expand Up @@ -1315,7 +1319,8 @@ The following sets of tools are available:
- `repo`: Repository name (string, required)

- **fork_repository** - Fork repository
- **Required OAuth Scopes**: `repo`
- **Required OAuth Scopes**: `public_repo`
- **Accepted OAuth Scopes**: `public_repo`, `repo`
- `organization`: Organization to fork to (string, optional)
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
Expand Down Expand Up @@ -1399,7 +1404,8 @@ The following sets of tools are available:
- `repo`: Repository name (string, required)

- **push_files** - Push files to repository
- **Required OAuth Scopes**: `repo`
- **Required OAuth Scopes**: `public_repo`
- **Accepted OAuth Scopes**: `public_repo`, `repo`
- `branch`: Branch to push to (string, required)
- `files`: Array of file objects to push, each object with path (string) and content (string) (object[], required)
- `message`: Commit message (string, required)
Expand Down
6 changes: 4 additions & 2 deletions docs/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ runtime behavior (such as output formatting) won't appear here.
### `remote_mcp_ui_apps`

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

- **issue_write** - Create or update issue/pull request
- **Required OAuth Scopes**: `repo`
- **Required OAuth Scopes**: `public_repo`
- **Accepted OAuth Scopes**: `public_repo`, `repo`
- **MCP App UI**: `ui://github-mcp-server/issue-write`
- `assignees`: Usernames to assign to this issue (string[], optional)
- `body`: Issue body content (string, optional)
Expand Down
6 changes: 4 additions & 2 deletions docs/insiders-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ The list below is generated from the Go source. It covers tool **inventory and s
### `remote_mcp_ui_apps`

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

- **issue_write** - Create or update issue/pull request
- **Required OAuth Scopes**: `repo`
- **Required OAuth Scopes**: `public_repo`
- **Accepted OAuth Scopes**: `public_repo`, `repo`
- **MCP App UI**: `ui://github-mcp-server/issue-write`
- `assignees`: Usernames to assign to this issue (string[], optional)
- `body`: Issue body content (string, optional)
Expand Down
4 changes: 2 additions & 2 deletions pkg/github/issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,7 @@ func AddIssueComment(t translations.TranslationHelperFunc) inventory.ServerTool
Required: []string{"owner", "repo", "issue_number"},
},
},
[]scopes.Scope{scopes.Repo},
[]scopes.Scope{scopes.PublicRepo},
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
owner, err := RequiredParam[string](args, "owner")
if err != nil {
Expand Down Expand Up @@ -2511,7 +2511,7 @@ Options are:
Required: []string{"method", "owner", "repo"},
},
},
[]scopes.Scope{scopes.Repo},
[]scopes.Scope{scopes.PublicRepo},
func(ctx context.Context, deps ToolDependencies, req *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
method, err := RequiredParam[string](args, "method")
if err != nil {
Expand Down
41 changes: 41 additions & 0 deletions pkg/github/public_repo_scopes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package github

import (
"context"
"testing"

"github.com/github/github-mcp-server/pkg/inventory"
"github.com/github/github-mcp-server/pkg/scopes"
"github.com/github/github-mcp-server/pkg/translations"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestPublicRepoContributionToolsAcceptPublicRepoScope(t *testing.T) {
t.Parallel()

tools := []struct {
name string
tool inventory.ServerTool
}{
{name: "fork_repository", tool: ForkRepository(translations.NullTranslationHelper)},
{name: "create_branch", tool: CreateBranch(translations.NullTranslationHelper)},
{name: "push_files", tool: PushFiles(translations.NullTranslationHelper)},
{name: "create_pull_request", tool: CreatePullRequest(translations.NullTranslationHelper)},
{name: "issue_write", tool: IssueWrite(translations.NullTranslationHelper)},
{name: "add_issue_comment", tool: AddIssueComment(translations.NullTranslationHelper)},
}

filter := CreateToolScopeFilter([]string{string(scopes.PublicRepo)})
for _, tt := range tools {
t.Run(tt.name, func(t *testing.T) {
tool := tt.tool
assert.Equal(t, []string{string(scopes.PublicRepo)}, tool.RequiredScopes)
assert.ElementsMatch(t, []string{string(scopes.PublicRepo), string(scopes.Repo)}, tool.AcceptedScopes)

included, err := filter(context.Background(), &tool)
require.NoError(t, err)
assert.True(t, included)
})
}
}
2 changes: 1 addition & 1 deletion pkg/github/pullrequests.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ func CreatePullRequest(t translations.TranslationHelperFunc) inventory.ServerToo
Required: []string{"owner", "repo", "title", "head", "base"},
},
},
[]scopes.Scope{scopes.Repo},
[]scopes.Scope{scopes.PublicRepo},
func(ctx context.Context, deps ToolDependencies, req *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
owner, err := RequiredParam[string](args, "owner")
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions pkg/github/repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ func ForkRepository(t translations.TranslationHelperFunc) inventory.ServerTool {
Required: []string{"owner", "repo"},
},
},
[]scopes.Scope{scopes.Repo},
[]scopes.Scope{scopes.PublicRepo},
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
owner, err := RequiredParam[string](args, "owner")
if err != nil {
Expand Down Expand Up @@ -1509,7 +1509,7 @@ func CreateBranch(t translations.TranslationHelperFunc) inventory.ServerTool {
Required: []string{"owner", "repo", "branch"},
},
},
[]scopes.Scope{scopes.Repo},
[]scopes.Scope{scopes.PublicRepo},
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
owner, err := RequiredParam[string](args, "owner")
if err != nil {
Expand Down Expand Up @@ -1641,7 +1641,7 @@ func PushFiles(t translations.TranslationHelperFunc) inventory.ServerTool {
Required: []string{"owner", "repo", "branch", "files", "message"},
},
},
[]scopes.Scope{scopes.Repo},
[]scopes.Scope{scopes.PublicRepo},
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
owner, err := RequiredParam[string](args, "owner")
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/http/oauth/oauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ func TestSupportedScopes(t *testing.T) {
// Verify all expected scopes are present
expectedScopes := []string{
"repo",
"public_repo",
"delete_repo",
"read:org",
"read:user",
Expand Down
1 change: 1 addition & 0 deletions pkg/scopes/scopes.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type oauthScopeDefinition struct {

var oauthScopeDefinitions = []oauthScopeDefinition{
{scope: Repo, byDefault: true},
{scope: PublicRepo},
{scope: DeleteRepo},
{scope: ReadOrg, byDefault: true},
{scope: ReadUser, byDefault: true},
Expand Down
2 changes: 2 additions & 0 deletions pkg/scopes/scopes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ func TestOAuthScopeCatalog(t *testing.T) {
defaults := DefaultOAuthScopes()

assert.Subset(t, supported, defaults)
assert.Contains(t, supported, string(PublicRepo))
assert.NotContains(t, defaults, string(PublicRepo))
assert.Contains(t, supported, string(DeleteRepo))
assert.NotContains(t, defaults, string(DeleteRepo))
assert.Contains(t, supported, string(Workflow))
Expand Down