Zuplo
MCP error

Dynamic Client Registration not supported

The MCP client reached your authorization server's metadata and found no way to obtain a client ID — no registration endpoint, no Client ID Metadata Document support, and none configured in the client — so it stopped before the OAuth flow began.

MCP Specification
2026-07-28

Is this you?

The error names registration, so read the authorization server's own metadata and see which of the three registration paths it actually offers. Two steps: find the authorization server from the 401, then read its metadata. If /.well-known/oauth-authorization-server returns 404, try /.well-known/openid-configuration — the 2025-11-25 spec accepts either, and some providers, Amazon Cognito among them, publish only the OpenID Connect document.

TerminalRun this to check — it changes nothing
# 1. Which authorization server? Read it out of the 401.
curl -sS -D - -o /dev/null -X POST https://your-server.example.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | grep -i '^www-authenticate'

# 2. Ask that authorization server how a client is meant to identify itself.
curl -sS https://your-idp.example.com/.well-known/oauth-authorization-server \
  | jq '{registration_endpoint,
         client_id_metadata_document_supported,
         token_endpoint_auth_methods_supported}'
This error
Both registration_endpoint and client_id_metadata_document_supported come back null. Or registration_endpoint is advertised and POSTing to it returns 401/403 (Okta without the okta.clients.register scope, Keycloak with no trusted host) or 404 (advertised but never served). client_id_metadata_document_supported: true with no "none" in token_endpoint_auth_methods_supported fails the same way: Claude documents that it then falls back to registration, which is exactly the error you are reading.
Then the fix is the next section.
Working
Either a registration_endpoint that answers an unauthenticated POST with 201 and a client_id, or client_id_metadata_document_supported: true together with "none" in token_endpoint_auth_methods_supported. One is enough. A client id you pre-registered and configured in the client is also a pass — then the metadata does not have to offer anything.
Then this is not your problem — try the error reference.
6 other strings clients print for this
  • Incompatible auth server: does not support dynamic client registration
  • The authorization server '<url>' does not support automatic client registration. Do you want to proceed by manually providing a client registration (client ID)?
  • Automatic client registration isn't supported by <connector>. Edit the connector and add an OAuth Client ID.
  • Couldn't register with <connector>'s sign-in service. You can try again, or add an OAuth Client ID in the connector settings.
  • Dynamic client registration failed: HTTP 422
  • {"error":"invalid_client_metadata","error_description":"Dynamic registration is not available for this client."}

Dotted spans such as <url> are placeholders — your client prints your own value there.

Fix it

Create the OAuth client in your identity provider by hand and give the MCP client the resulting id: oauth.clientId in mcp.json for VS Code, the OAuth Client ID field on a Claude custom connector, claude mcp add --client-id for Claude Code. Registration is optional in the 2025-11-25 spec, so a provider without it is not out of spec — Microsoft Entra ID and Amazon Cognito have no registration endpoint at all, and Okta, Auth0 and Keycloak ship theirs off or gated by default. If you would rather not pre-register an app for every client that connects, put an authorization server in front of the MCP route that accepts RFC 7591 registration or Client ID Metadata Documents itself.

Have your agent fix this

Copies a prompt that sends your coding agent to this page, then has it find and apply the right fix for your project.

The cause depends on your platform. Pick yours.

Microsoft Entra ID

If your authorization server is Microsoft Entra ID

  1. 1 Entra ID has no registration endpoint, and Microsoft's own MCP guidance says so plainly: many providers do not support Dynamic Client Registration, Entra ID among them, and where it is unavailable the client has to be preconfigured with a client ID.
  2. 2 Create an app registration for the MCP server and expose at least one delegated scope on it — api://<client-id>/user_impersonation is what App Service creates for you. Then add the MCP client's own Entra application id to preAuthorizedApplications for that scope. Skip the pre-authorization and a client that never surfaces an interactive login, such as GitHub Copilot in VS Code, fails on consent instead of on registration.
  3. 3 Give the client that pre-registered client id: oauth.clientId in mcp.json for VS Code, the OAuth Client ID field on a Claude custom connector, claude mcp add --client-id for Claude Code.
JSONjsonc
// .vscode/mcp.json
{
  "servers": {
    "my-server": {
      "type": "http",
      "url": "https://your-server.example.com/mcp",
      "oauth": { "clientId": "00000000-1111-2222-3333-444444444444" }
    }
  }
}
Microsoft Learn: MCP server authorization

Okta

If your authorization server is Okta

  1. 1 Okta does implement RFC 7591, and its authorization server metadata advertises a registration_endpoint of https://{yourOktaDomain}/oauth2/v1/clients — so the client will try registration rather than skip it. The POST is then rejected, because Okta documents that endpoint as requiring the okta.clients.register scope. There is no anonymous registration.
  2. 2 Create the OAuth app in Okta yourself and register every redirect URI the client will actually use. VS Code requires two: http://127.0.0.1:33418 and https://vscode.dev/redirect. Hosted Claude surfaces use https://claude.ai/api/mcp/auth_callback. Claude Code takes a loopback redirect on an ephemeral port, so pin the port with claude mcp add --callback-port 8080 and register http://localhost:8080/callback rather than trying to allow every port.
  3. 3 Hand that client id to the client. You can instead stand up a /register shim that forwards to Okta with your API token attached, and people do — but then every MCP client that reaches your server mints a real app in your Okta org, and you own that lifecycle.
Okta: Dynamic Client Registration API

Auth0

If your authorization server is Auth0

  1. 1 Auth0 accepts open registration at POST /oidc/register with no access token, but the tenant flag is off to begin with: Auth0 documents Dynamic Client Registration as disabled by default for all tenants. Enable it at Dashboard > Settings > Advanced, or PATCH /api/v2/tenants/settings with the enable_dynamic_client_registration flag.
  2. 2 Enabling it is not sufficient. Every app created by registration is a third-party application with a tpc_ client id prefix, and Auth0 is explicit that without default permissions such a client can access no API at all. Configure default permissions for third-party applications on the API your MCP server represents before you turn registration on, or registration succeeds and every tool call still comes back unauthorized.
  3. 3 If registration used to work and stopped, check the two limits rather than the flag: /oidc/register is rate-limited to 5 requests per second per tenant, and a Tenant Access Control List rule carrying the dcr scope can block requests to it. Note also that clients created this way only get authorization_code and refresh_tokenclient_credentials is not available through registration.
Terminalbash
curl --request PATCH \
  --url 'https://{yourDomain}/api/v2/tenants/settings' \
  --header 'authorization: Bearer {YOUR_MANAGEMENT_API_TOKEN}' \
  --header 'content-type: application/json' \
  --data '{ "flags": { "enable_dynamic_client_registration": true } }'
Auth0: Dynamic Client Registration

Keycloak

If your authorization server is Keycloak

  1. 1 Keycloak implements OIDC Dynamic Client Registration at /realms/<realm>/clients-registrations/openid-connect and advertises it in the realm's /.well-known/openid-configuration, so the client tries it. What an MCP client needs is the anonymous form, and Keycloak ships that off: the docs state that the Trusted Hosts policy whitelists no host by default, which leaves anonymous client registration de-facto disabled.
  2. 2 Either add the client's hosts and redirect-URI domains under Clients > Client registration > Client Registration Policies > Trusted Hosts, or create the client in the admin console and give the MCP client its client id. Trusted Hosts also constrains the redirect URIs a registered client may use, so a desktop client redirecting to loopback will not pass a policy scoped to public hostnames.
  3. 3 Two more anonymous-registration policies bite after Trusted Hosts. Max Clients Policy rejects registration once the realm holds 200 clients, which is the default for anonymous registrations. Client Scope Policy whitelists only the realm's default client scopes, so a client requesting the scope you defined for the MCP server is refused until you whitelist it.
Keycloak: client registration service

Amazon Cognito

If your authorization server is an Amazon Cognito user pool

  1. 1 Cognito has no registration endpoint to advertise. AWS's endpoint reference for a user pool covers /oauth2/authorize, /oauth2/token, /oauth2/userInfo, /oauth2/revoke, the IdP-response and SAML endpoints, and OIDC discovery — no registration endpoint appears on it. Discovery is OIDC only, and it sits on a different host from the rest: https://cognito-idp.<region>.amazonaws.com/<user-pool-id>/.well-known/openid-configuration. There is no RFC 8414 document, so a client that probes only /.well-known/oauth-authorization-server finds nothing at all.
  2. 2 Create an app client per MCP client, with that client's callback URL and no secret — MCP clients are public clients using PKCE. Mind the constraint AWS documents on callback URLs: HTTPS is required, and http://localhost is the only exception, so a client whose redirect is an IP loopback — VS Code requires http://127.0.0.1:33418 — falls outside it.
  3. 3 Put the returned client id in the client's config. If you need one client identity to cover many MCP clients, put an authorization server in front of the MCP route instead of writing a /register shim that calls CreateUserPoolClient: a shim hands anyone who can reach it the ability to create app clients in your pool.
Terminalbash
aws cognito-idp create-user-pool-client \
  --user-pool-id us-east-1_EXAMPLE \
  --client-name "Claude connector" \
  --no-generate-secret \
  --callback-urls "https://claude.ai/api/mcp/auth_callback" \
  --allowed-o-auth-flows code \
  --allowed-o-auth-scopes openid profile \
  --allowed-o-auth-flows-user-pool-client
AWS: user pool endpoints

Zuplo MCP Gateway

If your identity provider has no dynamic registration and you do not want to pre-register an app for every client that connects

  1. 1 For its MCP routes the gateway is both the OAuth 2.1 resource server and the authorization server. It accepts RFC 7591 registration at /oauth/register, and with CIMD enabled it advertises client_id_metadata_document_supported: true and accepts URLs as client_id values — so a client registers dynamically or presents a Client ID Metadata Document URL, and either works.
  2. 2 Browser identity is delegated to an OIDC identity provider you configure: Auth0, Okta, or any provider with OIDC discovery. The identity provider authenticates the user; the gateway then issues its own bearer token to the MCP client. The identity provider never sees the MCP client and never has to issue it a client id, so its lack of registration stops being the blocker.
  3. 3 On the upstream side the gateway is the OAuth client: clientRegistration: { mode: "auto" } publishes a per-upstream Client ID Metadata Document and falls back to RFC 7591 if the upstream will not accept a URL client id; mode: "manual" uses a pre-registered clientId and clientSecret for upstreams that require an approved client.
Zuplo MCP Gateway: authorization

Something else

Whatever your authorization server is, the fix has three shapes and you need only one of them. Pre-register the OAuth client and configure its client_id in the MCP client. Support Client ID Metadata Documents, so the client can present a URL instead of an id it had to be given. Or put something in front of the MCP route that owns client registration itself, and delegate user identity to your provider behind it. Read the metadata document from the curl above and pick the shape your provider can do today — and if it advertises a registration_endpoint that returns 401 or 403, the endpoint is gated rather than missing, so the setting to find is whichever policy decides who may register. Discount any advice that calls your provider non-conformant for lacking registration: it was a SHOULD in the 2025-06-18 revision and is a MAY in 2025-11-25.

Why it happens

The 2025-11-25 authorization spec says a client supporting every option SHOULD try them in this order: a client_id it already holds, then a Client ID Metadata Document if the authorization server advertises client_id_metadata_document_supported, then RFC 7591 registration if it advertises a registration_endpoint, and failing all three, prompt the user to enter the client information. When the metadata offers neither mechanism and no static client id is configured, that prompt is the whole remaining path — which is why VS Code asks and most other clients only report the error. Enterprise identity providers are the usual cause: they issue client ids through an admin console, and RFC 7591 open registration means an unauthenticated POST that creates a real OAuth client. The quieter shape of the same failure is a registration_endpoint that is advertised but protected — the client dutifully POSTs to it and gets back 401, 403 or 404.

The exchange

Each step in the exchange, in order.

  • MCP client no client_id yet
  • MCP server
  • Authorization server enterprise IdP
  • Browser user consent
  1. MCP client to MCP server

    POST /mcp no Authorization header
  2. MCP server to MCP client

    401 Unauthorized WWW-Authenticate: Bearer resource_metadata=…
  3. The client is checking the three ways it can get a client id: one you pre-registered and configured, a Client ID Metadata Document, or RFC 7591 registration. This metadata offers none of them.

    MCP client to Authorization server

    GET …/oauth-authorization-server
  4. Authorization server to MCP client

    200 OK no registration_endpoint, no CIMD
  5. VS Code offers to take a client id by hand at this point. Most other clients only report the error.

    Inside MCP client

    Nothing to put in client_id no pre-registered client id either

    Flow stops here — Browser not reached

The MCP client posts to the server with no credentials and gets a correct 401 pointing at the server's protected resource metadata, which names the authorization server. It reads that authorization server's metadata and finds no registration endpoint and no Client ID Metadata Document support, and it has no client id of its own, so the flow stops there. /authorize is never called, so no consent screen opens and no token is minted.
Zuplo

What lands on you next

Registration was the gate. Past it the questions stop being "can this client connect" and start being "what may it do, and what did it do."

The client is registered. Which of our tools can it now call?

mcp-capability-filter-inbound

A registered client is an authenticated client, not an authorized one. The filter allow-lists capabilities per route and blocks a hidden tool with MethodNotFound before the request is forwarded.

That client id is in six places now. Which one made this call?

capability_invocation

Each event carries the client and the caller alongside the capability and the outcome, so a bad call resolves to a client and a user rather than to a shared IP.

This token works. Can it be replayed against our other MCP route?

RFC 8707 resource indicators

No. A gateway-issued token is bound to one route's canonical resource URI, so a token minted for one MCP route is rejected at another.

Can I just forward that token to the API behind the server?

mcp-token-exchange-inbound

The spec forbids passthrough with a MUST NOT. Inbound auth headers are stripped and an independent upstream credential is minted per user or per gateway.

All of these attach to one MCP route's policies.inbound — the same policy engine on the way in and on the way out.

Stop debugging auth on every MCP server

A gateway in front of your MCP servers handles discovery, audience binding, and token validation once — for every server and every client.