Skip to content

Copilot CLI 1.0.79 rejects GitLab MCP OAuth metadata with an RFC 8414 issuer mismatch #4439

Description

@patrickzel

Describe the bug

Copilot CLI 1.0.79 rejects GitLab MCP OAuth metadata due to an RFC 8414 issuer mismatch

Describe the bug

GitHub Copilot CLI 1.0.79 fails to authenticate against a GitLab Self-Managed MCP server that uses OAuth 2.0 Dynamic Client Registration.

The CLI reports:

Authentication failed: MCPOAuthError: Incompatible authorization server:
authorization server advertised an issuer that does not match the URL
its metadata was discovered from (RFC 8414 Section 3.3). Refusing to connect.

The authorization server identifier advertised by GitLab and the issuer returned by its authorization server metadata are identical.

The same GitLab MCP configuration worked before upgrading Copilot CLI to version 1.0.79.

Affected version

GitHub Copilot CLI 1.0.79

Operating system:

Windows

MCP configuration

{
  "mcpServers": {
    "GitLab": {
      "type": "http",
      "url": "https://gitlab.example.com/api/v4/mcp",
      "headers": {},
      "tools": [
        "*"
      ]
    }
  }
}

Actual behavior

Copilot CLI rejects the authorization server metadata with the following error:

MCPOAuthError: Incompatible authorization server:
authorization server advertised an issuer that does not match the URL
its metadata was discovered from (RFC 8414 Section 3.3). Refusing to connect.

Protected resource metadata

The GitLab protected resource metadata endpoint returns:

GET https://gitlab.example.com/.well-known/oauth-protected-resource/api/v4/mcp

Response:

{
  "resource": [
    "https://gitlab.example.com/api/v4/mcp"
  ],
  "authorization_servers": [
    "https://gitlab.example.com"
  ],
  "scopes_supported": [
    "mcp"
  ]
}

The protected resource metadata identifies the authorization server as:

https://gitlab.example.com

Authorization server metadata

The resource-specific authorization server metadata endpoint returns:

GET https://gitlab.example.com/.well-known/oauth-authorization-server/api/v4/mcp

Response excerpt:

{
  "issuer": "https://gitlab.example.com",
  "authorization_endpoint": "https://gitlab.example.com/oauth/authorize",
  "token_endpoint": "https://gitlab.example.com/oauth/token",
  "registration_endpoint": "https://gitlab.example.com/oauth/register",
  "scopes_supported": [
    "mcp"
  ],
  "response_types_supported": [
    "code"
  ],
  "grant_types_supported": [
    "authorization_code",
    "client_credentials",
    "device_code",
    "refresh_token"
  ],
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ]
}

The metadata document returns the following issuer:

https://gitlab.example.com

This exactly matches the authorization server identifier advertised by the protected resource metadata:

https://gitlab.example.com

No redirect or external URL mismatch

The MCP endpoint is reachable and returns the expected unauthenticated response:

HEAD https://gitlab.example.com/api/v4/mcp

HTTP/1.1 401 Unauthorized

The authorization server metadata endpoint is also reachable without a redirect:

HEAD https://gitlab.example.com/.well-known/oauth-authorization-server

HTTP/1.1 200 OK

The public GitLab URL, MCP resource URL, authorization server identifier, OAuth endpoints, and issuer all use the same scheme and host.

Successful test with mcp-remote

The same GitLab MCP endpoint and OAuth Dynamic Client Registration flow work successfully through mcp-remote:

npx -y mcp-remote@latest `
  "https://gitlab.example.com/api/v4/mcp" `
  --static-oauth-client-metadata '{"scope":"mcp"}' `
  --debug

This command successfully performs the OAuth flow and connects to the GitLab MCP server.

The successful test confirms that the following components are operational:

  • GitLab MCP endpoint
  • Protected resource metadata discovery
  • Authorization server metadata discovery
  • OAuth Dynamic Client Registration
  • The mcp scope
  • Browser authorization
  • Token exchange
  • TLS and reverse proxy configuration

Only the native HTTP MCP transport in Copilot CLI 1.0.79 fails.

Working workaround

Using mcp-remote through the stdio transport works:

{
  "mcpServers": {
    "GitLab": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote@latest",
        "https://gitlab.example.com/api/v4/mcp",
        "--static-oauth-client-metadata",
        "{\"scope\":\"mcp\"}"
      ],
      "tools": [
        "*"
      ]
    }
  }
}

Suspected cause

Copilot CLI may be comparing the returned issuer against the MCP resource identifier:

https://gitlab.example.com/api/v4/mcp

instead of comparing it against the authorization server identifier advertised by the protected resource metadata:

https://gitlab.example.com

The /api/v4/mcp path identifies the protected MCP resource. It is not part of the authorization server issuer.

Another possibility is that the CLI derives the expected issuer incorrectly from the resource-specific authorization server metadata URL:

https://gitlab.example.com/.well-known/oauth-authorization-server/api/v4/mcp

The metadata document is resource-specific, but the returned issuer correctly identifies the authorization server as:

https://gitlab.example.com

Regression

The same GitLab instance and MCP configuration worked before Copilot CLI was upgraded to version 1.0.79.

No changes were made to GitLab, the reverse proxy, TLS, DNS, or the MCP configuration when the issue started.

Related issues

This issue may be related to the OAuth and MCP metadata handling described in:

This reproduction specifically concerns GitLab Self-Managed, OAuth Dynamic Client Registration, and RFC 8414 issuer validation in the native HTTP MCP transport.

Affected version

GitHub Copilot CLI 1.0.79

Steps to reproduce the behavior

  1. Configure a GitLab Self-Managed MCP server using the native HTTP transport as shown above.
  2. Start GitHub Copilot CLI 1.0.79.
  3. Open /mcp.
  4. Select the GitLab MCP server and start authentication.
  5. Observe that authentication fails before the browser authorization flow begins.

Expected behavior

Copilot CLI should accept the authorization server metadata because the authorization server identifier advertised by the protected resource metadata matches the issuer returned by the authorization server metadata.

The CLI should then continue with OAuth Dynamic Client Registration and the browser authorization flow.

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions