plesk-mcp
Provides SQL tools against Plesk databases (via the server's MySQL credentials) and directly reachable local MySQL databases, with a read-only query tool (SELECT/SHOW/DESCRIBE/EXPLAIN) and a separate write/DDL/administration tool.
Configures Node.js applications hosted on Plesk servers, including managing application settings and installing project dependencies.
Manages one or more Plesk servers, providing tools to upload/download/manage files, configure Node.js applications, install dependencies, read domain logs, and execute SQL against Plesk-hosted databases.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@plesk-mcp upload the dist folder to my prod server and restart the Node app"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
plesk-mcp
Local MCP server for managing one or more Plesk servers:
Upload, download, and manage files.
Configure Node.js applications.
Install dependencies.
Read domain logs.
Run SQL against Plesk databases and local MySQL databases.
It replaces the mysql MCP server (DBHub): all database access goes through
this server.
Requirements
Node.js 22 or newer.
Plesk Obsidian 18.0.81 or newer on Linux (validated on 18.0.81).
A Plesk API key, or a username/password with REST API access.
For SQL on Plesk: at least one domain with shell access and the
mysqlormariadbclient installed. MySQL credentials (dbUser/dbPass) are configured per Plesk server.For archive-based transfers: command execution enabled in the Plesk REST extension and
taravailable. If command execution is unavailable, the server falls back to REST-only transfers.
Related MCP server: cpanel-mcp
Installation
Install the package globally:
npm install -g @rubcc95/plesk-mcpOr run it directly with npx:
npx -y @rubcc95/plesk-mcpInstall from a clone:
npm install
npm run build
npm test
npm linkThe package exposes a single binary, plesk-mcp:
Without arguments it starts the MCP server over stdio.
With a subcommand (
init,doctor,servers,project-info) it runs the configuration CLI.--helpand--versionshow CLI help and the package version.
MCP client setup
Add the server once to your MCP client. Example for OpenCode:
{
"mcp": {
"servers": {
"plesk": {
"type": "local",
"command": ["npx", "-y", "@rubcc95/plesk-mcp"],
"environment": {
"PLESK_MCP_ACCESS": "client"
}
}
}
}
}PLESK_MCP_ACCESS=client means the server does not show its own confirmation
forms; your client's permission dialog is responsible for write operations. If
you omit environment, the server runs in confirm mode and asks for
confirmation through MCP elicitation. See Access control.
The local configuration file is resolved from the MCP process working
directory. If your client supports cwd, point it at the project that contains
.plesk/config.json. If it does not, set PLESK_PROJECT_ROOT to that project:
"environment": {
"PLESK_PROJECT_ROOT": "C:\\Users\\you\\projects\\my-project"
}Otherwise, use the global config file, which is always found.
Claude Code
Claude Code runs the server as a local stdio process. Add it to the project's
.mcp.json:
{
"mcpServers": {
"plesk": {
"command": "npx",
"args": ["-y", "@rubcc95/plesk-mcp"],
"env": {
"PLESK_MCP_ACCESS": "client",
"PLESK_PROJECT_ROOT": "${CLAUDE_PROJECT_DIR:-.}"
}
}
}
}Claude Code sets CLAUDE_PROJECT_DIR for stdio servers, so
PLESK_PROJECT_ROOT resolves to the project root. Approve the project server
from /mcp the first time.
Or register it from the command line:
claude mcp add --scope project --transport stdio plesk \
--env PLESK_MCP_ACCESS=client \
-- npx -y @rubcc95/plesk-mcpIf the local config is not found, pass an absolute path:
claude mcp add --scope project --transport stdio plesk \
--env PLESK_MCP_ACCESS=client \
--env PLESK_PROJECT_ROOT=/absolute/path/to/project \
-- npx -y @rubcc95/plesk-mcpCheck the connection:
claude mcp list
claude mcp get pleskClaude Code permission rules use mcp__<server>__<tool>. Minimal example for
.claude/settings.json:
{
"permissions": {
"allow": [
"mcp__plesk__execute_sql",
"mcp__plesk__list_databases",
"mcp__plesk__search_objects"
],
"ask": [
"mcp__plesk__execute_sql_write"
]
}
}Add the other write tools (mcp__plesk__file_write,
mcp__plesk__file_upload, mcp__plesk__file_delete,
mcp__plesk__deps_install, and so on) to ask as needed. The full list is in
docs/access-control.md.
Configuration
The server reads two files with the same format:
Global:
~/.config/plesk-mcp/config.jsonLocal:
<project>/.plesk/config.json
Set PLESK_GLOBAL_CONFIG to use a different global file.
Example:
{
"defaultServer": "prod-example",
"servers": [
{
"name": "prod-example",
"url": "https://plesk.example.com:8443",
"auth": {
"mode": "apiKey",
"apiKey": "env:PLESK_API_KEY"
},
"verifyTls": true,
"timeoutMs": null,
"dbUser": "db_admin",
"dbPass": "env:PLESK_DB_PASSWORD"
},
{
"name": "client-a",
"url": "https://plesk.client-a.example:8443",
"auth": {
"mode": "basic",
"username": "admin",
"password": "env:PLESK_CLIENT_A_PASSWORD"
},
"dbUser": "db_admin",
"dbPass": "env:PLESK_CLIENT_A_DB_PASSWORD"
}
],
"localDatabases": [
{
"name": "local-mysql-1",
"host": "192.168.1.50",
"port": 3306,
"user": "root",
"password": "env:MYSQL_LOCAL_1_PASSWORD",
"ssl": false
}
]
}Rules
Both files are loaded and merged by
name.If the same name exists in both files, the local entry wins.
The local
defaultServerwins over the global one.If no
defaultServeris set, the first merged server is the default.A
serversentry is a Plesk server, not a domain. Passdomainto tools that need it; if the server has only one domain, it is detected automatically.dbUser/dbPassare MySQL credentials for that Plesk server and are used for all of its databases. They must be provided together.localDatabasescontains direct MySQL connections reachable from your machine (nameis passed aspcin SQL tools).The same name cannot exist in both
serversandlocalDatabases(DUPLICATE_TARGET_NAME).Any string value can be
env:VARIABLE. References are resolved lazily when the target is used, so a missing variable only breaks that target.If neither file exists or both are empty, the MCP server still starts and exposes three configuration-error tools instead of failing to boot.
A flat array is also accepted, but only for Plesk servers:
[
{
"name": "prod-example",
"url": "https://plesk.example.com:8443",
"auth": { "mode": "apiKey", "apiKey": "env:PLESK_API_KEY" },
"dbUser": "db_admin",
"dbPass": "env:PLESK_DB_PASSWORD"
}
]In that format there is no defaultServer and no localDatabases; the first
server is the default.
Server fields
name: unique identifier used by theserverinput.url: Plesk base URL, usually with:8443.auth.mode:apiKeyorbasic.apiKey: requiresauth.apiKey.basic: requiresauth.usernameandauth.password.
verifyTls: verify the Plesk TLS certificate. Defaults totrue.timeoutMs: per-request timeout in milliseconds.nullor omitted means no timeout.dbUser/dbPass: MySQL credentials with access to the server databases.
Local database fields
name: unique identifier used by thepcinput.host,port: MySQL endpoint. Port defaults to3306.user,password: MySQL credentials.ssl: use TLS for the MySQL connection. Defaults tofalse.
Create the files
npx -y @rubcc95/plesk-mcp init # local project config
npx -y @rubcc95/plesk-mcp init --global # global configIf the package is installed globally, drop the npx -y @rubcc95/plesk-mcp
prefix and use plesk-mcp directly.
init creates an empty registry and adds .plesk/config.json to the project
.gitignore.
CLI commands
npx -y @rubcc95/plesk-mcp init [--global] [--force]
npx -y @rubcc95/plesk-mcp servers
npx -y @rubcc95/plesk-mcp project-info
npx -y @rubcc95/plesk-mcp doctor [--server <name>] [--domain <domain>]The CLI doctor checks configuration, authentication, domain resolution,
filesystem access, command execution, tar, and path access. It exits with a
non-zero status if any check fails. The MCP doctor tool additionally validates
SQL connectivity when dbUser/dbPass are configured.
Access control
The server is a single process and always registers every tool. Write protection is applied at two levels: the MCP server and the client.
Server modes
PLESK_MCP_ACCESS controls server-side confirmation:
Value | Behavior |
| Write tools ask for confirmation through MCP elicitation. If the client does not support elicitation, the call fails with |
| No server-side confirmation. Intended for clients that apply their own permission dialog, or for tests. |
| Alias for |
| Aliases for |
| Alias for |
Invalid values fall back to confirm and log a warning.
Additional rules:
dry_run: truenever asks for confirmation because it does not modify anything.file_downloadis classified as read-only on the server even though it writes to your local disk. It does not ask for confirmation.Every tool publishes standard annotations (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint).project_inforeports the active access mode.
SQL tools
SQL is split into two tools so the client can give them different permissions:
execute_sql: read-only (SELECT,SHOW,DESCRIBE,EXPLAIN).execute_sql_write: writes, DDL, administration, and unclassified SQL.
The server rejects a statement sent to the wrong tool with
SQL_TOOL_MISMATCH. In confirm mode, execute_sql_write also goes through the
generic write confirmation. In full/client mode it does not; the client's
permission layer is the only gate.
OpenCode example
{
"permissions": [
{ "action": "plesk_execute_sql", "resource": "*", "effect": "allow" },
{ "action": "plesk_execute_sql_write", "resource": "*", "effect": "ask" },
{ "action": "plesk_file_write", "resource": "*", "effect": "ask" },
{ "action": "plesk_file_delete", "resource": "*", "effect": "ask" }
],
"agents": {
"plan": {
"permissions": [
{ "action": "plesk_execute_sql_write", "resource": "*", "effect": "deny" },
{ "action": "plesk_file_write", "resource": "*", "effect": "deny" }
]
}
}
}The complete list of write tools and a full OpenCode configuration are in docs/access-control.md.
Tools
All Plesk tools accept an optional server. If omitted, the default server is
used. Tools that operate on a subscription accept an optional domain; if it is
omitted and the server has only one domain, it is detected automatically. If
there are several domains, the tool returns PLESK_DOMAIN_REQUIRED.
Project and diagnostics
Tool | Inputs | Description |
| - | Lists Plesk servers, local databases, their source, and the default. |
| - | Returns config paths, default server, access mode, servers, and local databases. No secrets. |
|
| Checks auth, domain, filesystem, SQL, command execution, |
Files
Tool | Inputs | Description |
|
| Lists a remote directory. |
|
| Returns size, type, permissions, and modification time. |
|
| Reads a file as UTF-8 or base64. Default limit 1 MB, maximum 10 MB. |
|
| Writes a file. Creates parent directories by default. |
|
| Uploads files or directories. |
|
| Downloads files or directories. |
|
| Creates a directory. |
|
| Moves or renames a path. |
|
| Copies a path. |
|
| Deletes a path. |
|
| Changes permissions. |
Remote paths are absolute and virtual to the subscription root
(/httpdocs/..., /private/...). The client translates them to the real
subscription home because the Plesk API resolves relative paths against the
document root.
Local paths must stay inside the project root. Symlinks that escape the project are rejected, and local symlinks are skipped during recursive uploads.
Node.js
Tool | Inputs | Description |
|
| Lists Node.js applications managed by Plesk. |
|
| Returns the application configuration. |
|
| Auto-configures the application when no options are passed; otherwise updates the given settings. |
| same as | Updates the given settings. |
|
| Lists environment variable names only. Never returns values. |
|
| Imports a local |
|
| Removes an environment variable. |
|
| Installs dependencies with the configured package manager. |
|
| Runs a |
|
| Restarts the application. |
|
| Starts the application. |
|
| Stops the application. |
|
| Returns the application status. |
node_env_set writes entries sequentially. If Plesk rejects an entry, the
operation stops and variables already written remain. Restart the application
after changing environment variables.
Dependencies
Tool | Inputs | Description |
|
| Runs an allowlisted installer: |
Logs
Tool | Inputs | Description |
|
| Searches domain logs. |
SQL
SQL tools require exactly one target: server for a Plesk server or pc for a
local database. There is no default target for SQL.
Tool | Inputs | Description |
|
| Runs read-only SQL. |
|
| Runs writes, DDL, administration, and unclassified SQL. |
|
| Lists databases. Default limit 100 (max 500). Uses cursor pagination. |
|
| Searches |
database is required except for object_type=schema; table is required for
columns and indexes. detail_level is names, summary (default), or full.
The SQL classifier assigns one of read, write, ddl, admin, or unknown:
SELECT,SHOW,DESCRIBE, andEXPLAINare reads.INSERT,UPDATE,DELETE, andREPLACEare writes.CREATE,ALTER,DROP,TRUNCATE, andRENAMEare DDL.GRANT,REVOKE,SET,CALL,USE, locks, transactions,FLUSH,KILL, and table maintenance are administrative.Unparseable or unrecognized SQL is
unknownand therefore only accepted byexecute_sql_write(fail closed).
Multi-statement SQL is classified with the most restrictive verdict. On Plesk, multi-statement output is returned as raw text. On local databases, each statement result is returned separately.
Plesk SQL execution
Plesk SQL does not use a direct TCP connection from your machine. The server
finds a domain with shell and the mysql/mariadb client, then runs a bash
script with a temporary --defaults-extra-file created under umask 077 and
removed by a trap on exit.
Local SQL execution
Local databases use mysql2 over TCP with multipleStatements: true and
utf8mb4. Connection pools are reused and evicted after 10 minutes of
inactivity.
File transfers
file_upload and file_download accept one or more paths. The destination is
interpreted by context:
A single file:
remote/localis the exact file path.A directory or multiple paths:
remote/localis the destination directory.
Direct transfer
A single file is transferred directly through REST in chunks. Uploads first
write to a temporary remote file and then move it into place; failures clean up
the temporary file. chunk_size_mb defaults to 4 MB and accepts up to 50 MB.
mode applies only to this direct single-file upload.
Archive and walk modes
For multiple files or directories, two engines are available:
archive: creates a.tar.gzon the server, transfers it, and extracts it. It is the fastest option but requiresexecandtar.walk: walks the tree withfs/listand transfers files over REST in parallel. It works on subscriptions without shell, including/bin/false, but makes one request per file.
The server always tries archive first and automatically falls back to walk
when command execution is unavailable.
Shell discovery
If the selected domain has no shell, the server looks for another domain with SSH access:
Domains in the same subscription (addon domains and subdomains) are preferred because they share the system user.
It verifies access with
test -e/-r/-wbefore using a foreign shell.For downloads, if the shell belongs to another domain, the
.tar.gzis created and downloaded from that domain's home.For uploads, a foreign shell is used only if it can write to the destination. Extracted files keep that user's ownership and the response includes a warning.
If no domain works, the transfer falls back to
walk.
doctor includes the execPaths check: if a shell exists but cannot access the
domain path, it reports the problem and confirms that walk will be used.
Transfer rules
Paths are preserved relative to the common ancestor.
/httpdocs/assetsproduceslocal/assets/.... To flatten a tree, list individual files instead of the directory.excludeaccepts glob patterns such asnode_modules,.git, or*.log.overwrite: falseskips files that already exist.There are no file count, depth, byte, or timeout limits. Transfers run until they complete or fail. Upload chunks are capped at 50 MB.
Transient errors (network, timeouts, 5xx, 429) are retried indefinitely with exponential backoff. Permanent errors (auth, DNS, TLS, invalid data) are returned immediately.
Walk mode uses a fixed concurrency of 4.
dry_runreturns the transfer plan without writing anything.The local
.tar.gz(.plesk/tmp) and remote temporary archive are always deleted, even when the transfer fails.Remote temp directories are tried in this order:
/.plesk-mcp-tmp, then<base>/.plesk-mcp-tmp.Local extraction rejects unsafe archive entries and names that Windows cannot create.
Remote symlinks are skipped by
walkmode.archivemode may preserve them, subject to the same safety checks on local extraction.Local symlinks are always skipped.
Security
.plesk/config.jsonis in.gitignore. Keep the global config outside the repository.Prefer
env:references for API keys and database passwords instead of storing secrets in the JSON file.Configure your MCP client to deny reading the local and global config files.
Write tools require human confirmation in
confirmmode, or the client's permission dialog infull/clientmode.deps_installaccepts only known installers (npm,pnpm,yarn,composer,bundle,pip,pip3).file_uploadandfile_downloadexecutetaronly with validated paths and exclusion patterns.If the selected domain has no shell, another domain's shell can be used, but always as that domain's system user (never root) and only after verifying real access with
test -e/-r/-w.The only internal commands executed by the server are
whoami,test,pwd,printenv,tar,mysql/mariadb, theplesk ext nodejsCLI, and the installers allowed bydeps_install. There is no generic shell tool.node_run_scriptcan run any script defined in the application'spackage.json. Package installers may also run lifecycle scripts. Treat both as code execution on the server and restrict them with client permissions.Local symlinks are always skipped.
node_env_setdoes not accept keys or values directly: it imports a local.envfile, stores every entry as a secret in Plesk, and never returns the contents to the AI.Plesk MySQL credentials are not used over TCP from your machine. The
mysqlCLI runs on a domain with shell, with a temporaryumask 077credentials file that is deleted on exit.execute_sqlonly runs reads andexecute_sql_writeonly runs writes/DDL/administration (SQL_TOOL_MISMATCHotherwise). The human gate is provided by the client:execute_sql_writewithaskin Build anddenyin Plan.The Plesk MySQL user can access all databases on the server, so the SQL classifier and the client permissions are the write control.
The server itself is a guardrail against AI mistakes, not a security boundary: anyone who can start the process can set
PLESK_MCP_ACCESS=full.
Validation status
Validated on Plesk Obsidian 18.0.81 (Linux):
The
fsAPI resolves relative paths against the document root and accepts absolute paths inside the webspace. The client translates the MCP virtual paths (/httpdocs/...) to the real subscription home.fs/mkdirusespathas a query parameter with no request body.file_downloadend to end:archivemode withexec/taron a domain with shell.automode on a domain with/bin/false, falling back towalkand downloading in parallel over REST.overwrite=falseskips existing files in both modes.direct single-file transfer without
tar.
Configuration loading and precedence, SQL classification, and the file transfer engines are covered by unit tests.
Pending validation against real servers:
plesk ext nodejsflags through/cli/extension/call.Plesk upload chunk-size limits.
execute_sql_writein production withaskin Build anddenyin Plan.
Documentation
License
MIT
Available Tools
3 toolsdoctordoctorCRead-onlyIdempotent
No configuration is loaded. Returns the configuration error.
Inputs: no named parameters.
project_infoproject_infoCRead-onlyIdempotent
No configuration is loaded. Returns the configuration error.
Inputs: no named parameters.
servers_listservers_listCRead-onlyIdempotent
No configuration is loaded. Returns the configuration error.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
The three names hint at different intents (listing servers, project metadata, diagnostics), but every description is the identical 'No configuration is loaded. Returns the configuration error.', giving an agent no way to know what each tool actually returns or when to prefer one over another. `project_info` in particular is ambiguous in a Plesk context (which project? which info?).
`servers_list` uses a noun_plural + verb suffix, `project_info` is noun + attribute, and `doctor` is a bare noun with no resource qualifier. Three tools, three different conventions, with no shared verb_noun pattern to predict new tools from.
Three tools is borderline thin: a Plesk management server would need domain, mail, database, and subscription operations, and these three read more like bootstrap/diagnostic utilities than a scoped surface. The count itself isn't extreme, but it feels undersized for the apparent domain.
The implied domain is Plesk hosting administration, yet the surface offers no create/update/delete or even read operations for domains, websites, mailboxes, or databases — only a health check, a server list, and an info call. There are significant gaps that would block any real management workflow.
Maintenance
Related MCP Connectors
Agent-first web hosting: deploy sites, apps, databases and domains over MCP.
A MCP server built for developers enabling Git based project management with project and personal…
Manage your Servera hosting over MCP: VPS/VDS, DNS, firewall, backups, SSL, billing, tickets.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for managing remote servers via SSH, enabling command execution, file transfer, rsync, tunnels, health checks, backups, and database operations.172,541 npm1MIT
- AlicenseNot gradedqualityFmaintenanceA comprehensive MCP server for managing cPanel web hosting accounts via UAPI, enabling file, database, email, domain, cron, backup, and system monitoring operations.21 npm3MIT
- AlicenseAqualityDmaintenanceEnables reading, writing, editing, searching, running commands, transferring files, and using git on a remote Linux server over SSH via MCP tools.223AGPL 3.0
- AlicenseBqualityCmaintenanceEnables file operations, npm package management, and configuration checking through MCP.106 npm1MIT