You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MCP OAuth: pre-registered (static) client's secret isn't sent at token exchange → invalid_client #5351
With a pre-registered (static) confidential OAuth client, Copilot CLI completes the browser authorization step, but the authorization server rejects the code-for-token exchange:
Authentication failed: MCPOAuthError: Token exchange failed: Server returned error response: invalid_client: Bad credentials
The client ID and secret are correct. They work in Claude Code, VS Code and others.
Affected version
GitHub Copilot CLI 1.0.105 (macOS 26.6.2, arm64)
Steps to reproduce the behavior
Use a remote HTTP MCP server whose authorization server doesn't support dynamic client registration, and register a confidential OAuth client (client ID + secret) for it. We used https://mcp.pagerduty.com/mcp, with authorization server https://app.pagerduty.com/global/oauth/anonymous.
Add the server, either in /mcp or from a plugin's .mcp.json:
Connect it in /mcp. The CLI logs Client registration failed: Authorization server does not support dynamic client registration and shows the client credentials form.
Enter the client ID, press Tab, and enter the client secret (not marked as a public client).
Register the redirect URI shown in the browser's redirect_uri on the OAuth app (see the port note below), then approve in the browser.
The token exchange fails with invalid_client: Bad credentials.
~/.copilot/mcp-oauth-config/<hash>.json contains the client ID but no clientSecret:
Reproduced 3 times, both with a plugin-provided server and with one added by hand in /mcp. The token exchange error only appears in the UI, not in ~/.copilot/logs/*.log.
Expected behavior
For a static confidential client, the CLI should store the client secret and send it at the token exchange, using client_secret_basic or client_secret_post as the server's token_endpoint_auth_methods_supported advertises.
Additional context
Redirect port: the loopback callback uses a random port on every attempt (53676, 54429, 55205, 62372...), so a pre-registered client can't have a stable redirect URI on servers that require an exact match. The config schema has auth.redirectPort (McpServerAuthConfigRedirectPort), but setting "auth": {"redirectPort": 8080} in a plugin's.mcp.json has no effect: the port stays random. Please honor redirectPort for plugin-provided servers and document it.
Comparison: VS Code, with the same server, OAuth app, client ID and secret, succeeds once its redirect port is registered.
Closing: further testing shows the same invalid_client: Bad credentials at the token exchange from VS Code and Cursor too (Cursor uses a fixed redirect URI), with the same OAuth app and a freshly regenerated secret. The cause appears to be on the authorization server side, not in Copilot CLI. I'll reopen if that's ruled out.
The auth.redirectPort point (ignored for plugin-provided servers) still stands; happy to file that separately if useful.
Activity
t1agob commentedon Nov 4, 2026
Closing: further testing shows the same
invalid_client: Bad credentialsat the token exchange from VS Code and Cursor too (Cursor uses a fixed redirect URI), with the same OAuth app and a freshly regenerated secret. The cause appears to be on the authorization server side, not in Copilot CLI. I'll reopen if that's ruled out.The
auth.redirectPortpoint (ignored for plugin-provided servers) still stands; happy to file that separately if useful.