Share via

MCP Client Ignores authorization_servers Path from oauth-protected-resource Metadata - Always Resolves Well-Known Endpoints Against APIM Root Domain

Cesare Farina Busetto 0 Reputation points
2026-05-28T09:24:06.6266667+00:00

Environment

Component Detail
Gateway Azure API Management (Basic v2)
MCP Client VS Code (GitHub Copilot) and Claude Desktop
Auth spec MCP Authorization
Transport Streamable HTTP

Background

I deployed APIs and operations on an existing Azure API Management instance to act as the resource server for a remote MCP server endpoint, with OAuth 2.0 discovery implemented following the MCP Authorization spec (2025-03-26), RFC 9728 (Protected Resource Metadata), and RFC 8414 (Authorization Server Metadata).

The intended discovery flow is:

1. Client → POST https://example.azure-api.net/mcp
   ← 401 Unauthorized
      WWW-Authenticate: Bearer realm="...",
                        resource_metadata="https://example.azure-api.net/my-path/.well-known/oauth-protected-resource"

2. Client → GET https://example.azure-api.net/my-path/.well-known/oauth-protected-resource
   ← 200 OK
      {
        "resource": "https://example.azure-api.net/mcp",
        "authorization_servers": ["https://example.azure-api.net/my-path"]
      }

3. Client → GET https://example.azure-api.net/my-path/.well-known/oauth-authorization-server
   ← 200 OK  (expected — but this step never happens)

Problem

Steps 1 and 2 work correctly. The /.well-known/oauth-protected-resource endpoint is called and returns HTTP 200 with the correct JSON body, including "authorization_servers": ["https://example.azure-api.net/my-path"].

However, in step 3, instead of deriving the Authorization Server Metadata URL from the declared authorization_servers value, the client appears to strip the path prefix and resolve the well-known endpoint against the root domain only:

# Expected (per RFC 8414 §3 + RFC 9728):
GET https://example.azure-api.net/my-path/.well-known/oauth-authorization-server

# Actual (observed in both VS Code and Claude Desktop):
GET https://example.azure-api.net/.well-known/oauth-authorization-server

The path component (/my-path) from the declared authorization server URL is being ignored entirely.


What I Have Verified

  • The /.well-known/oauth-protected-resource endpoint returns HTTP 200
  • The response body contains a valid authorization_servers array with the full URL including path
  • The Content-Type header is application/json
  • The APIM policy correctly exposes both well-known endpoints under the /my-path prefix
  • The behavior is reproducible with both VS Code (GitHub Copilot MCP) and Claude Desktop

Questions

  1. Is this a known limitation or bug in current MCP client implementations (VS Code / Claude Desktop) where the path component of authorization_servers is not respected when constructing the /.well-known/oauth-authorization-server URL?
  2. Is there a recommended APIM topology or naming convention that avoids subpaths in the authorization server URL (e.g., keeping everything at the root domain) to work around this behavior?
  3. Has anyone successfully configured APIM with a non-root authorization server prefix for MCP OAuth discovery?
Azure API Management
Azure API Management

An Azure service that provides a hybrid, multi-cloud management platform for APIs.


1 answer

Sort by: Most helpful
  1. AI answer

    2026-05-28T09:24:52.61+00:00

    The behavior described matches current MCP client behavior when used with Microsoft Entra–protected resources and is effectively a client limitation: the clients don’t fully honor arbitrary authorization_servers paths from the protected resource metadata and instead probe well-known endpoints in a fixed way.

    From the documented MCP server authorization flow with Microsoft Entra ID:

    1. The MCP client (VS Code / GitHub Copilot) sends an initialization request.
    2. The MCP server responds with an authorization error that includes a pointer to Protected Resource Metadata (PRM).
    3. The client fetches the PRM and uses it to identify the authorization server.
    4. The client then attempts to obtain Authorization Server Metadata (ASM) from a well-known endpoint on the authorization server.
    5. Because Microsoft Entra ID does not support ASM on the “expected” well-known endpoint, the client falls back to the OpenID Connect metadata endpoint and tries multiple patterns, including inserting the well-known segment before or after path information, until it finds the working location.

    In other words, current MCP clients implement a hard-coded discovery strategy tailored to Microsoft Entra ID rather than a generic RFC 9728 / RFC 8414 implementation that strictly respects arbitrary path components in authorization_servers. The documentation explicitly notes that:

    • The client first tries a well-known endpoint pattern that Entra does not support.
    • It then falls back to the OpenID Connect metadata endpoint and adjusts the path ordering to match where Entra actually hosts it.

    This is consistent with what is observed: the client effectively normalizes discovery against the base authority and then probes well-known endpoints, instead of using the full path from authorization_servers as a strict base URL.

    Given the available information, the practical guidance is:

    1. Treat this as a client limitation rather than an APIM misconfiguration.
    2. Align the topology with what current MCP clients expect:
      • Expose the protected resource metadata and authorization server metadata in a way that works when the client resolves well-known endpoints relative to the root authority (host) rather than a subpath.
      • Avoid relying on non-root path prefixes in the authorization_servers URL for discovery, because the clients may ignore or reorder that path.
    3. When integrating with Microsoft Entra ID, follow the documented pattern used by Azure App Service and Azure Functions MCP samples, which rely on:
      • A PRM endpoint at /.well-known/oauth-protected-resource.
      • Client-side logic that falls back to the OpenID Connect metadata endpoint hosted by Entra ID (with the well-known segment after path information) instead of a custom subpath on the resource server.

    There is no example in the provided material of a successful MCP configuration that uses a non-root authorization server prefix behind APIM; all documented flows assume discovery against the standard well-known locations associated with the Entra authority rather than a custom APIM subpath.

    For a robust workaround with today’s clients, design the APIM surface so that:

    • The PRM endpoint is reachable at the standard well-known location for the resource host.
    • The authorization_servers value points to an authority whose metadata is available at the standard OpenID Connect / OAuth well-known locations without requiring additional path prefixes.

    References:

    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.