-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Add OAuth scope metadata to all MCP tools #1679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
SamMorrowDrums
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot this is pretty great, but let's only show accepted scopes where they differ, we generally want to omit those.
Also now all the changes are made you don't need NewToolWithScopes and can simply replace NewTool as all new tools should have explicitly require no scopes rather than having a different constructors.
Done in commit 29e9374. Changes made:
Examples from the generated documentation:
|
29e9374 to
c32646d
Compare
- Created pkg/scopes package with OAuth scope constants - Added RequiredScopes and AcceptedScopes fields to ServerTool - Added NewToolWithScopes helpers in dependencies.go - Updated context tools (get_me, get_teams, get_team_members) with scopes Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com>
- Updated 60+ tools with required and accepted OAuth scopes - Added scopes to: gists, git, notifications, projects, code scanning, dependabot, secret scanning, security advisories, actions, discussions, issues (partial), labels, pull requests (partial), repositories (partial), search (partial) - Remaining: ~20 tools in issues, pullrequests, repositories, and search files Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com>
- Updated all remaining tools with OAuth scope information - Added scope documentation generation to generate-docs command - Documentation now shows Required and Accepted OAuth scopes for each tool - All 100+ tools now have scope information defined - Tests pass, linter passes, documentation generated successfully Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com>
- Replace NewToolWithScopes with updated NewTool that includes scope parameters - All tools now use the same constructor with explicit scope requirements - Documentation only shows accepted scopes when they differ from required - Removed NewToolWithScopes and NewToolFromHandlerWithScopes helper functions Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com>
- Add ScopeHierarchy map defining parent-child scope relationships - Add ExpandScopes() function to derive accepted scopes from required scopes - Update NewTool/NewToolFromHandler to take []scopes.Scope and auto-derive AcceptedScopes - Add new scope constants: NoScope, User, ReadUser, UserEmail, ReadPackages, WritePackages - Update all tool files to use new signature with typed scopes - Add comprehensive tests for ExpandScopes The scope hierarchy allows automatic derivation of accepted scopes: - repo → public_repo, security_events - admin:org → write:org → read:org - project → read:project - write:packages → read:packages - user → read:user, user:email This enables the remote server to consume scope info directly from OSS tools.
public_repo is implicit - the GitHub API handles the distinction between public and private repos. Using repo as the required scope is more consistent with our enforcement model: - PATs: tools visible if token has repo scope - OAuth: scope challenge requests repo scope
c4c6491 to
742dfe3
Compare
Map iteration in Go is non-deterministic, which causes doc generation to produce different output on each run. Sort the scope slices in: - ScopeSet.ToSlice() - ScopeSet.ToStringSlice() - ExpandScopes()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds OAuth scope metadata infrastructure to all 100+ MCP tools, enabling users and systems to understand permission requirements for each tool. The implementation creates a new typed scope system with automatic scope hierarchy expansion and conditional documentation display.
Key changes:
- Created
pkg/scopespackage with typed OAuth scope constants and hierarchy-aware expansion logic - Extended tool infrastructure to include
RequiredScopesandAcceptedScopesmetadata fields - Updated all tool definitions with explicit scope requirements
- Enhanced documentation generation to display scope information conditionally
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pkg/scopes/scopes.go |
New package defining OAuth scope constants, hierarchy, and expansion logic that automatically derives accepted scopes from required scopes |
pkg/scopes/scopes_test.go |
Comprehensive test coverage for scope expansion and hierarchy validation |
pkg/inventory/server_tool.go |
Added RequiredScopes and AcceptedScopes fields to ServerTool struct for scope metadata storage |
pkg/github/dependencies.go |
Updated NewTool and NewToolFromHandler constructors to accept scope parameters and populate scope fields automatically |
pkg/github/actions.go |
Added scopes.Repo requirement to all GitHub Actions workflow tools |
pkg/github/code_scanning.go |
Added scopes.SecurityEvents requirement to code scanning alert tools |
pkg/github/context_tools.go |
Added nil scopes for get_me (public), scopes.ReadOrg for team tools |
pkg/github/dependabot.go |
Added scopes.SecurityEvents requirement to Dependabot alert tools |
pkg/github/discussions.go |
Added scopes.Repo requirement to all discussion tools |
pkg/github/gists.go |
Added nil scopes for read operations, scopes.Gist for write operations |
pkg/github/git.go |
Added scopes.Repo requirement to repository tree tool |
pkg/github/issues.go |
Added scopes.Repo for most issue tools, scopes.ReadOrg for list_issue_types |
pkg/github/labels.go |
Added scopes.Repo requirement to all label tools |
pkg/github/notifications.go |
Added scopes.Notifications requirement to all notification tools |
pkg/github/projects.go |
Added scopes.ReadProject for read tools, scopes.Project for write tools |
pkg/github/pullrequests.go |
Added scopes.Repo requirement to all pull request tools |
pkg/github/repositories.go |
Added scopes.Repo to most repository tools; incorrectly uses scopes.Repo instead of scopes.PublicRepo for star/unstar operations |
pkg/github/search.go |
Added scopes.Repo for repository/code/user search, scopes.ReadOrg for org search |
pkg/github/secret_scanning.go |
Added scopes.SecurityEvents requirement to secret scanning alert tools |
pkg/github/security_advisories.go |
Added scopes.SecurityEvents requirement to all security advisory tools |
cmd/github-mcp-server/generate_docs.go |
Enhanced to display OAuth scopes with conditional logic (shows accepted scopes only when they differ from required) |
README.md |
Generated documentation now displays OAuth scope requirements for all tools with proper conditional formatting |
| Required: []string{"owner", "repo"}, | ||
| }, | ||
| }, | ||
| []scopes.Scope{scopes.Repo}, |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the PR description's scope mapping, star_repository should require the public_repo scope (not repo). The mapping shows:
- required_scopes:
public_repo - accepted_scopes:
public_repo,repo
This should use []scopes.Scope{scopes.PublicRepo} instead of []scopes.Scope{scopes.Repo}.
| []scopes.Scope{scopes.Repo}, | |
| []scopes.Scope{scopes.PublicRepo}, |
| Required: []string{"owner", "repo"}, | ||
| }, | ||
| }, | ||
| []scopes.Scope{scopes.Repo}, |
Copilot
AI
Jan 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the PR description's scope mapping, unstar_repository should require the public_repo scope (not repo). The mapping shows:
- required_scopes:
public_repo - accepted_scopes:
public_repo,repo
This should use []scopes.Scope{scopes.PublicRepo} instead of []scopes.Scope{scopes.Repo}.
| []scopes.Scope{scopes.Repo}, | |
| []scopes.Scope{scopes.PublicRepo}, |
Summary
Added OAuth scope requirements to all 100+ MCP tools and automated scope documentation generation with conditional display logic.
Why
Enables users and systems to understand OAuth permission requirements for each tool. Prepares infrastructure for future scope validation logic.
What changed
pkg/scopespackage with typed OAuth scope constants (Repo,Gist,Notifications,ReadOrg,WriteOrg,AdminOrg,ReadProject,Project,SecurityEvents,PublicRepo)ServerToolstruct withRequiredScopesandAcceptedScopesstring slicesNewToolandNewToolFromHandlerto include scope parameters (all tools use same constructor)generate-docscommand to display scopes in tool documentationScope mapping examples:
get_me: no scopes required (public user data) - no scope info shownget_teams: requiresread:org, acceptsread:org,write:org,admin:org- shows bothcreate_gist: requiresgist, acceptsgist- only shows requiredstar_repository: requirespublic_repo, acceptspublic_repo,repo- shows bothrepo, acceptrepo- only shows requiredsecurity_events, acceptsecurity_events,repo- shows bothMCP impact
Prompts tested (tool changes only)
Security / limits
Tool renaming
Lint & tests
./script/lint./script/testDocs
Original prompt
I added a bunch of PRs in order to enable oauth scopes to be documented and available for end users.
Can you add per tool scope information provided for the server tools, and added to documentation using the new arch where tools are self defining. It should be small changes with current arch even though it is going to touch every tool definition. Maybe the available scopes should also be a typed set of string constants with a scopes package that can be used on remote server also.
We need both required and accepted scopes due to hierarchy and scopes getting rolled up, but for now just edit tools and document. Later we'll add logic.
Here's the tool scope's mapping:
{
"get_me": {
"required_scopes": {},
"accepted_scopes": {}
},
"get_teams": {
"required_scopes": {"read:org": true},
"accepted_scopes": {"read:org": true, "write:org": true, "admin:org": true}
},
"get_team_members": {
"required_scopes": {"read:org": true},
"accepted_scopes": {"read:org": true, "write:org": true, "admin:org": true}
},
"list_issue_types": {
"required_scopes": {"read:org": true},
"accepted_scopes": {"read:org": true, "write:org": true, "admin:org": true}
},
"list_gists": {
"required_scopes": {},
"accepted_scopes": {}
},
"get_gist": {
"required_scopes": {},
"accepted_scopes": {}
},
"create_gist": {
"required_scopes": {"gist": true},
"accepted_scopes": {"gist": true}
},
"update_gist": {
"required_scopes": {"gist": true},
"accepted_scopes": {"gist": true}
},
"list_notifications": {
"required_scopes": {"notifications": true},
"accepted_scopes": {"notifications": true}
},
"dismiss_notification": {
"required_scopes": {"notifications": true},
"accepted_scopes": {"notifications": true}
},
"get_notification_details": {
"required_scopes": {"notifications": true},
"accepted_scopes": {"notifications": true}
},
"manage_notification_subscription": {
"required_scopes": {"notifications": true},
"accepted_scopes": {"notifications": true}
},
"manage_repository_notification_subscription": {
"required_scopes": {"notifications": true},
"accepted_scopes": {"notifications": true}
},
"mark_all_notifications_read": {
"required_scopes": {"notifications": true},
"accepted_scopes": {"notifications": true}
},
"star_repository": {
"required_scopes": {"public_repo": true},
"accepted_scopes": {"public_repo": true, "repo": true}
},
"unstar_repository": {
"required_scopes": {"public_repo": true},
"accepted_scopes": {"public_repo": true, "repo": true}
},
"get_project": {
"required_scopes": {"read:project": true},
"accepted_scopes": {"read:project": true, "project": true}
},
"get_project_field": {
"required_scopes": {"read:project": true},
"accepted_scopes": {"read:project": true, "project": true}
},
"get_project_item": {
"required_scopes": {"read:project": true},
"accepted_scopes": {"read:project": true, "project": true}
},
"list_project_fields": {
"required_scopes": {"read:project": true},
"accepted_scopes": {"read:project": true, "project": true}
},
"list_project_items": {
"required_scopes": {"read:project": true},
"accepted_scopes": {"read:project": true, "project": true}
},
"list_projects": {
"required_scopes": {"read:project": true},
"accepted_scopes": {"read:project": true, "project": true}
},
"add_project_item": {
"required_scopes": {"project": true},
"accepted_scopes": {"project": true}
},
"delete_project_item": {
"required_scopes": {"project": true},
"accepted_scopes": {"project": true}
},
"update_project_item": {
"required_scopes": {"project": true},
"accepted_scopes": {"project": true}
},
"get_code_scanning_alert": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "repo": true}
},
"list_code_scanning_alerts": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "repo": true}
},
"get_dependabot_alert": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "repo": true}
},
"list_dependabot_alerts": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "repo": true}
},
"get_secret_scanning_alert": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "repo": true}
},
"list_secret_scanning_alerts": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "repo": true}
},
"get_global_security_advisory": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "repo": true}
},
"list_global_security_advisories": {
"required_scopes": {"security_events": true},
"accepted_scopes": {"security_events": true, "r...
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.