github / github/copilot-cli

github-mcp-server: /mcp authenticate always fails on Copilot Enterprise — enterprise MCP host advertises a cross-origin resource identifier

Open
#4,408 0 comments 1 reaction 1 assignee Claimed by @JoannaaKL View on GitHub
area:authentication area:enterprise area:mcp
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.