· by tcp3

    DCR is deprecated: what CIMD means for MCP servers

    on this page

    Every MCP client that connects to a server it has never seen before hits the same wall: OAuth expects the two parties to have met. A developer signs up at a provider's portal, collects a client ID and secret, ships them. That works right up until an assistant is pointed at a server nobody has ever registered with, at runtime, by a user pasting a URL.

    MCP's first answer was Dynamic Client Registration — let the client register itself, over HTTP, the moment it arrives. As of the 2026-07-28 specification that answer is deprecated1. The replacement is the Client ID Metadata Document, and it is a genuinely better shape. It also quietly hands your authorization server a new security problem.

    Why registration had to be dynamic

    Ordinary OAuth registration is an N-times-M problem. Every client would need a pre-arranged account at every authorization server, and every server operator would need to onboard every client. With hundreds of clients and thousands of MCP servers that does not scale — and worse, a brand-new server stays unusable by an existing client until somebody does paperwork.

    Dynamic Client Registration, RFC 7591, was the obvious escape hatch2. The client posts a JSON description of itself to a registration endpoint and gets an identity back. MCP's 2025-03-26 authorization spec said clients and authorization servers should support it, and in practice it became the assumed path: a client that could not do DCR could not connect to a server it had not been hard-coded for.

    The 2025-06-18 revision tightened everything around it — the MCP server is an OAuth 2.1 resource server, discovery runs through protected resource metadata, tokens are bound to the audience they were issued for — but left registration alone. That is the piece that has now changed.

    How DCR works, and where it breaks

    DCR is one unauthenticated POST. The authorization server advertises a registration endpoint in its metadata; the client posts a description of itself and gets an identity back.

    POST /register HTTP/1.1
    Content-Type: application/json
    
    {
      "client_name": "Example MCP Client",
      "redirect_uris": ["http://127.0.0.1:3000/callback"],
      "grant_types": ["authorization_code", "refresh_token"],
      "response_types": ["code"],
      "token_endpoint_auth_method": "none",
      "application_type": "native"
    }

    That endpoint is the root of every complaint about it.

    It is a free database row, for anyone

    Nothing authenticates the call — a client with no prior relationship is exactly the case it exists for. So is a script. Operators end up bolting on rate limiting, quotas and garbage collection that RFC 7591 never specified, with no signal for telling a real client from noise.

    The state it accumulates means nothing

    Every install of a desktop MCP client registers separately. Clear the token cache, reinstall, switch machines — another registration. The table fills with rows that each describe one copy of the same handful of applications, and nothing in the data says so.

    Identity does not survive anything

    A client ID from DCR is an opaque string, unique to one authorization server and to one registration event. You cannot allowlist a client, rate-limit one, revoke one across your estate, or notice that the thing asking for write access today is the thing that asked yesterday. Every per-client policy an enterprise wants to write is unwritable.

    Nothing in the registration is verified

    The client name and logo are strings the caller chose. An attacker registers under a well-known assistant's name, with its logo and their own redirect URI, and your consent screen renders it faithfully. The consent screen is the one place a user makes a trust decision, and it is displaying unvetted, attacker-supplied content.

    Plenty of identity providers simply won't do it

    Many enterprise identity providers either gate RFC 7591 behind an initial access token or don't expose it at all — reasonably, given everything above. A stranger client has no initial access token. So the universal mechanism frequently isn't there, and clients degrade to asking the user to paste a client ID by hand, which is the manual registration DCR was supposed to eliminate.

    CIMD: the client ID is a URL

    A Client ID Metadata Document inverts who holds the state. The client publishes a small JSON file at a stable HTTPS URL, and that URL is the client ID. There is no registration call and nothing for the authorization server to store3.

    {
      "client_id": "https://app.example.com/oauth/client-metadata.json",
      "client_name": "Example MCP Client",
      "client_uri": "https://app.example.com",
      "logo_uri": "https://app.example.com/logo.png",
      "redirect_uris": [
        "http://127.0.0.1:3000/callback",
        "http://localhost:3000/callback"
      ],
      "grant_types": ["authorization_code"],
      "response_types": ["code"],
      "token_endpoint_auth_method": "none"
    }

    The fields are ordinary RFC 7591 client metadata — the same vocabulary, published rather than posted. MCP requires at least the client ID, a client name and the redirect URIs. Symmetric secrets are forbidden in the document, as is any private key material; a client that needs to authenticate itself uses a signed assertion and a published JWKS URL instead.

    The flow is short. The client sends its metadata URL as the client ID on the authorization request. The server notices the client ID is a URL and fetches it. It then checks that the client ID inside the document matches the URL it fetched, by exact string comparison — no port normalization, no trailing-slash forgiveness — that the document parses and carries the required fields, and that the request's redirect URI appears in the document's list. Then it shows a consent screen and carries on as normal.

    Servers advertise support by setting client_id_metadata_document_supported to true in their authorization server metadata. That flag is what a client checks before choosing CIMD over DCR.

    What CIMD fixes, and what it doesn't

    The write endpoint is gone: nothing is created on the authorization server, so there is nothing to spam and nothing to prune. Client identity becomes stable and portable — one URL works at every server that supports CIMD, with no re-registration when a server switches its authorization server. Attribution gets an owner, because the name and logo on the consent screen are served from a domain someone controls and can be held to. And public clients stop storing secrets entirely.

    That is a real improvement. Here is the other half.

    You just built an SSRF primitive

    Your authorization server now fetches a URL that an unauthenticated caller supplies, inside the authorization request. The draft is blunt about it: servers must not fetch a client ID URL, or any URL inside the returned document, that resolves to a special-use IP address4. That means resolving DNS yourself, checking the address, and re-checking after every redirect — not handing the string to your HTTP client and hoping. The logo URL is the same hazard, one hop later.

    A domain is not a vetting process

    Anyone can buy a lookalike domain and publish a metadata document naming itself after a well-known assistant. CIMD moves impersonation from free to roughly ten dollars. Domain allowlists, reputation checks and warnings for first-seen domains are all optional in the spec. If you want trust rather than attribution, you build it yourself.

    Loopback clients are still impersonatable

    The spec says outright that Client ID Metadata Documents cannot prevent localhost URL impersonation on their own. A public client has no secret, so any local process can present someone else's metadata URL and collect the authorization code at its own loopback port. Servers should warn on localhost-only redirect URIs, and must display the redirect hostname during authorization.

    Your OAuth flow now has a CDN dependency

    If the metadata URL returns a 404, its certificate lapses, or an authorization server's egress filter blocks it, authorization fails for every user at once. Error responses must not be cached, so an outage is felt immediately rather than ridden out. And moving the document is changing identity: every authorization server sees an entirely new client, with no grants, no consent history and no allowlist entry.

    If you run an MCP server

    First, work out which half of the problem is actually yours. An MCP server is an OAuth resource server. Registration — DCR or CIMD — happens at the authorization server. If you delegate identity to a managed provider, which is most of the argument for a hosted MCP server in the first place5, you will not write a line of CIMD code.

    What you will do is ask your provider one question: does it advertise client_id_metadata_document_supported? A client that has dropped DCR cannot connect to a server whose authorization server only speaks DCR, and that failure will look like your server being broken. Auth0, Okta, Stytch, WorkOS and Descope have all published CIMD support. If your provider isn't on that list, check its current documentation rather than assuming — a gap there caps which MCP clients can reach you at all.

    Note the shape Auth0 and Okta both chose: an admin approval step on top of the raw mechanism, where a tenant admin imports and confirms a metadata URL before it becomes a usable client. That is the trust policy the spec leaves optional, and it is what enterprises will actually want. Expect "CIMD supported" to increasingly mean "CIMD supported, from domains we have approved."

    If you do run your own authorization server, the work is: advertise the flag; validate the client ID URL's form, meaning an https scheme, a path component, no userinfo, no fragment and no dot segments; fetch it through an SSRF-hardened HTTP client; verify the document's client ID equals the fetched URL exactly; verify the required fields and reject symmetric-secret authentication methods; exact-match the redirect URI; cache successes according to HTTP cache headers and never cache failures; and show both the client ID hostname and the redirect hostname on the consent screen, with a warning for localhost-only redirects and for domains you are seeing for the first time.

    Keep your registration endpoint running throughout. Turning DCR off today breaks every client that hasn't migrated.

    If you build an MCP client

    Your work is smaller but more permanent: publish one JSON file and never move it.

    Choose the URL as a long-lived identifier. It is your identity at every authorization server, and every allowlist entry anyone ever writes about you. Put it on a path on your primary domain — not a versioned path, not a bucket URL you might migrate later. Version the contents; the URL is forever.

    List every callback you will ever use, because servers exact-match the request's redirect URI against the document. Loopback port handling varies: OAuth 2.1 permits a server to ignore the port for loopback redirects, but not every implementation does, so test against the providers you actually care about rather than assuming your ephemeral port will be accepted.

    Treat the document as production infrastructure. Authorization fails for everyone, everywhere, if that URL goes down, so monitor it and serve it from something as reliable as your sign-in page. Set cache headers deliberately: long enough to absorb an outage, short enough that you can correct a mistake within a day.

    If customers self-host your client, consider a separate metadata URL per deployment. That lets their identity provider admin allowlist one specific instance — exactly the control DCR could never offer.

    And keep the fallback chain. The spec's priority order is pre-registered credentials first, then CIMD when the server advertises support, then DCR when it advertises a registration endpoint, then prompting the user. Dropping DCR from your client today cuts you off from every authorization server that hasn't shipped CIMD, and that is still a long list.

    How long you actually have

    DCR is deprecated, not removed, and it will keep working for a while yet.

    CIMD arrived in the 2025-11-25 revision as a recommended registration mechanism, sitting alongside DCR. The 2026-07-28 revision deprecated DCR outright: CIMD became a should, DCR dropped to a may, and the spec page now carries an explicit warning that new implementations should not adopt it. The same revision introduced a formal feature lifecycle policy, with a twelve-month minimum deprecation window and a public registry of deprecated features6.

    That registry puts DCR's earliest removal at the first specification revision released on or after 28 July 2027. Three things about that are worth reading carefully. "Earliest" means eligibility, not a schedule — actual removal is a maintainer decision taken at release time and may land later, which looks likely given how many authorization servers still lack CIMD. It is keyed to a revision rather than a calendar date, and MCP revisions do not ship on a fixed cadence. And deprecated already means something today: new implementations should not adopt DCR, so if you are writing registration code this quarter, write CIMD.

    DCR is not alone in that registry. Roots, sampling and logging were deprecated in the same revision with the same earliest removal, and the legacy HTTP+SSE transport was formally reclassified. If you are planning migration work, plan it as one pass.

    What to do now

    Adopt CIMD, keep DCR, and secure the fetch.

    If you build a client, publish a metadata document at a URL you are willing to keep forever, prefer CIMD when the server advertises it, keep the DCR fallback, and monitor that URL like production.

    If you run a server on a managed identity provider, confirm your provider supports CIMD and turn it on, decide whether your trust policy is open or admin-approved, and leave the registration endpoint advertised until your client population has moved.

    If you run your own authorization server, put the CIMD fetch behind an SSRF-hardened HTTP client before anything else, and make the consent screen show where the client actually came from.

    The migration window runs to at least the first spec revision on or after 28 July 2027, so there is no emergency. The engineering is small. The part that isn't small is deciding whose metadata documents you will actually trust — and the spec deliberately leaves that to you.

    Frequently asked questions

    What is a Client ID Metadata Document (CIMD)?

    It's a small JSON file, published by an OAuth client at a stable HTTPS URL, that describes the client — its name, logo, redirect URIs and grant types. That URL is then used directly as the client ID. Instead of registering with each authorization server, the client publishes once and every server fetches the document on demand.

    Is Dynamic Client Registration removed from MCP?

    Not yet. DCR was deprecated in the 2026-07-28 specification and remains available for backwards compatibility. The deprecated features registry puts its earliest removal at the first specification revision released on or after 28 July 2027, and removal is a maintainer decision that may come later than that.

    Do I need to change my MCP server?

    Probably not directly. An MCP server is an OAuth resource server; registration happens at the authorization server. If you use a managed identity provider, the change is enabling CIMD there and confirming it advertises support. If you run your own authorization server, you need to implement CIMD fetching and validation — with SSRF protection.

    Does CIMD make MCP authorization more secure?

    In parts. It removes an unauthenticated write endpoint, gives clients a stable identity that can be allowlisted or blocked, and anchors consent-screen branding to a domain someone owns. It does not vet anyone — a lookalike domain is cheap — and it introduces a server-side fetch of an attacker-supplied URL, which has to be hardened against SSRF.

    Footnotes

    1. MCP Authorization: Client Registration the three registration mechanisms, their priority order, and the DCR deprecation warning.
    2. RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol the mechanism MCP is moving away from.
    3. OAuth Client ID Metadata Document the IETF working group draft by Aaron Parecki and Emelia Smith that CIMD implements.
    4. MCP Authorization: Security Considerations SSRF, localhost impersonation and trust policies for Client ID Metadata Documents.
    5. What a hosted MCP server actually buys you why the auth and multi-tenancy plumbing is most of the work in a production MCP server.
    6. MCP deprecated features registry every feature currently scheduled for removal, with its earliest removal revision.