---
title: "CIMD Makes Your Authorization Server an HTTP Client. Plan For That."
description: "The 2026-07-28 MCP spec deprecates Dynamic Client Registration in favour of Client ID Metadata Documents, where the client_id is a URL your server fetches. It fixes real problems with DCR and hands you an outbound request to an attacker-influenced URL, which is a threat model worth writing down before you ship it."
image: "https://foundrysoft.co/api/og?type=article&title=CIMD+Makes+Your+Authorization+Server+an+HTTP+Client.+Plan+For+That.&cat=Tutorial+%2F%2F+MCP&rt=11+min+read&au=Varun+Raj+Manoharan&dt=2026-08-07"
url: "https://foundrysoft.co/blog/mcp-cimd-authorization-threat-model"
---

Tutorial // MCP 2026-08-07 11 min read

# CIMD Makes Your Authorization Server an HTTP Client. Plan For That.

The 2026-07-28 MCP spec deprecates Dynamic Client Registration in favour of Client ID Metadata Documents, where the client_id is a URL your server fetches. It fixes real problems with DCR and hands you an outbound request to an attacker-influenced URL, which is a threat model worth writing down before you ship it.

![Varun Raj Manoharan](https://foundrysoft.co/images/about/founder.webp)

Varun Raj Manoharan Founder & Principal Engineer

MCP OAuth CIMD Security SSRF

## Key takeaways

-   CIMD uses a client-controlled HTTPS URL as the OAuth client_id, so your authorization server fetches metadata on demand. That turns an inbound-only component into one that makes outbound requests to URLs it did not choose.
-   Treat the metadata fetch as a classic SSRF surface: deny private address ranges after DNS resolution, cap redirects and response size, set aggressive timeouts, and never let the fetch inherit ambient cloud credentials.
-   DCR's real failures were operational as much as cryptographic. It accumulated duplicate client identities that nobody could attribute, and it offered no reliable way to verify who a client actually was.
-   You have a twelve-month minimum deprecation window and DCR keeps working inside it, so the correct move is to implement CIMD alongside DCR now and measure which clients still need the old path before removing it.

The 2026-07-28 MCP specification did more than remove sessions. Alongside the stateless core, it formally deprecated OAuth Dynamic Client Registration in favour of Client ID Metadata Documents, and that change alters the security posture of your authorization server in a way that deserves its own conversation.

The short version of CIMD: a client publishes a JSON document at a stable HTTPS URL it controls, and that URL is used directly as the OAuth `client_id`. When a client shows up, the authorization server fetches the URL, learns the client's metadata, validates the redirect URIs against it, and caches the result.

It is elegant, it fixes genuine problems, and it means your authorization server now makes outbound HTTP requests to addresses supplied by whoever is authenticating. If you have ever written an SSRF finding into a pentest report, you already know why that sentence deserves attention.

## What was actually wrong with DCR

Worth being fair to the thing being replaced, because the reasons it is going away tell you what CIMD has to get right.

DCR was stateful, and statefulness was the theme of everything the 2026-07-28 revision removed. Every client that registered created a persistent record on your side. That record had to be stored, migrated, and reasoned about, and it existed whether or not the client ever came back.

The operational consequence was identity sprawl. A client that reinstalls, redeploys, or rotates registers again, and you accumulate an ever-growing pile of duplicate client identities with no reliable way to tell which ones correspond to the same real client. Anyone who has tried to answer "which of these four hundred registrations is the customer asking about" knows the shape of that problem.

The security consequence was worse. DCR gave no dependable way to verify client identity, which makes phishing straightforward: register a client with a convincing name, get a consent screen that shows the name you chose, and the user has no path to check whether it is the real thing.

CIMD addresses both. The client_id is a URL, so identity is anchored to a domain someone controls and can be checked. There is no registration record to accumulate because there is nothing to register.

## The new surface, stated plainly

Your authorization server, which previously only accepted inbound requests, now performs an outbound HTTPS GET against a URL that an unauthenticated party chose.

Enumerate what that enables if you implement it naively.

Internal network reconnaissance, by pointing the client_id at `http://10.0.0.5:8080/` and reading behaviour differences in the error responses. Cloud metadata service access, the classic `169.254.169.254` route to instance credentials, catastrophic rather than merely bad. Denial of service, by pointing at an endpoint that never responds, or one that streams gigabytes, or one that redirects in a loop. Request amplification, where your infrastructure becomes the thing making requests to a third party you have no relationship with.

None of this is novel. It is textbook SSRF, and the reason for restating it is that the component acquiring this behaviour is one that historically did not have it, and it is likely maintained by people whose threat model for it was "handles tokens carefully."

## The controls that actually matter

Here is the set I would consider non-negotiable before this path goes live.

**Resolve DNS first, then check the address, then connect to the address you checked.** The naive implementation validates the hostname, then hands the URL to an HTTP client, which resolves it again. Those two resolutions can return different answers, which is the entire DNS rebinding attack. Resolve once, validate the resulting IP against your deny list, and connect to that IP with the original hostname passed for TLS verification and Host header.

**Deny private and special-purpose ranges after resolution.** RFC 1918 space, loopback, link-local including the cloud metadata address, and IPv6 equivalents including the mapped forms. The IPv6 variants get forgotten routinely and are exactly as exploitable.

**Cap redirects, and revalidate on every hop.** A URL that passes your checks and then redirects to `169.254.169.254` defeats validation that only ran once. Two or three hops maximum, each one revalidated with the same rules.

**Cap response size and set aggressive timeouts.** A client metadata document is small. Anything past a few tens of kilobytes is not a metadata document, and you should stop reading rather than buffering it. Connect and total-request timeouts should be measured in low single-digit seconds, because this fetch is inline with an authorization flow that a human is waiting on.

**Make the fetch credential-free.** The outbound request must not carry ambient cloud credentials, instance role tokens, or internal service authentication. In practice that often means the fetch runs from a component with a deliberately minimal identity, or through an egress proxy that strips credentials. This is the control that turns a bad day into an ordinary one when something else fails.

**Cache aggressively, with a floor and a ceiling.** Fetching the document on every authorization attempt is both a performance problem and an amplification vector. Cache by URL with a sane TTL, and serve stale rather than failing open if the fetch errors. Do not let a client control your cache duration.

**Log the fetch as a security event.** Destination URL, resolved IP, status, size, duration. When something goes wrong here you will want the history, and this is a low-volume, high-value log.

## What CIMD does not solve

Worth being clear, because "the client_id is a URL you can check" invites more confidence than it earns.

Domain control is not organisational trust. Anyone can obtain a domain and publish a metadata document. CIMD gives you an identifier that is attributable and consistent, strictly better than a self-asserted name, but it does not tell you the client is legitimate. It tells you which domain to blame, and it makes an allowlist possible where previously it was not.

Consent screens still need care. A client_id of `https://totally-legit-mcp-client.example.com/metadata.json` is anchored and verifiable and can still be a phish. The improvement over DCR is real but partial: you now have something stable to display, block, and reputation-track. What you display and how you display it is still your design problem.

And the document is fetched from a live endpoint, which means its content can change after you first saw it. Your cache TTL is the window in which a client's declared redirect URIs can shift without you noticing. Pick that TTL deliberately.

## The rest of the deployment story

The auth change lands alongside several others in the same revision that together change how you run a server, and they read best as one shift rather than separately.

The protocol core is now stateless request/response, so a remote MCP server can sit behind a plain round-robin load balancer with no session affinity. That is a genuine operational simplification and it is the reason for most of the other changes.

Routing can key on an `Mcp-Method` header, which means your edge can make routing decisions without parsing a JSON body. If you have ever wanted to send expensive tool calls to a different pool than cheap list operations, that is now a load balancer rule rather than an application concern.

List results are cacheable, with the server declaring a `ttlMs`. Clients can hold `tools/list` responses for as long as you permit. If your tool list is stable, this removes a surprising amount of traffic.

There is now a formal extensions framework, and tasks have moved out of the experimental core into the `io.modelcontextprotocol/tasks` extension. Roots, sampling, and logging are deprecated. All of these keep working for at least twelve months, but new implementations should not adopt them.

## A migration order that will not hurt

You have a twelve-month minimum window and DCR continues to function inside it. That is enough room to do this without drama, and the sequencing matters.

Implement CIMD support alongside DCR rather than instead of it, with the full SSRF control set from day one. Do not ship the fetch and add the controls later, because "later" arrives after the first incident.

Instrument which registration path each authorization uses, so you can see the mix. This is the measurement that tells you when removal is safe, and without it you will be guessing.

Announce the deprecation to your client developers with a date, and give them the URL-based path in your documentation as the default with DCR marked legacy. Most client work here is small; what it needs is notice.

Watch the mix until DCR usage is a rounding error, then remove it. Note the date you removed it in your changelog, because someone will show up eighteen months later with a client nobody remembered.

Then go back and re-read your SSRF controls, because by then your infrastructure will have changed underneath them, and the egress rules that were correct when you wrote them are exactly the kind of thing that silently stops being correct after a network migration.

#### Related reading

[MCP, A2A, and the Protocol Questions to Put in Your Next AI Contract

Agent interoperability standards settled faster than anyone expected. MCP for tools, A2A for delegation, both under Linux Foundation governance. Here is what that means for buyers, and the contract language that keeps you from being locked in.

MCP A2A Protocol AI Vendor Lock-In

](https://foundrysoft.co/blog/mcp-a2a-agent-protocol-contract-questions)[Agent Adoption Is Not a Model Problem Anymore. It Is an Integration Problem.

Model capability stopped being the constraint. Roughly 46% of enterprises now name integration with existing systems as their biggest blocker to AI agent deployment. Here is what that work actually consists of, and how long each part really takes.

AI Agent Integration Enterprise AI Legacy Systems

](https://foundrysoft.co/blog/agent-adoption-integration-problem)[MCP Went Stateless: Migrating Your Server to the 2026-07-28 Spec

The 2026-07-28 MCP revision removes sessions, the initialize handshake, and server-initiated requests. Here's what actually breaks in your server, the new wire format, the requestState and MRTR patterns that replace sessions, and the SDK v2 migration path.

MCP Model Context Protocol AI Agents

](https://foundrysoft.co/blog/mcp-stateless-spec-migration)

#### Next Article

[

Long-Horizon Agents Are Batch Jobs. Build Them Like It.

](https://foundrysoft.co/blog/long-horizon-agents-checkpoint-resume)

Available for new projects

## Let's build something great.

Have a project in mind? We are an elite software and AI development studio ready to bring your ideas to production. Let's talk about your roadmap.

Start a Project [See our work](https://foundrysoft.co/work)

```json
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "FoundrySoft",
  "url": "https://foundrysoft.co",
  "logo": "https://foundrysoft.co/logo.svg",
  "description": "FoundrySoft builds production-grade software and AI systems for US companies, from an India-based team of senior engineers.",
  "sameAs": [
    "https://github.com/foundrysofthq",
    "https://www.linkedin.com/company/foundrysoft",
    "https://www.instagram.com/foundrysoft/"
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "FoundrySoft",
  "url": "https://foundrysoft.co"
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "headline": "CIMD Makes Your Authorization Server an HTTP Client. Plan For That.",
  "description": "The 2026-07-28 MCP spec deprecates Dynamic Client Registration in favour of Client ID Metadata Documents, where the client_id is a URL your server fetches. It fixes real problems with DCR and hands you an outbound request to an attacker-influenced URL, which is a threat model worth writing down before you ship it.",
  "url": "https://foundrysoft.co/blog/mcp-cimd-authorization-threat-model",
  "mainEntityOfPage": "https://foundrysoft.co/blog/mcp-cimd-authorization-threat-model",
  "image": [
    "https://foundrysoft.co/images/blog/mcp-cimd-authorization-threat-model.webp"
  ],
  "datePublished": "2026-08-07",
  "dateModified": "2026-08-07",
  "keywords": "MCP, OAuth, CIMD, Security, SSRF",
  "author": {
    "@type": "Person",
    "name": "Varun Raj Manoharan"
  },
  "publisher": {
    "@type": "Organization",
    "name": "FoundrySoft",
    "logo": {
      "@type": "ImageObject",
      "url": "https://foundrysoft.co/logo.svg"
    }
  }
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://foundrysoft.co/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Blog",
      "item": "https://foundrysoft.co/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "CIMD Makes Your Authorization Server an HTTP Client. Plan For That.",
      "item": "https://foundrysoft.co/blog/mcp-cimd-authorization-threat-model"
    }
  ]
}
```
