Describe the bug
When signing in to a remote (type: http) MCP server whose authorization server is Microsoft Entra ID, configured with a statically-provided oauthClientId + oauthPublicClient: true (no Dynamic Client Registration), Copilot CLI opens the browser to Entra ID's /authorize endpoint without a scope query parameter at all, even though the server's OAuth metadata correctly advertises scopes_supported. Microsoft Entra ID's v2.0 endpoint requires scope on both the authorization request and the token exchange (unlike base RFC 6749, where it's optional), so the flow fails immediately with:
Sorry, but we're having trouble signing you in.
AADSTS900144: The request body must contain the following parameter: 'scope'.
This is very likely the same root-cause bug class as #4464 (silent refresh fails with AADSTS70011 due to mishandled scope on the refresh_token grant) — in both cases the OAuth client isn't correctly deriving/propagating the scope parameter for Entra ID flows built from server-advertised metadata. It's also functionally identical to anthropics/claude-code#69547, which reports the exact same AADSTS900144 error for the exact same scenario (pre-registered/static public client against an Entra ID-backed MCP server, since Entra ID doesn't support DCR) in a different MCP client, suggesting this is a well-known interoperability gap for MCP clients talking to Entra ID with a fixed client id.
Affected version
1.0.80 (Windows x64). Also reproduced on a locally-modified 1.0.79-era build before upgrading.
Steps to reproduce the behavior
- Configure a remote HTTP MCP server backed by Microsoft Entra ID with a statically-provided client id (no DCR), e.g. in
~/.copilot/mcp-config.json:
{
"mcpServers": {
"example-server": {
"type": "http",
"url": "https://example.org",
"oauthClientId": "<entra-app-client-id>",
"oauthPublicClient": true
}
}
}
The server's /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server documents are RFC 8414-compliant: authorization_servers matches the document's own issuer exactly, and authorization_endpoint/token_endpoint point at the real Microsoft Entra ID tenant endpoints (https://login.microsoftonline.com/<tenant>/oauth2/v2.0/authorize and .../token). The authorization-server metadata's scopes_supported correctly lists the resource's App ID URI scope, e.g. ["openid", "profile", "email", "api://<app-id>/access_as_user"].
2. In the app, open MCP settings and click Sign in for that server.
3. A browser window opens and navigates to Microsoft's /authorize endpoint. The observed request URL was:
https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize
?response_type=code
&client_id=<client-id>
&state=<state>
&code_challenge=<challenge>
&code_challenge_method=S256
&redirect_uri=http%3A%2F%2F127.0.0.1%3A<port>%2F
&client_session=<session-id>
Note there is no scope= parameter anywhere in this URL.
4. Entra ID immediately rejects the request:
AADSTS900144: The request body must contain the following parameter: 'scope'.
Expected behavior
The MCP OAuth client should build the scope parameter for the /authorize request (and again for the /token exchange) from the target server's advertised scopes_supported (from either the oauth-authorization-server or oauth-protected-resource metadata document), the same way it presumably does for servers that use Dynamic Client Registration. For Entra ID specifically, scope must be present on every leg of the flow (authorize request, token exchange, and refresh), since Entra ID's v2.0 endpoint treats scope as mandatory rather than optional.
Additional context
Describe the bug
When signing in to a remote (
type: http) MCP server whose authorization server is Microsoft Entra ID, configured with a statically-providedoauthClientId+oauthPublicClient: true(no Dynamic Client Registration), Copilot CLI opens the browser to Entra ID's/authorizeendpoint without ascopequery parameter at all, even though the server's OAuth metadata correctly advertisesscopes_supported. Microsoft Entra ID's v2.0 endpoint requiresscopeon both the authorization request and the token exchange (unlike base RFC 6749, where it's optional), so the flow fails immediately with:This is very likely the same root-cause bug class as #4464 (silent refresh fails with AADSTS70011 due to mishandled
scopeon therefresh_tokengrant) — in both cases the OAuth client isn't correctly deriving/propagating thescopeparameter for Entra ID flows built from server-advertised metadata. It's also functionally identical to anthropics/claude-code#69547, which reports the exact sameAADSTS900144error for the exact same scenario (pre-registered/static public client against an Entra ID-backed MCP server, since Entra ID doesn't support DCR) in a different MCP client, suggesting this is a well-known interoperability gap for MCP clients talking to Entra ID with a fixed client id.Affected version
1.0.80 (Windows x64). Also reproduced on a locally-modified 1.0.79-era build before upgrading.
Steps to reproduce the behavior
~/.copilot/mcp-config.json:{ "mcpServers": { "example-server": { "type": "http", "url": "https://example.org", "oauthClientId": "<entra-app-client-id>", "oauthPublicClient": true } } }The server's
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-serverdocuments are RFC 8414-compliant:authorization_serversmatches the document's ownissuerexactly, andauthorization_endpoint/token_endpointpoint at the real Microsoft Entra ID tenant endpoints (https://login.microsoftonline.com/<tenant>/oauth2/v2.0/authorizeand.../token). The authorization-server metadata'sscopes_supportedcorrectly lists the resource's App ID URI scope, e.g.["openid", "profile", "email", "api://<app-id>/access_as_user"].2. In the app, open MCP settings and click Sign in for that server.
3. A browser window opens and navigates to Microsoft's
/authorizeendpoint. The observed request URL was:Note there is no
scope=parameter anywhere in this URL.4. Entra ID immediately rejects the request:
Expected behavior
The MCP OAuth client should build the
scopeparameter for the/authorizerequest (and again for the/tokenexchange) from the target server's advertisedscopes_supported(from either theoauth-authorization-serveroroauth-protected-resourcemetadata document), the same way it presumably does for servers that use Dynamic Client Registration. For Entra ID specifically,scopemust be present on every leg of the flow (authorize request, token exchange, and refresh), since Entra ID's v2.0 endpoint treatsscopeas mandatory rather than optional.Additional context
authorization_servers, byte-for-byte, across 15 parallel requests) before this bug surfaced, ruling out a server-side metadata problem.oauthClientId/oauthPublicClient: trueand skips theregistration_endpoint(Dynamic Client Registration) flow — DCR responses may carry scope information that the static-client path doesn't otherwise obtain fromscopes_supported..default+ resource-specific scopes), forcing repeated interactive sign-in #4464 (refresh-token grant mishandles Entra ID scope, AADSTS70011), Copilot CLI 1.0.79 rejects GitLab MCP OAuth metadata with an RFC 8414 issuer mismatch #4439 / Atlassian MCP OAuth fails with "Incompatible authorization server (RFC 8414 §3.3)" on 1.0.79 — regression from 1.0.71 #4480 (separate RFC 8414 issuer-mismatch bugs, now fixed/in progress).