Configure an MCP Client Manually
Configure an MCP client manually when you know its redirect URI ahead of time, such as MCP Inspector or a client you built yourself. This gives you a stable Client ID before the client ever connects. If the client's vendor publishes a metadata document, register it from that document instead.
Prerequisites
- ThunderID is running. See Get Started.
- You can sign in to the ThunderID Console.
- The redirect URI your MCP client uses for its OAuth callback, if it acts on behalf of a user.
Step 1: Start the Application Wizard
- Sign in to the ThunderID Console.
- Navigate to Applications and click Add application.
- Select MCP client.
- If prompted, select an organization unit.
- On Which MCP client are you connecting?, select I'll configure it myself and click Continue.
- Enter a name for the client.
Step 2: Choose the Client Type
The Client type step is the most important choice on this page: it decides how the client obtains tokens and whether it acts for a signed-in user.
On Behalf of a User
Select On behalf of a user for an MCP client running inside a host app, such as an IDE, desktop app, or chat client, that a person signs in to interactively. MCP Inspector is this type.
This option configures the Authorization Code flow with PKCE. PKCE stays required while the client has the authorization code grant, so the Advanced tab shows PKCE required as read-only. Selecting this type also embeds the redirect URI editor directly in this step, so add at least one redirect URI here before continuing.
By default, ThunderID registers the client as a public client with no client secret. Turn on Confidential client for a client with a backend that can keep a secret. ThunderID then registers it with the client_secret_basic authentication method and issues a client secret. PKCE stays required. A client must be confidential to use identity assertions (ID-JAG).
Machine-to-Machine
Select On its own behalf for a client that authenticates with its own credentials and has no signed-in user, such as an autonomous agent or a background service calling MCP servers directly.
This option configures the Client Credentials flow and registers the client as a confidential client. ThunderID issues a client secret, and no redirect URI is collected because this client type never redirects a user anywhere.
Step 3: Finish
Click Finish. ThunderID creates the application and opens its detail page. For a client with a client secret, either machine-to-machine or user-delegated with Confidential client on, a dialog shows the secret first. Copy it before you click Continue, because ThunderID does not display it again.
Open the General tab: its Connection card shows the Client ID. See Where Credentials Live for the rest of the client's credentials.
Redirect URI Rules
For a user-delegated client, each redirect URI must satisfy one of two rules:
- A loopback address over
http:: the host must belocalhost,127.0.0.1, or[::1], with an optional port (for example,http://localhost:6274/oauth/callback). - Any address over
https:.
Any other scheme is rejected, including plain http:// on a non-loopback host. Wildcards (*) are rejected anywhere in the URI. The backend's create-time validation independently rejects a wildcard in a redirect URI's port unconditionally, and rejects a wildcard host unless the deployment has explicitly opted in to wildcard redirect URIs, so a wildcard MCP redirect URI is never accepted through the Console.
Ports must match exactly. If your client picks a random callback port each time it starts, such as a local CLI tool that binds to an ephemeral port, you cannot register that exact port ahead of time. Dynamic Client Registration exists for this case: the client registers its own redirect URI, including whatever port it happened to bind, at connection time instead of you pre-registering it.
Where Credentials Live
The application's General tab holds a Connection card with:
- Application ID: the ThunderID application identifier.
- Client ID: the OAuth 2.1 client ID, for both client types.
For a confidential client, the Connection card links to the Credentials tab. That tab shows the Client ID again, along with the following settings:
- Client secret: shown only for a client that authenticates with a client secret (
client_secret_basicorclient_secret_post). The field displays a masked placeholder, never the actual value. Click Regenerate client secret, then Regenerate to confirm. ThunderID shows the new secret once in a dialog. Copy it immediately: closing the dialog without copying means regenerating another one, which invalidates the previous secret for any client already using it. - Certificate: the client's public keys, as an inline JWKS or a JWKS URI. A client that authenticates with
private_key_jwtneeds one, and the Console does not save that authentication method without it.
Access Control
For a user-delegated client, the General tab also shows an Access card:
- Allowed user types: which user types can sign up through this client. Leave it empty if users should not be able to sign up through it.
- Enable agent sign-in: whether agents of any agent type can sign in to this client through its sign-in flow. If the client allows only specific agent types, set through the API, the card lists them. See Agent Sign-In.
- Client URI: an optional public homepage for the client.
- Authorized redirect URIs: the same redirect URIs configured during creation, editable here. Each one follows the redirect URI rules above. At least one is required while the client has the authorization code grant.
A machine-to-machine client has no signed-in user, so the Console does not show this card for it.
Browser-Based Clients Need a CORS Origin
If your MCP client runs in a browser, such as a web-based inspector or dashboard, and calls ThunderID cross-origin, its origin must be explicitly allowed. This is a deployment-wide CORS setting, not a per-application one, so it is configured separately from the steps above.
Add the origin to config/resources/server_configs/cors.yaml in your ThunderID distribution:
name: cors
value:
allowedOrigins:
- "http://localhost:6274"
If the file already exists, append to the existing allowedOrigins list instead of replacing it. You can also update this at runtime with PUT /server-config/cors. Restart ThunderID after editing the file.
Use Identity Assertions (ID-JAG)
A confidential MCP client can use identity assertions (ID-JAG) with ThunderID in either direction:
- To request identity assertions for an external authorization server, use a user-delegated client. Open its Advanced tab and turn on Identity assertions (ID-JAG). Add at least one entry under Allowed audiences, because Save stays disabled until you do. Turning on the toggle also adds the Token exchange grant type, which you cannot remove from Grant types until you turn identity assertions off. The client signs the user in with the authorization code grant, then exchanges the user's ID token for an assertion. See Issue Identity Assertions (ID-JAG).
- To redeem identity assertions from a trusted identity provider, open the Advanced tab and add the JWT bearer grant type. See Accept Identity Assertions from an External IdP.
The Identity assertions (ID-JAG) toggle is disabled for a public client. To make a public client confidential, turn off Public client on the Advanced tab, or select JWT bearer, which also turns it off. Either way, Client authentication method changes to client_secret_basic, and Public client stays disabled while JWT bearer is selected or identity assertions are on. Saving the change does not display a client secret, so click Regenerate client secret on the Credentials tab to get one. Saving and regenerating both invalidate the refresh tokens issued before them, so users must sign in again.
Some clients only redeem identity assertions and never sign users in themselves, such as an MCP client that reaches MCP servers through enterprise-managed authorization. For such a client, keep JWT bearer selected and turn off Identity assertions (ID-JAG) if it is on. Then remove Token exchange and clear authorization_code in Grant types.
Clearing authorization_code also removes refresh_token and turns off PKCE required. Authorized redirect URIs then become optional, so you can delete the redirect URI the wizard asked for. The Flows and Customization tabs are hidden, and the Connection card shows the client as On behalf of a user (JWT bearer with ID-JAG).
Manage the Client
To update a client's configuration, open it from the Applications list, change the setting on its tab, and click Save in the bar that appears. Changes take effect immediately for new authentication requests. Active sessions and issued access tokens stay valid until they expire. Refresh tokens stop working once you remove refresh_token from Grant types, and the token endpoint rejects them with unauthorized_client. Clearing authorization_code also removes refresh_token.
To rotate the client secret, click Regenerate client secret on the Credentials tab, then Regenerate to confirm. This immediately invalidates the previous secret. It also revokes the access and refresh tokens issued before the rotation, so users must sign in again.
To delete a client, open it from the Applications list and click Delete application under Danger zone on the Advanced tab. This is permanent: any caller using the client's Client ID immediately loses the ability to authenticate. ThunderID also revokes every token issued through the Client ID and removes the client from active sessions. Deleting through the DELETE /applications/{id} API removes the record only, so its tokens stay valid until they expire.
Next Steps
- Dynamic Client Registration: Let clients register themselves instead of pre-registering them here.
- Secure Your MCP Server: Protect the MCP server this client connects to.
- Enterprise-Managed Authorization for MCP: Let an enterprise identity provider govern which MCP clients reach which MCP servers through identity assertions.
- Manage Applications: General application management, covering all application types.
- Connect a Python MCP Server: A runnable quickstart that registers an MCP Inspector client this way, end to end.