> ## Documentation Index
> Fetch the complete documentation index at: https://www.truefoundry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP DCR client_id & Redirect URL Validation — v0.148

> MCP OAuth now validates client_id and redirect URLs on every request. Clients caching credentials must re-register after the v0.148 upgrade.

<Info>
  **Applicable to:** **All** customers — both SaaS and on-prem — trying to **re-initiate authentication** for MCP servers that were added to their IDE or desktop app (Cursor, Claude Desktop, Claude Code, OpenCode) **before v0.148.0**. MCPs that are already connected and working continue to work; only **re-authentication** with credentials cached before the change fails — those clients must re-register.
</Info>

<Warning>
  The following are **not** required and will not fix the issue on their own:

  * Rotating your Personal Access Token
  * Disconnecting / reconnecting MCP servers from the TrueFoundry UI
  * Clearing browser cookies or cache
</Warning>

## What Is Changing

MCP OAuth Dynamic Client Registration (DCR) now enforces strict validation of the `client_id` and redirect URL on every authorization request. Previously, a `client_id` obtained during an earlier registration could be reused across sessions without re-validation.

Starting with v0.148, the control plane will reject any authorization request that presents:

* A `client_id` that does not match an active, in-scope registration, or
* A redirect URL that was not registered as part of the original DCR flow.

## Why This Change

MCP OAuth now applies stricter security validation of the `client_id` and redirect URL on every authorization request, instead of trusting a previously issued `client_id` indefinitely. This closes credential-reuse gaps and keeps each authorization tightly scoped.

The trade-off is that credentials cached before the upgrade are no longer valid and must be re-registered through a fresh DCR handshake.

## Who Is Affected

Some MCP clients may not work after upgrading — specifically those that **cache** the `client_id` from a previous session and reuse it for subsequent authorizations. This includes:

* **Cursor** (IDE)
* **Claude Desktop**
* **Claude Code** (CLI)
* Any other OAuth 2.0 client that persists DCR credentials locally

Typical error symptoms after upgrading. The primary symptom is a stale `client_id` failing validation at `GET /:tenant/:server/authorize`:

```
{ "statusCode": 400, "message": "Invalid client_id" }
```

A redirect URL that was not registered during the original DCR flow returns:

```
{ "statusCode": 400, "message": "redirect_uri '<uri>' is not registered for this client" }
```

<Note>
  You may also see `{ "statusCode": 400, "message": "Invalid state" }` if a client replays a stale OAuth `state` blob, but this is a separate, secondary case from the `client_id` validation above.
</Note>

## What You Need to Do

### 1. Make sure the gateway is using the V2 OAuth flow

The strict `client_id` and redirect validation is enforced by the **control plane** (v0.148+). The **gateway plane** is what selects whether MCP clients use the older **V1** flow or the new **V2** flow. The two are versioned and shipped separately.

This is the root of the broken connections: **once the control plane is on v0.148 or later, the old V1 OAuth flow no longer works** — so the gateway must be switched to the **V2 flow**. V2 is the default in **gateway v0.148.2+**, and can be enabled on earlier gateways via an env var. What you need to do depends on your [deployment model](/docs/platform/deployment-overview#deployment-options):

<Tabs>
  <Tab title="Fully managed SaaS">
    TrueFoundry hosts both the control plane and the gateway.

    **No action needed** — TrueFoundry keeps the control plane on v0.148+ and the gateway on the V2 flow.
  </Tab>

  <Tab title="Hybrid (self-hosted gateway)">
    You self-host the gateway plane; the control plane runs on TrueFoundry SaaS.

    The SaaS control plane is already on v0.148+, so a self-hosted gateway still using the **V1 flow will break**. Switch your gateway to the V2 flow by upgrading the `tfy-llm-gateway` chart to **v0.148.2+** (V2 by default).

    <Note>
      **Temporary opt-in:** If you must stay on a gateway version **>= v0.146.2 and \< v0.148.0** for now, set `USE_MCP_OAUTH_V2_API=true` in your gateway deployment to switch to the V2 flow without upgrading. Upgrading is preferred so you don't have to maintain the env var.
    </Note>
  </Tab>

  <Tab title="Fully self-hosted">
    You self-host both the control plane and the gateway plane.

    Upgrading the control plane to v0.148+ while the gateway is still on the **V1 flow breaks MCP OAuth**, so move both together: upgrade the bundled `truefoundry` control-plane chart to a release whose [pinned gateway version](/docs/platform/control-plane-upgrade#gateway-plane-dependencies) is **v0.148.2+**, which puts the gateway on the V2 flow by default. Avoid running a v0.148+ control plane against a gateway still on V1.

    <Note>
      **Temporary opt-in:** If your gateway must stay on a version **>= v0.146.2 and \< v0.148.0** for now, set `USE_MCP_OAUTH_V2_API=true` in your gateway deployment to switch to the V2 flow without upgrading. Upgrading is preferred so you don't have to maintain the env var.
    </Note>
  </Tab>
</Tabs>

### 2. Reset cached credentials on each client

This step applies to **every** affected user across all deployment models, regardless of how the new flow was enabled.

After upgrading, every client must drop the `client_id` it cached before the upgrade and re-register. **The exact steps differ by client — for some, a restart is not enough.**

<Tabs>
  <Tab title="Cursor (IDE)">
    1. Open the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) and run **MCP: Clear All MCP Tokens** to remove the cached OAuth credentials.
    2. Quit Cursor completely and relaunch it (tokens are cached at runtime, so a restart is required for the clear to take effect).
    3. Re-initiate the MCP connection so the client performs a fresh DCR handshake.
  </Tab>

  <Tab title="Claude Code & Claude Desktop">
    Both Claude apps cache the DCR `client_id` and secret, so the stale credentials need to be cleared and re-registered.

    **Claude Code (CLI):** Run `/mcp` inside a session, select the affected server, and choose **Clear authentication**, then **Authenticate** to register fresh credentials. If you see `redirect_uri '...' is not registered for this client`, simply **retry** — Claude can change its local callback port between registration and authorization, and the next attempt typically succeeds. See the [MCP authentication documentation](https://code.claude.com/docs/en/mcp#authenticate-with-remote-mcp-servers).

    **Claude Desktop:** Start with the UI flow below — it resets only the affected connection and leaves your config and chat history intact. A restart alone keeps the cached credentials, so clear them as described.

    1. In Claude Desktop, go to **Settings > Connectors**, remove (disconnect) the affected MCP connector, then re-add it. This forces a fresh DCR handshake for that connection only.
    2. If the cached credentials persist after re-adding the connector, clear them at the OS level:

           <Tabs>
             <Tab title="macOS">
               Delete the app's encryption key, then relaunch Claude Desktop and re-authenticate. This clears the cached MCP OAuth credentials while preserving your config and chat history.

               ```bash theme={"dark"}
               security delete-generic-password -s "Claude Safe Storage" -a "Claude Key"
               ```
             </Tab>

             <Tab title="Linux">
               Edit `~/.config/Claude/config.json` and remove only the affected server's cached OAuth/credential entry (back up the file first), then relaunch Claude Desktop and re-authenticate. Do **not** delete the entire config file — that would wipe your settings and chat history.
             </Tab>
           </Tabs>

    See Claude's [data storage & credentials documentation](https://claude.com/docs/cowork/3p/data-storage#credentials) for where these credentials live.
  </Tab>

  <Tab title="OpenCode (CLI)">
    Log out and re-authenticate the affected server:

    ```bash theme={"dark"}
    opencode mcp logout <mcp-server>
    opencode mcp auth <mcp-server>
    ```

    See OpenCode's [MCP servers documentation](https://opencode.ai/docs/mcp-servers/#authenticating) for managing credentials.
  </Tab>
</Tabs>

***

If you continue to experience issues after following the steps for your client, reach out and we'll be happy to assist.
