Authenticate MCP clients with OAuth

Sign an AI client in to CAST Imaging with OAuth instead of a CAST Imaging API key

Overview

Available in ≥ 3.6.6-funcrel

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.

Requirements

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 confidential mcp-token-exchange client are created automatically at start up
  • the CAST Imaging gateway (the imaging-services component) 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

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

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 localhost and 127.0.0.1
  • the list in the policy matches the origin of the client_id URL 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 documentationexternal link.

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 http or https depending 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) or 443 (https) - when https runs on port 443 the port can be omitted
  • the endpoint of the target MCP Server:
MCP Server Endpoint
CAST Imaging /mcp
CAST Gatekeeper /mcp/gatekeeper

  1. 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
  1. Run claude, then enter /mcp and select cast-imaging > Authenticate. A browser window opens on the Keycloak sign-in page.
  2. Sign in with your CAST Imaging credentials.
  3. Confirm the connection:
$ claude mcp list
  1. Create an mcp.json file 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"
    }
  }
}
  1. Start the server using the gutter action in mcp.json, then click Allow. A browser window opens on the Keycloak sign-in page.
  2. Sign in with your CAST Imaging credentials.
  3. Open Chat and select Agent mode - the CAST tools are listed in the tool picker.

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.