@@ -7,6 +7,29 @@ import (
77 "github.com/github/github-mcp-server/pkg/scopes"
88)
99
10+ // repoScopesSet contains scopes that grant access to repository content.
11+ // Tools requiring only these scopes work on public repos without any token scope,
12+ // so we don't filter them out even if the token lacks repo/public_repo.
13+ var repoScopesSet = map [string ]bool {
14+ string (scopes .Repo ): true ,
15+ string (scopes .PublicRepo ): true ,
16+ }
17+
18+ // onlyRequiresRepoScopes returns true if all of the tool's accepted scopes
19+ // are repo-related scopes (repo, public_repo). Such tools work on public
20+ // repositories without needing any scope.
21+ func onlyRequiresRepoScopes (acceptedScopes []string ) bool {
22+ if len (acceptedScopes ) == 0 {
23+ return false
24+ }
25+ for _ , scope := range acceptedScopes {
26+ if ! repoScopesSet [scope ] {
27+ return false
28+ }
29+ }
30+ return true
31+ }
32+
1033// CreateToolScopeFilter creates an inventory.ToolFilter that filters tools
1134// based on the token's OAuth scopes.
1235//
@@ -19,6 +42,7 @@ import (
1942//
2043// The filter returns true (include tool) if:
2144// - The tool has no scope requirements (AcceptedScopes is empty)
45+ // - The tool is read-only and only requires repo/public_repo scopes (works on public repos)
2246// - The token has at least one of the tool's accepted scopes
2347//
2448// Example usage:
@@ -31,6 +55,10 @@ import (
3155// inventory := github.NewInventory(t).WithFilter(filter).Build()
3256func CreateToolScopeFilter (tokenScopes []string ) inventory.ToolFilter {
3357 return func (_ context.Context , tool * inventory.ServerTool ) (bool , error ) {
58+ // Read-only tools requiring only repo/public_repo work on public repos without any scope
59+ if tool .Tool .Annotations != nil && tool .Tool .Annotations .ReadOnlyHint && onlyRequiresRepoScopes (tool .AcceptedScopes ) {
60+ return true , nil
61+ }
3462 return scopes .HasRequiredScopes (tokenScopes , tool .AcceptedScopes ), nil
3563 }
3664}
0 commit comments