Skip to content

Commit f3a32d6

Browse files
refactor(oauth): derive scope sets from catalog
Generate protected-resource supported scopes and the lower-risk default OAuth grant from one canonical scope definition list. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4b04480c-c2e9-483e-9b0f-34830b76a2f8
1 parent ec7bd6f commit f3a32d6

2 files changed

Lines changed: 34 additions & 29 deletions

File tree

pkg/http/oauth/oauth.go

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,44 @@ const (
1919
OAuthProtectedResourcePrefix = "/.well-known/oauth-protected-resource"
2020
)
2121

22-
// DefaultScopes are requested by stdio OAuth unless the operator explicitly
23-
// supplies --oauth-scopes. High-risk scopes such as delete_repo require opt-in.
24-
var DefaultScopes = []string{
25-
"repo",
26-
"read:org",
27-
"read:user",
28-
"user:email",
29-
"read:packages",
30-
"write:packages",
31-
"read:project",
32-
"project",
33-
"gist",
34-
"notifications",
35-
"workflow",
36-
"codespace",
22+
type scopeDefinition struct {
23+
name string
24+
byDefault bool
25+
}
26+
27+
var scopeDefinitions = []scopeDefinition{
28+
{name: "repo", byDefault: true},
29+
{name: "delete_repo"},
30+
{name: "read:org", byDefault: true},
31+
{name: "read:user", byDefault: true},
32+
{name: "user:email", byDefault: true},
33+
{name: "read:packages", byDefault: true},
34+
{name: "write:packages", byDefault: true},
35+
{name: "read:project", byDefault: true},
36+
{name: "project", byDefault: true},
37+
{name: "gist", byDefault: true},
38+
{name: "notifications", byDefault: true},
39+
{name: "workflow", byDefault: true},
40+
{name: "codespace", byDefault: true},
3741
}
3842

3943
// SupportedScopes lists every OAuth scope that an MCP tool may require. HTTP
4044
// protected-resource metadata advertises this full set so clients can step up
4145
// authorization for tools excluded from the default grant.
42-
var SupportedScopes = []string{
43-
"repo",
44-
"delete_repo",
45-
"read:org",
46-
"read:user",
47-
"user:email",
48-
"read:packages",
49-
"write:packages",
50-
"read:project",
51-
"project",
52-
"gist",
53-
"notifications",
54-
"workflow",
55-
"codespace",
46+
var SupportedScopes = scopesFromDefinitions(false)
47+
48+
// DefaultScopes are requested by stdio OAuth unless the operator explicitly
49+
// supplies --oauth-scopes. High-risk scopes such as delete_repo require opt-in.
50+
var DefaultScopes = scopesFromDefinitions(true)
51+
52+
func scopesFromDefinitions(defaultOnly bool) []string {
53+
result := make([]string, 0, len(scopeDefinitions))
54+
for _, scope := range scopeDefinitions {
55+
if !defaultOnly || scope.byDefault {
56+
result = append(result, scope.name)
57+
}
58+
}
59+
return result
5660
}
5761

5862
// Config holds the OAuth configuration for the MCP server.

pkg/http/oauth/oauth_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ func TestSupportedScopes(t *testing.T) {
587587
}
588588

589589
func TestDefaultScopesRequiresExplicitDeleteRepoOptIn(t *testing.T) {
590+
assert.Subset(t, SupportedScopes, DefaultScopes)
590591
assert.Contains(t, SupportedScopes, "delete_repo")
591592
assert.NotContains(t, DefaultScopes, "delete_repo")
592593
assert.Contains(t, DefaultScopes, "repo")

0 commit comments

Comments
 (0)