# MCP Server

Source: https://apereo.github.io/cas/development/installation/Admin-MCP-Server.html

CAS can act as a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server, allowing AI assistants, agents and other MCP clients to examine the state of a CAS deployment through a set of read-only tools. Typical use cases include troubleshooting an application registration, inspecting a single sign-on session or verifying the attributes CAS resolves for a given person, all from within the MCP client of your choice.

Support is enabled by adding the following module into the overlay:

```groovy
dependencies {
    /*
        The following platform references are included automatically and are listed for reference only.

        implementation enforcedPlatform("org.apereo.cas:cas-server-support-bom:${project.'cas.version'}")
        implementation platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
        
    */
    implementation "org.apereo.cas:cas-server-support-mcp"
}
```

## Transport

The MCP server uses the [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http) transport and is available by default at `/cas/mcp`. The endpoint accepts JSON-RPC messages over HTTP `POST` and answers with either JSON or server-sent events, as the specification requires. The server name, version, instructions, transport protocol and endpoint path along with the capabilities advertised to clients can be adjusted via CAS settings.

The following settings and properties are available from the CAS configuration catalog:

- `spring.ai.mcp.server.annotation-scanner.enabled` (Third party; type `Boolean`; default `true`)
- `spring.ai.mcp.server.base-url` (Third party; type `String`; deprecation `WARNING`, no replacement)
- `spring.ai.mcp.server.capabilities.completion` (Third party; type `Boolean`; default `true`)
- `spring.ai.mcp.server.capabilities.prompt` (Third party; type `Boolean`; default `true`)
- `spring.ai.mcp.server.capabilities.resource` (Third party; type `Boolean`; default `true`)
- `spring.ai.mcp.server.capabilities.tool` (Third party; type `Boolean`; default `true`)
- `spring.ai.mcp.server.enabled` (Third party; type `Boolean`; default `true`): Enable/disable the MCP server. When set to false, the MCP server and all its components will not be initialized.
- `spring.ai.mcp.server.expose-mcp-client-tools` (Third party; type `Boolean`; default `false`): Whether to re-expose downstream MCP tools (provided by MCP clients) as tools in this MCP server. Defaults to false.
- `spring.ai.mcp.server.instructions` (Third party; type `String`): The instructions of the MCP server instance. These instructions are used to provide guidance to the client on how to interact with this server.
- `spring.ai.mcp.server.keep-alive-interval` (Third party; type `Duration`; deprecation `WARNING`, no replacement): The duration to keep the connection alive. Disabled by default.
- `spring.ai.mcp.server.modern.discover-cache-scope` (Third party; type `McpSchema.CacheScope`; default `private`): Who may reuse a cached `server/discover` result.
- `spring.ai.mcp.server.modern.discover-ttl` (Third party; type `Duration`; default `0`): How long clients may cache the `server/discover` result. Zero disables caching.
- `spring.ai.mcp.server.modern.keep-alive-interval` (Third party; type `Duration`; default `30s`): Interval between keep-alive comments on streaming responses. Zero or negative disables keep-alives.
- `spring.ai.mcp.server.modern.list-cache-scope` (Third party; type `McpSchema.CacheScope`; default `private`): Who may reuse cached list results.
- `spring.ai.mcp.server.modern.list-ttl` (Third party; type `Duration`; default `0`): How long clients may cache list results (`tools/list`, `prompts/list`, `resources/list`, `resources/templates/list`). Zero disables caching.
- `spring.ai.mcp.server.modern.max-request-size` (Third party; type `DataSize`; default `16MB`): Maximum accepted request body size.
- `spring.ai.mcp.server.modern.mcp-endpoint` (Third party; type `String`; default `/mcp`): The HTTP endpoint the server listens on. POST only.
- `spring.ai.mcp.server.modern.page-size` (Third party; type `Integer`): Maximum number of entries per list page (`tools/list`, `prompts/list`, `resources/list`, `resources/templates/list`) of the in-memory repositories. Unset returns everything on a single page.
- `spring.ai.mcp.server.modern.request-state-secret` (Third party; type `String`): Secret used to seal the multi round-trip `requestState`, at least 32 bytes. Must be shared by every instance behind a load balancer. When unset a random per-instance key is used and retries must reach the same instance.
- `spring.ai.mcp.server.modern.request-state-ttl` (Third party; type `Duration`): How long a sealed `requestState` stays valid.
- `spring.ai.mcp.server.modern.resource-subscribe` (Third party; type `Boolean`; default `false`): Whether the server advertises per-resource subscriptions (`resources.subscribe`).
- `spring.ai.mcp.server.modern.subscriptions` (Third party; type `Boolean`; default `true`): Whether to serve `subscriptions/listen` for list-changed and resource-updated notifications.
- `spring.ai.mcp.server.modern.supported-versions` (Third party; type `List<String>`): The protocol versions the server accepts in `_meta`. Defaults to the latest revision the SDK implements.
- `spring.ai.mcp.server.name` (Third party; type `String`; default `mcp-server`): The name of the MCP server instance. This name is used to identify the server in logs and monitoring.
- `spring.ai.mcp.server.prompt-change-notification` (Third party; type `Boolean`; default `true`): Enable/disable notifications for prompt changes. Only relevant for MCP servers with prompt capabilities. When enabled, the server will notify clients when prompt templates are modified.
- `spring.ai.mcp.server.protocol` (Third party; type `McpServerProperties.ServerProtocol`; default `streamable`)
- `spring.ai.mcp.server.request-timeout` (Third party; type `Duration`; default `20s`): Sets the duration to wait for server responses before timing out requests. This timeout applies to all requests made through the client, including tool calls, resource access, and prompt operations.
- `spring.ai.mcp.server.resource-change-notification` (Third party; type `Boolean`; default `true`): Enable/disable notifications for resource changes. Only relevant for MCP servers with resource capabilities. When enabled, the server will notify clients when resources are added, updated, or removed.
- `spring.ai.mcp.server.sse-endpoint` (Third party; type `String`; deprecation `WARNING`, no replacement; default `/sse`): An SSE endpoint, for clients to establish a connection and receive messages from the server
- `spring.ai.mcp.server.sse-message-endpoint` (Third party; type `String`; deprecation `WARNING`, no replacement; default `/mcp/message`): A regular HTTP POST endpoint for clients to send messages to the server.
- `spring.ai.mcp.server.stdio` (Third party; type `Boolean`; default `false`): Enable/disable the standard input/output (stdio) transport. When enabled, the server will listen for incoming messages on the standard input and write responses to the standard output.
- `spring.ai.mcp.server.streamable-http.disallow-delete` (Third party; type `Boolean`; default `false`)
- `spring.ai.mcp.server.streamable-http.keep-alive-interval` (Third party; type `Duration`): The duration to keep the connection alive.
- `spring.ai.mcp.server.streamable-http.mcp-endpoint` (Third party; type `String`; default `/mcp`)
- `spring.ai.mcp.server.tool-change-notification` (Third party; type `Boolean`; default `true`): Enable/disable notifications for tool changes. Only relevant for MCP servers with tool capabilities. When enabled, the server will notify clients when tools are registered or unregistered.
- `spring.ai.mcp.server.tool-response-mime-type` (Third party; type `Map<String,String>`): (Optional) response MIME type per tool name.
- `spring.ai.mcp.server.type` (Third party; type `McpServerProperties.ApiType`; default `sync`): The type of server to use for MCP server communication. Supported types are: - SYNC - Standard synchronous server (default) - ASYNC - Asynchronous server
- `spring.ai.mcp.server.version` (Third party; type `String`; default `1.0.0`): The version of the MCP server instance.

**Groovy scripting**

CAS takes advantage of Apache Groovy in forms of either embedded or external scripts that allow one to, by default, dynamically build constructs, attributes, access strategies and a lot more. To activate the functionality described here, you may need to prepare CAS to support and integrate with Apache Groovy.

Please [review this guide](https://apereo.github.io/cas/development/integration/Apache-Groovy-Scripting.html) to configure your build.

## Security

Every request to the MCP endpoint must be authenticated with HTTP Basic authentication. The credentials are verified by the same user stores that protect CAS actuator endpoints, such as the Spring Security user, JSON, JDBC, LDAP or JAAS user details sources.

The following settings and properties are available from the CAS configuration catalog:

- `spring.security.user.name` (Third party; type `String`; default `user`): Default user name.
- `spring.security.user.password` (Third party; type `String`): Password for the default user name.
- `spring.security.user.roles` (Third party; type `List<String>`): Granted roles for the default user name.

Authenticated users may initialize a session and list the available tools. Calling a tool additionally requires the `ROLE_MCP_ADMIN` role/authority, and calling one of the [tools that change CAS](https://apereo.github.io/cas/development/installation/Admin-MCP-Server.html#tools-that-change-cas) requires the `ROLE_MCP_OPERATOR` role/authority. A tool call made by a user without the required role is answered with an error result and the tool is not executed.

Every tool call and resource read is recorded in the [audit log](https://apereo.github.io/cas/development/audits/Audits.html) under the MCP user who made it, with the action `MCP_TOOL_CALL_SUCCESS`, `MCP_TOOL_CALL_DENIED` or `MCP_TOOL_CALL_FAILED` and, as the resource, the tool name or resource URI along with its arguments. Calls refused for lack of the `MCP_ADMIN` role are recorded too.

> **Usage Warning!**
>
> The tools return sensitive data, such as the attributes CAS resolves and releases for a person, single sign-on session identifiers and full application definitions. Only grant the `MCP_ADMIN` role to trusted operators, keep the MCP endpoint on a protected network and always use TLS.

### OAuth Access Tokens

When [OpenID Connect](https://apereo.github.io/cas/development/authentication/OIDC-Authentication.html) is also included, the MCP endpoint is an OAuth protected resource, as the [MCP authorization specification](https://modelcontextprotocol.io/specification/latest/basic/authorization) expects, and MCP clients may sign people in with CAS and call the MCP server with the access tokens CAS issues to them. HTTP Basic authentication keeps working alongside.

A request without credentials is answered with `401` and two challenges: `Basic`, and `Bearer` with the `mcp:read` scope and the location of the protected resource metadata ([RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728)), which MCP clients follow to discover CAS as their authorization server. The metadata is published under the CAS context path, at `/cas/.well-known/oauth-protected-resource/mcp`:

```json
{
  "resource": "https://sso.example.org/cas/mcp",
  "authorization_servers": [
    "https://sso.example.org/cas/oidc"
  ],
  "scopes_supported": [
    "mcp:read"
  ],
  "bearer_methods_supported": [
    "header"
  ],
  "resource_name": "Apereo CAS MCP Server"
}
```

An access token is accepted in the `Authorization: Bearer` header only, never as a request parameter, and only when:

- it is found in the ticket registry, either by its identifier or, for JWT access tokens, by the identifier it carries, and has not expired;
- it was issued for the MCP endpoint, which clients request with the `resource` parameter ([RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)). CAS allows every client to [request the MCP endpoint](https://apereo.github.io/cas/development/authentication/OAuth-Authentication-Clients.html#resources-for-every-client) by default;
- the application it was issued to is still registered and allowed;
- it is not bound to a [DPoP](https://apereo.github.io/cas/development/authentication/OIDC-Authentication-DPoP.html) key or a client certificate. Sender-constrained tokens are not accepted yet.

Otherwise the request is refused with `401` and `error="invalid_token"`. A token without the `mcp:read` scope is refused with `403` and `error="insufficient_scope"`. When the [tools that change CAS](https://apereo.github.io/cas/development/installation/Admin-MCP-Server.html#tools-that-change-cas) are turned on, the protected resource metadata also lists the `mcp:write` scope.

Like a Basic user, the person behind a token may connect and list tools, but only calls tools with the `MCP_ADMIN` role. With an access token, the role is granted only to people whose principal attributes match all the attributes and regular expressions defined in CAS settings. These are the attributes CAS resolves for the person when the token is used, through its attribute repositories, so the role does not depend on the attributes released to the client and follows changes to the person’s attributes. No attributes are defined by default, so tokens grant nobody the role until you define them. The audit record of a call made with a token also names the OAuth client.

The `MCP_OPERATOR` role, which the tools that change CAS require, is granted to the person behind a token only when the token also carries the `mcp:write` scope and the person’s attributes match a separate set of attributes and regular expressions, which is empty by default. A token that carries `mcp:write` grants nothing more without those attributes, and a person with those attributes cannot change CAS with a token issued for `mcp:read` only. Add `mcp:write` to the scopes of the discovery document and to the applications that may change CAS, in the same way as `mcp:read`.

The following settings and properties are available from the CAS configuration catalog:

- `cas.mcp.oauth.operator-required-attributes` (Optional; type `Map<String,String>`)
- `cas.mcp.oauth.required-attributes` (Optional; type `Map<String,String>`)

The OpenID Connect provider only issues scopes it supports, so add `mcp:read` to the scopes of the OpenID Connect discovery document and to the scopes of the applications that may call the MCP server.

MCP clients usually have no prior relationship with CAS. Besides applications registered by an administrator, they can identify themselves with [client ID metadata documents](https://apereo.github.io/cas/development/authentication/OIDC-Authentication-Client-ID-Metadata-Documents.html), which the MCP authorization specification recommends, or register through [dynamic client registration](https://apereo.github.io/cas/development/authentication/OIDC-Authentication-Dynamic-Registration.html).

**Feature Activation**

To activate this feature, the following feature toggle(s) must be turned on:

```properties
CasFeatureModule.AI.mcp-oauth.enabled=true
```

To learn more about configuration feature toggles, please [see this page](https://apereo.github.io/cas/development/configuration/Configuration-Feature-Toggles.html).

## Tools

The following tools are available. All tools are read-only and are advertised to clients with the `readOnlyHint` annotation. When the requested object cannot be found, the result says why in a `reason` field, except for `findService` and `matchService`, which return nothing.

| Tool | Parameters | Description |
| --- | --- | --- |
| `findService` | `serviceId` (long) | Look up a [registered service](https://apereo.github.io/cas/development/services/Service-Management.html) by its numeric id. The definition is returned as JSON, in the same format used by the JSON service registry, with client secrets, passwords, keys and inline key sets replaced by `<redacted>`. |
| `matchService` | `service` (string) | Find the registered service that matches an application URL, the same way CAS does at login, and return its definition as JSON with secrets replaced by `<redacted>`. |
| `evaluateAccess` | `username`, `service` (string) | Evaluate the [access strategy](https://apereo.github.io/cas/development/services/Configuring-Service-Access-Strategy.html) of the matching registered service against the person’s resolved attributes, and explain why access is denied. |
| `previewAttributeRelease` | `username`, `service` (string) | Preview the username and [attributes](https://apereo.github.io/cas/development/integration/Attribute-Release-Policies.html) CAS would release to the application for the person, along with the access decision. |
| `listMultifactorProviders` | none | List the configured [multifactor authentication providers](https://apereo.github.io/cas/development/mfa/Configuring-Multifactor-Authentication.html) with their ids, names, order and failure modes. |
| `evaluateMultifactorTriggers` | `username`, `service` (string), `clientIpAddress`, `userAgent`, `geoLocation` (optional) | Run the [multifactor authentication triggers](https://apereo.github.io/cas/development/mfa/Configuring-Multifactor-Authentication-Triggers.html) in order for the person and application, and report which provider is required and which trigger selected it. |
| `searchServices` | `query` (string) | Search registered services whose name, service id pattern, description or numeric id contains the text, and return a summary of each. |
| `findSessions` | `username` (string) | Summarize the active single sign-on sessions of a person: a session reference, when each was created and last used, the authentication handlers and the applications accessed. |
| `findTicket` | `ticketId` (string), `username` (optional) | Look up a ticket by its id in the [ticket registry](https://apereo.github.io/cas/development/ticketing/Configuring-Ticketing-Components.html), or a single sign-on session by its session reference and the person’s username, and summarize it: type, creation and last use, number of uses, expiration policy, the principal with the names of its principal and authentication attributes, the application of a service ticket, the session reference, and the applications of a single sign-on session. Attribute values, session ids and the serialized ticket are never returned. Expired tickets are not found. |
| `findPerson` | `username` (string) | Resolve a person by username through the [attribute repositories](https://apereo.github.io/cas/development/integration/Attribute-Resolution.html) and return the principal with its attributes. |
| `findSessionsWithAttribute` | `attributeName`, `attributeValue` (string) | Summarize the active single sign-on sessions, with their session reference and principal, whose principal or authentication attributes contain the value. |
| `previewLogout` | `ticketId` (string), `username` (optional) | Preview which applications would receive a [single logout](https://apereo.github.io/cas/development/installation/Logout-Single-Signout.html) notification if the single sign-on session ended now, with the logout URL and channel of each. Takes a ticket-granting ticket id, or a session reference with the person’s username. Nothing is logged out. |
| `getRegistryStatistics` | none | Report how many single sign-on sessions, service tickets and tickets the ticket registry holds, and how many registered services are loaded. |
| `findTenant` | `tenantId` (string) | Look up a [tenant](https://apereo.github.io/cas/development/multitenancy/Multitenancy-Overview.html) and its policies, along with the names of the settings it overrides; setting values are never returned. |
| `findAuditRecords` | `username` (string), `days` and `action` (optional) | Return the most recent [audit records](https://apereo.github.io/cas/development/audits/Audits.html) of a person, optionally limited to a number of days and to actions that contain the given text. |
| `findAuthenticationEvents` | `username` (string), `days` (optional) | Return the most recent recorded [authentication events](https://apereo.github.io/cas/development/authentication/Configuring-Authentication-Events.html) of a person, such as single sign-on sessions created and destroyed and authentication failures, with the client IP address, user agent and location of each. Device fingerprints are never returned. |
| `describeDeployment` | none | Describe the deployment: CAS version, server name and prefix, active profiles, the feature modules that are turned on, the CAS modules on the classpath, ticket and service registry types, authentication handlers and policies, attribute repositories, and which optional MCP tool groups are active along with the setting that turns each one on. |
| `explainLogin` | `username`, `service` (string), `clientIpAddress`, `userAgent`, `geoLocation` (optional) | Walk through a login in one call, in the order CAS applies each step: the registered service and its access strategy, the risk of the attempt, the multifactor authentication provider, the interrupt and the released username and attributes. Returns the outcome and, for each step, its status and the result of the tool that evaluates it. Passwords are not checked. |
| `validateServiceDefinition` | `definition` (string), `urls` (optional list) | Check a proposed registered service definition, given as JSON, without saving it: whether CAS can read it, whether its service id pattern is valid, whether its id or name collides with an existing service, and for each URL whether it matches, which existing service matches today and which of the two CAS would pick by evaluation priority and order. The definition is not returned. |
| `findThrottledLogins` | `username`, `clientIpAddress` (optional) | Return the failed login attempts that [authentication throttling](https://apereo.github.io/cas/development/authentication/Configuring-Authentication-Throttling.html) tracks, with the username, client IP address, last failure, end of the lock and whether each is throttled now, along with the failure threshold, range and lock window. |
| `findAttributeSources` | `username` (string) | Ask each [attribute repository](https://apereo.github.io/cas/development/integration/Attribute-Resolution.html) separately which attributes it returns for a person, and report the attribute names and any error per repository. Attribute values are not returned; `findPerson` has them. |
| `findAttributeDefinitions` | `query` (optional) | List the [attribute definitions](https://apereo.github.io/cas/development/integration/Attribute-Definitions.html) whose key, name or source attribute contains the text, with their type, scoping, encryption, canonicalization and hashing settings. Scripts are not returned, only whether a definition is scripted. |

The `service` parameter is the application URL, such as the `service` parameter an application sends to CAS at login. Access evaluations are recorded in the [audit log](https://apereo.github.io/cas/development/audits/Audits.html) like any other access strategy decision, and session summaries are limited to the most recent fifty sessions; more about a session can be fetched with `findTicket`.

A ticket-granting ticket id grants access to the single sign-on session it identifies, so the tools never return one. Sessions are identified by a *session reference* instead, such as `session:3f2a…`, derived from the ticket id with a one-way digest. `findTicket` and `previewLogout` accept a session reference together with the username of the person, and look for it among that person’s sessions only. Ticket ids passed to the tools are masked in the audit log the same way CAS masks them in its own audit records.

Multifactor authentication triggers are evaluated against the person’s resolved attributes and a request that carries no parameters, headers, cookies or query string, so triggers that depend on the HTTP request, such as a request parameter or header, are not activated during the evaluation. The optional client IP address, user agent and location describe the login attempt for adaptive triggers: they become the client address, the `User-Agent` header and the `geolocation` parameter that the triggers see. Without them the client is unknown; the address of the MCP request, which belongs to the operator, is never used. Counting tickets may require a scan of the whole ticket registry, depending on the registry in use.

Audit records can only be returned when CAS is configured with an audit storage option that supports querying, such as a database or Redis; the default audit log that is written to the CAS logs cannot be searched. Search results are limited to the first fifty matches, and audit lookups to the most recent hundred records.

Authentication events are only returned when CAS records them in an [events repository](https://apereo.github.io/cas/development/authentication/Configuring-Authentication-Events.html), such as memory, a database or Redis; lookups are limited to the most recent hundred events.

`explainLogin` runs `evaluateAccess`, `evaluateAuthenticationRisk`, `evaluateMultifactorTriggers`, `previewInterrupt` and `previewAttributeRelease` in turn and stops at the first step that denies the login, with the outcome `SERVICE_NOT_REGISTERED`, `ACCESS_DENIED`, `BLOCKED_AS_RISKY`, `BLOCKED_BY_INTERRUPT` or `LOGIN_SUCCEEDS`. Each step has the status `PASSED`, `TRIGGERED` (a requirement such as multifactor authentication is added), `BLOCKED`, `SKIPPED` or `FAILED`. Risk is evaluated only when a client IP address and user agent are given and risk-based authentication is installed, and a step whose module is not installed is skipped. The call is recorded once in the audit log as `explainLogin`; the tools it runs are not recorded separately.

`findThrottledLogins` reads the throttling records that CAS keeps in memory or in Hazelcast. Throttling backed by a database, MongoDB or Redis keeps its records in the audit trail instead, which `findAuditRecords` returns with the action `THROTTLED_LOGIN_ATTEMPT`; the `auditBased` field of the result says when that is the case. At most a hundred records are returned, most recent first.

### Structured Output

Every tool except `findService` and `matchService`, whose definitions are free-form, advertises an `outputSchema` in `tools/list` and returns its result as `structuredContent`, along with the same JSON as text for clients that do not read structured content. Fields without a value are left out of the result rather than set to `null`.

### Optional Tools

Additional tools become available when the feature they examine is included in the CAS build. They are listed by the MCP server only when the corresponding module is present, and each group can be turned off via feature toggles.

| Tool | Requires | Parameters | Description |
| --- | --- | --- | --- |
| `findConsentDecisions` | [Attribute consent](https://apereo.github.io/cas/development/integration/Attribute-Release-Consent.html) | `username` (string) | Return the consent decisions of a person: the application, when consent was given, the reminder settings and the names of the attributes consented to. Attribute values are never returned. |
| `resolveSamlMetadata` | [SAML2 identity provider](https://apereo.github.io/cas/development/authentication/Configuring-SAML2-Authentication.html) | `entityId` (string) | Resolve the metadata of a service provider the way CAS does, and report the matching registration and metadata source, the validity period, assertion consumer and single logout endpoints, name id formats and certificates with their expiration dates, or the error when resolution fails. |
| `findOidcClient` | [OpenID Connect](https://apereo.github.io/cas/development/authentication/OIDC-Authentication.html) | `clientId` (string) | Summarize an OAuth or OpenID Connect client registration: redirect URI pattern, grant and response types, scopes, audience, allowed resource indicators, client authentication, token settings, issuer and ID token settings. Client secrets are never returned. |
| `checkOidcClientResource` | [OpenID Connect](https://apereo.github.io/cas/development/authentication/OIDC-Authentication.html) | `clientId`, `resource` (string) | Check whether a client may request a resource with the RFC 8707 `resource` parameter: whether it is an absolute URI without a fragment, the allowed resource expression it fully matches, or why it would be refused with `invalid_target`, whether the client or the allowed resources in the OAuth settings allowed it, and the token audience. |
| `listJwksKeys` | [OpenID Connect](https://apereo.github.io/cas/development/authentication/OIDC-Authentication.html) | none | List the keys of the CAS OpenID Connect keystore with their key id, type, algorithm, use and rotation state. Key material is never returned. |
| `findTrustedDevices` | [Trusted devices](https://apereo.github.io/cas/development/mfa/Multifactor-TrustedDevice-Authentication.html) | `username` (string) | Return the devices a person has registered as trusted for multifactor authentication: the device name, the multifactor authentication provider, when it was registered, when it expires and whether it has expired. Device fingerprints and record keys are never returned. |
| `findSurrogateAccounts` | [Surrogate authentication](https://apereo.github.io/cas/development/authentication/Surrogate-Authentication.html) | `username` (string), `service` (optional) | Return the accounts a person may impersonate, optionally for an application, and whether the person may impersonate any account. |
| `previewInterrupt` | [Authentication interrupts](https://apereo.github.io/cas/development/webflow/Webflow-Customization-Interrupt.html) | `username`, `service` (string) | Ask each interrupt source in order which notification CAS would show the person after authenticating to the application, and report the first interrupt with its message, links and whether it blocks the login. The interrupt policy of the matching registered service is reported, but its attribute and script conditions are not evaluated. |
| `evaluateAuthenticationRisk` | [Risk-based authentication](https://apereo.github.io/cas/development/authentication/Configuring-RiskBased-Authentication.html) | `username`, `service`, `clientIpAddress`, `userAgent` (string), `geoLocation` (optional) | Score a login attempt from the given client against the person’s recorded sign-ins, reporting each risk calculator’s score, the overall score, the threshold and whether CAS would treat the attempt as risky. |
| `findOneTimeTokenAccounts` | [Google Authenticator](https://apereo.github.io/cas/development/mfa/GoogleAuthenticator-Authentication.html) | `username` (string) | Return the one-time password devices a person has registered: the device name, when it was registered and last used, where the registration came from and how many scratch codes are left. Secret keys, validation codes and scratch codes are never returned. |
| `findWebAuthnDevices` | [FIDO2 WebAuthn](https://apereo.github.io/cas/development/mfa/FIDO2-WebAuthn-Authentication.html) | `username` (string) | Return the security keys and passkeys a person has registered: the nickname, registration time, transports, whether it is a discoverable credential, the AAGUID of the authenticator model and the signature count. Credential ids, user handles and public keys are never returned. |
| `findPasswordlessAccount` | [Passwordless authentication](https://apereo.github.io/cas/development/authentication/Passwordless-Authentication.html) | `username` (string) | Return the passwordless account of a person: masked email address and phone number, whether a password is still requested, the selection menu, multifactor and delegated authentication eligibility, allowed identity providers and the account source. Account attributes are not returned. |
| `listIdentityProviders` | [Delegated authentication](https://apereo.github.io/cas/development/integration/Delegate-Authentication.html) | none | List the external identity providers CAS can delegate to with their name, type, display name, callback URL, auto-redirect setting and principal attribute. Client secrets and other provider settings are never returned. |
| `findAuthorizableResources` | [Heimdall](https://apereo.github.io/cas/development/authorization/Heimdall-Authorization-Overview.html) | `namespace` (optional) | Return the resources of a Heimdall namespace: URI pattern and method, AuthZEN resource type, id pattern and actions, whether every policy must grant, the policy types and the property names. Policy definitions and property values are never returned; without a namespace, the known namespaces are listed. |

Interrupt sources run as they do at login: a source that fails is recorded and skipped, and sources such as a REST endpoint or a Groovy script are called for real, so `previewInterrupt` is advertised with the `openWorldHint` annotation. Risk is scored for the client details passed to `evaluateAuthenticationRisk`, never those of the MCP request, which describe the operator; a person with no recorded sign-ins is always regarded as risky, and each evaluation is recorded in the [audit log](https://apereo.github.io/cas/development/audits/Audits.html).

## Tools That Change CAS

The MCP server can also offer tools that change CAS, for troubleshooting and day-to-day administration. They are turned off by default and are only registered when turned on via feature toggles; each tool that depends on an optional feature is also listed only when that feature is included in the CAS build. Calling them requires the `ROLE_MCP_OPERATOR` role/authority; the `ROLE_MCP_ADMIN` role alone is not enough, and a person usually needs both, to look before changing.

| Tool | Requires | Parameters | Description |
| --- | --- | --- | --- |
| `revokeSessions` | none | `username` (string), `sessionReference` (optional) | End the single sign-on sessions of a person, or the one session with a session reference returned by `findSessions`, and send single logout to their applications as when the person logs out. |
| `releaseThrottledLogins` | none | `username`, `clientIpAddress` (optional, at least one) | Release the failed login attempts that in-memory or Hazelcast throttling tracks, so the person may try again right away. Throttling backed by the audit trail is not changed. |
| `setServiceEnabled` | none | `serviceId` (number), `enabled` (boolean) | Turn an application on or off through the enabled flag of its access strategy, including the strategies of a chain, and save it in the service registry. Returns whether it was allowed before and after. |
| `setLogLevel` | none | `loggerName` (string), `level` (optional) | Change the level of a logger of this CAS server until it restarts, or reset it to its configured level when no level is given. Returns the effective level before and after. |
| `revokeOAuthTokens` | [OAuth](https://apereo.github.io/cas/development/authentication/OAuth-Authentication.html) | `username`, `clientId` (optional, at least one) | Remove the access tokens and refresh tokens issued to a person, to a client, or to a person for one client from the ticket registry. |
| `revokeConsentDecisions` | [Attribute consent](https://apereo.github.io/cas/development/integration/Attribute-Release-Consent.html) | `username` (string), `decisionId` (optional) | Revoke the consent decisions of a person, or one decision returned by `findConsentDecisions`, so consent is asked again. |
| `removeTrustedDevices` | [Trusted devices](https://apereo.github.io/cas/development/mfa/Multifactor-TrustedDevice-Authentication.html) | `username` (string), `deviceId` (optional) | Remove the trusted devices of a person, or one device returned by `findTrustedDevices`, so multifactor authentication is asked again on those devices. |
| `removeOneTimeTokenAccounts` | [Google Authenticator](https://apereo.github.io/cas/development/mfa/GoogleAuthenticator-Authentication.html) | `username` (string), `accountId` (optional) | Remove the one-time password devices of a person, or one device returned by `findOneTimeTokenAccounts`, so the person registers a new device at the next login. |
| `removeWebAuthnDevices` | [FIDO2 WebAuthn](https://apereo.github.io/cas/development/mfa/FIDO2-WebAuthn-Authentication.html) | `username` (string) | Remove all the security keys and passkeys of a person, so the person registers a new one at the next login. |

These tools are advertised without the `readOnlyHint` annotation, and all but `setLogLevel` with the `destructiveHint` annotation, so MCP clients that honor them ask before calling. Every call is recorded in the [audit log](https://apereo.github.io/cas/development/audits/Audits.html) like any other tool call. Single sign-on session identifiers and token identifiers are never accepted or returned. A log level change applies to the node that handles the call only, and the service registry change is subject to how the registry replicates changes in a cluster.

> **Usage Warning!**
>
> These tools change CAS for real, with no undo. Only grant the `MCP_OPERATOR` role to a few trusted operators. The `DEBUG` and `TRACE` log levels may write sensitive data, such as attributes, tickets and tokens, to the logs; reset the logger when done.

**Feature Activation**

To activate this feature, the following feature toggle(s) must be turned on:

```properties
CasFeatureModule.AI.mcp-write.enabled=true
```

To learn more about configuration feature toggles, please [see this page](https://apereo.github.io/cas/development/configuration/Configuration-Feature-Toggles.html).

## Resources

The MCP server offers the CAS settings catalog as an [MCP resource](https://modelcontextprotocol.io/specification/2025-11-25/server/resources) template, `cas://settings/{name}`, which clients read with `resources/read`, for example `cas://settings/` followed by the name of the setting. The JSON result describes the setting: its description, type, default value, the CAS module that provides it, whether it is required, deprecated, or accepts durations, regular expressions or expressions, and whether it is defined in this deployment. The value of a setting is never returned, since settings carry keys, passwords and other secrets. Reading a resource requires the `ROLE_MCP_ADMIN` role/authority like any tool.

To find the name of a setting, the `searchSettings` tool takes a `query` of at least three characters, matched against setting names and descriptions (every word must match), and an optional CAS `module` such as `cas-server-support-ldap`. It returns up to fifty settings with their name, a short description, module, type, deprecation and the `cas://settings/{name}` URI to read.

Registered services are offered as the resource template `cas://services/{id}`, such as `cas://services/1001`, which returns the definition as JSON with the same secret redaction as `findService`.

Resources are advertised only when the resource capability of the MCP server is turned on, which CAS does by default.

Clients that support [argument completion](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/completion) can complete the setting name of `cas://settings/{name}` from at least two typed characters, and the service id of `cas://services/{id}` from the first digits of the id or part of the service name. MCP completion applies to resource templates and prompts only, not to tool parameters. Completion is turned on by default and requires the `ROLE_MCP_ADMIN` role/authority.

**Feature Activation**

To activate this feature, the following feature toggle(s) must be turned on:

```properties
CasFeatureModule.AI.mcp-settings.enabled=true
```

To learn more about configuration feature toggles, please [see this page](https://apereo.github.io/cas/development/configuration/Configuration-Feature-Toggles.html).

## Client Configuration

Most MCP clients can connect to a remote Streamable HTTP server using a configuration similar to the following:

```json
{
  "mcpServers": {
    "cas": {
      "type": "http",
      "url": "https://sso.example.org/cas/mcp",
      "headers": {
        "Authorization": "Basic <base64-encoded username:password>"
      }
    }
  }
}
```

MCP clients that support OAuth need only the URL. Without credentials, they follow the `Bearer` challenge, sign the person in with CAS and request a token for the MCP endpoint (see [OAuth Access Tokens](https://apereo.github.io/cas/development/installation/Admin-MCP-Server.html#oauth-access-tokens)):

```json
{
  "mcpServers": {
    "cas": {
      "type": "http",
      "url": "https://sso.example.org/cas/mcp"
    }
  }
}
```

### Browser Clients

MCP clients that run in a web browser, such as web-based MCP inspectors and playgrounds, call the MCP endpoint from another origin, so the browser first sends a CORS preflight request. CAS does not answer cross-origin requests unless [CORS](https://apereo.github.io/cas/development/planning/Security-Guide.html#cors) is turned on; without it, such clients report a CORS or network error even though the server is reachable. Clients that do not run in a browser, such as desktop applications and command-line tools, are not affected.

When CORS is turned on for a browser client, allow the origin of that client, the `POST`, `GET`, `DELETE` and `OPTIONS` methods, and the `Authorization`, `Content-Type`, `Accept`, `Mcp-Session-Id`, `MCP-Protocol-Version` and `Last-Event-ID` request headers. The `Mcp-Session-Id` response header must also be exposed; otherwise the browser hides the session id returned by `initialize` and every later call fails. Browser clients that use access tokens also need the `WWW-Authenticate` response header exposed, to read the challenges.

The following settings and properties are available from the CAS configuration catalog:

- `cas.http-web-request.cors.enabled` (Required; type `Boolean`; default `false`): Whether CORS should be enabled for http requests.
- `cas.http-web-request.cors.allow-credentials` (Optional; type `Boolean`; default `true`): The Access-Control-Allow-Credentials header Indicates whether or not the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. Note that simple GET requests are not preflighted, and so if a request is made for a resource with credentials, if this header is not returned with the resource, the response is ignored by the browser and not returned to web content.
- `cas.http-web-request.cors.allow-headers` (Optional; type `List<String>`): The Access-Control-Allow-Headers header is used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. Default is everything.
- `cas.http-web-request.cors.allow-methods` (Optional; type `List<String>`): The Access-Control-Allow-Methods header specifies the method or methods allowed when accessing the resource. This is used in response to a pre-flight request. The conditions under which a request is pre-flighted are discussed above. Default is everything.
- `cas.http-web-request.cors.allow-origin-patterns` (Optional; type `List<String>`): Comma-separated list of origin patterns to allow. Unlike allowed origins which only supports `*`, origin patterns are more flexible (for example `https://*.example.com`) and can be used when credentials are allowed. When no allowed origin patterns or allowed origins are set, CORS support is disabled.
- `cas.http-web-request.cors.allow-origins` (Optional; type `List<String>`): The Origin header indicates the origin of the cross-site access request or preflight request. The origin is a URI indicating the server from which the request initiated. When credentials are allowed, '*' cannot be used and origin patterns should be configured instead. It does not include any path information, but only the server name.
- `cas.http-web-request.cors.exposed-headers` (Optional; type `List<String>`): The Access-Control-Expose-Headers header lets a server accept headers that browsers are allowed to access.
- `cas.http-web-request.cors.max-age` (Optional; type `Long`; default `3600`): The Access-Control-Max-Age header indicates how long the results of a preflight request can be cached.

> **Usage Warning!**
>
> CORS settings apply to every CAS endpoint, not only to the MCP endpoint. Allow only the exact origins of the clients you trust, never all origins, and do not allow credentials: browser clients send their credentials in the `Authorization` header, and allowing credentials would let other origins use a CAS session cookie of the browser.

## Feature Toggle

The MCP server tools are enabled by default when the module is present, and can be turned off via feature toggles. When turned off, CAS registers no tools and no longer opens the MCP endpoint to authenticated users.

**Feature Activation**

To activate this feature, the following feature toggle(s) must be turned on:

```properties
CasFeatureModule.AI.mcp.enabled=true
```

To learn more about configuration feature toggles, please [see this page](https://apereo.github.io/cas/development/configuration/Configuration-Feature-Toggles.html).
