Skip to content

Commit 6b631f8

Browse files
Add OAuth scopes customization via CLI flag and environment variable
- Add --oauth-scopes CLI flag to allow users to limit requested scopes - Add GITHUB_OAUTH_SCOPES environment variable support - Update OAuth authentication documentation with scopes customization guide - Add examples for minimal, read-only, and custom scope configurations - Update OAuth client ID comment to indicate it's a testing app (TODO for production) Co-authored-by: SamMorrowDrums <[email protected]>
1 parent 4e68d8f commit 6b631f8

File tree

4 files changed

+91
-6
lines changed

4 files changed

+91
-6
lines changed

cmd/github-mcp-server/main.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ var (
6565
}
6666
}
6767

68+
// Parse OAuth scopes (similar to toolsets)
69+
var oauthScopes []string
70+
if viper.IsSet("oauth-scopes") {
71+
if err := viper.UnmarshalKey("oauth-scopes", &oauthScopes); err != nil {
72+
return fmt.Errorf("failed to unmarshal oauth-scopes: %w", err)
73+
}
74+
}
75+
6876
ttl := viper.GetDuration("repo-access-cache-ttl")
6977
stdioServerConfig := ghmcp.StdioServerConfig{
7078
Version: version,
@@ -83,6 +91,7 @@ var (
8391
RepoAccessCacheTTL: &ttl,
8492
OAuthClientID: viper.GetString("oauth-client-id"),
8593
OAuthClientSecret: viper.GetString("oauth-client-secret"),
94+
OAuthScopes: oauthScopes,
8695
}
8796
return ghmcp.RunStdioServer(stdioServerConfig)
8897
},
@@ -110,6 +119,7 @@ func init() {
110119
rootCmd.PersistentFlags().Duration("repo-access-cache-ttl", 5*time.Minute, "Override the repo access cache TTL (e.g. 1m, 0s to disable)")
111120
rootCmd.PersistentFlags().String("oauth-client-id", "", "OAuth App client ID for device flow authentication (optional, uses default if not provided)")
112121
rootCmd.PersistentFlags().String("oauth-client-secret", "", "OAuth App client secret for device flow authentication (optional, for confidential clients)")
122+
rootCmd.PersistentFlags().StringSlice("oauth-scopes", nil, "Comma-separated list of OAuth scopes to request during device flow authentication (optional, uses default if not provided)")
113123

114124
// Bind flag to viper
115125
_ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets"))
@@ -126,6 +136,7 @@ func init() {
126136
_ = viper.BindPFlag("repo-access-cache-ttl", rootCmd.PersistentFlags().Lookup("repo-access-cache-ttl"))
127137
_ = viper.BindPFlag("oauth-client-id", rootCmd.PersistentFlags().Lookup("oauth-client-id"))
128138
_ = viper.BindPFlag("oauth-client-secret", rootCmd.PersistentFlags().Lookup("oauth-client-secret"))
139+
_ = viper.BindPFlag("oauth-scopes", rootCmd.PersistentFlags().Lookup("oauth-scopes"))
129140

130141
// Add subcommands
131142
rootCmd.AddCommand(stdioCmd)

docs/oauth-authentication.md

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ The GitHub MCP Server provides the following CLI flags for OAuth configuration:
242242
|------|-------------|---------|---------|
243243
| `--oauth-client-id` | OAuth App client ID for device flow authentication | Default GitHub MCP OAuth App | `--oauth-client-id Ov23liYourClientID` |
244244
| `--oauth-client-secret` | OAuth App client secret (optional, for confidential clients) | None | `--oauth-client-secret your_client_secret` |
245+
| `--oauth-scopes` | Comma-separated list of OAuth scopes to request | Default scopes (see below) | `--oauth-scopes repo,read:org,gist` |
245246
| `--gh-host` | GitHub hostname for API requests and OAuth endpoints | `github.com` | `--gh-host https://github.yourcompany.com` |
246247

247248
### Usage Examples
@@ -256,6 +257,11 @@ github-mcp-server stdio
256257
github-mcp-server stdio --oauth-client-id Ov23liYourClientID
257258
```
258259

260+
**Limiting scopes (minimal permissions):**
261+
```bash
262+
github-mcp-server stdio --oauth-scopes repo,read:org,gist
263+
```
264+
259265
**GHES with custom OAuth App:**
260266
```bash
261267
github-mcp-server stdio --gh-host https://github.yourcompany.com --oauth-client-id Ov23liGHESClientID
@@ -266,6 +272,11 @@ github-mcp-server stdio --gh-host https://github.yourcompany.com --oauth-client-
266272
github-mcp-server stdio --oauth-client-id Ov23liYourClientID --oauth-client-secret your_secret
267273
```
268274

275+
**Custom scopes with custom OAuth App:**
276+
```bash
277+
github-mcp-server stdio --oauth-client-id Ov23liYourClientID --oauth-scopes repo,read:org,user:email
278+
```
279+
269280
## Environment Variables
270281

271282
All CLI flags can also be configured via environment variables with the `GITHUB_` prefix:
@@ -274,6 +285,7 @@ All CLI flags can also be configured via environment variables with the `GITHUB_
274285
|---------------------|---------------------|---------|
275286
| `GITHUB_OAUTH_CLIENT_ID` | `--oauth-client-id` | `export GITHUB_OAUTH_CLIENT_ID=Ov23liYourClientID` |
276287
| `GITHUB_OAUTH_CLIENT_SECRET` | `--oauth-client-secret` | `export GITHUB_OAUTH_CLIENT_SECRET=your_secret` |
288+
| `GITHUB_OAUTH_SCOPES` | `--oauth-scopes` | `export GITHUB_OAUTH_SCOPES=repo,read:org,gist` |
277289
| `GITHUB_HOST` | `--gh-host` | `export GITHUB_HOST=https://github.yourcompany.com` |
278290
| `GITHUB_PERSONAL_ACCESS_TOKEN` | N/A (disables OAuth) | `export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_token` |
279291

@@ -309,11 +321,63 @@ These scopes form a superset of the `gh` CLI minimal scopes (`repo`, `read:org`,
309321

310322
### Customizing Scopes
311323

312-
Currently, scopes are not customizable via CLI flags or environment variables. They are defined in the source code (`pkg/github/auth.go`) as `DefaultOAuthScopes`. To customize scopes, you would need to:
324+
You can customize the requested scopes using the `--oauth-scopes` CLI flag or `GITHUB_OAUTH_SCOPES` environment variable:
325+
326+
**CLI Flag:**
327+
```bash
328+
github-mcp-server stdio --oauth-scopes repo,read:org,gist
329+
```
330+
331+
**Environment Variable:**
332+
```bash
333+
export GITHUB_OAUTH_SCOPES=repo,read:org,user:email
334+
github-mcp-server stdio
335+
```
313336

314-
1. Fork the repository
315-
2. Modify the `DefaultOAuthScopes` variable
316-
3. Build your custom version
337+
**Docker with environment variable:**
338+
```json
339+
{
340+
"github": {
341+
"command": "docker",
342+
"args": ["run", "-i", "--rm", "-e", "GITHUB_OAUTH_SCOPES", "ghcr.io/github/github-mcp-server"],
343+
"env": {
344+
"GITHUB_OAUTH_SCOPES": "repo,read:org,gist"
345+
}
346+
}
347+
}
348+
```
349+
350+
#### Minimal Recommended Scopes
351+
352+
For basic functionality, you can use a minimal set of scopes:
353+
354+
```bash
355+
--oauth-scopes repo,read:org,gist
356+
```
357+
358+
This provides:
359+
- `repo`: Access to repositories, issues, and PRs
360+
- `read:org`: Read organization and team information
361+
- `gist`: Manage gists
362+
363+
**Note**: Some MCP tools may not function properly with reduced scopes. Review the scopes table above to understand which scopes are required for specific functionality.
364+
365+
#### Common Scope Combinations
366+
367+
**Read-only operations:**
368+
```bash
369+
--oauth-scopes repo,read:org,read:user
370+
```
371+
372+
**Full repository access with notifications:**
373+
```bash
374+
--oauth-scopes repo,read:org,notifications,user:email
375+
```
376+
377+
**Enterprise with minimal scopes:**
378+
```bash
379+
--oauth-scopes repo,read:org,read:gpg_key
380+
```
317381

318382
## Security Considerations
319383

internal/ghmcp/server.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ type MCPServerConfig struct {
7474

7575
// OAuthClientSecret is the OAuth App client secret (optional, for confidential clients).
7676
OAuthClientSecret string
77+
78+
// OAuthScopes is a list of OAuth scopes to request during device flow authentication.
79+
// If empty, the default scopes defined in DefaultOAuthScopes are used.
80+
OAuthScopes []string
7781
}
7882

7983
// githubClients holds all the GitHub API clients created for a server instance.
@@ -287,7 +291,7 @@ func NewUnauthenticatedMCPServer(cfg MCPServerConfig) (*UnauthenticatedServerRes
287291
oauthHost := github.NewOAuthHostFromAPIHost(cfg.Host)
288292

289293
// Create auth manager
290-
authManager := github.NewAuthManager(oauthHost, cfg.OAuthClientID, cfg.OAuthClientSecret, nil)
294+
authManager := github.NewAuthManager(oauthHost, cfg.OAuthClientID, cfg.OAuthClientSecret, cfg.OAuthScopes)
291295

292296
// Create the MCP server with capabilities advertised for dynamic tool registration
293297
serverOpts := &mcp.ServerOptions{
@@ -456,6 +460,10 @@ type StdioServerConfig struct {
456460

457461
// OAuthClientSecret is the OAuth App client secret (optional, for confidential clients).
458462
OAuthClientSecret string
463+
464+
// OAuthScopes is a list of OAuth scopes to request during device flow authentication.
465+
// If empty, the default scopes defined in DefaultOAuthScopes are used.
466+
OAuthScopes []string
459467
}
460468

461469
// RunStdioServer is not concurrent safe.
@@ -494,6 +502,7 @@ func RunStdioServer(cfg StdioServerConfig) error {
494502
Logger: logger,
495503
OAuthClientID: cfg.OAuthClientID,
496504
OAuthClientSecret: cfg.OAuthClientSecret,
505+
OAuthScopes: cfg.OAuthScopes,
497506
// Pass config for use after authentication
498507
EnabledToolsets: cfg.EnabledToolsets,
499508
EnabledTools: cfg.EnabledTools,

pkg/github/auth.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ func NewOAuthHostFromAPIHost(hostname string) OAuthHost {
111111
}
112112

113113
// DefaultOAuthClientID is the OAuth App client ID for the GitHub MCP Server.
114-
// This OAuth App is registered and managed by GitHub for use with this server.
114+
// TODO: This is currently a testing OAuth App. An official GitHub-managed OAuth App
115+
// will be registered before production release.
115116
// The client ID is safe to embed in source code per OAuth 2.0 spec for public clients.
116117
// Users can override this with --oauth-client-id for enterprise scenarios.
117118
const DefaultOAuthClientID = "Ov23ctTMsnT9LTRdBYYM"

0 commit comments

Comments
 (0)