A Model Context Protocol (MCP) server that connects Claude Desktop and other MCP clients to one or more live DirectAdmin hosting control panel servers.
Manage domains, email, DNS, databases, SSL, backups, FTP accounts, and server services through natural language — across a fleet of DirectAdmin servers simultaneously.
- Multi-server support — connect to any number of DirectAdmin servers, reference each by a short alias
- 89 tools spanning the full DirectAdmin feature set
- Admin impersonation — act as any managed user without a separate login key
- Read-only mode — block all write operations for safe exploration
- Two transport modes —
stdiofor Claude Desktop,httpfor remote/shared access - Self-signed cert support — per-server TLS verification toggle (no global bypass)
- Per-server rate limiting — independent request budgets per server
- Audit logging — structured log of every tool call, including impersonation targets
This MCP server connects directly to your live DirectAdmin servers.
Actions marked
Use Read-Only Mode when browsing or sharing access with others.
This software is provided as-is, without warranty of any kind. Use at your own risk.
The authors accept no liability for data loss, service disruptions, or any other damage resulting from the use of this software. You are solely responsible for:
- Securing your login keys and auth tokens
- Validating any actions before confirming them with Claude
- Maintaining backups of your server data
- Ensuring compliance with your DirectAdmin licence and hosting terms
This project is not affiliated with or endorsed by JBMC Software (DirectAdmin) or Anthropic.
- Node.js ≥ 18
- One or more DirectAdmin servers with API access
- A DirectAdmin Login Key for each server (created under Account Manager → Login Keys)
npx directadmin-mcp setupThe setup wizard will:
- Ask for transport mode (choose
stdiofor Claude Desktop) - Walk through adding each DirectAdmin server (URL with port, admin username, login key)
- Test the connection before saving
- Write
.envandservers.jsonto the current directory
Then add to your claude_desktop_config.json:
{
"mcpServers": {
"directadmin-mcp": {
"command": "npx",
"args": ["directadmin-mcp"]
}
}
}Restart Claude Desktop. The tools will appear automatically.
npx directadmin-mcp setup
# choose 'http' as transport mode
npx directadmin-mcpConfigure your MCP client to connect to http://host:3000/mcp with a Bearer <token> header.
Created by the setup wizard. Place in the current directory or your home directory.
{
"default": "prod-web1",
"servers": [
{
"name": "prod-web1",
"url": "https://server1.example.com:2222",
"username": "admin",
"loginKey": "xxxxxxxxxxxxxxxxxxxx",
"label": "Production Web Server 1",
"insecure": false
},
{
"name": "staging",
"url": "https://staging.example.com:2222",
"username": "admin",
"loginKey": "xxxxxxxxxxxxxxxxxxxx",
"label": "Staging (self-signed cert)",
"insecure": true
}
]
}| Field | Required | Description |
|---|---|---|
name |
✓ | Short alias used in all tool calls (e.g. "prod-web1") |
url |
✓ | Full URL including port — DirectAdmin default is :2222 but can differ |
username |
✓ | Admin or reseller username |
loginKey |
✓ | Login key from Account Manager → Login Keys |
label |
— | Human-readable description shown in da_server_list |
insecure |
— | true to skip TLS verification (self-signed certs on private networks only) |
Security: servers.json is set to mode 600 (owner read/write only) on Linux/macOS. Never commit it — it is in .gitignore.
TRANSPORT=stdio # stdio | http
# HTTP only
PORT=3000
BIND_HOST=127.0.0.1
MCP_AUTH_TOKEN= # min 16 chars
# Feature flags
READ_ONLY=false # block ALL write/modify operations
RATE_LIMIT_RPM=60 # requests/minute limit, applied per server independently
# HTTP access control
WHITELIST_IPS= # comma-separated allowed client IPs (empty = allow all)
WHITELIST_STRICT=false # block if client IP is undetectable
TRUST_PROXY= # IPs of trusted reverse proxies whose X-Forwarded-For is believed
# Logging
LOG_FILE= # path for structured audit logLogin keys are more secure than passwords — they can be restricted to specific IP addresses and API commands in DirectAdmin (Account Manager → Login Keys → Create).
Recommended key permissions for full MCP access: CMD_API_* (all commands). For read-only deployments, restrict to CMD_API_SHOW_* and similar read commands.
All tools are prefixed da_. Every tool that operates on a server accepts an optional server parameter (the server alias). Omit it to use the default server.
Tools that operate on behalf of a managed user accept an optional as_user parameter — the admin or reseller account impersonates that user without needing a separate login key.
| Prefix | Who can call it |
|---|---|
[admin] |
Admin account only |
[reseller] |
Admin or reseller |
[user] |
Any account level, or via as_user impersonation |
| Tool | Description |
|---|---|
da_server_list |
List all configured servers with labels and URLs |
da_server_ping |
Health-check one or all servers; returns per-server status |
da_server_stats |
[admin] Get load, memory, and disk usage |
da_server_get_api_spec |
[admin] Fetch the server's Swagger/OpenAPI spec to discover available endpoints |
da_server_test_impersonation |
[admin/reseller] Verify as_user impersonation works for a username |
da_ip_list |
[admin] List all IPs available on a server |
| Tool | Description |
|---|---|
da_account_list_users |
[admin/reseller] List user accounts. Resellers see only their own users. |
da_account_list_resellers |
[admin] List all reseller accounts |
da_account_get |
[admin/reseller] Get details for a specific user |
da_account_create_user |
[admin/reseller] Create a new user account |
da_account_create_reseller |
[admin] Create a new reseller account |
da_account_suspend |
[admin/reseller] Suspend a user account |
da_account_unsuspend |
[admin/reseller] Unsuspend a user account |
da_account_delete |
[admin/reseller] Permanently delete a user account |
da_account_change_package |
[admin/reseller] Change a user's hosting package |
da_account_set_quota |
[admin/reseller] Update disk/bandwidth quotas |
| Tool | Description |
|---|---|
da_package_list |
[admin/reseller] List all hosting packages |
da_package_get |
[admin/reseller] Get full details of a specific package |
da_package_create |
[admin] Create a new hosting package |
da_package_delete |
[admin] Delete a hosting package |
| Tool | Description |
|---|---|
da_domain_list |
[user] List all domains for a user |
da_domain_add |
[user] Add a domain (use da_ip_list to find the IP to assign) |
da_domain_delete |
[user] Permanently remove a domain and all its data |
da_subdomain_list |
[user] List subdomains for a domain |
da_subdomain_add |
[user] Create a subdomain |
da_subdomain_delete |
[user] Remove a subdomain |
da_pointer_list |
[user] List domain pointers (parked domains) |
da_pointer_add |
[user] Add a domain pointer |
da_pointer_delete |
[user] Remove a domain pointer |
| Tool | Description |
|---|---|
da_email_list |
[user] List email accounts for a domain |
da_email_create |
[user] Create an email account |
da_email_delete |
[user] Delete an email account |
da_email_change_password |
[user] Change an email account password |
da_email_set_quota |
[user] Set mailbox size quota |
da_forwarder_list |
[user] List email forwarders |
da_forwarder_create |
[user] Create an email forwarder |
da_forwarder_delete |
[user] Delete a forwarder |
da_autoresponder_list |
[user] List autoresponders |
da_autoresponder_set |
[user] Create or update an autoresponder |
da_autoresponder_delete |
[user] Delete an autoresponder |
da_spamfilter_get |
[user] Get spam filter settings for a domain |
da_spamfilter_set |
[user] Update spam filter settings |
| Tool | Description |
|---|---|
da_dns_list |
[user] List all DNS records for a domain |
da_dns_add |
[user] Add a DNS record (A, AAAA, CNAME, MX, TXT, SRV, NS, etc.) |
da_dns_delete |
[user] Delete a DNS record |
da_dns_set_ttl |
[user] Update the default TTL for a domain's DNS zone |
| Tool | Description |
|---|---|
da_db_list |
[user] List databases for a user |
da_db_create |
[user] Create a new database |
da_db_delete |
[user] Permanently delete a database |
da_db_user_list |
[user] List database users |
da_db_user_create |
[user] Create a database user |
da_db_user_delete |
[user] Delete a database user |
da_db_user_set_password |
[user] Change a database user password |
da_db_assign_user |
[user] Assign a database user to a database |
| Tool | Description |
|---|---|
da_ftp_list |
[user] List FTP accounts for a user |
da_ftp_create |
[user] Create an FTP account |
da_ftp_delete |
[user] Delete an FTP account |
da_ftp_change_password |
[user] Change an FTP account password |
| Tool | Description |
|---|---|
da_ssl_get |
[user] Get SSL certificate info for a domain |
da_ssl_enable_letsencrypt |
[user] Enable a free Let's Encrypt certificate |
da_ssl_disable |
[user] Disable SSL for a domain |
da_ssl_upload |
[user] Upload a custom SSL certificate and private key |
| Tool | Description |
|---|---|
da_backup_create |
[user] Initiate a backup job (async — returns immediately, not when complete) |
da_backup_list |
[user] List available backups for a user |
da_backup_restore |
[user] Restore a backup — overwrites current account data |
da_backup_delete |
[user] Permanently delete a backup file |
| Tool | Description |
|---|---|
da_file_list |
[user] List files and directories at a path |
da_file_chmod |
[user] Change file or directory permissions |
da_file_delete |
[user] Permanently delete a file or directory |
| Tool | Description |
|---|---|
da_system_info |
[admin] Get DirectAdmin version and OS information |
da_system_services |
[admin] List all monitored services and their status |
da_system_restart_service |
[admin] Restart a named service (apache, nginx, mysql, etc.) |
da_system_tail_log |
[admin] Return the last N lines of a system log file (max 1000 lines) |
| Tool | Description |
|---|---|
da_cron_list |
[user] List all cron jobs for a user |
da_cron_add |
[user] Add a cron job (schedule fields: minute, hour, dayom, month, dayow) |
da_cron_delete |
[user] Delete a cron job by its exact command |
| Tool | Description |
|---|---|
da_php_list_versions |
[admin] List all PHP versions available on the server |
da_php_get |
[user] Get the current PHP version for a domain |
da_php_set |
[user] Set the PHP version for a domain |
| Tool | Description |
|---|---|
da_mailqueue_list |
[admin] List messages currently in the mail queue |
da_mailqueue_delete |
[admin] Delete one or all messages from the queue |
da_mailqueue_flush |
[admin] Flush the queue — retry delivery of all queued messages |
| Tool | Description |
|---|---|
da_reseller_ip_list |
[admin] List IP addresses assigned to a reseller |
da_reseller_ip_add |
[admin] Assign an IP from the server pool to a reseller |
da_reseller_ip_remove |
[admin] Remove an IP from a reseller (returns to server pool) |
| Tool | Description |
|---|---|
da_modsec_status |
[user] Get the ModSecurity status and ruleset for a domain |
da_modsec_set |
[user] Enable or disable ModSecurity for a domain |
| Tool | Description |
|---|---|
da_totp_status |
[admin] Get the TOTP/2FA status for a user account |
da_totp_disable |
[admin] Disable 2FA for a user account (for account recovery) |
Reference any server by its alias in tool calls:
"List domains on the staging server"
→ da_domain_list with server="staging"
"Check services on all servers"
→ da_server_ping (no server arg — pings all)
"Create a database for johndoe on prod-web1"
→ da_db_create with server="prod-web1", as_user="johndoe"
When server is omitted, the tool operates on the default server defined in servers.json.
cp .env.example .env
cp servers.json.example servers.json
# edit both files
docker compose up -dBoth .env and servers.json are mounted as read-only volumes at runtime — they are never baked into the image.
The container exposes port 3000 (configurable) and responds to GET /health for health checks.
npm install --production
pm2 start ecosystem.config.cjs
pm2 saveAlways use login keys, not admin passwords. Keys can be restricted to specific IP addresses and API commands in DirectAdmin (Account Manager → Login Keys). If a key is compromised, it can be revoked without changing the admin password.
Set READ_ONLY=true to block all 45 state-changing operations. Use this when exploring a production server or granting access to others. Only read-only tools remain available — no creates, updates, password changes, or deletes.
Set insecure: true on a server entry only for self-signed certificates on trusted private networks. On public internet, a valid certificate (e.g. Let's Encrypt on port 443 or 2222) is strongly recommended. The insecure flag is scoped per server — it never affects other outbound connections.
- Use a strong randomly generated
MCP_AUTH_TOKEN(the setup wizard offers to auto-generate one) - Bind to
127.0.0.1unless you have a reverse proxy in front - Set
WHITELIST_IPSwhen the endpoint is exposed beyond localhost - Set
TRUST_PROXY=<proxy_ip>only when a known reverse proxy (nginx, Caddy, etc.) sits in front. When set,X-Forwarded-Foris trusted only from that proxy's IP — the real client IP is resolved by walking XFF right-to-left past trusted entries, preventing a forged leftmost-IP from bypassing the whitelist. Leave blank (the default) to ignore XFF entirely. - Put the HTTP endpoint behind TLS in production
Set LOG_FILE=/path/to/audit.log to enable structured JSON logging of every tool call. Log entries include the tool name, target server, impersonated user, execution duration, and outcome. PEM key material and other credentials are automatically redacted from log entries.
as_user uses DirectAdmin's built-in impersonation mechanism (admin|targetuser Basic Auth). It works with a single admin login key — no separate keys are needed per user. All impersonated calls are recorded in the audit log.
All major DirectAdmin API areas are now covered. Additional coverage can be added as additional tool modules following the existing pattern in src/tools/.
# Install dependencies
npm install
# Run the setup wizard
npm run setup
# Start in stdio mode (for testing with an MCP client)
npm start
# Run tests
npm testTests use Node.js built-in node:test — no external test framework required. All tool handlers are tested via a MockDAClient that avoids live network calls.
- Add the definition object to the relevant module's
definitionsarray - Prefix the name
da_; start the description with[admin],[reseller], or[user] - Add
serverandas_userparams toinputSchemaif applicable - Add the
handle()case; usebase.asUser()whenargs.as_useris set - If it changes server state: add the name to
WRITE_TOOLSinsrc/tools/index.js - Add tests in
test/tools/usingMockDAClient
MIT