MCP authorization reference

MCP dynamic client registration without a shared secret

How an MCP server accepts RFC 7591 registration from clients it has never met, which fields to reject, and why the only safe answer for a desktop agent is a public PKCE client.

Updated July 2026Implementation guidemcp dynamic client registration
Built for

Engineers whose MCP server must work with clients they cannot pre-provision.

Decision supported

Whether to support dynamic client registration, and how to accept it without creating an unauthenticated way to mint credentials.

The control gap

MCP clients are installed by end users, not by your administrators. Claude Desktop, an IDE extension, and a colleague's script all arrive without a client identifier, and there is no realistic way to issue one in advance. RFC 7591 solves the introduction, but a naive registration endpoint is an open door: anything on the internet can create client records, and a client that asks for a secret gets one it cannot protect on a laptop.

What good looks like

Unknown clients can register, but only as public clients using PKCE, with redirect URIs validated at registration and again at authorization, and with the registration record carrying no authority of its own until a human completes consent.

  • Accept only token_endpoint_auth_method none. A desktop or browser client cannot hold a secret, so issuing one creates a false sense of client authentication.
  • Require PKCE with S256 at the authorization endpoint and reject plain, so an intercepted authorization code is useless.
  • Validate every redirect URI at registration: no wildcards, no open redirectors, and loopback only on the forms the client genuinely needs.
  • Treat a registered client as an identity, not a permission. Authority arrives only when a named user completes consent for a named resource.

A production workflow

  1. The client discovers the registration endpoint from authorization server metadata.
  2. It posts its name, redirect URIs, and grant types, and receives a client identifier with no secret.
  3. It runs the authorization code flow with PKCE and the resource parameter for the specific MCP endpoint.
  4. The user consents, the token is bound to that user, that client, and that resource, and every later tool call is evaluated against the consent that produced it.

Copy this

This is the exchange Endram accepts at /oauth/register. Anything asking for a secret, a confidential auth method, or an unsupported grant is refused rather than downgraded silently.

POST /oauth/register
Content-Type: application/json

{
  "client_name": "Acme Desktop Agent",
  "redirect_uris": ["http://127.0.0.1:33418/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "none"
}

HTTP/1.1 201 Created
{
  "client_id": "tfc_...",
  "client_name": "Acme Desktop Agent",
  "redirect_uris": ["http://127.0.0.1:33418/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

# What the authorization server advertises, so the client knows this is available
GET /.well-known/oauth-authorization-server
{
  "registration_endpoint": "https://endram.com/oauth/register",
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "authorization_response_iss_parameter_supported": true
}

Note what is absent. There is no client_credentials grant and no client secret. A registration record on its own cannot call a tool, which is what keeps an open registration endpoint from being an open credential endpoint.

Evidence to require

  • Every registration, with the submitted client name, redirect URIs, and the identifier issued.
  • Which registered clients have ever completed consent, and which never progressed past registration.
  • The user, resource, and scope attached to each consent, and its expiry.
  • Rejected registrations and the field that caused the rejection.

Buyer checklist

  • Can a registered client do anything at all before a user consents?
  • Are redirect URIs re-validated at authorization time, not only at registration?
  • Is there a rate limit and a retention policy for registrations that never lead to consent?
  • Can an operator see which client a given token belongs to when investigating an unexpected tool call?

Practical answers

Common implementation questions

Is dynamic client registration safe to expose publicly?

It is safe when a registration confers no authority. The risk is not the record; it is issuing secrets or standing grants at registration time. Keep the endpoint public, keep it PKCE-only, and put the authority behind user consent.

What if a client insists on a client secret?

Endram refuses any token_endpoint_auth_method other than none. A confidential client running on a user device is a secret in a config file, and treating it as authentication misrepresents the security of the flow.

How do we stop registration spam?

Rate limit by source, expire registrations that never reach consent, and alert on bursts. Because a bare registration grants nothing, spam is a storage and hygiene problem rather than a security incident.

Continue the evaluation

Related controls