Skip to content

Enterprise: Copilot github-mcp-server still fails to connect (api.githubcopilot.com interception insufficient) #594

Description

@nikolanovoselec

Summary

In enterprise mode, Copilot CLI's built-in github-mcp-server fails to start with:

Failed to connect to MCP server github-mcp-server

The first fix attempt — intercepting Copilot's remote MCP host api.githubcopilot.com and stamping a GitHub Bearer token (commit c80aa7c, REQ-GITHUB-003 AC1/AC2) — is deployed and live but does not resolve the failure.

Environment

What was tried (and is confirmed insufficient)

c80aa7c added api.githubcopilot.com to interceptedGithubHosts and added a Bearer-injection branch in the GitHubInterceptor:

  • src/github-interceptor.ts:51-58gitCopilotMcpHost + interceptedGithubHosts now include api.githubcopilot.com (env-overridable via GITHUB_COPILOT_MCP_HOST).
  • src/github-interceptor.ts:162-166 — on api.githubcopilot.com it strips the container placeholder and sets Authorization: Bearer <user GitHub token> (no X-GitHub-Api-Version).
  • Wired at container start in src/container/index.ts (wireGithubInterception) — confirmed it loops all three GitHub hosts.

Unit tests pass (the interceptor does stamp Bearer on that host), but the real-world outcome the AC claims — "the remote github-mcp-server connects authenticated" — is false in production. So either the request isn't actually reaching/leaving the interceptor as expected, or a static GitHub Bearer token is not what that endpoint's handshake requires.

Candidate root causes (to be confirmed with logs, ranked by likelihood)

  1. The remote GitHub MCP server uses an OAuth 2.0 handshake, not a static Bearer token. MCP Streamable-HTTP servers commonly answer the initial request with 401 + WWW-Authenticate pointing at an authorization server, then the client runs an OAuth/discovery dance (potentially across other hosts, e.g. github.com/login/oauth/* or a .well-known endpoint). Injecting a static Bearer <github-oauth-token> would not satisfy that flow, and the multi-step connect would fail → generic "Failed to connect". This is the leading hypothesis.
  2. Wrong credential kind. api.githubcopilot.com/mcp may require a Copilot-scoped token, not the user's GitHub OAuth token from the codeflare deploy-keys connect flow. (Would more likely surface as a 401, but could also break the handshake.)
  3. Request isn't actually being intercepted. Possible if: the MCP transport opens a connection the L7 interceptOutboundHttps layer doesn't cover; the container doesn't trust the interception CA for this host; or (under strict egress) host precedence routes it to the EgressController catch-all / env.EGRESS instead of the GitHubInterceptor. Note the cf1:network EGRESS binding is committed commented-out, so if strict egress were ON the path would fail-closed 503 — but git over the same GitHubInterceptor works, suggesting strict egress is OFF here and this is less likely.
  4. HTTP/transport handling in the interceptor breaks MCP. redirect:'manual' surfaces a 3xx (e.g. /mcp/mcp/) to the client instead of following it; or a stripped/altered header (Mcp-Session-Id, Accept: text/event-stream, content negotiation) breaks the Streamable-HTTP handshake.
  5. Wrong/incomplete host or path. Copilot may dial an additional endpoint (token/discovery) beyond api.githubcopilot.com/mcp that is not intercepted.

Diagnostic plan (do this before any further code change)

  1. wrangler tail the enterprise-integration worker while reproducing in a fresh session. Confirm whether GitHubInterceptor: injected credential ... api.githubcopilot.com/mcp fires at all:
    • Not hit → interception/precedence/CA/host problem (causes 3/5).
    • Hit, upstream non-2xx (esp. 401 + WWW-Authenticate) → OAuth-handshake / wrong-credential problem (causes 1/2).
    • Hit, upstream 3xx → redirect/transport problem (cause 4).
  2. Capture the exact host(s) + path(s) + status codes Copilot's github-mcp-server requests during connect (it may be more than one host).
  3. Identify what credential the endpoint actually expects (GitHub PAT vs OAuth-app token vs Copilot token) and whether an OAuth discovery/authorization step is involved.

Follow-ups

  • Spec truth: REQ-GITHUB-003 AC2 currently asserts Copilot's MCP "connects authenticated". Until root cause is fixed, that claim is not satisfied in production — the AC / Status should be revisited (the interceptor test verifies header-stamping, not end-to-end connection).
  • Once the real mechanism is known, decide whether interception+Bearer can ever work, or whether Copilot's remote MCP requires a fundamentally different approach in the zero-secret enterprise container.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions