MCP Client Identity
An MCP client that connects to a remote MCP server over HTTP acts as an OAuth 2.1 client. It cannot call a protected MCP server without credentials and a token, the same as any other client calling a protected API. An MCP client connecting to a server launched locally over stdio is outside the MCP authorization specification; it takes credentials from the environment instead.
Public vs. Confidential Clients
An OAuth client is either public, unable to hold a secret in confidence, or confidential, able to authenticate with one. Most MCP clients, desktop AI hosts, CLI tools, and debug UIs among them, run entirely on the user's machine or in a context where a bundled secret could be extracted. That makes them public clients, and a public client requesting a token on a user's behalf must use PKCE (Proof Key for Code Exchange) to protect the authorization code from interception.
User-Delegated vs. Machine-to-Machine Clients
An MCP client authenticates in one of two shapes:
- User-delegated: a human is the subject. The client runs Authorization Code with PKCE, and the token it receives carries the signed-in user's access.
- Machine-to-machine: the client itself is the subject, with no user involved. The client runs Client Credentials, and the token carries the client's own access.
Redirect URIs for Local Clients
A user-delegated client needs a redirect URI to receive the authorization code. Local MCP clients complicate this in ways a typical web app redirect URI does not:
- Redirect URIs match exactly, port included, with no wildcards.
- Local clients typically use a loopback callback (
http://localhost:PORT/callbackor127.0.0.1), rather than a public HTTPS redirect URI. - Some clients pick a random port each time they start, so there is no fixed redirect URI to register ahead of time.
That last case is why static registration alone does not cover every MCP client.
Registering Clients You Did Not Build
Registering a client ahead of time, giving it a client ID and a fixed redirect URI before it ever connects, works when you know the client in advance. Many MCP clients are different. Claude and Visual Studio Code are the same client on every user's device, and they connect to MCP servers their vendor has never seen, so they cannot arrive with a client ID your server already knows, and you cannot pre-register every install.
The MCP specification identifies these clients with a Client ID Metadata Document (CIMD). The vendor publishes the client's metadata as a JSON document at an HTTPS URL on its own domain, and that URL is the client ID on every install. The redirect URIs come from the vendor's document, so authorization codes return only to the vendor's domain or to the user's own device. In ThunderID, you register such a client once from its document, and ThunderID reads the document only when you register or re-fetch it.
The specification keeps Dynamic Client Registration (DCR) for backward compatibility. With DCR, each install registers itself when it connects and supplies its own metadata. Every install becomes a separate client with self-asserted metadata, so there is no stable client ID to allow or refuse.
How ThunderID Fits
ThunderID represents an MCP client as the MCP client application type, configured as either user-delegated or machine-to-machine. There are three ways to create a client: register it from its metadata document, configure it manually in the Console, or let it register itself the first time it connects.
Compare the Registration Options
| Metadata document | Configure manually | Dynamic Client Registration | |
|---|---|---|---|
| Who defines the client | The vendor's metadata document | You, in the Console | The client, when it registers itself |
| How it works | You enter the client's metadata document URL, or pick a known client, and review what the document declares before ThunderID creates the application. | You create the application ahead of time and set its redirect URI. | The client registers itself against the DCR endpoint the first time it connects. |
| Best for | Third-party clients that publish a metadata document, such as Claude and Visual Studio Code. | Clients you build or configure yourself, such as MCP Inspector or your own agent. | Clients you cannot enumerate in advance, or that expect DCR, such as Claude Code. |
| What you control | Which clients are registered. The redirect URIs and authentication method come from the vendor's document. | The client's name, redirect URI, and client type, set up front in the Console. | Whether Dynamic Client Registration is enabled, and whether it requires authentication. |
Which Should You Pick?
Register the client from its metadata document when its vendor publishes one. You choose which clients may connect, and the vendor keeps the redirect URIs and keys accurate. Configure the client manually when you know it ahead of time and can set its redirect URI yourself, such as a client you built. Reach for Dynamic Client Registration when you cannot enumerate every client in advance, or when the client itself expects DCR and has no way to accept a pre-issued client ID, such as Claude Code.
The choice is not exclusive at the deployment level. You can register some clients from their metadata documents, configure others manually, and leave Dynamic Client Registration enabled for the rest.
Related
- Register an MCP Client from Its Metadata Document: register a client its vendor describes in a metadata document.
- Configure an MCP Client Manually: create an application for a known client.
- Enable Dynamic Client Registration: let clients register themselves on first connect.