Complete Setup Guide
End-to-end guide for deploying suitecrm-mcp v4.x from scratch.
Overview
What the gateway does:
- Handles OAuth2 login (Authorization Code flow)
- Issues personal, revocable API keys to authenticated users
- Provisions CRM accounts via SSH on first login (if configured)
- Proxies MCP tool calls to the appropriate SuiteCRM instance
Steps 1-4: Install
Set up Auth0 or Azure AD before installing the gateway. The installer will prompt for the credentials you collect here.
See Identity Provider Setup for step-by-step instructions. Minimum required:
- Auth0 domain
- Auth0 client ID and client secret
- Redirect URI registered:
https://YOUR_GATEWAY_DOMAIN/auth/callback
Requirements: Ubuntu 20.04+ (or Debian 11+), public IP or domain, ports 80 and 443 open, SSH access to CRM VMs if using SSH provisioning.
git clone https://github.com/Anirudhx7/suitecrm-mcp.git cd suitecrm-mcp
cp entities.example.json entities.json
Edit entities.json:
{
"crm1": {
"label": "Main CRM",
"endpoint": "https://crm.yourcompany.com/legacy/service/v4_1/rest.php",
"port": 3101,
"group": "CRM-Main"
}
}
endpoint- full REST API URL. If unsure, leave as the base URL and the installer auto-detects the correct path.group- the JWT claim value a user must have to access this entity. Must match a role/group in your identity provider.port- each entity gets its own port (3101, 3102, ...). With nginx these are internal-only.
Finding your REST API path:
for path in /service/v4_1/rest.php /legacy/service/v4_1/rest.php /crm/service/v4_1/rest.php; do
curl -sf -X POST "https://crm.example.com$path" \
--data-urlencode 'method=get_server_info' \
--data-urlencode 'input_type=JSON' \
--data-urlencode 'response_type=JSON' \
--data-urlencode 'rest_data={}' | python3 -m json.tool && echo "FOUND: $path" && break
done
sudo python3 install.py \ --config entities.json \ --domain mcp.yourcompany.com \ --email you@yourcompany.com
The installer will: install Node.js, nginx, and certbot; prompt for OAuth2 configuration; generate a random API_KEY_SECRET; write env files to /etc/suitecrm-mcp/; create and start systemd services; configure nginx with entity routing; and obtain a Let's Encrypt certificate.
Non-interactive install (CI/automation):
sudo python3 install.py \ --config entities.json \ --domain mcp.yourcompany.com \ --email you@yourcompany.com \ --oauth-issuer https://your-tenant.auth0.com \ --oauth-client-id YOUR_CLIENT_ID \ --oauth-client-secret YOUR_CLIENT_SECRET \ --oauth-audience https://your-tenant.auth0.com/api/v2/ \ --gateway-url https://mcp.yourcompany.com
Steps 5-6: CRM Prep
If users authenticate via LDAP or SSO, they have no local SuiteCRM password. The gateway needs a local password to call the REST API on their behalf.
Copy tools/crm-provision-user.sh to each CRM VM and run as root:
# Single user sudo crm-provision-user alice SecurePass123 # Bulk from CSV (username,password) sudo crm-provision-user --csv users.csv
Lets the gateway automatically provision CRM accounts when users first log in via OAuth.
# On the gateway VM, generate a key if you don't have one ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N "" # Copy to each CRM VM ssh-copy-id -i /root/.ssh/id_ed25519.pub root@crm1.internal
Create /etc/suitecrm-mcp/crm-hosts.json:
{
"crm1": {
"ssh_host": "crm1.internal",
"ssh_user": "ubuntu",
"ssh_key": "/etc/suitecrm-mcp/crm-ssh-key"
}
}
Add to the entity env file (/etc/suitecrm-mcp/crm1.env):
CRM_HOSTS_FILE=/etc/suitecrm-mcp/crm-hosts.json
Restart: sudo systemctl restart suitecrm-mcp-crm1
Steps 7-8: Test & Connect
# Check services are running sudo python3 install.py --status # Test gateway health curl https://mcp.yourcompany.com/health # Test auth redirect (should return 302 Location: /auth/login) curl -I https://mcp.yourcompany.com/ # Test OIDC discovery curl https://YOUR_DOMAIN/.well-known/openid-configuration
Visit https://mcp.yourcompany.com in a browser and complete the login flow. You should see the success page with your API key.
Admin Operations
Periodic session cleanup
sessions.json accumulates expired entries over time. Safe to run at any time:
# Purge expired sessions python3 tools/mcp-admin sessions --purge-expired # Example cron: daily at 2am echo "0 2 * * * suitecrm-mcp python3 /opt/suitecrm-mcp/tools/mcp-admin sessions --purge-expired" | sudo crontab -
Manage user profiles and API keys
python3 tools/mcp-admin list python3 tools/mcp-admin whoami --sub <sub> python3 tools/mcp-admin revoke --sub <sub>
Add a user manually (bypass OAuth)
python3 tools/mcp-admin add --sub <sub> --entity <entity_code> --user <crm_username> --pass <crm_password>
Update server code without reinstalling
git pull sudo python3 install.py --update --config entities.json --skip-oauth
Add a new entity
# Edit entities.json to add the new entry, then:
sudo python3 install.py --add --config entities.json --skip-oauth
Remove an entity
sudo python3 install.py --remove crm2
Enable HTTPS on an existing plain HTTP install
sudo python3 install.py --config entities.json --domain mcp.yourcompany.com --email you@example.com --skip-oauth
File Layout After Install
/opt/suitecrm-mcp/ gateway server code index.mjs auth.mjs package.json node_modules/ /etc/suitecrm-mcp/ config and runtime state (mode 700, owned by suitecrm-mcp) entities.json entity list (written by installer) auth.env env vars for auth service (mode 600) crm1.env env vars for entity crm1 (mode 600) user-profiles.json per-user API keys and CRM creds (mode 600, written at runtime) sessions.json active gateway sessions (mode 600, written at runtime) crm-hosts.json SSH host map for provisioning (if configured) domain saved domain for nginx rebuild /etc/systemd/system/ suitecrm-mcp-auth.service suitecrm-mcp-crm1.service /etc/nginx/sites-available/ suitecrm-mcp nginx config with entity and /auth/ routing
Identity Provider Setup
The gateway supports any OIDC-compliant provider. This guide covers Auth0 and Azure AD, the two most common configurations.
Auth0
1. Create a Regular Web Application
- Log in to the Auth0 Dashboard
- Go to Applications > Applications > Create Application
- Name it (e.g.
SuiteCRM MCP Gateway) - Choose Regular Web Application - required for Authorization Code flow
- Click Create
2. Configure the application
On the Settings tab:
| Field | Value |
|---|---|
| Allowed Callback URLs | https://YOUR_GATEWAY/auth/callback |
| Allowed Logout URLs | https://YOUR_GATEWAY |
| Allowed Web Origins | https://YOUR_GATEWAY |
Under Advanced Settings > Grant Types, ensure Authorization Code and Refresh Token are checked. Under Advanced Settings > OAuth, set JWT Signature Algorithm to RS256. Click Save Changes.
3. Note your credentials
From the Settings tab, copy:
- Domain (e.g.
your-tenant.auth0.com) - this is yourAUTH0_DOMAIN - Client ID - this is your
AUTH0_CLIENT_ID - Client Secret - this is your
AUTH0_CLIENT_SECRET
For AUTH0_AUDIENCE, use the Auth0 Management API identifier (https://your-tenant.auth0.com/api/v2/) or create a custom API in Auth0 > APIs.
4. Configure groups claim
The gateway reads group membership from the JWT to decide which CRM entities a user can access. Auth0 does not include custom claims by default - add an Action:
- Go to Actions > Flows > Login
- Click + to add a custom action
- Paste this code:
exports.onExecutePostLogin = async (event, api) => {
const namespace = 'https://suitecrm-mcp/';
api.idToken.setCustomClaim(namespace + 'groups', event.authorization?.roles ?? []);
api.accessToken.setCustomClaim(namespace + 'groups', event.authorization?.roles ?? []);
};
- Deploy the action and add it to the Login flow
Then set OAUTH_GROUPS_CLAIM=https://suitecrm-mcp/groups in the gateway env file.
In Auth0 > User Management > Roles, create roles matching the group field in your entities.json (e.g. CRM-MyCompany). Assign users to roles.
5. Connect Azure AD (optional - corporate SSO)
- In Auth0, go to Authentication > Enterprise > Microsoft Azure AD
- Create a new connection using your Azure AD tenant ID, client ID, and secret
- Enable the connection on your SuiteCRM MCP Gateway application
- Users will see "Log in with Microsoft" on the Auth0 login page
Azure AD (direct, without Auth0)
Use this if you want to skip Auth0 and authenticate directly against Azure AD.
1. Register an application
- Go to Azure Portal > App registrations > New registration
- Name:
SuiteCRM MCP Gateway - Supported account types: Accounts in this organizational directory only
- Redirect URI: Web -
https://YOUR_GATEWAY/auth/callback - Click Register
2. Add a client secret
Certificates & secrets > New client secret - set an expiry and copy the value immediately.
3. Configure token claims
Token configuration > Add optional claim > ID token: add email, preferred_username.
For groups: Token configuration > Add groups claim. Select Security groups (or All groups). Under each token type, choose Group ID (object ID) or sAMAccountName if synced from on-prem AD.
REQUIRED_GROUP in the entity env to the group's object ID, or configure optional claims to emit onpremisessecurityidentifier.4. Note your credentials
| Gateway env var | Azure AD value |
|---|---|
AUTH0_DOMAIN | login.microsoftonline.com/YOUR_TENANT_ID/v2.0 |
AUTH0_CLIENT_ID | Application (client) ID |
AUTH0_CLIENT_SECRET | Client secret value |
AUTH0_AUDIENCE | Application (client) ID (same as client ID) |
OAUTH_GROUPS_CLAIM | groups |
Installer Prompts Reference
When you run sudo python3 install.py, the OAuth section asks:
| Prompt | What to enter |
|---|---|
| Auth0 domain | Auth0: your-tenant.auth0.com / Azure: login.microsoftonline.com/TENANT_ID/v2.0 |
| Auth0 client ID | From your app registration |
| Auth0 client secret | From your app registration (keep this secret) |
| Auth0 audience | Auth0: your API identifier / Azure AD: your client ID |
| Gateway public URL | https://mcp.yourcompany.com - must match the registered callback origin |
| JWT groups claim | Auth0 with custom action: https://suitecrm-mcp/groups / Azure AD: groups / default: AUTH0_AUDIENCE + '/groups' |
Verification
After installation, visit https://YOUR_GATEWAY/auth/login. You should be redirected to your identity provider's login page. After logging in, you should see the success page with your API key.
If you see an error, check:
- The callback URL registered in your identity provider matches exactly
AUTH0_DOMAINhas no trailing slash- The
/.well-known/openid-configurationendpoint is reachable from the gateway VM:curl https://YOUR_DOMAIN/.well-known/openid-configuration
Connecting Claude Desktop
Claude Desktop connects directly to the gateway via SSE using a gateway-issued API key. No CRM credentials are stored on your machine.
How authentication works
- Your admin installs the gateway and configures an identity provider
- You visit the gateway URL in your browser and log in with your corporate account
- The success page shows your personal API key - copy it
- Paste the key into the Claude Desktop config below
Your API key is tied to your identity. The gateway uses it to look up your CRM account and connect on your behalf. Keys expire after 30 days (configurable by your admin).
Prerequisites
- Gateway v4.x installed and running
- Claude Desktop installed
- Your API key from
https://YOUR_GATEWAY/auth/login
Get your API key
- Visit
https://YOUR_GATEWAY/auth/login(or justhttps://YOUR_GATEWAY- it redirects) - Log in with your corporate account
- On the success page, expand Claude Desktop and copy the config block shown
Config file location
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
Single entity
{
"mcpServers": {
"suitecrm": {
"type": "sse",
"url": "https://mcp.yourcompany.com/sse",
"headers": {
"Authorization": "Bearer YOUR_API_KEY_HERE"
}
}
}
}
Multi entity
Add one entry per entity. Each entity gets its own /{code}/sse path:
{
"mcpServers": {
"suitecrm_crm1": {
"type": "sse",
"url": "https://mcp.yourcompany.com/crm1/sse",
"headers": {
"Authorization": "Bearer YOUR_API_KEY_HERE"
}
},
"suitecrm_crm2": {
"type": "sse",
"url": "https://mcp.yourcompany.com/crm2/sse",
"headers": {
"Authorization": "Bearer YOUR_API_KEY_HERE"
}
}
}
}
The same API key works for all entities you have access to.
Apply changes
Fully quit and relaunch Claude Desktop (menu bar > Quit, then reopen).
Verify
Click the hammer icon in the bottom-left of the chat window. You should see 24 tools: suitecrm_search, suitecrm_get, etc. (or suitecrm_crm1_search for multi entity).
Test prompt: "List the first 5 accounts in the CRM" - Claude should call suitecrm_search automatically.
Rotating your API key
- Visit
https://YOUR_GATEWAY/auth/loginagain - a new key is issued automatically - Update
Authorizationin the config file - Restart Claude Desktop
Your admin can also revoke a key immediately via mcp-admin revoke <sub>.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| No hammer icon / tools missing | Config file path wrong or JSON syntax error | Validate JSON, check file path |
HTTP 401 Unauthorized | API key invalid or expired | Re-authenticate at /auth/login and update the config |
HTTP 403 Forbidden | Not in the required group for this entity | Ask your admin to check your group membership |
Connection refused | Gateway not running | Check with your admin: systemctl status suitecrm-mcp |
429 Too Many Requests | Rate limit hit on /sse (20 req/15 min) | Wait 15 minutes |
Connecting Claude Code (CLI)
Claude Code connects directly to the gateway via SSE using a gateway-issued API key. No CRM credentials are stored on your machine.
How authentication works
- Visit the gateway URL in your browser and log in with your corporate account
- The success page shows your personal API key
- Run the
claude mcp addcommand shown on the success page - or paste the key into the command below
Prerequisites
- Gateway v4.x installed and running
- Claude Code CLI installed:
npm install -g @anthropic-ai/claude-code - Your API key from
https://YOUR_GATEWAY/auth/login
Get your API key
- Visit
https://YOUR_GATEWAY/auth/login - Log in with your corporate account
- On the success page, expand Claude Code and copy the ready-to-run command
Commands
Single entity
claude mcp add suitecrm \ --transport sse \ --header "Authorization:Bearer YOUR_API_KEY_HERE" \ https://mcp.yourcompany.com/sse
Multi entity
Run once per entity. Each gets its own MCP server entry:
claude mcp add suitecrm_crm1 \ --transport sse \ --header "Authorization:Bearer YOUR_API_KEY_HERE" \ https://mcp.yourcompany.com/crm1/sse claude mcp add suitecrm_crm2 \ --transport sse \ --header "Authorization:Bearer YOUR_API_KEY_HERE" \ https://mcp.yourcompany.com/crm2/sse
Verify
claude mcp list
Start a session and test:
claude > List the first 5 accounts in the CRM
Claude should call suitecrm_search automatically.
Manage entries
# List all MCP servers claude mcp list # Remove an entry claude mcp remove suitecrm
Rotating your API key
# Remove the old entry claude mcp remove suitecrm # Re-authenticate, then re-add with the new key claude mcp add suitecrm \ --transport sse \ --header "Authorization:Bearer YOUR_NEW_API_KEY" \ https://mcp.yourcompany.com/sse
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
HTTP 401 Unauthorized | API key invalid or expired | Re-authenticate at /auth/login and re-add the entry |
HTTP 403 Forbidden | Not in the required group for this entity | Ask your admin to check your group membership |
Connection refused | Gateway not running | systemctl status suitecrm-mcp on the gateway machine |
429 Too Many Requests | Rate limit hit on /sse (20 req/15 min) | Wait 15 minutes |
| TLS error with self-signed cert | NODE_TLS_REJECT_UNAUTHORIZED not set | Add --tls-skip during gateway install |
Connecting OpenClaw
OpenClaw uses a two-machine architecture: a remote gateway and a local bridge plugin.
Architecture
The bridge is a Node.js plugin that OpenClaw loads. It is silent at startup - no auth prompt, no polling. Authentication is triggered lazily the first time a SuiteCRM tool is actually called. The bridge requests a one-time login URL from the gateway, returns it as the tool response, and polls in the background. Once the user clicks the link and logs in, the token is saved and all subsequent tool calls work silently. No CLI needed on the OpenClaw machine.
Prerequisites
- A dedicated Ubuntu VM or server for the gateway
- OpenClaw installed on the client machine (Node.js required)
- Access to the gateway auth URL in a browser
Installation
Single entity
sudo python3 install.py --url https://crm.example.com --domain mcp.example.com --email you@example.com
Multi entity
cp entities.example.json entities.json
# Edit entities.json: add your CRM codes, labels, ports, endpoints, and group names
sudo python3 install.py --config entities.json --domain mcp.example.com --email you@example.com
--domain flag enables automatic TLS via Let's Encrypt. Without it, API keys travel unencrypted.Single entity
sudo python3 install-bridge.py \ --gateway https://mcp.example.com \ --code mycrm \ --label "My CRM"
Multi entity
sudo python3 install-bridge.py \ --gateway https://mcp.example.com \ --entities entities.json
Specific users only
sudo python3 install-bridge.py --gateway ... --entities entities.json alice bob
Agent scoping (optional)
# All agents in OpenClaw get access sudo python3 install-bridge.py --gateway ... --code mycrm --attach all # Only specific agents (comma-separated names or IDs) sudo python3 install-bridge.py --gateway ... --code mycrm --attach "Sales Bot,Support Agent"
sudo systemctl restart openclaw-USERNAME
Authentication Flow
Authentication is lazy - nothing happens at startup. The first time a user asks the agent to do something with SuiteCRM:
- User invokes a SuiteCRM tool - the bridge detects no token and calls
POST /auth/bridge/start. - Gateway returns a one-time login URL tied to a short-lived nonce. The bridge returns this URL as the tool response, visible in Teams chat or wherever the agent runs.
- User clicks the link and logs in with their corporate account.
- Bridge polls in the background every 3 seconds. Once the gateway resolves the nonce session, the bridge saves the token to
~/.suitecrm-mcp/gateway.token. - Subsequent tool calls work silently. Token is stored per-Linux-user.
- On expiry or revocation, the bridge receives HTTP 401, clears the saved token, and sends a fresh login URL on the next tool call. No restart needed.
Verify
OpenClaw should now expose 24 tools per entity: suitecrm_mycrm_search, suitecrm_mycrm_get, suitecrm_mycrm_create, and 21 more.
Test prompt: "List the first 5 accounts in the CRM" - OpenClaw should call suitecrm_mycrm_search automatically.
Re-authenticating
If the token expires (default 30 days) or is revoked: the next tool call returns HTTP 401, the bridge clears the token and calls POST /auth/bridge/start, and returns a fresh login URL. Same flow as first-time auth. No agent restart needed.
Revoking a user's token (operators)
Using mcp-admin (recommended)
mcp-admin revoke <sub>
Using the REST endpoint directly
curl -X POST https://mcp.example.com/auth/revoke \
-H "X-Admin-Key: your-admin-key" \
-H "Content-Type: application/json" \
-d '{"sub": "user@example.com"}'
Updating the bridge
sudo python3 install-bridge.py --update \ --gateway https://mcp.example.com \ --entities entities.json
Removing the bridge
sudo python3 install-bridge.py \ --remove alice bob \ --gateway https://mcp.example.com \ --entities entities.json
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Tool call returns a login URL instead of CRM data | Expected - first-time auth or token expired | Click the URL and log in; next tool call works normally |
| Login URL never appears as tool response | Bridge plugin not loaded | Check openclaw.json plugins section; re-run installer |
| Login URL expired before user clicked it | Nonce TTL (15 min) elapsed | Call any SuiteCRM tool again - a fresh URL is generated |
| Auth polling times out after 15 min | User did not complete login | Re-invoke any SuiteCRM tool to get a new login URL |
Token rejected (HTTP 401) in logs | Token expired or revoked | Bridge clears token and sends fresh login URL on next tool call |
HTTP 403 Forbidden | User not in required group for entity | Admin checks group membership in identity provider |
Rate limited (HTTP 429) in logs | Too many reconnects | Wait 15 min; backoff is automatic |
Gateway connect failed | Wrong gateway URL or gateway down | Check --gateway URL; systemctl status suitecrm-mcp-* on gateway |
| TLS error | Self-signed cert on CRM | Add --tls-skip during gateway install |
Observability
Prometheus metrics, Grafana dashboards, and Loki log aggregation - shipped in docker-compose.yml and ready to run alongside the gateway.
Starting the stack
The full observability stack (Prometheus + Grafana + Loki + Promtail) is bundled in docker-compose.yml. It starts automatically alongside the gateway:
docker compose up -d
Set GRAFANA_PASSWORD in your environment before starting, then visit http://localhost:3000. Both dashboards are provisioned automatically - no manual import needed.
docker compose up -d from the repo directory after the gateway is running. Point Prometheus at your gateway's metrics port using monitoring/prometheus.yml.
Prometheus metrics
Two components expose metrics on separate localhost ports. Both are scraped by the bundled Prometheus instance.
Gateway entity metrics (default port 9090)
| Metric | Type | Description |
|---|---|---|
suitecrm_mcp_active_connections | Gauge | Currently open SSE connections |
suitecrm_mcp_connections_total | Counter | Total SSE connections established |
suitecrm_mcp_tool_calls_total | Counter | Tool calls by name and status (success/error) |
suitecrm_mcp_tool_duration_seconds | Histogram | Tool call latency (p50/p95/p99) |
suitecrm_mcp_crm_api_duration_seconds | Histogram | CRM REST API call latency |
suitecrm_mcp_session_renewals_total | Counter | CRM session re-authentications |
suitecrm_mcp_auth_failures_total | Counter | Authentication failures |
suitecrm_mcp_circuit_breaker_state | Gauge | 0 = closed, 1 = half-open, 2 = open |
suitecrm_mcp_circuit_breaker_openings_total | Counter | Circuit breaker trip events |
Auth service metrics (default port 9091)
| Metric | Type | Description |
|---|---|---|
suitecrm_auth_logins_total | Counter | OAuth2 login completions by result (new/reused/error) |
suitecrm_auth_bridge_sessions_total | Counter | Bridge session events (started/completed/expired) |
suitecrm_auth_sessions_active | Gauge | Non-expired gateway sessions currently stored |
Scrape manually to verify metrics are flowing:
# Gateway entity metrics curl http://127.0.0.1:9090/metrics # Auth service metrics curl http://127.0.0.1:9091/metrics
For systemd (multi-entity), add each entity's metrics port to monitoring/prometheus.yml:
scrape_configs:
- job_name: suitecrm-mcp-auth
static_configs:
- targets: ['127.0.0.1:9091']
- job_name: suitecrm-mcp-crm1
static_configs:
- targets: ['127.0.0.1:9101'] # port 3101 + 6000
- job_name: suitecrm-mcp-crm2
static_configs:
- targets: ['127.0.0.1:9102'] # port 3102 + 6000
Grafana dashboards
Two dashboards are auto-provisioned from monitoring/grafana/dashboards/:
- suitecrm-mcp - per-entity view with 33 panels across 5 rows: system health, users/sessions table, CRM backend (latency, error codes, circuit breaker), security (auth failures, rate limits), and tool call breakdown
- suitecrm-mcp-fleet - multi-entity overview showing all entities at a glance: circuit breaker state, active connections, error rates, and latency per entity
Open http://localhost:3000, log in with admin / $GRAFANA_PASSWORD, and both dashboards appear under Dashboards. No manual import or datasource setup needed.
Loki & log queries
Promtail tails Docker JSON logs and ships them to Loki. All gateway log lines are structured JSON (via pino) - every line includes sub (user identity), entity, reqId, and tool where relevant. Sensitive fields (password, token, fields, search_string) are redacted before logging.
Query logs in Grafana Explore (select Loki datasource):
# All logs for a specific user {job="suitecrm-mcp"} | json | sub="auth0|abc123" # All tool calls on a specific entity {job="suitecrm-mcp"} | json | entity="crm1" | msg="tool call" # Auth failures in the last hour {job="suitecrm-mcp"} | json | level="warn" | msg=~"auth.*fail|invalid.*key" # Trace a request by ID {job="suitecrm-mcp"} | json | reqId="req-xyz"
docker compose up -d loki promtail grafana separately and point Promtail at the journal or log files.
Alerting rules
Prometheus alerting rules are in monitoring/prometheus/rules.yml and loaded automatically by the bundled Prometheus. Four rules are configured:
| Alert | Condition | Severity |
|---|---|---|
| Circuit breaker open | circuit_breaker_state == 2 for 1 min | Critical |
| High auth failure rate | >10 failures/min for 5 min | Warning |
| Latency SLO breach | p99 tool latency > 5s for 5 min | Warning |
| Session expiry storm | >20 renewals/min for 3 min | Warning |
To wire up notifications (Slack, PagerDuty, email), add an Alertmanager config to docker-compose.yml and point Prometheus at it via alerting.alertmanagers in monitoring/prometheus.yml.