Skip to content

50% off your first year. Join before 2027. Claim →

Publish authorization server metadata

This check verifies that your authorization server publishes its metadata, and that the metadata’s issuer is the URL listed in your protected resource metadata.

Check id server_metadata (server metadata). Results:

pass fail skipped

The authorization server metadata tells an agent where the sign-in page and the token endpoint are, and which features the server supports, such as PKCE and client registration. Without it, the agent knows which authorization server to use but cannot talk to it.

The issuer field is a safety check. An agent builds the metadata URL from the issuer it found in authorization_servers, and rejects a document whose issuer is a different URL, so that a server cannot pose as another one.

  • The MCP authorization specification requires authorization servers to publish RFC 8414 metadata or OpenID Connect Discovery, requires clients to try both at fixed URLs, and requires them not to use a document whose issuer differs from the issuer they started from (MCP: Authorization server metadata discovery).
  • Claude needs either form at the authorization server’s /.well-known/ paths, reachable from Anthropic’s published network range (Claude: Authentication for connectors).
  • ChatGPT reads authorization_endpoint, token_endpoint and the other capabilities from this document, and expects issuer to be the exact value in authorization_servers (OpenAI: Authentication).

Other agents follow the MCP specification; MCP Tower has not verified them.

The check runs after authorization servers passes and uses the first entry of authorization_servers. Without it, the check is skipped with “Needs the protected resource metadata.” or “Needs an authorization server.”

  1. MCP Tower requests these URLs in order and stops at the first that answers 200 with JSON of at most 64 KB, with the same rules as the protected resource metadata lookup. For the issuer https://auth.example.com/tenant1:

    • https://auth.example.com/.well-known/oauth-authorization-server/tenant1 (RFC 8414);
    • https://auth.example.com/.well-known/openid-configuration/tenant1 (OpenID Connect, path inserted);
    • https://auth.example.com/tenant1/.well-known/openid-configuration (OpenID Connect, path appended).

    For an issuer without a path, such as https://auth.example.com, only the first two are tried, without the suffix.

  2. If no URL works, the result is fail. The message lists each URL with its outcome, as on the protected resource metadata page: HTTP <status>, or an error class such as dns_error or timeout.

  3. MCP Tower compares the document’s issuer with the listed issuer, ignoring only a trailing /. A difference is fail. MCP Tower does not try the remaining URLs after a document that parses, so a wrong issuer in the first document fails even if a later URL is correct.

  4. Otherwise the result is pass. After a failure, the later discovery checks are skipped with “Needs the authorization server metadata.” or “Needs valid authorization server metadata.”

StatusMessageMeaningFix
passAuthorization server metadata found.Agents can read your endpoints and capabilities.
failNo authorization server metadata was found for <issuer>. Tried: <url> (<outcome>), <url> (<outcome>).None of the URLs served a JSON document.Publish the metadata
failThe metadata’s issuer “<issuer>” does not match “<listed issuer>”, the URL it was fetched for.The document names another issuer.Make issuer match the listed URL
skippedNeeds the protected resource metadata. / Needs an authorization server.An earlier discovery check failed.Authorization servers

The next step for the first failure is: “Publish RFC 8414 metadata at /.well-known/oauth-authorization-server, or OpenID discovery.” For the second it is: “Make issuer in the authorization server metadata equal the URL listed in authorization_servers.”

  1. Serve the metadata at the RFC 8414 URL for your issuer, such as https://auth.example.com/.well-known/oauth-authorization-server. An OpenID Connect provider can serve /.well-known/openid-configuration instead.
  2. Answer 200 with JSON and no sign-in, from a host agents can reach.
  3. Include at least issuer, authorization_endpoint, token_endpoint, code_challenge_methods_supported and the client registration fields your server supports.
https://auth.example.com/.well-known/oauth-authorization-server
{
"issuer": "https://auth.example.com",
"authorization_endpoint": "https://auth.example.com/authorize",
"token_endpoint": "https://auth.example.com/token",
"registration_endpoint": "https://auth.example.com/register",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none", "client_secret_basic"],
"client_id_metadata_document_supported": true,
"authorization_response_iss_parameter_supported": true,
"scopes_supported": ["mcp:tools"]
}

The later checks cover the fields: endpoints, PKCE and client identity.

  1. Compare the issuer in the document with the first entry of authorization_servers. They must be the same string: scheme, host, port and path.
  2. Change whichever one is wrong. Usually authorization_servers should change, to the issuer your authorization server already uses, because tokens carry that value in their iss claim.
  3. If your authorization server serves several tenants, list the issuer of the tenant, with its path, and check that the tenant’s document names that same issuer.

MCP Tower never rewrites authorization server metadata. Agents talk to your authorization server at its own URL, and the issuer, the endpoints and authorization_servers pass through as they are. The issuer must match the iss claim in the tokens the authorization server signs, and rewriting it would break token validation. If your authorization server runs on your origin host, such as https://origin.example.com, list that URL as the issuer, and make sure agents can reach it there.

Read the issuer from your protected resource metadata, then fetch its metadata:

Terminal window
ISSUER=$(curl -s https://mcp.example.com/.well-known/oauth-protected-resource/mcp | jq -r '.authorization_servers[0]')
curl -si "$ISSUER/.well-known/oauth-authorization-server" -H 'Accept: application/json'

For an issuer with a path, insert /.well-known/oauth-authorization-server between the host and the path. The problem is fixed when the response is 200 and its issuer equals $ISSUER:

HTTP/1.1 200 OK
Content-Type: application/json
{"issuer":"https://auth.example.com","authorization_endpoint":"https://auth.example.com/authorize","token_endpoint":"https://auth.example.com/token","code_challenge_methods_supported":["S256"]}

Then select Scan again on the server’s page.