AI Assistant (MCP)

Last updated

jabali-mcp is a stdio MCP server that wraps the panel’s REST API as 75+ tools an AI assistant can call. It reimplements no auth, no validation, no scoping — every call goes through the same ownership checks the panel enforces for any API client, using your API token as your identity.

Marketing overview: jabali-panel.com/mcp. Source: github.com/shukiv/jabali-mcp. Full tool reference: docs/TOOLS.md.

What it is

  • Transport: stdio. The MCP client launches the binary on demand — nothing runs when no client is attached.
  • Language / binary: single Go binary, AGPL-3.0.
  • Auth: Bearer token (JABALI_API_TOKEN) minted from the panel’s tenant shell → API TokensMCP tab. Sent only to the configured panel URL over TLS.
  • Panel URL: JABALI_PANEL_URL, e.g. https://panel.example:8443/api/v1.

Safety model

The server ships with four layers of guardrails. All four are on by default.

  • Read-only by default. Mutating tools are not registered unless JABALI_MCP_ALLOW_WRITE=1 is set. Without it, an assistant that tries to call a write tool sees the tool doesn’t exist.
  • Two-step destructive actions. Deletes, restores, and password rotations always return a preview first. The tool executes only when re-called with confirm: true. An assistant cannot destroy anything in one call.
  • Dry-run. JABALI_MCP_DRY_RUN=1 (or per-call dry_run: true) shows the exact REST request that would be sent, without sending it. Useful when writes are enabled and you’re not sure what a prompt will do.
  • Token boundary. Ownership is enforced server-side by the panel on every endpoint. The MCP server can’t reach anything your token can’t. A tenant token is scoped to that tenant’s resources only.

Every tool call is a normal REST request in your panel’s audit trail.

Install

Prebuilt binaries: https://github.com/shukiv/jabali-mcp/releases/latest.

Or install from source:

go install github.com/shukiv/jabali-mcp/cmd/jabali-mcp@latest

Setup

1. Mint a token

Log in to the panel as the tenant whose resources the assistant should manage. Go to API TokensMCP. The wizard generates a client-config JSON block with your token pre-filled — entirely in the browser, no server round-trip after the token is issued.

Use a tenant token, not the admin token, whenever possible. Ownership scoping means the assistant sees only that tenant’s domains, mailboxes, databases, etc.

2. Run the wizard

jabali-mcp init

Prompts for panel URL + token, verifies the connection, writes the config file the client will read.

3. Register with your client

Claude Code:

claude mcp add jabali -- jabali-mcp

Claude Desktop / Cursor / Windsurf / any client using the standard mcpServers block:

{
  "mcpServers": {
    "jabali": {
      "command": "jabali-mcp",
      "env": {
        "JABALI_PANEL_URL": "https://panel.example:8443/api/v1",
        "JABALI_API_TOKEN": "jat_…"
      }
    }
  }
}

Environment variables

VariableRequiredPurpose
JABALI_PANEL_URLyesPanel REST API base URL. Include /api/v1 suffix. TLS required — no http://.
JABALI_API_TOKENyesBearer token minted from the panel’s tenant shell.
JABALI_MCP_ALLOW_WRITEno (default 0)Set to 1 to register mutating tools. Without it the server is read-only.
JABALI_MCP_DRY_RUNno (default 0)Set to 1 to make every mutating call return the planned REST request instead of sending it.
JABALI_CA_FILEnoPath to a CA bundle. Point at your CA when the panel uses a self-signed or private-CA cert. TLS verification is always on — there is no way to disable it.

Tool surface

75+ tools grouped by resource area:

  • Domains: list_domains, get_domain, diagnose_domain, get_domain_bandwidth, get_domain_whois, tail_web_log.
  • DNS: list_dns_records and (in write mode) DNS record CRUD gated by panel validation.
  • SSL: get_ssl_status per domain.
  • Mail: list_mailboxes, get_mailbox, list_forwarders, get_autoresponder, list_mail_logs.
  • Databases: list_databases, get_database, list_database_users.
  • Applications: list_applications, get_application, list_app_catalog.
  • Backups: list_backups, get_backup_manifest.
  • Cron: list_cron_jobs, get_cron_job, get_cron_log.
  • Files: list_files, preview_file.
  • PHP: get_php_settings, list_php_versions.
  • Ops: list_activity, list_api_tokens, list_ssh_keys, get_disk_usage, whoami.
  • Meta: report_issue (drafts a GitHub bug report with live diagnostics for you to review before posting).

The authoritative, always-up-to-date list is generated from the code: docs/TOOLS.md.

diagnose_domain is worth highlighting: a single call gathers domain config, SSL status, DNS records, recent nginx errors, and bandwidth, so the assistant has everything it needs to explain “why is example.com down?” without a dozen follow-up tool calls.

Common tasks

Read-only checks the assistant can run in the default config:

  • Explain an outage: “Why is example.com down?” — one diagnose_domain call, results explained.
  • SSL sweep: “Which of my domains don’t have SSL?” — list_domains + get_ssl_status per domain.
  • Mail audit: “List every mailbox with a forwarder set.” — list_mailboxes + list_forwarders.
  • Backup verification: “Show me the newest manifest for user X.” — list_backups + get_backup_manifest.

With JABALI_MCP_ALLOW_WRITE=1:

  • Provisioning: “Create two mailboxes and a catch-all forwarder on my new domain.”
  • DNS edits: “Add an A record for vpn pointing at 203.0.113.5, TTL 300.”
  • Cert issuance sweep: “Enable Let’s Encrypt on every domain that doesn’t have it.”
  • Database provisioning: “Create a database + user for the shop app, read-write.”

Client compatibility

Any MCP-capable client works. Documented as of jabali-mcp v0.4.0:

  • Claude Code
  • Claude Desktop
  • Cursor
  • Windsurf
  • Cline
  • OpenAI Codex
  • OpenCode
  • Gemini CLI

Troubleshooting

  • connect: connection refused — check JABALI_PANEL_URL and that the panel is reachable from the machine running the MCP client, not just from the panel host itself.
  • x509: certificate signed by unknown authority — panel uses a private CA. Set JABALI_CA_FILE to your CA bundle.
  • 401 unauthorized — token wrong, revoked, or from the wrong tenant. Re-mint in the panel’s API TokensMCP tab.
  • Assistant says “no such tool” for a write — writes are read-only unless JABALI_MCP_ALLOW_WRITE=1 is set in the client’s env block. Restart the MCP client after changing env vars.
  • Assistant asks to confirm a destructive action — expected. Re-call the tool with confirm: true to actually execute.

Community

Roadmap and requests: github.com/shukiv/jabali-panel/discussions/963.