Skip to main content
Glama
cPanel/WHM MCP Server

cPanel/WHM MCP Server

by nathjc2
README.md
# cPanel/WHM MCP Server

A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that lets AI assistants such as Claude manage cPanel and WHM servers through their official APIs. It is read-only unless you turn writes on, and every change has to be previewed and confirmed first.

```
Claude (Desktop / Code)  ⇄  this server (local, stdio)  ⇄  WHM API 1 / cPanel UAPI (HTTPS, port 2087)
```

It runs on your own machine. There is nothing to host, no open ports, and nothing to install on the WHM server.

> **Status: early development, not yet tested against a live WHM server.** The API calls were written from cPanel's published API reference (version 11.138) and tested against a fake server. See [Before relying on it](#before-relying-on-it).

This is an unofficial project. It is not affiliated with or endorsed by cPanel, L.L.C. cPanel and WHM are trademarks of their owner.

## What you can ask

- "Which accounts are using more than 80% of their disk quota?"
- "List every account still running PHP 7.4."
- "Show me the last 50 PHP errors for example.co.uk."
- "Which SSL certificates expire in the next 14 days?"
- "Why didn't mail to sales@example.co.uk arrive yesterday?"
- "Who are the top 10 bandwidth users this month?"
- "Create a mailbox for info@example.co.uk and forward it to the owner." (needs `email` writes enabled)

## Setup

You need Node.js 22 or later and a WHM API token from **WHM » Development » Manage API Tokens**. See [Token privileges](#token-privileges).

```bash
npm ci
npm run build
```

Then add the server to your MCP client.

**Claude Desktop** (`claude_desktop_config.json`), or **Claude Code** (`.mcp.json` in your project; keep this file out of version control, as it holds your token):

```json
{
  "mcpServers": {
    "whm": {
      "command": "node",
      "args": ["/absolute/path/to/cpanel-whm-mcp/dist/index.js"],
      "env": {
        "WHM_HOST": "server.example.com",
        "WHM_API_TOKEN": "your-token"
      }
    }
  }
}
```

### Configuration

| Variable | Default | Purpose |
|---|---|---|
| `WHM_HOST` | required | Server hostname. HTTPS only; `http://` is refused. |
| `WHM_API_TOKEN` | required | The WHM API token. |
| `WHM_USERNAME` | `root` | The user that owns the token (root or a reseller). |
| `WHM_PORT` | `2087` | WHM's HTTPS port. |
| `WHM_WRITE_CATEGORIES` | empty | Write tools to enable: any of `accounts`, `dns`, `email`, or `all`. Empty means read-only. |
| `WHM_AUDIT_LOG` | `~/.whm-mcp/audit.log` | Where write actions are logged. |
| `WHM_TIMEOUT_MS` | `30000` | Timeout for each API request. |
| `WHM_TLS_INSECURE` | `false` | Skips certificate checks. Anyone able to intercept the connection could capture your token, so use this only on a network you trust, and prefer giving the server a valid certificate. |

## Tools

### Read-only (always available)

| Area | Tool | What it does |
|---|---|---|
| Accounts | `whm_list_accounts` | List and search accounts |
| | `whm_get_account` | Full details of one account |
| | `whm_disk_usage` | Disk and inode usage; find accounts near quota or the biggest users |
| | `whm_bandwidth_usage` | Bandwidth per account for a month, highest first |
| Domains and DNS | `whm_list_domains` | Domains and subdomains; find which account owns a domain |
| | `whm_list_dns_zones` | List zones |
| | `whm_get_dns_zone` | Records and serial of one zone |
| SSL | `whm_ssl_certificates` | Installed certificates, soonest expiry first |
| | `whm_autossl_problems` | Why AutoSSL can't validate an account's domains |
| Email | `whm_list_email_accounts` | Mailboxes, usage and suspension status |
| | `whm_list_email_forwarders` | Forwarders on a domain |
| | `whm_email_delivery_search` | Mail delivery records; failures and deferrals by default |
| Databases | `whm_list_databases` | An account's MySQL databases |
| | `whm_list_database_users` | An account's MySQL users |
| PHP | `whm_php_versions` | PHP version per site; find outdated versions |
| Diagnostics | `whm_get_error_log` | PHP or Apache error log lines for a domain |
| | `whm_account_resource_usage` | One account's usage against its limits |
| | `whm_server_status` | Load averages and this server's safety settings |

### Write (off until enabled)

| Category | Tool | What it does |
|---|---|---|
| `accounts` | `whm_suspend_account` | Suspend an account, with a required reason |
| | `whm_unsuspend_account` | Unsuspend an account |
| `dns` | `whm_edit_dns_zone` | Add, edit or remove records |
| `email` | `whm_create_email_account` | Create a mailbox and email a set-password invitation |
| | `whm_add_email_forwarder` | Forward an address to other email addresses |

### Deliberately left out

- **Account termination and other irreversible actions.** Out of scope for the first versions.
- **Copying a database.** cPanel's UAPI reference lists no copy function. `Mysql::dump_database_schema` returns the structure but not the data, and `Backup::restore_databases` restores a backup file with no option to choose a different target database, so using it could overwrite the live one. A safe dev copy needs another route, such as SSH.
- **Forwarding mail to programs or system users.** Piping mail to a program amounts to running code on the server.
- **Reading arbitrary files.** The log tool takes a domain and works out the path itself, so it can't be pointed at other files.

## Safety model

**Read-only by default.** A write tool whose category isn't enabled is never registered, so the model can't see or call it.

**Preview, then confirm.** The first call to a write tool changes nothing. It returns exactly what would change and a token. The token only works once, only for that tool with those same parameters, and expires after five minutes.

**Human approval.** If your MCP client supports [elicitation](https://modelcontextprotocol.io/specification/draft/client/elicitation), the server also asks you directly, and declining or closing the prompt stops the change.

> **Know the limit.** On a client without elicitation, the preview step is carried out by the model, which is instructed to ask you first but could in principle send the token without asking. On those clients, your client's own tool-approval prompt is the real human checkpoint, so **don't auto-approve the write tools.**

**DNS edits can't overwrite someone else's change.** An edit must quote the zone's current serial, and it's rejected if the zone has changed since. SOA records can't be changed at all, and changes to NS records carry a warning.

**No secrets in output.** Tool results, error messages and the audit log are all scrubbed of the API token and of values under keys such as `password` or `private_key`. New mailboxes get a random password that is never shown or stored; the owner sets their own through the emailed invitation. Scrubbing log contents is best-effort: it catches `password=...` patterns, but an application could log a secret in some other form.

**Audit log.** Each write is logged as one line of JSON with a timestamp and its parameters: when it's attempted, then whether it succeeded or failed. Declined changes are logged too. If the attempt can't be logged, the change doesn't go ahead.

**Untrusted content.** Logs and mail records contain text written by outsiders, who could try to plant instructions for the AI. These results are labelled as data, but that lowers the risk rather than removing it, so check any change the assistant proposes after reading them.

### Token privileges

Give the token only what you need. These are WHM's privilege names for the features this server uses. cPanel's API reference doesn't list the privilege each function needs, so treat this as a starting point: if a tool reports `AUTH_FAILED` or "Access denied", the token is probably missing one, and some functions may only work for root.

| Needed for | Privileges |
|---|---|
| Accounts and usage | `list-accts`, `acct-summary`, `show-bandwidth` |
| Server status | `basic-system-info`, `status`, `stats` |
| SSL | `ssl` |
| Mail delivery search | `mailcheck` |
| Email, databases, Apache and PHP logs, per-account usage | `cpanel-api` |
| Suspending accounts | `suspend-acct` |
| DNS | `edit-dns` |

**`cpanel-api` is broad.** It lets the token call any cPanel function on the accounts it controls, including ones that change things. With that privilege, or with a root token, this server's read-only mode limits what the assistant can do, but the token itself could do more. Keep it safe accordingly.

## Before relying on it

Everything here is tested against a fake server built from cPanel's documentation, so these points need checking on a real one. Start with a test server, in read-only mode:

1. **Read tools:** try each one and compare the results with what WHM shows.
2. **PHP log paths:** does `Fileman::get_file_information` accept an absolute path, and how does it respond when the file is missing? The docs aren't clear on either.
3. **Mail search limits:** `emailtrack_search` has an optional per-type result cap and the docs don't give its default, so results could be cut short.
4. **POST requests:** the docs only show GET. Writes use POST so that parameters stay out of access logs, and this needs confirming, especially for `uapi_cpanel`.
5. **DNS edit format:** the docs' URL example wraps the record JSON in single quotes, which looks like leftover shell quoting, so this server sends plain JSON. The serial is read from the third SOA field, which the docs don't spell out either. Try this on a throwaway zone.
6. **Mailbox invitations:** check that `UserManager::create_user` sends the invitation, and that the generated password meets your server's strength rules.

## Development

```bash
npm run typecheck
npm test          # builds first, as some tests run the built server
```

The tests cover the request and response handling, every tool and the safety controls. They also run the built server over stdio against a local HTTPS server, which needs `openssl` on your PATH; those tests are skipped without it.

## Roadmap

- [x] Project setup, config and WHM API client
- [x] Read-only tools: accounts, domains, SSL, PHP versions, logs
- [ ] Tests against a dev/test WHM instance
- [x] Write tools behind config flags, with confirmation and audit log
- [x] Documentation and example prompts
- [ ] First public release on GitHub
- [ ] Optional remote (HTTP) mode with proper authentication

## License

[MIT](LICENSE)

TDQS

B3.4/5.0

Scored across 18 tools

Disambiguation4/5

Most tools target a clearly distinct resource (accounts, DNS, SSL, email, databases, PHP, logs), and descriptions add useful cross-references (e.g. get_dns_zone pointing to edit_dns_zone, error-log source hints). Minor overlap: whm_list_accounts vs whm_get_account, and whm_disk_usage/whm_bandwidth_usage/whm_account_resource_usage all report usage from different angles, so an agent must read descriptions to pick correctly.

Naming Consistency3/5

All names share a consistent whm_ prefix, but the conventions below that are mixed: verb_noun (whm_get_account, whm_list_accounts, whm_get_error_log) versus plain noun phrases (whm_disk_usage, whm_ssl_certificates, whm_php_versions, whm_server_status) and one noun_verb oddity (whm_email_delivery_search). It stays readable, but the pattern is not predictable from name alone.

Tool Count4/5

18 tools is on the high side, but each maps to a distinct facet of server administration (accounts, DNS, SSL/AutoSSL, mail, databases, PHP, logs, server health), so none feel redundant. Slightly heavy but reasonable for a WHM-wide inspection surface.

Completeness3/5

The read/diagnostic surface is broad and coherent, but it is almost entirely read-only: no write/edit/delete operations appear, and whm_get_dns_zone explicitly instructs passing the serial to whm_edit_dns_zone, a tool that does not exist in this set. whm_server_status hints write tools may be gated, but from the agent's view these are dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues