{ "id": "stirling-mcp", "realm": "stirling-mcp", "displayName": "Stirling PDF MCP Test", "displayNameHtml": "
Stirling PDF MCP
", "enabled": true, "sslRequired": "none", "registrationAllowed": false, "registrationEmailAsUsername": true, "rememberMe": true, "verifyEmail": false, "loginWithEmailAllowed": true, "duplicateEmailsAllowed": false, "resetPasswordAllowed": true, "editUsernameAllowed": false, "bruteForceProtected": false, "accessTokenLifespan": 300, "accessTokenLifespanForImplicitFlow": 900, "ssoSessionIdleTimeout": 1800, "ssoSessionMaxLifespan": 36000, "offlineSessionIdleTimeout": 2592000, "users": [ { "username": "mcpuser@stirling.local", "email": "mcpuser@stirling.local", "emailVerified": true, "firstName": "MCP", "lastName": "TestUser", "enabled": true, "credentials": [ { "type": "password", "value": "mcppassword", "temporary": false } ], "realmRoles": ["user"] }, { "username": "ghost@stirling.local", "email": "ghost@stirling.local", "emailVerified": true, "firstName": "Ghost", "lastName": "NoAccount", "enabled": true, "credentials": [ { "type": "password", "value": "ghostpassword", "temporary": false } ], "realmRoles": ["user"] } ], "roles": { "realm": [ { "name": "user", "description": "Regular user role", "composite": false, "clientRole": false } ] }, "clients": [ { "clientId": "mcp-test-client", "name": "Stirling PDF MCP Test Client (confidential)", "description": "Confidential client for scripted MCP testing: ROPC (direct grant) for the validation script and standard/PKCE flow for browser-based MCP clients.", "rootUrl": "http://localhost:8080", "baseUrl": "http://localhost:8080", "enabled": true, "clientAuthenticatorType": "client-secret", "secret": "mcp-test-secret", "redirectUris": [ "http://localhost:8080/*", "http://localhost:6274/*", "http://127.0.0.1:6274/*" ], "webOrigins": ["*"], "bearerOnly": false, "consentRequired": false, "standardFlowEnabled": true, "implicitFlowEnabled": false, "directAccessGrantsEnabled": true, "serviceAccountsEnabled": false, "publicClient": false, "frontchannelLogout": false, "protocol": "openid-connect", "attributes": { "oidc.ciba.grant.enabled": "false", "backchannel.logout.session.required": "true", "oauth2.device.authorization.grant.enabled": "false", "display.on.consent.screen": "false", "backchannel.logout.revoke.offline.tokens": "false", "pkce.code.challenge.method": "S256" }, "fullScopeAllowed": true, "protocolMappers": [ { "name": "email", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "user.attribute": "email", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "email", "jsonType.label": "String" } }, { "name": "preferred_username", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "user.attribute": "username", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "preferred_username", "jsonType.label": "String" } }, { "name": "mcp-audience", "protocol": "openid-connect", "protocolMapper": "oidc-audience-mapper", "consentRequired": false, "config": { "included.custom.audience": "http://localhost:8080/mcp", "id.token.claim": "false", "access.token.claim": "true" } } ], "defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email", "mcp.tools.read", "mcp.tools.write" ], "optionalClientScopes": ["offline_access", "microprofile-jwt"] }, { "clientId": "mcp-client", "name": "MCP public client (authorization-code + PKCE)", "description": "Generic public client for any browser-based MCP client. Authorization-code + PKCE, no secret. Broad localhost redirect URIs so any local MCP client callback port is accepted.", "rootUrl": "http://localhost", "baseUrl": "http://localhost", "enabled": true, "clientAuthenticatorType": "client-secret", "redirectUris": [ "http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*" ], "webOrigins": ["*"], "bearerOnly": false, "consentRequired": false, "standardFlowEnabled": true, "implicitFlowEnabled": false, "directAccessGrantsEnabled": false, "serviceAccountsEnabled": false, "publicClient": true, "frontchannelLogout": false, "protocol": "openid-connect", "attributes": { "oidc.ciba.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false", "display.on.consent.screen": "false", "pkce.code.challenge.method": "S256" }, "fullScopeAllowed": true, "protocolMappers": [ { "name": "email", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "user.attribute": "email", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "email", "jsonType.label": "String" } }, { "name": "preferred_username", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "user.attribute": "username", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "preferred_username", "jsonType.label": "String" } }, { "name": "mcp-audience", "protocol": "openid-connect", "protocolMapper": "oidc-audience-mapper", "consentRequired": false, "config": { "included.custom.audience": "http://localhost:8080/mcp", "id.token.claim": "false", "access.token.claim": "true" } } ], "defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email", "mcp.tools.read", "mcp.tools.write" ], "optionalClientScopes": ["offline_access", "microprofile-jwt"] }, { "clientId": "other-client", "name": "Unrelated client (negative test)", "description": "Issues VALID tokens (good signature + issuer) that do NOT carry the MCP audience and have no mcp.tools.* scopes - used to prove the resource server rejects tokens minted for a different audience (RFC 8707).", "enabled": true, "clientAuthenticatorType": "client-secret", "publicClient": true, "bearerOnly": false, "standardFlowEnabled": false, "implicitFlowEnabled": false, "directAccessGrantsEnabled": true, "serviceAccountsEnabled": false, "protocol": "openid-connect", "attributes": { "pkce.code.challenge.method": "S256" }, "fullScopeAllowed": false, "defaultClientScopes": ["web-origins", "acr", "profile", "roles", "email"], "optionalClientScopes": ["offline_access", "microprofile-jwt"] } ], "clientScopes": [ { "name": "mcp.tools.read", "description": "MCP: read-only tool access (list / describe / inspect PDF operations)", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "true", "display.on.consent.screen": "true" } }, { "name": "mcp.tools.write", "description": "MCP: write tool access (run PDF operations that produce output)", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "true", "display.on.consent.screen": "true" } }, { "name": "mcp-audience", "description": "Injects the MCP resource-server audience (RFC 8707) into access tokens. A default scope so even dynamically-registered clients produce tokens Stirling accepts.", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "false", "display.on.consent.screen": "false" }, "protocolMappers": [ { "name": "mcp-audience", "protocol": "openid-connect", "protocolMapper": "oidc-audience-mapper", "consentRequired": false, "config": { "included.custom.audience": "http://localhost:8080/mcp", "id.token.claim": "false", "access.token.claim": "true" } } ] }, { "name": "email", "description": "OpenID Connect built-in scope: email", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "true", "display.on.consent.screen": "true" }, "protocolMappers": [ { "name": "email", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "user.attribute": "email", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "email", "jsonType.label": "String" } }, { "name": "email verified", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "user.attribute": "emailVerified", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "email_verified", "jsonType.label": "boolean" } } ] }, { "name": "profile", "description": "OpenID Connect built-in scope: profile", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "true", "display.on.consent.screen": "true" }, "protocolMappers": [ { "name": "username", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-property-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "user.attribute": "username", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "preferred_username", "jsonType.label": "String" } } ] }, { "name": "roles", "description": "OpenID Connect scope for user roles", "protocol": "openid-connect", "attributes": { "include.in.token.scope": "false", "display.on.consent.screen": "true" }, "protocolMappers": [ { "name": "realm roles", "protocol": "openid-connect", "protocolMapper": "oidc-usermodel-realm-role-mapper", "consentRequired": false, "config": { "userinfo.token.claim": "true", "id.token.claim": "true", "access.token.claim": "true", "claim.name": "roles", "jsonType.label": "String", "multivalued": "true" } } ] } ], "defaultDefaultClientScopes": [ "profile", "email", "roles", "web-origins", "acr", "mcp.tools.read", "mcp.tools.write", "mcp-audience" ], "defaultOptionalClientScopes": ["offline_access", "microprofile-jwt"], "browserSecurityHeaders": { "contentSecurityPolicyReportOnly": "", "xContentTypeOptions": "nosniff", "referrerPolicy": "no-referrer", "xRobotsTag": "none", "xFrameOptions": "SAMEORIGIN", "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", "xXSSProtection": "1; mode=block", "strictTransportSecurity": "max-age=31536000; includeSubDomains" }, "eventsEnabled": false, "eventsListeners": ["jboss-logging"], "enabledEventTypes": [], "adminEventsEnabled": false, "adminEventsDetailsEnabled": false, "internationalizationEnabled": false, "supportedLocales": [], "components": { "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ { "name": "Trusted Hosts", "providerId": "trusted-hosts", "subType": "anonymous", "config": { "trusted-hosts": ["localhost", "127.0.0.1"], "host-sending-registration-request-must-match": ["false"], "client-uris-must-match": ["true"] } }, { "name": "Allowed Client Scopes", "providerId": "allowed-client-templates", "subType": "anonymous", "config": { "allow-default-scopes": ["true"] } } ] }, "keycloakVersion": "24.0.0" }