vercel/ai · error

Incompatible auth server: does not support dynamic client re

Error message

Incompatible auth server: does not support dynamic client registration

What it means

registerClient performs OAuth dynamic client registration (RFC 7591). When authorization server metadata is available, it requires a registration_endpoint; if the metadata has none, the server does not support dynamic registration and the function throws. Callers must supply pre-registered client information instead.

Source

Thrown at packages/mcp/src/tool/oauth.ts:1115

 * Performs OAuth 2.0 Dynamic Client Registration according to RFC 7591.
 */
export async function registerClient(
  authorizationServerUrl: string | URL,
  {
    metadata,
    clientMetadata,
    fetchFn,
  }: {
    metadata?: AuthorizationServerMetadata;
    clientMetadata: OAuthClientMetadata;
    fetchFn?: FetchFunction;
  },
): Promise<OAuthClientInformationFull> {
  let registrationUrl: URL;

  if (metadata) {
    if (!metadata.registration_endpoint) {
      throw new Error(
        'Incompatible auth server: does not support dynamic client registration',
      );
    }

    registrationUrl = new URL(metadata.registration_endpoint);
  } else {
    registrationUrl = new URL('/register', authorizationServerUrl);
  }
  assertSafeOAuthEndpoint(registrationUrl);

  const applicationType =
    clientMetadata.application_type ??
    inferOAuthApplicationType(clientMetadata.redirect_uris);
  const response = await (fetchFn ?? fetch)(registrationUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Manually register a client in the AS admin console and return it from provider.clientInformation() so dynamic registration is skipped.
  2. Enable the dynamic client registration plugin/feature on the authorization server if you control it.
  3. Verify the metadata is being fetched from the correct AS (a fallback to the MCP server itself as AS may lack a registration endpoint).
  4. If the AS publishes a registration_endpoint via a different discovery document, fix the discovery URL configuration.

Example fix

// before: relying on dynamic registration
class MyProvider { async clientInformation() { return undefined; } }
// after: supply a statically registered client
class MyProvider {
  async clientInformation() {
    return { client_id: process.env.OAUTH_CLIENT_ID, client_secret: process.env.OAUTH_CLIENT_SECRET };
  }
}
Defensive patterns

Strategy: validation

Validate before calling

const metadata = await discoverAuthorizationServerMetadata(asUrl);
if (metadata && !metadata.registration_endpoint && !(await provider.clientInformation())) {
  throw new Error('Register a client manually; this AS has no registration_endpoint');
}

Type guard

function supportsDynamicRegistration(m: { registration_endpoint?: string } | undefined): boolean {
  return typeof m?.registration_endpoint === 'string' && m.registration_endpoint.length > 0;
}

Try / catch

try {
  await auth(provider, { serverUrl });
} catch (error) {
  if (String(error.message).includes('does not support dynamic client registration')) {
    console.error('Provide pre-registered client credentials via provider.clientInformation().');
  }
}

Prevention

When it happens

Trigger: Calling registerClient (or auth() when provider.clientInformation() returns nothing) against an AS whose metadata omits registration_endpoint.

Common situations: Enterprise IdPs (e.g. Azure AD/Entra, many SAML-first providers) that require manual/static client registration, or OAuth servers where dynamic registration is disabled by policy.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/149c2929381739b9. Report an issue: GitHub.