Skip to content

Commit 84ca9bb

Browse files
committed
feat(http): add --authorization-server flag to override OAuth AS URL
When deploying the MCP server behind an OAuth proxy (e.g. for GHES, which does not natively support RFC 8414, RFC 7591, or PKCE), the /.well-known/oauth-protected-resource endpoint currently always derives the authorization_servers URL from GITHUB_HOST. There is no way to point clients at a different authorization server without intercepting that endpoint at the ingress/proxy layer. The oauth.Config struct already has an AuthorizationServer field with the conditional logic in place (pkg/http/oauth/oauth.go), but it was never wired to any configuration surface. This commit exposes it as: - --authorization-server CLI flag on the http subcommand - GITHUB_AUTHORIZATION_SERVER environment variable (via viper's existing GITHUB_ prefix + automatic env mapping) When set, the value is passed through ServerConfig into oauth.Config, and the protected resource metadata advertises it directly instead of calling apiHost.AuthorizationServerURL().
1 parent 870f3c7 commit 84ca9bb

3 files changed

Lines changed: 39 additions & 3 deletions

File tree

cmd/github-mcp-server/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ var (
180180
ListenHost: viper.GetString("listen-host"),
181181
BaseURL: viper.GetString("base-url"),
182182
ResourcePath: viper.GetString("base-path"),
183+
AuthorizationServer: viper.GetString("authorization-server"),
183184
ExportTranslations: viper.GetBool("export-translations"),
184185
EnableCommandLogging: viper.GetBool("enable-command-logging"),
185186
LogFilePath: viper.GetString("log-file"),
@@ -235,6 +236,7 @@ func init() {
235236
httpCmd.Flags().String("listen-host", "", "Host the HTTP server binds to (e.g. 127.0.0.1). Empty binds to all interfaces.")
236237
httpCmd.Flags().String("base-url", "", "Base URL where this server is publicly accessible (for OAuth resource metadata)")
237238
httpCmd.Flags().String("base-path", "", "Externally visible base path for the HTTP server (for OAuth resource metadata)")
239+
httpCmd.Flags().String("authorization-server", "", "Override the authorization server URL in OAuth resource metadata. Useful when deploying behind an OAuth proxy (e.g. for GHES). Env: GITHUB_AUTHORIZATION_SERVER")
238240
httpCmd.Flags().Bool("scope-challenge", false, "Enable OAuth scope challenge responses")
239241
httpCmd.Flags().Bool("trust-proxy-headers", false, "Honor X-Forwarded-Host and X-Forwarded-Proto when constructing OAuth resource metadata URLs. Only enable when the server is deployed behind a trusted proxy that sets these headers. Ignored when --base-url is set.")
240242

@@ -260,6 +262,7 @@ func init() {
260262
_ = viper.BindPFlag("listen-host", httpCmd.Flags().Lookup("listen-host"))
261263
_ = viper.BindPFlag("base-url", httpCmd.Flags().Lookup("base-url"))
262264
_ = viper.BindPFlag("base-path", httpCmd.Flags().Lookup("base-path"))
265+
_ = viper.BindPFlag("authorization-server", httpCmd.Flags().Lookup("authorization-server"))
263266
_ = viper.BindPFlag("scope-challenge", httpCmd.Flags().Lookup("scope-challenge"))
264267
_ = viper.BindPFlag("trust-proxy-headers", httpCmd.Flags().Lookup("trust-proxy-headers"))
265268
// Add subcommands

docs/streamable-http.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,31 @@ github-mcp-server http --trust-proxy-headers
7171

7272
Equivalent environment variable: `GITHUB_TRUST_PROXY_HEADERS=1`. Only enable this when the upstream proxy is trusted to set or strip these headers; otherwise prefer `--base-url`. When `--base-url` is set, it always takes precedence and `--trust-proxy-headers` has no effect.
7373

74+
### With an OAuth Proxy (GHES / non-standard authorization server)
75+
76+
When deploying against GitHub Enterprise Server, GHES does not natively support the OAuth extensions required by MCP (RFC 8414 metadata discovery, RFC 7591 Dynamic Client Registration, PKCE). In this case you can run a separate OAuth proxy that implements the MCP OAuth spec and forwards authentication to GHES. Use `--authorization-server` to advertise the proxy's URL in the protected resource metadata instead of the one derived from `--gh-host`:
77+
78+
```bash
79+
github-mcp-server http \
80+
--gh-host https://github.example.com \
81+
--base-url https://mcp.example.com \
82+
--authorization-server https://mcp.example.com/oauth-proxy
83+
```
84+
85+
The `authorization_servers` field in the protected resource metadata will then point at your proxy:
86+
87+
```json
88+
{
89+
"resource": "https://mcp.example.com",
90+
"authorization_servers": [
91+
"https://mcp.example.com/oauth-proxy"
92+
],
93+
...
94+
}
95+
```
96+
97+
Equivalent environment variable: `GITHUB_AUTHORIZATION_SERVER=https://mcp.example.com/oauth-proxy`.
98+
7499
## Client Configuration
75100

76101
### Using OAuth Authentication

pkg/http/server.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ type ServerConfig struct {
4949
// This is used to restore the original path when a proxy strips a base path before forwarding.
5050
ResourcePath string
5151

52+
// AuthorizationServer overrides the authorization server URL advertised in the
53+
// OAuth Protected Resource Metadata (/.well-known/oauth-protected-resource).
54+
// When set, this URL is used instead of the one derived from the GitHub host.
55+
// Useful when deploying behind an OAuth proxy (e.g. for GHES, which does not
56+
// natively support RFC 8414 / RFC 7591 / PKCE).
57+
AuthorizationServer string
58+
5259
// TrustProxyHeaders indicates whether X-Forwarded-Host and X-Forwarded-Proto
5360
// should be honored when constructing OAuth resource metadata URLs. Only
5461
// enable this when the server is deployed behind a trusted proxy that sets
@@ -163,9 +170,10 @@ func RunHTTPServer(cfg ServerConfig) error {
163170

164171
// Register OAuth protected resource metadata endpoints
165172
oauthCfg := &oauth.Config{
166-
BaseURL: cfg.BaseURL,
167-
ResourcePath: cfg.ResourcePath,
168-
TrustProxyHeaders: cfg.TrustProxyHeaders,
173+
BaseURL: cfg.BaseURL,
174+
ResourcePath: cfg.ResourcePath,
175+
TrustProxyHeaders: cfg.TrustProxyHeaders,
176+
AuthorizationServer: cfg.AuthorizationServer,
169177
}
170178

171179
serverOptions := []HandlerOption{}

0 commit comments

Comments
 (0)