github-mcp-server: /mcp authenticate always fails on Copilot Enterprise — enterprise MCP host advertises a cross-origin resource identifier
- Dominant language
- Shell
- Stars
- 11.2k
- Forks
- 1.9k
- Avg merge
- 14h 16m
- Merged PRs (30d)
- 6
Description
### Describe the bug
On a Copilot **Enterprise-routed** account, selecting the built-in `github-mcp-server` in `/mcp` starts an OAuth flow that can never succeed:
```
Authenticating: github-mcp-server
Authentication failed: MCPOAuthError: Failed to discover authorization server metadata for https://api.enterprise.githubcopilot.com/mcp/readonly
```
**Root cause** — the built-in server URL is derived from the account's Copilot API base, so for enterprise-routed accounts it becomes `https://api.enterprise.githubcopilot.com/mcp/readonly`. But that host advertises a protected-resource identifier on a **different origin**:
```console
$ curl -si -X POST https://api.enterprise.githubcopilot.com/mcp/readonly \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}'
HTTP/2 401
www-authenticate: Bearer error="invalid_request",
error_description="No access token was provided in this request",
resource_metadata="https://api.githubcopilot.com/.well-known/oauth-protected-resource/mcp/readonly"
^^^^^^^^^^^^^^^^^^^^^^^^^ different origin than the resource server
```
```console
$ curl -s https://api.enterprise.githubcopilot.com/.well-known/oauth-protected-resource/mcp/readonly
{
"resource": "https://api.githubcopilot.com/mcp/readonly",
^^^^^^^^^^ declares the NON-enterprise origin
"authorization_servers": ["https://github.com/login/oauth"],
...
}
```
The CLI enforces RFC 9728 same-origin on the resource identifier — `runtime.node` contains the guard string:
> `Protected resource metadata declares resource `…`, which does not belong to `…
so discovery aborts before an authorization server is ever contacted. Both requests above are **unauthenticated**, so this reproduces for any enterprise-routed account regardless of local credentials.
Note the AS metadata itself is fine and reachable (`https://github.com/.well-known/oauth-authorization-server/login/oauth` → 200) — the flow never gets that far.
This looks like the built-in first-party instance of #3100: `/mcp` initiates OAuth discovery on selection even when the server already has a working `Authorization: Bearer` header. Here the server **is** healthy — its tools work normally in the same session — so the OAuth attempt is both unnecessary and unsatisfiable.
### Affected version
`1.0.79-9` (macOS 15 / darwin-arm64). Account is enterprise-routed, so `authGetCopilotApiUrl` resolves to `https://api.enterprise.githubcopilot.com`.
### Steps to reproduce the behavior
1. Sign in with an account whose Copilot is provided through a GitHub Enterprise (so the Copilot API base is `api.enterprise.githubcopilot.com`).
2. Confirm the built-in server is healthy — e.g. invoke `github-mcp-server/search_users`. It succeeds.
3. Run `/mcp` and select `github-mcp-server` from the numbered list (the only action offered is "authenticate").
4. Observe `Authentication failed: MCPOAuthError: Failed to discover authorization server metadata for https://api.enterprise.githubcopilot.com/mcp/readonly`.
### Expected behavior
Any of:
1. **Skip OAuth when a bearer is already attached.** The built-in server is authenticated via an injected `Authorization: Bearer` header (`Starting pending GitHub MCP server "github-mcp-server" after authentication`), so it should report *authenticated* and not offer/enter an OAuth flow at all. (Same ask as #3100.)
2. **Honour the advertised resource identifier** when the resource server explicitly points at a sibling Copilot origin, rather than rejecting it as cross-origin.
3. **Or fix the service side** so `api.enterprise.githubcopilot.com` advertises its own origin in `resource` / `resource_metadata`.
### Additional context
- Discovery is rejected purely on the URL — independent of token, scopes, keychain, or local config. Verified unauthenticated via `curl` above.
- `GITHUB_MCP_URL_OVERRIDE` appears not to be read from the process environment in 1.0.79-9: setting it to an unroutable URL (`http://127.0.0.1:9/mcp/readonly`) still produced a fully working `github-mcp-server` with no connection attempt to that address, so it can't be used as a workaround.
- Overriding the built-in by declaring a user-level `github-mcp-server` in `mcp-config.json` pointed at `https://api.githubcopilot.com/mcp/readonly` does suppress the failure (log: `User has explicitly configured github-mcp-server by name, skipping built-in setup`), but it is **not** a viable workaround: the plain endpoint doesn't expose the Copilot-only tools, so `web_search`, `get_copilot_space` and `list_copilot_spaces` all disappear.
Contributor guide
Assessment
This issue has not been assessed yet.