Authenticate MCP clients with OAuth
Overview
This page explains how to connect an MCP-aware AI client - Claude Code or Visual Studio Code - to a CAST MCP Server using OAuth, instead of passing a CAST Imaging API key in the client configuration. It is intended for the administrator who configures Keycloak, and for the end user who configures the AI client. It applies to both MCP Server for CAST Imaging and MCP Server for CAST Gatekeeper.
With OAuth enabled, the first request from the AI client opens a browser window and the user signs in to CAST Imaging through Keycloak. The access token is then exchanged by CAST Imaging so that all downstream API calls carry the roles and permissions of the signed-in user. No API key is stored in the client configuration file.
- Authentication using a CAST Imaging API key remains fully supported and is unchanged - see Generating an API key. Existing
mcp.jsonfiles continue to work and do not need to be migrated. Choose OAuth or an API key for a given client, not both. - OAuth relies on the Client ID Metadata Document (CIMD) feature of Keycloak, which is flagged as experimental by Keycloak. Keycloak has announced no timeline for making it generally available.
Requirements
- CAST Imaging 3.6.6-funcrel or later (see below)
- the MCP Server release matching the results you query:
- MCP Server for CAST Imaging: 3.0.4-funcrel or later
- MCP Server for CAST Gatekeeper: 3.0.1-funcrel or later
- access to the Keycloak admin UI at
http://<imaging-services-fqdn>:8090/authwith thekcadminaccount - see Configure authentication and Keycloak accounts and passwords - an MCP-aware client, either Claude Code or Visual Studio Code
- for a production setup HTTPS configuration enabled on the CAST Imaging gateway is highly recommended
What is already configured
The following is provided by the CAST Imaging installation and requires no action:
- the Keycloak CIMD feature is enabled out of the box
- the
mcp:*client scopes, their audience mappers, and the confidentialmcp-token-exchangeclient are created automatically at start up - the CAST Imaging gateway (the
imaging-servicescomponent) performs the token exchange for MCP requests
The configuration you perform is the per-client CIMD policy in Keycloak (Step 1) and the AI client configuration itself (Step 2), plus the PUBLIC_URL environment variable described below for a Windows installation accessed over http.
Windows installations accessed over HTTP
This applies to a Windows installation only, when CAST Imaging is accessed over http. No action is required for a Docker installation, or when HTTPS configuration is enabled.
On the machine on which the imaging-services component is installed, create a SYSTEM level environment variable called PUBLIC_URL, using the fully qualified domain name of that machine and the user access port 8090:
PUBLIC_URL=http://<imaging-services-fqdn>:8090
Restart the imaging-services services for the change to be taken into account.
Step 1 - Create the CIMD client policy in Keycloak
In Keycloak, a CIMD policy consists of two linked objects:
- a profile, which holds the rules
- a policy, which determines the clients the rules apply to
Create one profile and one policy per AI client you intend to support. Log in to the Keycloak admin UI, ensure you are working in the aip-realm realm, then navigate to Realm Settings > Client Policies.
Use the tabs below to select the configuration matching your deployment: HTTPS for a production deployment, HTTP for a development or test deployment only.
Claude Code
Create the profile from Profiles > Create client profile, then add the client-id-metadata-document executor:
| Setting | Value |
|---|---|
| Name | cimd-profile-claude |
| Executor | client-id-metadata-document |
| Allow http scheme | OFF |
| Restrict same domain | OFF |
| Only Allow Confidential Client | OFF |
| Trusted domains | claude.ai, localhost, 127.0.0.1 |
Create the policy from Policies > Create client policy, then add the client-id-uri condition:
| Setting | Value |
|---|---|
| Name | cimd-policy-claude |
| Condition | client-id-uri |
| URI scheme | https |
| Trusted domains | claude.ai |
Visual Studio Code
Create the profile from Profiles > Create client profile, then add the client-id-metadata-document executor:
| Setting | Value |
|---|---|
| Name | cimd-profile-vscode |
| Executor | client-id-metadata-document |
| Allow http scheme | OFF |
| Restrict same domain | OFF |
| Only Allow Confidential Client | OFF |
| Trusted domains | vscode.dev, code.visualstudio.com, 127.0.0.1 |
Create the policy from Policies > Create client policy, then add the client-id-uri condition:
| Setting | Value |
|---|---|
| Name | cimd-policy-vscode |
| Condition | client-id-uri |
| URI scheme | https |
| Trusted domains | vscode.dev |
- Link the profile to the policy. Open the policy, for example
cimd-policy-claude, then in Associated client profiles add the matching profile, for examplecimd-profile-claude. Without this link the policy has no effect and the browser sign-in fails without an error message. This is the most common configuration mistake. - The CAST Imaging gateway holds the confidential token exchange secret and must remain the only entry point exposed to end users. Do not expose the MCP Server or Keycloak directly.
This configuration allows the http scheme and loopback callbacks, and is acceptable only on a trusted local or CI host that is not reachable from the internet. Use the HTTPS (production) configuration for any shared deployment.
For a Windows installation, ensure that the PUBLIC_URL environment variable is set - see Windows installations accessed over HTTP.
Claude Code
Create the profile from Profiles > Create client profile, then add the client-id-metadata-document executor:
| Setting | Value |
|---|---|
| Name | cimd-profile-claude |
| Executor | client-id-metadata-document |
| Allow http scheme | ON |
| Restrict same domain | OFF |
| Only Allow Confidential Client | OFF |
| Trusted domains | claude.ai, localhost, 127.0.0.1 |
Create the policy from Policies > Create client policy, then add the client-id-uri condition:
| Setting | Value |
|---|---|
| Name | cimd-policy-claude |
| Condition | client-id-uri |
| URI scheme | https, http |
| Trusted domains | claude.ai |
Visual Studio Code
Create the profile from Profiles > Create client profile, then add the client-id-metadata-document executor:
| Setting | Value |
|---|---|
| Name | cimd-profile-vscode |
| Executor | client-id-metadata-document |
| Allow http scheme | ON |
| Restrict same domain | OFF |
| Only Allow Confidential Client | OFF |
| Trusted domains | vscode.dev, code.visualstudio.com, 127.0.0.1 |
Create the policy from Policies > Create client policy, then add the client-id-uri condition:
| Setting | Value |
|---|---|
| Name | cimd-policy-vscode |
| Condition | client-id-uri |
| URI scheme | https, http |
| Trusted domains | vscode.dev |
Link the profile to the policy. Open the policy, for example cimd-policy-claude, then in Associated client profiles add the matching profile, for example cimd-profile-claude. Without this link the policy has no effect and the browser sign-in fails without an error message. This is the most common configuration mistake.
About the two trusted domain lists
The two Trusted domains lists serve different purposes and are not interchangeable:
- the list in the profile defines where Keycloak fetches the client metadata document from, and validates the loopback callback address, which is why it includes
localhostand127.0.0.1 - the list in the policy matches the origin of the
client_idURL only
Each AI client presents a fixed client_id:
| AI client | client_id |
|---|---|
| Claude Code | https://claude.ai/oauth/client-metadata.json |
| Visual Studio Code | https://vscode.dev/oauth/client-metadata.json |
The client_id must contain a path and must not carry a query string or a fragment. For the full description of the executor and condition see the Keycloak MCP authorization server documentation .
Step 2 - Configure your AI client
The AI client must point to the CAST Imaging gateway - the machine on which the imaging-services component is installed - and not to the MCP Server directly. Use:
- either
httporhttpsdepending on whether HTTPS configuration has been enabled - the fully qualified domain name of the machine, such as
imaging.corp.mycompany.com, or its IP address - the user access port for CAST Imaging, either
8090(http) or443(https) - whenhttpsruns on port443the port can be omitted - the endpoint of the target MCP Server:
| MCP Server | Endpoint |
|---|---|
| CAST Imaging | /mcp |
| CAST Gatekeeper | /mcp/gatekeeper |
Selecting a target domain (tenant) is not supported when using OAuth: there is no equivalent to the x-user-tenant header available with API key authentication - see domain mapping.
- Add the MCP Server, adjusting the URL and the endpoint to match your environment:
$ claude mcp add --transport http --scope user cast-imaging http[s]://<fqdn-or-IP-address-imaging-services-machine:[port]>/mcp
- Run
claude, then enter/mcpand select cast-imaging > Authenticate. A browser window opens on the Keycloak sign-in page. - Sign in with your CAST Imaging credentials.
- Confirm the connection:
$ claude mcp list
- Create an
mcp.jsonfile in the.vscode/folder of your workspace, or use MCP: Open User Configuration, and update the URL and the endpoint to match your environment:
{
"servers": {
"cast-imaging": {
"type": "http",
"url": "http[s]://<fqdn-or-IP-address-imaging-services-machine:[port]>/mcp"
}
}
}
- Start the server using the gutter action in
mcp.json, then click Allow. A browser window opens on the Keycloak sign-in page. - Sign in with your CAST Imaging credentials.
- Open Chat and select Agent mode - the CAST tools are listed in the tool picker.
The OAuth configuration contains no inputs block and no headers block: this is the difference from the API key configuration described in the installation instructions.
Step 3 - Verify
Run the following from any machine that can reach the CAST Imaging gateway, replacing the URL and the endpoint with your own values:
# Protected resource metadata, unauthenticated - returns JSON pointing at the Keycloak issuer
$ curl -s http[s]://<fqdn-or-IP-address-imaging-services-machine:[port]>/.well-known/oauth-protected-resource/mcp | jq
# The healthcheck endpoint remains open - expect 200
$ curl -s -o /dev/null -w '%{http_code}\n' http[s]://<fqdn-or-IP-address-imaging-services-machine:[port]>/mcp/healthcheck
# An unauthenticated POST returns the Bearer challenge
$ curl -s -i -X POST http[s]://<fqdn-or-IP-address-imaging-services-machine:[port]>/mcp | grep -i www-authenticate
The last command returns a header of the following form:
WWW-Authenticate: Bearer resource_metadata="http[s]://<fqdn-or-IP-address-imaging-services-machine:[port]>/.well-known/oauth-protected-resource/mcp"
The setup is complete when, after signing in from the AI client, a query such as List all applications returns results.
Troubleshooting
Claude Code reports "JSON Parse error: Unrecognized token '<'"
Claude Code probes the path-inserted discovery URLs first, and the error is raised when those URLs return HTML instead of JSON. CAST Imaging already redirects these requests to the Keycloak discovery endpoint, so no action is required. If the error persists, confirm that the AI client points to the CAST Imaging gateway and the /mcp endpoint, and not to the MCP Server or to Keycloak directly.
The browser sign-in never opens, or the callback fails
Check the following:
- the domain of the AI client is listed in the Trusted domains of both the profile and the policy
- the profile is linked to the policy through Associated client profiles
- for a development deployment over
http, the Allow http scheme setting is ON in the profile
Sign-in succeeds but the tools return 401 or 403
The token issued to the AI client carries no CAST Imaging roles until it has been exchanged, and the exchange is performed by the CAST Imaging gateway. Confirm that requests are routed through the gateway - the imaging-services machine - and not sent directly to the MCP Server.
The policy exists but CIMD is ignored
The profile is not linked to the policy. Open the policy, then in Associated client profiles add the matching cimd-profile-* profile.
FAQ
See the frequently asked questions for MCP Server for CAST Imaging and for MCP Server for CAST Gatekeeper.