An MCP server for Evertrust Horizon - a Certificate Lifecycle Management (CLM) platform. It lets MCP-compatible LLM clients (Claude Desktop, Claude Code, Cursor, Codex, OpenCode) drive certificate issuance, renewal and revocation, run HQL searches over certificates/requests/events, manage discovery campaigns and external datasources, decode X.509/CSR/CRL/OCSP/TSA payloads, and look up Evertrust's official product documentation through natural language. It is aimed at PKI engineers, platform teams and security operators who want to operate Horizon without leaving their IDE or chat client.
Most MCP servers hand an LLM a list of tools and leave it to figure out the domain. horizon-mcp ships 17 core knowledge URIs, 4 curated integration playbooks, and generated section resources for the longest operational guides. Together they cover Horizon's query languages, profile modules, computation engine, workflows, RBAC model, discovery system, external datasources, validation rules, dictionary entries, REST notification connectors, and deterministic tool-selection guidance for smaller models. MCP clients can read these resources to ground tool selection and payload construction, but the server does not force a preload step or guarantee that every client will read them before acting.
- 84 tools across 11 domains, each annotated with a safety tier (
read-only,mutating-safe,mutating-destructive). - Knowledge catalog: 17 core topic URIs, 4 curated playbooks, plus auto-generated section URIs derived from H2 headings of the longest guides.
- Four authentication modes: API key, mTLS (PEM), mTLS (PKCS12/PFX), and OIDC browser session (Playwright-driven).
- HQL helpers: validators and natural-language translators for HCQL (certificates), HRQL (requests), HEQL (events), and HDQL (discovery events).
- Crypto decoding: parse X.509, PKCS#10 CSR, PKCS#7, CRL, OCSP, and RFC 3161 timestamp responses to structured JSON without leaving the chat.
- Confirmation safeguards: every mutating tool emits a STOP confirmation block; destructive tools additionally require an
expected_nameparameter that must match the target object. - Standalone binaries for macOS (x64/arm64), Linux (x64/arm64), and Windows (x64).
Tool counts per domain:
| Domain | Tools | Highlights |
|---|---|---|
| Assist | 20 | whoami, grading, HQL validators, crypto decoders, simulators |
| Lifecycle | 17 | search/aggregate certs, requests, events, enroll, approve, revoke |
| Dashboards | 12 | dashboard CRUD, charts, saved HQL queries |
| Datasources | 8 | DNS / LDAP / REST datasources, plus a test_datasource dry-run |
| Discovery | 6 | campaign CRUD and flush |
| Triggers | 6 | REST notifications and credential listing |
| Discovery feed | 4 | push-mode certificate and event ingestion |
| Discovery events | 3 | search, fetch, CSV export |
| Reports | 3 | list, download, delete |
| Docs | 3 | search product docs, search API docs, fetch a page |
| Profiles | 2 | list and inspect (CRUD lives in the Horizon admin UI) |
Full per-tool table with safety tiers in docs/tools-reference.md.
- Bun 1.x+ (recommended) or Node.js >= 24.10
- An Evertrust Horizon instance (tested on 2.8, expected to work on 2.7 and 2.9)
- API credentials, a client certificate, or browser-based OIDC access to that instance
No install needed:
bunx @evertrust/horizon-mcp
# or
npx -y @evertrust/horizon-mcpDownload the pre-built binary for your platform from the releases page. The release artifacts cover:
horizon-mcp-darwin-x64horizon-mcp-darwin-arm64horizon-mcp-linux-x64horizon-mcp-linux-arm64horizon-mcp-windows-x64.exe
Make it executable and run it:
chmod +x horizon-mcp-darwin-arm64
./horizon-mcp-darwin-arm64git clone https://github.com/evertrust/horizon-mcp.git
cd horizon-mcp
bun install
bun run build
node dist/index.jsThe server is configured entirely through HORIZON_* environment variables. A starter template lives in .env.example; copy it to .env.local and adjust.
The server auto-detects the authentication mode based on which variables are set. Priority order: mTLS > API key > OIDC browser.
| Variable | Required? | Default | Description |
|---|---|---|---|
HORIZON_URL |
Yes | https://localhost |
Base URL of your Horizon instance. Trailing slash is stripped automatically. |
HORIZON_API_ID |
API key mode | API key identifier. | |
HORIZON_API_KEY |
API key mode | API key secret. | |
HORIZON_CLIENT_CERT |
mTLS (PEM) mode | Filesystem path to a PEM client certificate. | |
HORIZON_CLIENT_KEY |
mTLS (PEM) mode | Filesystem path to the matching PEM private key. | |
HORIZON_CLIENT_KEY_PASSWORD |
No | Decryption password for an encrypted PEM private key. | |
HORIZON_CLIENT_PFX |
mTLS (PFX) mode | Filesystem path to a PKCS12 / PFX bundle. | |
HORIZON_CLIENT_PFX_PASSWORD |
No | Decryption password for the PKCS12 bundle. | |
HORIZON_VERIFY_SSL |
No | true |
Set to false or 0 to skip TLS verification on the Horizon endpoint (development only). |
HORIZON_TIMEOUT |
No | 30 |
HTTP request timeout in seconds for standard API calls. |
HORIZON_LOGIN_TIMEOUT |
No | 300 |
Timeout in seconds for the OIDC browser login window. |
HORIZON_EXPORT_TIMEOUT |
No | 120 |
Timeout in seconds for CSV exports and other long-running endpoints. |
HORIZON_LOG_LEVEL |
No | INFO |
One of DEBUG, INFO, WARNING, ERROR. |
HORIZON_TESTED_VERSIONS |
No | 2.8 |
Comma-separated list of Horizon versions known to fully work with this build. |
HORIZON_WARN_VERSIONS |
No | 2.7,2.9 |
Comma-separated list of versions that are likely to work but emit a warning. |
HORIZON_AUTH_MODE |
DEPRECATED | No longer required. Kept readable for backward compatibility; setting it logs a warning. |
OIDC browser sessions need no extra variables: when neither API key nor mTLS variables are set, the server launches Playwright Chromium pointed at HORIZON_URL and waits for HORIZON_LOGIN_TIMEOUT seconds for the user to complete login.
These variables are read by the test suite only and never by the server itself:
| Variable | Used by | Description |
|---|---|---|
HORIZON_E2E_URL |
bun run test:e2e |
Base URL of the Horizon instance for E2E tests. |
HORIZON_E2E_API_ID |
bun run test:e2e |
API key identifier for E2E tests. |
HORIZON_E2E_API_KEY |
bun run test:e2e |
API key secret for E2E tests. |
HORIZON_LLM_EVAL_MODEL |
bun run test:llm |
Model identifier used by the LLM evaluation harness. |
The binary name shipped by this package is horizon-mcp (declared in package.json bin). Use that exact name in every client configuration; do not call it horizon-mcp-server.
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"horizon": {
"command": "bunx",
"args": ["@evertrust/horizon-mcp"],
"env": {
"HORIZON_URL": "https://horizon.example.com",
"HORIZON_API_ID": "<your-api-id>",
"HORIZON_API_KEY": "<your-api-key>"
}
}
}
}Create .mcp.json in your project root:
{
"mcpServers": {
"horizon": {
"command": "bunx",
"args": ["@evertrust/horizon-mcp"],
"env": {
"HORIZON_URL": "https://horizon.example.com",
"HORIZON_API_ID": "<your-api-id>",
"HORIZON_API_KEY": "<your-api-key>"
}
}
}
}Create .cursor/mcp.json in your project root (or ~/.cursor/mcp.json for global access) with the same mcpServers block as Claude Code.
For Codex, OpenCode, and MCP Inspector configurations, see docs/client-setup.md. To point any of the above clients at a standalone binary instead of bunx, replace command with the absolute path to the downloaded binary and drop the args field.
- API key - the recommended mode for headless or service-account use. Issue an API identity in Horizon, set
HORIZON_API_IDandHORIZON_API_KEY, and the server signs every request with those credentials. - Mutual TLS (PEM) - use when your Horizon instance enforces client certificates and you already have separate cert and key files. Set
HORIZON_CLIENT_CERT,HORIZON_CLIENT_KEY, and optionallyHORIZON_CLIENT_KEY_PASSWORD. - Mutual TLS (PKCS12 / PFX) - same as above but using a combined
.p12/.pfxbundle. SetHORIZON_CLIENT_PFXand optionallyHORIZON_CLIENT_PFX_PASSWORD. - OIDC browser session - useful for human operators who already have SSO. Set only
HORIZON_URLand install Playwright Chromium (bun install playwright && bunx playwright install chromium); the server opens a browser window at startup and captures thePLAY_SESSIONcookie once login completes.
See docs/authentication.md for the full step-by-step guide and troubleshooting tips.
The 84 tools are grouped into 11 domains. Each tool ships with explicit "use when / do not use when" guidance for smaller models. The table at the top of this README lists tool counts; docs/tools-reference.md has the full per-tool table with safety tiers and one-line descriptions.
Knowledge resources are exposed at horizon://knowledge/* URIs. See docs/knowledge-resources.md for the full catalog.
These natural language prompts work with any connected LLM.
What profiles are configured on this Horizon instance?
Show me the discovery campaigns and their current status.
Find all certificates expiring in the next 30 days.
Search for revoked certificates issued by the "Internal-CA" profile.
Show me certificates with a grade lower than B.
Export a CSV of all valid certificates matching dn contains ".example.com".
List my certificates (resolve me with whoami first, then query owner and team).
Enroll a new certificate through the WebRA-TLS profile with CN=app.example.com and SAN=DNS:app.example.com.
Download certificate abc123 in PKCS12 format with password "changeit".
Revoke the certificate with ID xyz789, reason: keyCompromise.
Decode this PEM CSR and tell me which extensions it requests.
Fetch the live TLS certificate from horizon.example.com:443 and report its grade.
Who am I authenticated as, and what permissions do I have?
Validate this HCQL query: dn matches ".*\.internal" and valid.until before 30d
List all configured external datasources.
Create a DNS datasource that looks up CNAME records for certificate SAN validation.
Build a REST notification that creates a ServiceNow incident when a certificate
is about to expire, and assigns it to the team that owns the certificate.
The build:binary script compiles the current package for the host platform:
bun run build:binary
# -> dist/horizon-mcpbuild:binaries cross-compiles for all five supported targets (macOS x64/arm64, Linux x64/arm64, Windows x64):
bun run build:binaries
# -> dist/horizon-mcp-{darwin,linux,windows}-{x64,arm64}[.exe]Both scripts pass --external playwright (and --external chromium-bidi --external electron for the cross-compile target) so the resulting binaries do not embed Playwright. If you plan to use OIDC browser auth, install Playwright separately in the runtime environment.
bun install
source .env.local # QA credentials for E2E and LLM tests
bun run validate:ci # format:check + lint + typecheck + build + truth checks + docs diff + unit + LLM scenariosMore granular scripts:
| Command | Purpose |
|---|---|
bun run dev |
Start the server with tsx (no build step). |
bun run build |
Production build via tsup. |
bun run test |
Unit tests with Vitest (80%+ coverage threshold). |
bun run test:e2e |
E2E tests against a live Horizon instance. |
bun run test:llm |
Deterministic tool-selection scenarios (no LLM call). |
bun run test:llm:live |
Real Claude-in-the-loop MCP usability tests. |
bun run lint |
ESLint over src/ and tests/. |
bun run typecheck |
tsc --noEmit only. |
bun run docs:refresh |
Regenerate embedded docs from upstream sources. |
bun run test:llm:live drives the real Claude Agent SDK against the local Horizon MCP server, asking Claude a curated set of natural-language questions and asserting that it picks the right MCP tools. Use it before merging changes that alter tool names, descriptions, or input schemas - the deterministic ranker in test:llm is a fast proxy, but only a real model exposes whether your wording works for an actual user.
Prerequisites:
claudeCLI onPATHwith an active subscription session (runclaude loginonce)HORIZON_E2E_*credentials in the environment (source .env.localfirst)ANTHROPIC_API_KEYunset - the suite refuses to run against API billing to avoid surprise per-token charges. Subscription-only by design.
Cost / billing:
- Each scenario consumes one or two Claude Haiku 4.5 turns drawn from your Claude plan's credits (or the dedicated Agent SDK monthly credit after Anthropic's 2026-06-15 billing change).
- A hard
maxBudgetUsdcap (default$0.05) andmaxTurnscap (default2) are enforced per scenario to bound any runaway loop. - Override the model with
HORIZON_LLM_LIVE_MODEL=claude-sonnet-4-6 bun run test:llm:livewhen you want a stricter fidelity check.
The suite is intentionally excluded from validate:ci so PR builds never burn subscription credits.
See docs/development.md for environment setup, fixture management, and contribution tips.
HORIZON_API_ID and HORIZON_API_KEY must both be set- exactly one auth mode must be fully configured. Either provide both API key variables, both mTLS variables (cert+key or pfx), or neither (for OIDC).- TLS handshake failures - check
HORIZON_URLuseshttps://, that the Horizon CA is trusted by your system store, and (for development only) thatHORIZON_VERIFY_SSL=falseis honoured. HQL-001parse errors - HQL field names are lowercase (contactemail, notcontactEmail). The two exceptions aregroupByandsortedBy, which are camelCase because they are API parameters rather than query fields. Seehorizon://knowledge/query-languages.- Missing CSRF token in OIDC mode - if you see CSRF errors after a long browser session, restart the server so it can reopen Chromium and capture a fresh
csrf-tokencookie alongsidePLAY_SESSION. - Version compatibility warnings - the server logs a warning when the connected Horizon version is in
HORIZON_WARN_VERSIONS. Functionality is best-effort on those versions; promote toHORIZON_TESTED_VERSIONSonly after running your own E2E suite. Chromium browser not foundfor OIDC - runbunx playwright install chromium(ornpx playwright install chromium) inside the environment where the server runs.
| Horizon version | Status |
|---|---|
| 2.8.5+ | Tested (full feature set including Base64/Raw computation rules) |
| 2.8.0-2.8.4 | Tested (Base64/Raw computation rules not available) |
| 2.7 | Expected to work (in HORIZON_WARN_VERSIONS) |
| 2.9 | Expected to work (in HORIZON_WARN_VERSIONS) |
The following capabilities require direct Horizon API calls or the Horizon UI:
- Configuration objects - CAs, trust chains, labels, HTTP proxies, password policies, grading policies, and grading rulesets
- Profile management - creating, updating, or deleting profiles (read-only listing and inspection are supported)
- Credential management - creating, updating, or deleting stored credentials (read-only listing IS supported via
list_credentials) - PKI and third-party connector management - connectors to ADCS, EJBCA, HashiCorp Vault, etc.
- Email/webhook trigger management - email and webhook (Teams/Slack/Mattermost) triggers (REST notifications ARE supported via
create_rest_notification) - Trigger attachment to profiles - use the Horizon admin UI or profile API
- Role, team, IDP, and principal administration
- Analytics - sync status and reindex operations
- SMTP and notification server configuration
- Intune, Jamf, and MDM integration setup
- Scheduler and system-level automation
PRs welcome. Before opening a pull request, run bun run validate:ci (it runs formatting, lint, typecheck, build, truth checks, docs diff, unit tests, and the LLM scenario suite). Source .env.local first if you have QA credentials; the LLM scenarios degrade gracefully without them but you get more signal with them set. Keep commits to one-line conventional messages (type: description).
Caution
Experimental software - this MCP server is experimental and should only be used for exploratory purposes at this time.
Permissions - the MCP server authenticates as the configured user and the AI agent operates with that user's full permissions. Evertrust recommends against granting AI agents highly privileged access to the CLM to prevent unintended incidents.
No guaranteed boundaries - while the MCP server attempts to enforce permission boundaries between the user and the AI agent, this may not work in all cases. Users bear sole responsibility for actions taken by the AI agent on their behalf.
AI-generated output - all output is AI-generated and should be subject to manual human validation before being relied upon.
Third-party AI providers - use of AI agents is subject to the terms of service and privacy policy of the AI provider. These are not controlled by the MCP server or by Evertrust.
| Document | Contents |
|---|---|
| Installation | Install methods, OIDC setup, troubleshooting |
| Authentication | All four auth modes with environment variable reference |
| Client setup | Claude Desktop, Claude Code, Cursor, Codex, OpenCode, MCP Inspector |
| Tool reference | All 84 tools by domain with safety tiers |
| Knowledge resources | 17 core URIs, 4 curated playbooks, generated section resources |
| Development | Dev setup, tests, linting |
Copyright 2025-2026 Evertrust. Licensed under the Apache License 2.0.
This project was developed with the assistance of Anthropic's Claude and OpenAI's Codex.