If you’ve tried to connect an MCP client protected by Microsoft Entra ID and hit an unexpected wall, this post is for you. It’s one of the most common friction points in enterprise MCP authentication, and it comes down to a gap between what the MCP spec expects and what Entra actually supports. That gap centers on Dynamic Client Registration (DCR), defined in OAuth RFC 7591, and its newer counterpart, Client ID Metadata Documents (CIMD). Here’s what each one is, why they matter, where Entra stands on both, and what you can do about it today.
What Is Dynamic Client Registration?
Dynamic Client Registration (DCR) is an OAuth 2.0 standard, defined in RFC 7591 (with a companion Client Registration Management Protocol in RFC 7592), that lets OAuth clients register themselves with an authorization server programmatically, at runtime. In MCP, dynamic client registration is part of the MCP authorization specification. Without DCR, registering an OAuth client is a manual process. Someone goes into the IdP admin console, creates an app registration, configures the redirect URIs, copies the client ID and secret, and hands them to the developer. That works fine when you’re doing it once. It doesn’t work when MCP clients need to connect to new servers dynamically. The MCP spec introduced MCP Dynamic Client Registration for exactly this reason: it addresses the scaling bottleneck that shows up once an ecosystem has many clients trying to reach many servers, with no prior relationship between them. The model context protocol handles authorization at the transport layer, and the MCP client acts on behalf of the resource owner when connecting to restricted servers. Clients need to discover and connect to MCP servers without someone manually provisioning an OAuth app registration every time. DCR makes that possible: the client sends a registration request to the authorization server, and dynamic client registration in the MCP authorization specification returns a client ID and credentials so the client can proceed with the OAuth flow. No admin console, no manual steps.
The Client Registration Request and Response
Here’s what a minimal DCR request looks like:
POST /register HTTP/1.1
Host: auth.example.com
Content-Type: application/json
{
"client_name": "My MCP Client",
"redirect_uris": ["https://client.example.com/callback"],
"grant_types": ["authorization_code"],
"response_types": ["code"]
}
This is a standard client registration request, submitted as JSON to the authorization server’s registration endpoint over HTTP POST. The authorization server validates the client metadata parameters (redirect URIs, grant types, response types, and any optional fields like client_uri, logo_uri, or software_statements) before assigning a new client identifier.
If the registration request is accepted, the authorization server issues a client information response containing at minimum a client_id, and depending on the client type, additional fields:
A few fields worth understanding, since they show up throughout RFC 7591 and RFC 7592:
client_id. The unique client identifier the authorization server assigns. Every subsequent request from this client uses it.
client_secret. Issued for confidential clients (typically server-side apps that can keep a secret safe). Most MCP clients are public clients and rely on PKCE instead, so this field is often absent or null.
registration_access_token. A separate credential the client can use later to read, update, or delete its own registration, per RFC 7592. This is distinct from the OAuth access tokens used to call MCP tools.
initial_access_token. An optional token an authorization server can require before a client is allowed to register at all, giving the operator a gate on who can even attempt dynamic registration. Not all authorization servers require one.
The client uses the returned client_id (and client_secret, if issued) to proceed with the standard OAuth authorization code flow, where the returned authorization code is exchanged securely after user consent. No admin intervention is required for a new client to come online.
Client Registration Error Responses
Not every registration request succeeds, and the spec defines how a registration error condition should be communicated back to the client. A typical error response looks like this:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_redirect_uri",
"error_description": "One or more redirect URIs are not valid"
}
Common reasons a client registration error response occurs:
An unsupported or malformed redirect_uris value.
A requested authentication method the authorization server doesn’t allow for dynamically registered clients (public clients requesting client_secret_post, for instance).
Missing required client metadata fields.
A rate limit or abuse-prevention check on the registration endpoint itself. Registration endpoints that accept unauthenticated requests are a plausible target for a denial of service attack, so authorization servers commonly rate-limit or gate this endpoint.
If you’re implementing an authorization server that accepts DCR, treat the registration endpoint the same way you’d treat any other unauthenticated intake point: validate input values strictly, log every registration attempt for forensic and compliance purposes, and don’t let a malformed request produce an unhandled error.
Why MCP Dynamic Client Registration Matters for Enterprise Deployments
In a small or personal deployment, you might register your OAuth app once and hardcode the credentials. Annoying, but manageable. In an enterprise environment, that approach breaks down fast. Every new client-server combination needs its own app registration: a matrix of manual work that grows with every MCP server you add. Here’s a concrete example. You have three MCP clients: Claude Desktop, a custom agent, and an IDE plugin. You have five MCP servers. Without dynamic registration, that’s potentially fifteen separate OAuth app registrations to manage, keep in sync, and update whenever something changes. Add a sixth server and you’re back in the admin console three more times. DCR (or its successor, covered next) collapses that. Clients register once, dynamically. The authorization server handles the rest, which is exactly what lets increasingly autonomous AI clients connect to whichever MCP servers a task requires, without a human provisioning access in advance for each one.
DCR Is No Longer the Default: Client ID Metadata Documents (CIMD)
This is worth stating plainly, because it changes the practical advice below: as of the MCP spec update dated November 25, 2025, Dynamic Client Registration is no longer the primary recommended mechanism for client registration. The spec introduced a new option, Client ID Metadata Documents (CIMD), based on an IETF draft, and made it the preferred default. DCR is still supported, but its status moved from “SHOULD support” to “MAY support,” and it’s now positioned as a fallback for backward compatibility rather than the primary path.
The current MCP client registration priority order is:
Pre-registered client information, if the client already has it for this specific server.
Client ID Metadata Documents (CIMD), if the authorization server advertises client_id_metadata_document_supported: true.
Dynamic Client Registration, as a fallback, if the authorization server advertises a registration_endpoint.
Prompt the user to enter client information manually, if none of the above are available.
How CIMD works
Instead of asking the authorization server to mint and permanently store a new client record, CIMD flips the model: the client hosts its own metadata document at a stable HTTPS URL, and uses that URL itself as its client_id.
When the client initiates OAuth, the authorization server detects the URL-formatted client_id, fetches the document, validates that its contents match the URL, and proceeds, without needing to permanently store a new client registration by default. This meaningfully reduces server-side state (the authorization server isn’t accumulating a growing database of dynamically registered clients), gives clients a cleaner update path (change the hosted document, no re-registration protocol needed), and ties client identity to something with an existing trust model: domain control and TLS, the same signals browsers already use to establish web trust.
CIMD doesn’t replace DCR everywhere. It specifically doesn’t help clients that can’t host a stable, public HTTPS metadata endpoint, which includes a lot of MCP clients: desktop apps, CLI tools, IDE plugins, and internal agents running on a developer’s laptop, all of which commonly use localhost or custom-scheme redirects and don’t control a public domain. For those, DCR (or pre-registration) remains the practical option.
The Entra Problem: Neither DCR Nor CIMD Is Supported
Microsoft Entra ID does not support Dynamic Client Registration, and it does not support Client ID Metadata Documents either.
This isn’t an oversight on either count, it’s a deliberate product decision on Microsoft’s part, and Microsoft has explained the reasoning for both. For DCR, Entra’s app registration model is built around manual configuration in the Azure portal or via the Microsoft Graph API, and there’s no endpoint that accepts a registration request per RFC 7591. For CIMD, Microsoft has specifically pointed to security concerns with the mechanism itself: supporting it would require Entra’s authorization endpoints to make outbound HTTP requests to fetch a client’s metadata document, which raises server-side request forgery (SSRF) risk, DDoS amplification risk, and the fact that a CIMD document is self-asserted, with no equivalent to Entra’s own verified publisher attestation for app registrations.
For MCP deployments in organizations running on Entra (which is a lot of enterprises) this creates a direct conflict with both paths the MCP spec offers for dynamic client identification. If you’re already connecting Microsoft Office 365 MCP servers in your environment, you’ve likely already run into this wall, whichever mechanism you tried first.
In practice, every MCP client that wants to connect to an Entra-protected resource needs a manually provisioned app registration. Without a standardized authorization flow across MCP servers, implementations become inconsistent, operationally fragile, and prone to dangerous MCP OAuth shortcuts. If you have five clients and ten MCP servers, someone is doing a lot of clicking in the Azure portal, and every time a new MCP server gets added, the cycle starts again.
Common Workarounds and Their Limits
The obvious move is to create one shared app registration and distribute the client ID and secret to all your MCP clients. It works. But it means every client shares the same credentials, you can’t revoke access for one client without affecting all of them, and your audit logs can’t distinguish between clients. Security teams tend not to love this. The other common approach is scripting app registrations via the Microsoft Graph API. Better than clicking through the portal, but you’re still managing a growing inventory of registrations, and the underlying problem hasn’t gone away, since Entra still won’t accept either a DCR registration request or a CIMD document from an unknown client.
The Control Plane Fix
The cleaner solution is to put a control plane in front of MCP servers that can speak DCR (or CIMD) to clients on one side, while handling the OAuth relationship with Entra the way Entra actually requires on the other. In practice, this means real integration work between three parties: the MCP client, each MCP server, and the control plane acting as the API gateway that sits between them, translating dynamic registration on the client-facing side into the static app registration Entra actually requires.
The control plane exposes a DCR-compatible registration endpoint to MCP clients today, with CIMD support becoming a natural next step for control planes generally as client-side CIMD adoption grows. From the client’s perspective, MCP Dynamic Client Registration works exactly as the spec intends, and the MCP client reads a metadata document to discover the corresponding authorization server instead of relying on manual configuration. Behind the scenes, the control plane holds the static Entra app registrations and handles the OAuth flow to Entra on behalf of the clients.
In a full MCP OAuth setup, that usually means exposing /authorize and /token, optionally /register for DCR clients, plus the login and consent experience for the user’s browser.
The result: clients register once, dynamically. The control plane manages the Entra configuration centrally. When you want to add a new MCP server, you update the control plane, not every client.
Instead of this:
Client A → static config for Server 1
Client A → static config for Server 2
Client B → static config for Server 1
Client B → static config for Server 2
(repeat for every client/server combination)
You get this:
All clients → DCR endpoint on control plane
Control plane → static config per server, managed once
The matrix of manual registrations collapses into a single configuration layer. New clients register dynamically. New servers get added to the control plane once. Entra never needs to know about DCR. Behind the scenes, the control plane acts as a central MCP security proxy and publishes protected resource metadata at a resource metadata URL; clients use it for authorization server discovery, locate the right OAuth authorization server, then fetch and validate that server’s authorization server metadata to confirm its authorization server endpoints.
A control plane also lets MCP servers implement the OAuth 2.0 Protected Resource Metadata specification, so a corresponding authorization server can be located efficiently. That improves onboarding, too, and is a natural place to enforce critical MCP security best practices. Users get a standardized single-click web consent interface instead of bespoke per-server setup.
This is exactly the pattern Obot implements out of the box. Connect your Entra app registration once — Obot handles DCR for every client from there. Try Obot for free or talk to an architect if you’re unsure where to start.
Common Pitfalls to Watch For When Implementing This Pattern
Redirect URI management still matters. Even with a control plane handling Entra, the control plane’s redirect URIs must be registered correctly in your Entra app registrations. The authorization request sends the user’s browser to the authorization URL and then back during the authorization code flow, where both the redirect URI and state must be validated. This is usually a one-time setup, but it’s the first place to check when the OAuth flow breaks.
Token lifetimes are set in Entra. The control plane can handle token refresh, but the initial token lifetime and refresh token policies are configured in Entra. Short-lived access tokens (15 to 60 minutes) paired with longer-lived refresh tokens are the typical starting point; the access token itself is issued at the token endpoint during the authorization code exchange. Proof Key for Code Exchange (PKCE) is mandatory under OAuth 2.1, so public clients should use it instead of a client secret. Set these before you go to production.
The control plane holds sensitive credentials. It holds the Entra app credentials and issues tokens on behalf of clients, so treat it accordingly. Secure authorization depends on token validation at the resource server, and skipping it can allow unauthorized access to protected resources. Every token issuance and tool call should also be logged and audited for forensics. Restrict access, rotate credentials on a schedule, and ensure the control plane itself is behind your standard access control for MCP servers.
This isn’t Entra-specific. Any IdP that doesn’t support DCR or CIMD has the same problem, and it’s one of several strategic MCP security risks leaders must address. Entra is just the most common one we see in enterprise deployments. The control plane pattern applies equally to others. When implementing OAuth, make sure consent clearly shows the requested scopes at the authorization endpoint, and that clients ask only for what they need under least privilege.
Bottom Line
If your organization runs on Entra, support for DCR or CIMD isn’t coming from Microsoft anytime soon, for either mechanism. The practical path forward is a control plane that bridges the gap by implementing the MCP OAuth authorization flow and, where needed, running the authorization server as a separate entity from the resource server. The MCP server acts as the resource server, while the MCP client discovers and follows the authorization mechanism the control plane exposes, whether that’s DCR today or CIMD as client support catches up.
Secure MCP access is a good next read for a more extensive look at what it requires across your organization.
It’s one of those problems that looks like a blocker until you understand the architecture. Then it’s just a configuration decision. While more involved, this approach is preferable to API keys, because clients can request access to and access protected resources with revocable tokens instead of static secrets. The Obot AI Learning Center for MCP and agentic AI covers gateways, catalogs, and authentication patterns across MCP in more depth.
MCP Dynamic Client Registration (DCR) is the application of OAuth’s RFC 7591 standard within the Model Context Protocol, letting an MCP client register itself with an authorization server programmatically, without a human manually creating an app registration first.
Does Microsoft Entra ID support Dynamic Client Registration?
No. Entra ID does not implement an endpoint that accepts DCR registration requests per RFC 7591. App registration in Entra is a manual process through the Azure portal or Microsoft Graph API.
Does Microsoft Entra ID support Client ID Metadata Documents (CIMD)?
No. Microsoft has stated this is a deliberate decision, citing SSRF risk, DDoS amplification risk, and the lack of a publisher-verification equivalent for self-hosted CIMD documents, unlike Entra’s own verified publisher program for app registrations.
What is the difference between DCR and CIMD?
DCR has the client send its metadata to the authorization server, which stores it and issues a new client ID. CIMD has the client host its own metadata document at a stable HTTPS URL and use that URL as its client ID; the authorization server fetches and validates it on demand instead of storing a permanent record.
Is DCR deprecated in MCP?
As of the November 2025 spec update, DCR’s status changed from a recommended (“SHOULD support”) mechanism to an optional (“MAY support”) fallback, with CIMD as the new preferred default. A more recent draft of the spec marks DCR as deprecated outright for new implementations, while keeping it available for backward compatibility.
How do I connect MCP clients to Entra-protected MCP servers without DCR or CIMD?
The practical options are a shared app registration (works, but weakens per-client auditability and revocation), scripting registrations through the Microsoft Graph API, or putting a control plane in front of your MCP servers that holds the Entra app registration centrally and speaks DCR or CIMD to clients on the other side.
What is a registration access token?
It’s a credential, separate from OAuth access tokens, that a dynamically registered client can use later to read, update, or delete its own client registration, as defined in RFC 7592 (the companion management protocol to RFC 7591’s DCR).