coolify-mcp
Drive a self-hosted Coolify instance through an MCP server: full REST CRUD and deploy control, plus optional flag-gated SSH/Docker/Postgres host operations.
Trigger, watch, and cancel deployments; list active deployments or app deployment history.
List, inspect, create, update, and delete applications, databases, and services; start/stop/restart resources.
Manage persistent storage, database backups, scheduled tasks, and environment variables.
Manage projects and environments, servers, SSH keys, and Hetzner provisioning/inventory.
Fetch application log snapshots and live-tail Docker logs when host-ops is enabled.
With host-ops: run SSH commands, Docker CLI operations, read-only Coolify DB queries, and read restricted host files under /data/coolify/**.
Route tool calls across multiple configured Coolify instances and list instance metadata without secrets.
Safety gates: destructive actions require --allow-destructive plus confirm:true, support dry_run previews, and host-ops requires --enable-host-ops and is never exposed over HTTP transport.
Allows managing Docker containers on the Coolify host via SSH, including live log streaming and ad-hoc access.
Allows executing read-only queries against the Coolify PostgreSQL database via a configured read-only role, with SQL injection safeguards.
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., "@coolify-mcp list all my projects and their deployment status"
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.
coolify-mcp
A TypeScript MCP server that drives a self-hosted Coolify instance. Full REST CRUD, deploy/watch, and a flag-gated host-ops tier (SSH + Docker + psql) for live log streaming and ad-hoc access.
Quick Start
# Install from npm
npm install -g @jimrarras/coolify-mcp
# …or run ad-hoc without installing: npx -y @jimrarras/coolify-mcp doctor
#
# (Or install the latest straight from GitHub: npm install -g github:jimrarras/coolify-mcp)
#
# The published build is a single self-contained bundle with ZERO native/runtime
# dependencies — it installs on any machine with no C/C++ toolchain and runs no
# install scripts. No flags needed.
# Configure — guided wizard writes ~/.coolify-mcp/config.json (recommended)
coolify-mcp init
# …or just set the two required env vars (token format: <id>|<secret>):
export COOLIFY_BASE_URL="https://coolify.example.com"
export COOLIFY_TOKEN="<id>|<secret>"
# Run (API tier only)
coolify-mcp
# Run with host-ops (SSH access) enabled
coolify-mcp --enable-host-ops
# Run with destructive actions allowed (requires confirm:true per-call)
coolify-mcp --enable-host-ops --allow-destructiveGuided setup (recommended)
Two commands take you from installed to working:
coolify-mcp init # one-time interactive wizard — writes ~/.coolify-mcp/config.json
coolify-mcp doctor # verify the setup any time, with a specific fix for each failurePrefer not to touch a config file? The zero-file env-var mode (just
COOLIFY_BASE_URL+COOLIFY_TOKEN) still works for the API tier —initis for a guided setup that also wires up host-ops.
What init asks
Base URL + API token — validated live against your instance before continuing. The token must be
<id>|<secret>with scope write + read:sensitive.Enable host-ops? If yes, it resolves the SSH control host. On a standard single-server install Coolify reports the host's IP as
host.docker.internal, so auto-detect can't match it —initthen lists your servers and asks you to pick the control host (anti-hijack: it won't silently guess). It substitutes yourbaseUrlhost as the reachable SSH address.It then auto-discovers a working SSH key — it scans
~/.ssh, tries each OpenSSH key against the host, and prompts (masked) for a passphrase if the key needs one. (A PuTTY.ppkis detected and you're told to export an OpenSSH key first.)It shows the host's key fingerprint and asks you to confirm before pinning it.
Enable
query_coolify_db? If yes, it prints ready-to-runCREATE ROLE … GRANT … REVOKE …SQL (with a generated password) for you to run on your Coolify Postgres.
It writes ~/.coolify-mcp/config.json (backing up any existing one) at mode 0600. By default the
secrets you just entered are stored directly in that file, so setup works immediately — no
environment variables to set. For example:
{
"defaultInstance": "default",
"instances": {
"default": {
"baseUrl": "https://coolify.example.com",
"token": "5|the-actual-token",
"enableHostOps": true,
"allowDestructive": false,
"ssh": {
"keyPath": "/home/you/.ssh/id_ed25519",
"hostServer": "<control-server-uuid>",
"fingerprint": "SHA256:…",
"passphrase": "the-actual-passphrase"
}
}
}
}Then just run coolify-mcp doctor to verify — and your MCP client only needs
{ "command": "coolify-mcp" } (no env block).
Prefer to keep secrets out of the file? Run coolify-mcp init --env-secrets. It writes ${ENV}
references instead (token: "${COOLIFY_TOKEN}", passphrase: "${COOLIFY_SSH_KEY_PASSPHRASE}", …) and
prints the variables to set in your shell or your MCP client's env block; the references are
expanded at startup. (If a referenced variable isn't set, startup fails with a message naming it.)
doctor
doctor runs read-only checks and prints a fix for anything that fails (add --enable-host-ops
to include the SSH/DB checks):
$ coolify-mcp doctor --enable-host-ops
── instance: default ──
PASS api — Coolify 4.1.2 reachable
PASS control_host — root@coolify.example.com:22 (using baseUrl host)
PASS ssh — SSH root@coolify.example.com:22 OK
SKIP db_role — query_coolify_db not configuredIt exits non-zero if any check fails, so it's usable as a preflight in scripts.
Add to your MCP client config (e.g. ~/.claude/claude_desktop_config.json):
{
"mcpServers": {
"coolify": {
"command": "coolify-mcp",
"args": [],
"env": {
"COOLIFY_BASE_URL": "https://coolify.example.com",
"COOLIFY_TOKEN": "<id>|<secret>"
}
}
}
}Related MCP server: coolify-mcp
Configuration
1. Zero-file quick start
Set two environment variables and run — no config file needed:
export COOLIFY_BASE_URL="https://coolify.example.com"
export COOLIFY_TOKEN="<id>|<secret>"
coolify-mcpThe token format is <id>|<secret> — both parts required. The id is an integer; the secret is an alphanumeric string.
2. Config file
For multi-instance setups or richer per-instance settings, supply a JSON config file.
File resolution order:
--config <path>CLI flagCOOLIFY_CONFIGenvironment variable~/.coolify-mcp/config.json(auto-discovered if present)Falls back to env-var mode (step 1) if none of the above exists
${ENV} expansion is applied to every string value in the file, including nested ones.${VAR} — substitutes the environment variable; throws if unset.${VAR:-default} — uses default when VAR is unset or absent.
Only baseUrl and token are required per instance; everything else is optional and defaults to safe values.
See config.example.json for a full multi-instance example.
3. Host-ops configuration
To enable SSH access, set "enableHostOps": true and provide ssh.keyPath.
The SSH host, user, and port are auto-derived from the Coolify API — no need to set them manually.
Single-server installs (
host.docker.internal). Coolify's built-in "localhost" server often reports itsipashost.docker.internal(a Docker-internal alias) that a remote workstation can't SSH to. Two things handle this:
Select the control host explicitly with
ssh.hostServer(its UUID or name) — required because a non-matching server is not auto-selected (anti-hijack). When the selected server'sipis a non-routable alias, coolify-mcp automatically substitutes thebaseUrlhost (which is reachable and operator-trusted).Override the SSH address with
ssh.hostwhen even thebaseUrlhost isn't SSH-reachable (e.g. it's behind a proxy/CDN) — set it to the server's real IP/hostname.Minimal host-ops config for a standard single-server install:
"ssh": { "keyPath": "~/.ssh/id_ed25519", "hostServer": "<server-uuid-or-name>" }Add
"host": "<reachable-ip>"ifbaseUrlisn't directly SSH-reachable.
"ssh": {
"keyPath": "~/.ssh/id_ed25519"
}Tilde (~) is expanded to the home directory. Optional overrides:
Field | Description |
| Path to the SSH private key (required for host-ops). |
| Explicit SSH host/IP override. Use when the API-derived address isn't reachable (e.g. it reports |
| Path to a known_hosts file. Defaults to |
| SHA-256 host fingerprint (alternative to known_hosts). |
| UUID or name of the Coolify control server (override when auto-match fails). |
| SSH user override (else from API). |
| SSH port override (else from API). |
| Private key passphrase. |
SSH host-key verification is fail-closed. The server will not connect unless the key presented by the remote host matches either ssh.fingerprint (SHA-256, from ssh-keyscan <host> | ssh-keygen -lf -) or the appropriate entry in ssh.knownHostsPath / ~/.ssh/known_hosts. A missing or non-matching entry is an immediate connection refusal. Note: known_hosts matching is literal — wildcard (*.example.com) and hashed (|1|...) entries are not matched; use ssh.fingerprint or a literal host line for those hosts.
Threat-model note (host-ops trusts the Coolify API). The SSH host/user/port are derived from the Coolify API (GET /servers). A compromised Coolify API could therefore influence which host the MCP connects to — but this is bounded by the fail-closed host-key verification above (a redirect to an untrusted host is refused). For the strongest assurance set ssh.fingerprint to pin the control host's key regardless of known_hosts. Connections to remote managed servers run via docker -H ssh://… on the Coolify host, so that hop is governed by the Coolify host's own SSH trust store rather than this client's.
4. query_coolify_db — read-only DB role
Set db.readonlyUser per instance to enable the query_coolify_db tool. The in-code SQL blocklist and output redaction are best-effort defense-in-depth only — they cannot make arbitrary free-form SQL safe. You MUST provision the role so PostgreSQL enforces the constraints:
CREATE ROLE coolify_ro LOGIN PASSWORD '...' NOSUPERUSER NOCREATEDB NOCREATEROLE;
GRANT CONNECT ON DATABASE coolify TO coolify_ro;
GRANT USAGE ON SCHEMA public TO coolify_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO coolify_ro; -- omit sensitive tables/columns you don't want exposed
REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA public FROM coolify_ro; -- blocks adminpack/dblink/file fns
-- do NOT grant pg_read_server_files / pg_write_server_files / pg_execute_server_program / superuserTreat query_coolify_db output as "whatever this role may SELECT" — redaction reduces incidental leakage but is not guaranteed.
5. Multi-instance + per-call instance selector
A single coolify-mcp process can drive multiple Coolify instances simultaneously.
Every tool exposes an optional instance argument; omit it to use the default instance.
// config.json
{
"defaultInstance": "prod",
"instances": {
"prod": { "baseUrl": "https://coolify.prod.example.com", "token": "${PROD_TOKEN}" },
"staging": { "baseUrl": "https://coolify.staging.example.com", "token": "${STAGING_TOKEN}" }
}
}Example tool call routing to the non-default instance:
{ "tool": "list_resources", "arguments": { "instance": "staging", "type": "applications" } }enableHostOps/allowDestructive are per-instance — you can allow destructive actions on staging while keeping them blocked on prod.
Managing instances
init merges into your existing ~/.coolify-mcp/config.json — re-run it to add another
instance (it asks for a name, whether to make it the default, and confirms before overwriting an
existing one; your other instances are left untouched).
coolify-mcp instances # list configured instances (* = default); never prints secrets
coolify-mcp instances default <name> # set the default instance
coolify-mcp instances rm <name> # remove an instance (alias: `remove`)
coolify-mcp instances edit <name> # interactive edit — Enter keeps each current value
coolify-mcp instances set <name> <field> [value] # one-shot field edit (see fields below)
coolify-mcp instances unset <name> <field> # clear an optional field, or a whole ssh/db blockinstances rm refuses to remove the only instance, and refuses to remove the current default while
several remain (set a new default first with instances default <name>); removing the default when a
single instance is left auto-promotes the survivor.
Editing an instance. instances set accepts these fields: baseUrl, token, enableHostOps,
allowDestructive, pinnedCoolifyVersion, ssh.keyPath, ssh.host, ssh.hostServer, ssh.user,
ssh.port, ssh.fingerprint, ssh.knownHostsPath, ssh.passphrase, db.readonlyUser,
db.readonlyPassword. Omit the value for a secret field (token, ssh.passphrase,
db.readonlyPassword) to be prompted with hidden input — keeps the secret out of shell history:
coolify-mcp instances set prod allowDestructive on
coolify-mcp instances set prod token # prompts hidden — token rotation in one line
coolify-mcp instances unset prod ssh # drop host-ops SSH config entirelyAfter every change the instance is re-verified (API health always, SSH when ssh fields changed);
skip with --no-verify. set/unset keep the write on a failed verification and point at the
.bak backup; instances edit verifies changed credentials before writing and aborts untouched
on failure. Values stored as ${ENV} references are shown and preserved verbatim — editing never
silently inlines a referenced secret. Run coolify-mcp help instances for the full reference.
6. CLI flags + back-compat
When no config file is used, the legacy flags and environment variables still work and map onto the synthesized default instance:
Flag / Variable | Maps to |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When a config file is loaded, --enable-host-ops and --allow-destructive are ignored (a warning is printed); per-instance gating comes from the file.
7. HTTP transport (optional)
By default the server speaks MCP over stdio. To serve it over Streamable HTTP
instead, pass --http [port] (default 3000) or set COOLIFY_MCP_HTTP_PORT:
export COOLIFY_MCP_HTTP_TOKEN="<a long random secret>" # required
coolify-mcp --http 3000Variable | Description |
| Enable HTTP on this port (or use |
| Required (min 16 chars). Bearer token clients must send as |
| Bind address. Defaults to |
| Comma-separated |
The host-ops tier is never exposed over HTTP. ssh_exec, docker_op,
query_coolify_db, read_host_file, and stream_logs are root-level operations
registered only on the stdio transport — over HTTP the server serves the API tier
(read/write/destructive) only, regardless of enableHostOps. Keep the bind on
127.0.0.1, keep the bearer token secret, and treat any non-localhost bind as
internet-facing.
Token Scope Guidance
Coolify tokens carry full-account permissions. For read-only use (monitoring, querying), prefer creating a dedicated read-only token in Coolify's settings if the feature is available for your version. For write operations, use a token scoped to the team/project you intend to manage. Never share the same token across environments.
Tools
Tools are grouped by tier. Tier determines what flags must be set for the tool to be registered and callable.
Tier | Meaning | Required flags |
R (read) | Non-mutating reads: list, get, inspect | none |
W (write) | Creates and updates | none (but Coolify token must have write access) |
D (destructive) | Deletes and stop/restart/kill operations |
|
host | SSH, Docker, psql, file reads |
|
Destructive host actions (docker rm/rmi/stop/kill/prune/exec) additionally require --allow-destructive and confirm: true. The host tier is root-level read access by design: read-only docker_op actions (inspect, logs, …) and read_host_file can surface container configuration including environment variables/secrets — treat their output as sensitive. docker_args rejects shell metacharacters and {} template braces, but plain docker inspect <container> still returns that container's full config; only enable --enable-host-ops for trusted callers.
Deploy
Tool | Tier | Description |
| W | Trigger a deployment for a resource by UUID or tag. |
| W | Trigger and poll until a terminal deploy status, emitting MCP progress. |
| R | List active deployments or fetch deployment history for an application. |
| D | Cancel a running deployment. |
Resources (Applications, Databases, Services)
Tool | Tier | Description |
| R | List all resources of a given kind with summary fields. |
| R | Fetch full details for a single resource by UUID. |
| W | Create an application (public/private-github-app/private-deploy-key/dockerfile/dockerimage), database, or service. |
| D | Update an existing resource's settings via the |
| W/D | Start/stop/restart a resource (stop/restart require |
| D | Permanently delete a resource. Requires |
| W/D | List, create, update, or delete persistent storage volumes for a resource. Create/update take a |
| W/D | List, create, update, or delete backup schedules for databases. Create/update take a |
| W/D | List, create, update, or delete scheduled tasks for apps/services. |
The fields pass-through (update_resource, create_resource, manage_storage, manage_backups)
Pass request-body fields in the fields object; they are forwarded verbatim to the
corresponding Coolify endpoint (e.g. PATCH /api/v1/applications/{uuid}), so any
field the endpoint accepts works:
{
"type": "applications",
"uuid": "abc123",
"fields": { "post_deployment_command": "php artisan migrate --force" },
"confirm": true
}The declared fields parameter exists because some MCP clients enforce strict input
schemas and silently strip undeclared top-level properties, which previously reached
Coolify as an empty PATCH body (HTTP 400 "Empty JSON"). Top-level extra properties
are still accepted from permissive clients; on a key conflict, fields wins. If no
updatable field is provided at all, the tool returns invalid_input instead of
calling the API. For clients whose strict schema handling also empties nested
free-form objects, every fields-taking tool additionally accepts fields_json —
the same object JSON-encoded as a string (mutually exclusive with fields).
update_resource is fenced: it requires --allow-destructive at startup and
confirm: true per call (dry_run: true previews which fields would change),
because fields can rewrite the commands Coolify executes on deploy.
Commonly updated application fields: name, description, domains
(comma-separated URL list — do not send fqdn, which Coolify rejects; the tool
remaps fqdn to domains defensively), git_branch, build_pack,
install_command, build_command, start_command, ports_exposes,
base_directory, publish_directory, docker_registry_image_name,
docker_registry_image_tag, pre_deployment_command, post_deployment_command,
health_check_enabled, health_check_path (and the other health_check_* settings),
custom_docker_run_options, watch_paths. Applications with build_pack: "dockercompose" cannot use domains — set per-service domains via
docker_compose_domains, e.g. { "fields": { "docker_compose_domains": [{ "name": "web", "domain": "https://app.example.com" }] } }.
Databases accept their own PATCH fields (e.g. name, description, image,
is_public, public_port, engine credential fields). Credential values echoed back
in the update response are redacted before being returned. Services accept only
name, description, instant_deploy, docker_compose_raw,
connect_to_docker_network, urls, force_domain_override, and
is_container_label_escape_enabled; service URLs are set via urls: [{ "name": "<compose-service-name>", "url": "https://..." }] — services have no domains field.
All three resource types also accept instant_deploy: true in fields, which queues
a deployment immediately after the update is saved — omit it (the default) to change
configuration without deploying.
For create_resource, git-based applications (public, private-github-app,
private-deploy-key) require build_pack (now a declared parameter); any less common
create-body field can go in fields. manage_storage create requires
fields.type and fields.mount_path (plus name, host_path, content,
is_directory, fs_path as needed). manage_backups create requires
fields.frequency (cron), and accepts enabled, save_s3, s3_storage_uuid,
databases_to_backup, dump_all, backup_now, database_backup_retention_*,
timeout.
Environment Variables
Tool | Tier | Description |
| W/D | List, upsert-bulk, or delete environment variables for a resource. |
Projects
Tool | Tier | Description |
| R/W/D | List, get, create, update, or delete projects and their environments. |
Instances
Tool | Tier | Description |
| R | List configured Coolify instances (names, base URLs, default, tier flags). Never returns secrets. |
Servers & Keys
Tool | Tier | Description |
| R | List servers or get a single server with validation/resource info. |
| W/D | Create, update, or delete servers. |
| W | Provision a new Hetzner cloud server via Coolify. |
| R | List Hetzner locations, server types, images, or SSH keys. |
| W/D | Manage Coolify private keys and cloud provider tokens. |
Logs
Tool | Tier | Description |
| R / host | Snapshot logs for an application (REST API). For databases and services, falls back to |
| host | Live-tail Docker logs via SSH/HostOps. Sends MCP progress every 25 lines. Hard cap: 1000 lines / 15 min. |
Host Ops
Tool | Tier | Description |
| host | Run a shell command on a server over SSH. Returns stdout, stderr, exit code. |
| host | Run a Docker CLI sub-command on a server. Mutating actions require |
| host | Execute a read-only SELECT query against the Coolify PostgreSQL database. |
| host | Read an allowed file on the Coolify host (restricted to |
Security Notes
Never-Exposed Endpoints (Lockout Policy)
The following Coolify API endpoints are intentionally never exposed as tools, because calling them from an automated agent risks locking out all access to the Coolify UI:
GET /enable— enables CoolifyGET /disable— disables CoolifyPOST /mcp/enable— enables Coolify's own MCP endpointPOST /mcp/disable— disables Coolify's own MCP endpointIP-allowlist mutation endpoints
Destructive Operations
All destructive operations follow a deny-by-default, double-confirmation model:
The server must be started with
--allow-destructive.Each individual call must include
confirm: truein its arguments.You can pass
dry_run: trueto preview what would be executed without performing it.
Host-Ops Tier
When enableHostOps: true is set for an instance (or --enable-host-ops in env mode), the server opens an SSH connection to the Coolify host on first use. Commands run as the configured SSH user (typically root). File access is restricted to /data/coolify/** prefixes. SQL access is restricted to read-only SELECT statements.
SSH host-key verification is fail-closed. The server refuses to connect unless the key presented by the remote host matches either ssh.fingerprint (SHA-256, from ssh-keyscan <host> | ssh-keygen -lf -) or the appropriate entry in ssh.knownHostsPath / ~/.ssh/known_hosts. A missing or non-matching entry is an immediate connection refusal.
Development
pnpm install
pnpm test # vitest
pnpm run build # esbuild -> single self-contained dist/cli/index.js bundle
pnpm run probe # scripts/probe.ts (requires COOLIFY_TEST_BASE_URL / COOLIFY_TEST_TOKEN)Note —
dist/is committed.pnpm run buildbundles the CLI, the MCP server, and all runtime deps (ssh2, the MCP SDK, …) into a singledist/cli/index.jsvia esbuild, with ssh2's native bindings externalized (it falls back to pure-JS crypto). The result has zero runtime dependencies, sonpm install github:…compiles nothing and runs no install scripts on the user's machine. Because no build runs at install time, the bundle is checked into git: runpnpm run buildand commit the updateddist/cli/index.js(and the regeneratedTHIRD-PARTY-NOTICES.txt) whenever you change anything undersrc/. (Runtime libs live indevDependenciessince they're bundled, not installed by consumers.) CI runsgit diff --exit-code dist/ THIRD-PARTY-NOTICES.txtso a stale committed bundle fails the build.
License
MIT. The published single-file bundle inlines third-party packages (ssh2, the MCP
SDK, ajv, …); their license and copyright notices are reproduced in
THIRD-PARTY-NOTICES.txt, regenerated at build time.
Available Tools
22 toolscancel_deploymentA
Cancel an in-progress deployment by its deployment UUID (fenced). Requires --allow-destructive and confirm:true.
Inputs: deployment_uuid (required), confirm, dry_run, instance.
control_resourceA
Start, stop (fenced), or restart (fenced) a Coolify resource. stop and restart are destructive — they require --allow-destructive and confirm:true. For applications, start/restart return a deployment_uuid that can be used to track progress.
Inputs: type (required), uuid (required), action (required), confirm, +3 more.
create_resourceA
Create a new Coolify resource. kind discriminates: application (with source sub-discriminator), database (with engine), or service (with service_type XOR docker_compose_raw base64). FENCED: requires --allow-destructive and confirm:true (code/credential write).
Inputs: kind (required), name, engine, fields, +18 more.
delete_resourceA
Delete a Coolify resource permanently. Requires confirm:true and --allow-destructive flag.
Inputs: type (required), uuid (required), confirm, dry_run, +1 more.
deployA
Trigger a new deployment for an application (by UUID or tag). Optionally force-rebuild or deploy a pull-request preview. FENCED: requires --allow-destructive and confirm:true (code/credential write).
Inputs: pr, tag, uuid, force, +3 more.
deploy_watchA
Trigger a deployment and block until it reaches a terminal state (finished/failed/cancelled/skipped). Emits MCP progress notifications while polling. Returns per-resource final statuses and a logs tail on failure. FENCED: requires --allow-destructive and confirm:true (code/credential write).
Inputs: pr, tag, uuid, force, +4 more.
get_deploymentsA
List active deployments (no args) or the deployment history for a specific application (app_uuid). Supports pagination with skip/take.
Inputs: skip, take, app_uuid, instance.
get_logsA
Fetch a log snapshot for a Coolify resource. • application: uses GET /applications/{uuid}/logs?lines= (REST API). • database / service: requires --enable-host-ops; the docker logs fallback is wired in Task 31.
Inputs: kind (required), uuid (required), lines, instance.
get_resourceA
Get full details of a specific Coolify resource by type and UUID.
Inputs: type (required), uuid (required), instance.
get_serversA
Query Coolify servers. Actions: list (summary fields by default; include:true for full), get, validate, resources, domains.
Inputs: uuid, action, include, instance.
hetzner_inventoryA
Browse Hetzner Cloud resource catalog exposed by Coolify. Use before provision_hetzner to pick a server type and location.
Inputs: instance, resource.
list_instancesA
List the Coolify instances this server is configured to drive (names, base URLs, default, and per-instance host-ops/destructive flags). Never returns tokens or other secrets. Pass an instance name as the 'instance' arg to any other tool to route to it.
Inputs: instance.
list_resourcesA
List all Coolify resources (applications, databases, services) across all projects. Optionally filter by type.
Inputs: type, instance.
manage_backupsA
List, create, update, or delete database backup schedules and executions. Only applicable to databases. For create/update, pass the schedule fields in fields (create requires frequency, a cron expression; also enabled, save_s3, s3_storage_uuid, databases_to_backup, dump_all, backup_now, database_backup_retention_*, timeout).
Inputs: uuid (required), action (required), fields, confirm, +5 more.
manage_envA
Manage environment variables for a Coolify resource (application, database, or service). action=list returns all vars with a redaction_hint when any value appears empty or masked. action=set upserts one var ({ key, value }) or many ({ vars: [{key,value},...] }) via bulk API. action=delete (fenced) removes a single var by its env_uuid (UUID returned from list); requires --allow-destructive and confirm:true.
Inputs: type (required), uuid (required), action (required), key, +6 more.
manage_keysA
Manage Coolify SSH private keys (security keys). Actions: list, get, create (fenced), update (fenced), delete (fenced). create and update are credential writes — they require --allow-destructive and confirm:true. Note: update uses a collection-level PATCH — uuid is passed in the body.
Inputs: action (required), name, uuid, confirm, +5 more.
manage_projectsC
Manage Coolify projects and their environments. Actions: list, get, create, update, delete (fenced), list_environments, create_environment, get_environment, delete_environment (fenced).
Inputs: action (required), name, uuid, confirm, +4 more.
manage_scheduled_tasksA
List, create (fenced), update (fenced), delete (fenced), or view executions of scheduled tasks on an application or service. create and update are code-execution writes — they require --allow-destructive and confirm:true.
Inputs: type (required), uuid (required), action (required), name, +9 more.
manage_serverC
Create, update, or delete (fenced) a Coolify server.
Inputs: action (required), ip, name, port, +9 more.
manage_storageB
List, create, update, or delete persistent volume storage for an application, database, or service. For create/update, pass the storage fields in fields (create requires type and mount_path; also name, host_path, content, is_directory, fs_path).
Inputs: type (required), uuid (required), action (required), fields, +5 more.
provision_hetznerA
Provision a new server on Hetzner Cloud via Coolify (destructive — creates billable infrastructure). Requires --allow-destructive flag and confirm:true.
Inputs: name (required), location (required), hetzner_server_type (required), ip, +10 more.
update_resourceA
Update configuration fields of an existing Coolify resource. FENCED: requires --allow-destructive and confirm:true (fields can rewrite deploy/start commands — a code-execution write). Pass the fields to change in fields (or fields_json); they are sent verbatim as the PATCH body. Applications commonly accept: name, description, domains (comma-separated URL list — NOT fqdn; dockercompose apps must use docker_compose_domains [{name, domain}] instead of domains), git_branch, build_pack, install_command, build_command, start_command, ports_exposes, base_directory, publish_directory, docker_registry_image_name, docker_registry_image_tag, pre_deployment_command, post_deployment_command, health_check_* settings, custom_docker_run_options, watch_paths. instant_deploy: true additionally queues an immediate redeploy after saving. Services accept only: name, description, instant_deploy, docker_compose_raw, connect_to_docker_network, urls [{name, url}], force_domain_override, is_container_label_escape_enabled.
Inputs: type (required), uuid (required), fields, confirm, +3 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 22 tools
Most tools are clearly separated by resource type (resources, deployments, storage, backups, env vars, servers, keys, projects, instances). However, deploy vs deploy_watch both trigger deployments with only blocking behavior differing, and get_servers vs list_instances could be confused, though descriptions help.
Naming is mixed: verb_noun style (list_resources, create_resource, cancel_deployment) coexists with manage_* tools (manage_storage, manage_env, manage_projects) and unique names like control_resource, provision_hetzner. Snake_case is consistent, but the verb pattern is not uniform.
22 tools is on the higher end, but Coolify is a broad platform covering resources, deployments, servers, projects, env vars, storage, backups, scheduled tasks, keys, and instances. Each tool earns its place, making the count appropriate for the scope.
The tool surface covers CRUD and lifecycle for most domains: resources, deployments, servers, projects, env vars, storage, backups, scheduled tasks, and keys. Minor gaps exist, such as no update_environment action and no single-deployment detail fetch (only list), but core workflows are supported.
Maintenance
Related MCP Connectors
MCP server for interacting with the Supabase platform
MCP server for InsForge BaaS — database, storage, edge functions, and deployments
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Build, deploy, and host full-stack web apps from any MCP client. DB, auth, storage, cron included.
Related MCP Servers
- AlicenseBqualityDmaintenanceMCP server that integrates with Coolify to let AI assistants manage Coolify instances via a clean toolkit wrapping the official REST API.35370 npm7MIT
- AlicenseBqualityBmaintenanceMCP server for managing Coolify instances, enabling control of applications, databases, services, servers, and more via natural language.13657 npmMIT
- AlicenseBqualityBmaintenanceMCP server for Coolify API that enables full deployment workflows from zero to production, including project, server, and application management.6570 npm4MIT
- AlicenseAqualityBmaintenanceOne MCP server to manage self-hosted Coolify instances: verify connectivity, discover servers, deploy applications, tail logs, diagnose incidents, and run emergency ops from any MCP client.1999 npmMIT