An MCP (Model Context Protocol) server that exposes Ploi.io API functionality as tools for AI assistants like Claude.
Deploy your sites with a simple "deploy" command - no clicking around in dashboards!
- One-command deployments - Just say "deploy" and watch it happen
- Verified deploys - Deployments wait for real completion and report success/failure (no false "success")
- Project linking - Link projects to Ploi sites with
.ploi.json - Full site lifecycle - Create, delete, deploy, suspend, resume, view logs
- Server management - List, restart, view logs
- Environment & deploy script - Read and update a site's
.envand deploy script without SSH - Daemons & queue workers - Manage
queue:workdaemons and Ploi's per-site queue workers (create/restart/pause/delete) - Cron jobs - Add/verify the Laravel scheduler (
* * * * * schedule:run) and other crons - SSL certificates - Request (Let's Encrypt), list, and delete certificates
- Databases - Create/delete databases; list, run, schedule, and delete backups
- Service restart - Restart nginx / php-fpm / mysql / redis / supervisor
- Optional id allowlist - Hard-bound which servers/sites the mutating tools may touch (see Configuration)
npm install -g ploi-mcpSkip installation - npx will download and run it automatically when configured.
Get your token from ploi.io/profile/api-keys.
π Keep your token out of the command line. Passing
--tokenexposes it in the process list (ps aux) and shell history, and stores it in plaintext in~/.claude.json. Prefer one of the secure options below. ploi-mcp resolves the token in this order:--token-fileβ--token(deprecated) βPLOI_API_TOKENenv β~/.ploi/config.php(the officialploi tokenstore).
Add to ~/.claude.json β pass the token via the env block, not args:
If you installed globally:
{
"mcpServers": {
"ploi": {
"type": "stdio",
"command": "ploi-mcp",
"env": { "PLOI_API_TOKEN": "YOUR_TOKEN" }
}
}
}If using npx (no install):
{
"mcpServers": {
"ploi": {
"type": "stdio",
"command": "npx",
"args": ["-y", "ploi-mcp"],
"env": { "PLOI_API_TOKEN": "YOUR_TOKEN" }
}
}
}Already use the Ploi CLI? Run ploi token once and ploi-mcp will read the token from ~/.ploi/config.php automatically β no token in your MCP config at all.
Close and reopen Claude Code for the MCP server to load.
In Claude Code, say:
"Link this project to mydomain.com"
Just say:
"deploy"
That's it! The deployment will run and notify you when complete.
Add to ~/.claude.json:
{
"mcpServers": {
"ploi": {
"type": "stdio",
"command": "ploi-mcp",
"args": ["--token", "YOUR_TOKEN"]
}
}
}Or using environment variable:
{
"mcpServers": {
"ploi": {
"type": "stdio",
"command": "ploi-mcp",
"env": {
"PLOI_API_TOKEN": "YOUR_TOKEN"
}
}
}
}Add to config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"ploi": {
"command": "ploi-mcp",
"args": ["--token", "YOUR_TOKEN"]
}
}
}The Ploi API token is account-wide β by default the assistant can deploy, restart, suspend, or delete-backups on any server or site in your account. Two layers reduce that blast radius:
-
Scope the token itself. Create a least-privilege API token in Ploi (https://ploi.io/profile/api-keys) limited to only the servers you want the assistant to manage. This is the strongest bound β the MCP can't exceed what the token allows.
-
Set an id allowlist (optional, defence-in-depth). When these env vars are set, every mutating tool (
deploy_site,deploy_project,restart_server,suspend_site,resume_site,create/run/delete_database_backup) refuses ids outside the list. Read-only tools (list/get) are unaffected.{ "mcpServers": { "ploi": { "command": "ploi-mcp", "env": { "PLOI_API_TOKEN": "YOUR_TOKEN", "PLOI_ALLOWED_SERVER_IDS": "12,34", "PLOI_ALLOWED_SITE_IDS": "567,890" } } } }Comma-separated ids. Unset or blank = no restriction (default). A typo (a non-numeric id) fails loudly rather than silently denying everything.
ploi-mcp --token YOUR_TOKEN
ploi-mcp -t YOUR_TOKEN
PLOI_API_TOKEN=YOUR_TOKEN ploi-mcpLink a project to its Ploi site for one-command deployments:
"Link this project to mydomain.com"
This creates .ploi.json in your project:
{
"server_id": 12345,
"site_id": 67890
}Now just say "deploy" and it will:
- Trigger deployment
- Wait for completion (polling every 5 seconds)
- Report success or failure
| Tool | Description |
|---|---|
deploy_project |
Deploy current project and wait for completion |
init_project |
Link project to a Ploi site by domain |
get_project_deploy_status |
Check deployment status |
| Tool | Description |
|---|---|
list_servers |
List all servers |
get_server |
Get server details |
restart_server |
Restart a server |
get_server_logs |
Get server logs (auth, error, lastlog, syslog) |
| Tool | Description |
|---|---|
list_sites |
List sites on a server |
get_site |
Get site details |
find_site_by_domain |
Search for a site by domain |
create_site |
Create a new site (vhost, directory, system user) |
delete_site |
Permanently delete a site (vhost, files, system user) |
deploy_site |
Deploy a site and wait for completion |
get_site_logs |
Get deployment logs |
suspend_site |
Suspend a site |
resume_site |
Resume a suspended site |
| Tool | Description |
|---|---|
get_site_env |
Read a site's .env |
update_site_env |
Replace a site's .env (full-file) |
get_deploy_script |
Read a site's deploy script |
update_deploy_script |
Replace a site's deploy script (full-file) |
| Tool | Description |
|---|---|
list_daemons |
List daemons (e.g. queue:work) on a server |
create_daemon |
Create a daemon |
restart_daemon |
Restart a daemon |
toggle_daemon |
Pause / resume a daemon |
delete_daemon |
Delete a daemon |
| Tool | Description |
|---|---|
list_crons |
List cron jobs on a server |
create_cron |
Create a cron job (e.g. the Laravel scheduler) |
delete_cron |
Delete a cron job |
| Tool | Description |
|---|---|
list_queues |
List a site's queue workers |
get_queue |
Get a single queue worker |
create_queue |
Create a queue worker |
restart_queue |
Restart a queue worker |
toggle_queue |
Pause / resume a queue worker |
delete_queue |
Delete a queue worker |
| Tool | Description |
|---|---|
list_certificates |
List a site's certificates |
request_certificate |
Request a certificate (defaults to Let's Encrypt) |
delete_certificate |
Delete a certificate |
| Tool | Description |
|---|---|
restart_service |
Restart nginx / php-fpm / mysql / redis / supervisor |
| Tool | Description |
|---|---|
list_databases |
List databases on a server |
create_database |
Create a database (optionally with a user/password) |
delete_database |
Permanently delete a database |
list_database_backups |
List database backup configurations |
get_database_backup |
Get a database backup configuration |
run_database_backup |
Run an existing backup configuration now ("backup now") |
create_database_backup |
Create a scheduled backup configuration (needs a backup destination) |
delete_database_backup |
Delete a backup configuration |
Note: mutating tools (anything that creates, updates, deletes, deploys, restarts, or toggles) carry a
destructiveHintso MCP hosts can prompt before running them, and honour the optional id allowlist.update_site_env/update_deploy_scriptwrites are applied asynchronously by Ploi β allow a few seconds before reading them back.
"List my servers"
"Deploy"
"Deploy mydomain.com"
"Create a Laravel site for app.mydomain.com"
"Add the scheduler cron to server 12"
"Restart the queue worker on app.mydomain.com"
"Request a Let's Encrypt cert for app.mydomain.com"
"Show me the .env for app.mydomain.com"
"Restart nginx on server 12"
"List my database backups"
"Run database backup 42 now"
git clone https://github.com/sudanese/ploi-mcp.git
cd ploi-mcp
npm install
npm run build
npm linkMIT