coolify-mcp
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-mcplist 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
npm install
npm test # vitest
npm run build # esbuild -> single self-contained dist/cli/index.js bundle
npm run probe # scripts/probe.ts (requires COOLIFY_TEST_BASE_URL / COOLIFY_TEST_TOKEN)Note —
dist/is committed.npm 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: runnpm 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.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | Must be true to confirm this destructive operation. | |
| dry_run | No | If true, show what would be cancelled without performing the action. | |
| instance | No | Coolify instance name (omit for the default). | |
| deployment_uuid | Yes | Coolify deployment UUID to cancel (alphanumeric). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must disclose behavior on its own. It indicates the operation is destructive by requiring --allow-destructive and confirm:true. It also scopes the action to 'in-progress' deployments. Yet it does not explain side effects, the 'fenced' term, or what happens to the deployment afterward, so transparency is adequate but not thorough.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the primary action and resource, and contains no filler. Every word adds value, making it highly concise and effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Considering there is no output schema and no annotations, the description covers the essential purpose and prerequisites but omits details like the meaning of 'fenced', behavior when the deployment is not in progress, and the return value. It is minimally sufficient for a simple cancellation tool but leaves some gaps for the agent to infer.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all parameters. The description adds only minor value by reinforcing that confirm:true is required for destructive operations and that the deployment is identified by UUID. This is a baseline 3 with a small amount of extra context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool cancels an in-progress deployment by UUID, using the verb 'cancel' and specifying the exact resource type. This distinguishes it from sibling tools like deploy (which starts deployments) and delete_resource (which removes entire resources).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context that the tool is for cancelling in-progress deployments and specifies the required confirm flag and --allow-destructive. However, it does not explicitly mention when not to use it or compare it to alternatives, keeping it at a 4.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| uuid | Yes | The Coolify UUID of the resource. | |
| action | Yes | ||
| confirm | No | Must be true to confirm destructive operations (stop, restart). | |
| dry_run | No | If true, show what would happen without performing the action (stop, restart). | |
| instance | No | Coolify instance name (omit for the default). | |
| instant_deploy | No | Applications only: skip the build queue. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description warns that stop and restart are destructive and require confirm:true, and notes deployment_uuid returns for applications. However, it mentions an '--allow-destructive' flag not present in the schema and uses 'fenced' without definition, causing confusion. No annotations exist, so the burden is on the description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three succinct sentences with front-loaded purpose; no waste except for the unexplained 'fenced' and stray CLI flag. It's concise but not perfectly clean.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and no annotations, the description should cover return behavior and prerequisites more thoroughly. It explains start/restart return for apps but not for databases/services, and doesn't clarify the 'fenced' qualifier or the allow-destructive flag. It covers the main safety and return aspects but remains incomplete for a 7-param tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaning to the action parameter by clarifying which actions are destructive and their confirmation requirement, and adds return-value semantics for applications. The schema already covers uuid, confirm, dry_run, instance, and instant_deploy; the description goes beyond these by explaining action-specific behavior, though the '--allow-destructive' reference is confusing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Start, stop, or restart a Coolify resource', naming the verb and resource type, and differentiates from sibling tools like delete_resource, deploy, and update_resource. The term 'fenced' is unclear but doesn't obscure the core purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives like deploy or delete_resource. It only notes destructive actions require confirm, not when to choose this lifecycle tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | The type of resource to create. | |
| name | No | Name for the new resource. | |
| engine | No | Required when kind=database. | |
| fields | No | Additional create-body fields (e.g. ports_exposes, domains, base_directory, destination_uuid), sent verbatim as the request body — any field the Coolify endpoint accepts is allowed. | |
| source | No | Required when kind=application. Determines which Coolify endpoint is called. | |
| confirm | No | Must be true to confirm resource creation (destructive: code/credential write). | |
| dry_run | No | If true, show what would be created without performing the action. | |
| instance | No | Coolify instance name (omit for the default). | |
| build_pack | No | Build pack. REQUIRED by Coolify for the public, private-github-app, and private-deploy-key sources. | |
| dockerfile | No | Dockerfile content (for dockerfile source). | |
| git_branch | No | Git branch (for git-based apps). | |
| fields_json | No | JSON-encoded alternative to `fields` (mutually exclusive) for clients whose strict schema handling strips free-form object contents. | |
| server_uuid | No | UUID of the target server. | |
| docker_image | No | Docker image reference (for dockerimage source). | |
| project_uuid | No | UUID of the target project. | |
| service_type | No | Required when kind=service and not using docker_compose_raw. Mutually exclusive with docker_compose_raw. | |
| git_repository | No | Git repository URL (for git-based apps). | |
| instant_deploy | No | Trigger deploy immediately after creation. | |
| github_app_uuid | No | GitHub App UUID (for private-github-app source). | |
| environment_name | No | Name of the Coolify environment. | |
| private_key_uuid | No | Private key UUID (for private-deploy-key source). | |
| docker_compose_raw | No | Base64-encoded docker-compose content. Required when kind=service and not using service_type. Mutually exclusive with service_type. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that the tool is FENCED, requires --allow-destructive and confirm:true, and characterizes the write as code/credential write. This is significant safety-relevant behavior. It does not detail all side effects, but the critical guardrails are covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences pack a large amount of high-value information: the core purpose, the discriminating logic, and the critical fencing requirement. The description is front-loaded and wastes no words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 22 parameters and no output schema, the description does not explain each parameter but relies on the rich schema. It does provide the essential high-level decision tree and safety context. It omits some conditional nuances (e.g., build_pack requirements), but the schema covers individual fields, making this sufficient for a create tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds relational semantics beyond individual field docs: it explains that `kind` discriminates among three types, `source` is a sub-discriminator for applications, `engine` is for databases, and `service_type` XOR `docker_compose_raw` (base64) applies to services. This helps the agent correctly combine parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Create a new Coolify resource.' It clearly distinguishes from sibling tools like update_resource and delete_resource by using 'create' and explaining the resource-kind discriminator. This makes the tool's purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies the tool is for creation and provides a decision tree via `kind` (application/database/service) with sub-discriminators. It does not explicitly state when not to use it or compare with alternatives, but the context is clear and no exclusions are needed beyond obvious creation tasks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_resourceA
Delete a Coolify resource permanently. Requires confirm:true and --allow-destructive flag.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| uuid | Yes | ||
| confirm | No | Must be true to execute. | |
| dry_run | No | Return preview without deleting. | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explicitly discloses the permanent, irreversible nature of the delete and the mandatory confirm parameter, which is critical for a destructive operation. It also mentions the --allow-destructive flag, indicating an extra safety gate. However, it does not elaborate on associated data loss or the exact scope of deletion, and it omits mention of dry_run's preview capability, leaving some behavioral aspects to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, focused sentence that front-loads the action and highlights the critical confirm requirement. It contains no filler and every word adds value, making it appropriately concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool with no annotations, the description adequately warns about permanence and the confirmation requirement, which are the most critical operational details. The schema covers parameter enumerations and dry_run behavior, so the description complements rather than duplicates it. However, the lack of any mention of return behavior or the meaning of `uuid` leaves minor gaps, but overall it is sufficient for safe invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema describes confirm, dry_run, and instance, but type and uuid lack descriptions, giving 60% coverage. The tool description reinforces confirm's necessity but adds no new meaning for type, uuid, or dry_run, and introduces an external flag not present in the schema. Thus, it does not significantly compensate for the undocumented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's function with the verb 'Delete' and specifies the target as 'a Coolify resource,' emphasizing permanence. The action is distinct from sibling tools like create_resource, update_resource, and control_resource, so the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a key usage requirement—confirm:true and the --allow-destructive flag—which is essential for executing a destructive operation. However, it does not explicitly differentiate when to use this tool versus alternatives like control_resource for temporary changes, nor does it mention dry_run as a safe preview option. The guidance is limited to prerequisites, not broader usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| pr | No | Pull-request number for preview deployments. | |
| tag | No | Deploy all resources sharing this tag. | |
| uuid | No | Coolify application UUID to deploy (alphanumeric, e.g. abc123). | |
| force | No | Force a rebuild without cache. | |
| confirm | No | Must be true to confirm this deployment (destructive: triggers production change). | |
| dry_run | No | If true, show what would be deployed without triggering. | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of disclosure. It clearly states the FENCED requirement: 'requires --allow-destructive and confirm:true (code/credential write)', providing critical safety and permission context beyond the schema. This adds value without contradicting any annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the primary action, and cleanly separates the safety note. Every word earns its place without unnecessary elaboration.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 7 parameters, no output schema, and no annotations, the description covers the core action, selection methods, options, and a critical safety constraint. It does not explain dry_run or return values, but the schema covers parameters, and the absence of output schema does not require over-explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds minor semantic grouping ('by UUID or tag', 'force-rebuild', 'pull-request preview') that maps to uuid/tag, force, and pr parameters, but it does not provide additional syntax or details beyond the already-rich schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'Trigger a new deployment' and identifies the target resource as 'an application (by UUID or tag)'. It also mentions optional force-rebuild and pull-request preview, distinguishing it clearly from siblings like cancel_deployment or get_deployments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: to trigger a deployment, optionally with force rebuild or PR preview. It does not explicitly mention alternatives or exclusions, but the purpose is unambiguous and distinct from deployment-related siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| pr | No | Pull-request number for preview deployments. | |
| tag | No | Deploy all resources sharing this tag. | |
| uuid | No | Coolify application UUID to deploy (alphanumeric). | |
| force | No | Force a rebuild without cache. | |
| confirm | No | Must be true to confirm this deployment (destructive: triggers production change). | |
| dry_run | No | If true, show what would be deployed without triggering. | |
| instance | No | Coolify instance name (omit for the default). | |
| timeout_seconds | No | Maximum seconds to wait before returning 'unknown'. Default 1800. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses blocking behavior, progress notifications, return content (per-resource statuses and logs tail on failure), and the FENCED requirement for --allow-destructive and confirm:true. This is substantial useful context, though it doesn't mention timeout behavior explicitly or what happens on internal errors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: three sentences, each providing valuable information. It front-loads the primary purpose, then adds behavioral details and safety constraints without redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 8 parameters, no output schema, and no annotations, the description provides a good deal of context: blocking behavior, terminal states, progress notifications, return values, failure logs, and destructive-confirmation requirements. It would be slightly more complete if it explicitly addressed timeout return behavior, but the schema covers that, and the overall picture is well-rounded.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 100%, so the input schema already documents all 8 parameters with descriptions. The description adds little parameter-specific meaning beyond what the schema already provides (e.g., confirm being mandatory and dry_run behavior are already in the schema). Thus, the description adds no significant extra parameter semantics, warranting the baseline score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource: 'Trigger a deployment and block until it reaches a terminal state'. It clearly distinguishes this tool from siblings by emphasizing blocking behavior and terminal-state outcomes, and it enumerates the terminal states (finished/failed/cancelled/skipped), leaving no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the use case: when you need to trigger a deployment and wait for its final outcome, with progress notifications and status/logs. However, it does not explicitly compare to sibling tools like 'deploy' or state when NOT to use this tool, and it lacks concrete alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_deploymentsA
List active deployments (no args) or the deployment history for a specific application (app_uuid). Supports pagination with skip/take.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip (pagination). Only used with app_uuid. | |
| take | No | Number of records to return (pagination). Only used with app_uuid. | |
| app_uuid | No | Application UUID whose deployment history to retrieve. Omit for all active deployments. | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses the two operational modes and pagination support. It doesn't explicitly state read-only status, but 'List' implies it. Slight ambiguity about pagination applying only to history mode is resolved by schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the main action, no wasted words. Perfectly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core behaviors and parameter usage. It doesn't describe return format, but for a list tool without output schema, this is acceptable. The tool is adequately scoped for selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already documents all parameters (100% coverage). The description adds the semantic distinction that app_uuid toggles modes and skip/take are pagination controls, which is valuable beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb 'List' with specific resource 'deployments', and distinguishes two modes: active deployments (no args) or history for a specific app (app_uuid). This differentiates it from siblings like list_resources and get_logs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context on when to use each mode and pagination parameters. However, it doesn't explicitly mention alternatives or when not to use this tool, so not a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | Resource type whose logs to fetch. | |
| uuid | Yes | Resource UUID. | |
| lines | No | Number of log lines to retrieve (default 100). Applies to application kind. | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the API endpoint and the host-ops requirement, implying a read operation. However, it does not describe the return format, size limits, or potential side effects. The reference to 'Task 31' is an implementation detail that does not clarify behavior for an agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the purpose and uses bullet points for clarity. It is relatively concise, though the trailing 'wired in Task 31' is irrelevant and adds noise. Overall, the structure is efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description lacks critical context for an agent to fully understand the tool's behavior without relying on external knowledge. It does not explain the return value structure, how 'instance' affects the request, or clarify the ambiguous '--enable-host-ops' requirement. Since there is no output schema and no annotations, this is insufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
While the schema already describes all parameters (100% coverage), the description adds meaningful context: it ties the 'lines' parameter to the API query string, and clarifies that 'database' and 'service' kinds have additional prerequisites. This goes beyond the schema definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool fetches a log snapshot for a Coolify resource, with a specific verb and resource type. It distinguishes from sibling tools like get_resource or get_deployments by focusing on logs, and further differentiates between application, database, and service kinds.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context on when to use the tool by explaining kind-specific behavior: applications use a REST API endpoint, while databases/services require --enable-host-ops. It does not explicitly mention exclusions or alternatives, but the prerequisites are useful for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_resourceA
Get full details of a specific Coolify resource by type and UUID.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | The resource type. | |
| uuid | Yes | The Coolify UUID of the resource. | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description indicates a read-only 'Get' operation, but with no annotations provided, it carries the full burden of behavioral disclosure. It does not mention what happens when the UUID is invalid, whether authentication/instance selection is needed, or confirm that no modifications occur. The read-only implication is clear, but no additional behavioral context is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, direct sentence that conveys purpose and scope without redundancy. It is appropriately sized for a simple getter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read operation with fully documented parameters and no output schema, the description is adequate: it names the resource types generically, but does not detail the response shape. Since 'full details' implies a comprehensive return, and format is not explained, there is a minor gap. However, the overall simplicity keeps completeness high.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully describes all parameters (100% coverage), including the enum for type and descriptions for uuid and instance. The description adds little beyond restating 'by type and UUID'—it does not explain the instance parameter or the meaning of each resource type. With high schema coverage, the baseline of 3 applies and the description provides no extra value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the operation ('Get full details') and the target ('a specific Coolify resource'), with precise scoping ('by type and UUID'). It is distinct from sibling tools like list_resources (lists all resources) and get_logs/get_deployments (which target other aspects). The verb and resource are specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided about when to use this tool versus alternatives. It does not mention that list_resources should be used to discover UUIDs, or that get_logs/get_deployments serve different purposes. The description implies its own use but offers no explicit context or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_serversA
Query Coolify servers. Actions: list (summary fields by default; include:true for full), get, validate, resources, domains.
| Name | Required | Description | Default |
|---|---|---|---|
| uuid | No | Server UUID (required for get, validate, resources, domains). | |
| action | No | Operation to perform. Defaults to list. | |
| include | No | If true, return full server objects instead of summary fields (list only). | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It implies read-only behavior via 'Query' and discloses the default summary/list behavior and 'include:true' modifier. However, it does not explicitly state that no data is modified, nor does it mention pagination, errors, or authentication requirements—adequate but with clear gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the main purpose, and every word contributes to understanding the tool's scope and actions. There is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is moderately complex (4 parameters, 5 actions, no output schema). The description lists the action names but does not explain what each action returns or any other behavioral details. Since there is no output schema, the description should compensate by clarifying each action, but it only elaborates on 'list'. This leaves 'get', 'validate', 'resources', and 'domains' underspecified, though their names are reasonably self-explanatory.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so each parameter is already described in the schema. The description's note 'list (summary fields by default; include:true for full)' adds no new information beyond the schema's own descriptions for 'action' and 'include'. It meets the baseline but provides no extra semantic value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool queries Coolify servers and enumerates specific actions (list, get, validate, resources, domains), distinguishing it from sibling tools like 'get_resource' and 'list_resources' which target resources generally. The verb 'Query' plus the resource and action list make the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Query Coolify servers' provides clear context for when to use this tool, and the action list (e.g., list, get, validate) indicates common operations. However, it does not explicitly mention when not to use it or name alternatives, so it falls one step short of full guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hetzner_inventoryA
Browse Hetzner Cloud resource catalog exposed by Coolify. Use before provision_hetzner to pick a server type and location.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Coolify instance name (omit for the default). | |
| resource | No | Resource type to list. Defaults to server-types. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. 'Browse' implies a read-only listing operation, and 'resource catalog' indicates it returns data, but it does not disclose return format, pagination, error behavior, or any potential side effects. This is basic but incomplete behavioral transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, no filler, and front-loads the purpose. Every word earns its place, making it highly concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with good schema coverage, and the description adds key workflow context. However, since there is no output schema, the description could have briefly mentioned the return format (e.g., a list of resources). Still, the current description is largely complete for a browsing tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (both instance and resource have descriptions). The description adds a workflow hint ('server type and location') that maps to enum values, but it does not add meaning beyond what the schema already provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function ('Browse Hetzner Cloud resource catalog') and explicitly ties it to the provisioning workflow ('Use before provision_hetzner to pick a server type and location'). This distinguishes it from generic list tools and clarifies its specific scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use before provision_hetzner to pick a server type and location' provides clear, explicit when-to-use guidance within the provisioning workflow. However, it does not name alternatives or state when not to use it, so it falls slightly short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Not used for routing here — the instance list is server-global. Pass an instance name to any OTHER tool to target a specific Coolify instance. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and explicitly notes that it 'Never returns tokens or other secrets,' adding a behavioral guarantee beyond the schema. It also discloses the scope (server-global) and the content of the list, providing adequate transparency for a read-only list operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences front-load the main purpose, then add a safety note and a routing tip. No waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple discovery tool with no output schema, the description mentions all relevant return fields and the safety constraint. It is complete enough for an agent to know what the tool returns and how to use the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single optional 'instance' parameter is fully documented in the schema, and the description reinforces that it is not used for routing here. Since schema coverage is 100%, the description adds no new parameter syntax but usefully repeats the cross-tool routing advice.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'List' and identifies the resource as 'Coolify instances this server is configured to drive,' with the fields returned ('names, base URLs, default, and per-instance host-ops/destructive flags'). This distinguishes it from sibling tools like list_resources or get_servers by focusing on instances and their routing configuration.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states that the instance list is server-global and directs users to pass an instance name to any other tool for routing, which gives clear usage context. It does not explicitly list when not to use this tool or name alternative list tools, but the routing instruction serves as practical guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_resourcesA
List all Coolify resources (applications, databases, services) across all projects. Optionally filter by type.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Optional filter by resource type. | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the broad scope and optional filter but omits behavioral details such as the read-only nature, the effect of the instance parameter, pagination, or permission requirements. Some context is added, but it is not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short, front-loaded sentences with a parenthetical enumeration. Every word contributes, and there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool, the description covers the main purpose and type filter, but fails to mention the instance parameter, which is important for multi-instance setups. Although the schema fills the gap, the description's ambiguity about instance scoping leaves room for misinterpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already has 100% coverage for both parameters. The description only redundantly mentions the type filter and does not describe the instance parameter at all, so it adds little over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a specific resource ('Coolify resources'), the scope ('across all projects'), and enumerates the resource types. It also notes the optional type filter, which distinguishes it from more specific tools like get_resource or list_instances.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use for listing resources but does not explicitly contrast with alternatives or specify when not to use it. No exclusions or alternative tool names are mentioned, so the usage guidance is only implied by the task description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| uuid | Yes | Database UUID. | |
| action | Yes | ||
| fields | No | Backup schedule fields for create/update (create requires frequency; also enabled, save_s3, s3_storage_uuid, databases_to_backup, dump_all, backup_now, database_backup_retention_*, timeout), sent verbatim as the request body — any field the Coolify endpoint accepts is allowed. | |
| confirm | No | Required for delete and delete_execution. | |
| dry_run | No | ||
| instance | No | Coolify instance name (omit for the default). | |
| backup_uuid | No | Required for update, delete, executions, delete_execution. | |
| fields_json | No | JSON-encoded alternative to `fields` (mutually exclusive) for clients whose strict schema handling strips free-form object contents. | |
| execution_uuid | No | Required for delete_execution. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden for behavioral disclosure. It mentions that the tool can create, update, and delete, implying mutability, but provides no details on side effects, permissions, reversibility, or confirmation requirements. The confirmation requirement for delete is only present in the input schema, not the description, so the agent is left without warning about destructive actions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact at two sentences, front-loading the core purpose. The second sentence is somewhat dense with a long list of fields, but each item adds relevant detail. It avoids unnecessary filler, so it remains appropriately sized for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (9 parameters, multiple actions, nested objects, no output schema), the description gives a high-level overview but misses some important distinctions. For example, it does not clarify the difference between 'list' (schedules) and 'executions', nor between 'delete' and 'delete_execution'. However, the input schema covers many required-field constraints, so the description does not need to repeat those. Still, the ambiguity around action applicability leaves gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaning beyond the schema by explaining that `fields` holds backup schedule parameters and lists which ones are required or optional for create/update. It specifically notes that `frequency` is a cron expression and includes the wildcard `database_backup_retention_*`, which is not obvious from the schema alone. This compensates for the 78% schema coverage by clarifying usage of the `fields` object.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'List, create, update, or delete database backup schedules and executions.' It names a specific resource (database backup schedules/executions) and distinct verbs for each action. The qualifier 'Only applicable to databases' further narrows scope, differentiating it from sibling tools like manage_scheduled_tasks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by specifying that the tool is 'Only applicable to databases,' which serves as an exclusion criterion. It also gives actionable guidance for create/update by stating that schedule fields go in `fields` and that `frequency` is required. However, it does not explicitly name alternative tools or state when not to use this tool beyond the database scope.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | Variable name. Required for action=set with a single var. | |
| type | Yes | The resource type. | |
| uuid | Yes | The Coolify UUID of the resource. | |
| vars | No | Array of { key, value } pairs for bulk set (action=set). | |
| value | No | Variable value. Required for action=set with a single var. | |
| action | Yes | Operation to perform on environment variables. | |
| confirm | No | Must be true to confirm destructive operations (action=delete). | |
| dry_run | No | If true, show what would be deleted without performing the action (action=delete). | |
| env_uuid | No | UUID of the env var to delete. Required for action=delete. | |
| instance | No | Coolify instance name (omit for the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses key behavioral traits: list returns a redaction_hint, set upserts via bulk API, delete is destructive and requires confirmation, and dry_run is supported. However, it does not mention side effects beyond deletion, error conditions, or authentication/rate limits, which are common gaps but not required given the tool's purpose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is around 70 words, front-loaded with the main purpose, and uses action= prefixes to organize behavior. Every sentence adds concrete information without redundancy, achieving high information density in a compact form.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and 10 parameters, the description does well: it explains list's output, set's bulk capability, and delete's requirements. It falls short by not describing return values for set/delete or error behaviors, and it omits that type and uuid are required across all actions (but that is in the schema). Overall, it covers the core operational context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds crucial relational meaning: it links action=set to key/value and vars, explains env_uuid comes from list, and ties confirm/dry_run to delete. This goes far beyond the schema's static descriptions and helps the agent choose the correct parameters per action.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear verb+resource statement: 'Manage environment variables for a Coolify resource (application, database, or service).' It then enumerates the three actions (list, set, delete) with specific behavioral details, making it distinct from sibling tools like manage_storage or manage_backups.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use each action (list for viewing, set for upserting, delete for removal) and specifies prerequisites like env_uuid from list. It also states that delete requires confirm:true. However, it does not explicitly compare with alternative tools or mention when not to use this tool, so it misses the explicit exclusion guidance that would earn a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Key display name. | |
| uuid | No | Key UUID (required for get, update, delete). | |
| action | Yes | Operation to perform. | |
| confirm | No | Must be true to confirm create, update, or delete. | |
| dry_run | No | Preview the action without executing (create, update, delete). | |
| instance | No | Coolify instance name (omit for the default). | |
| description | No | Optional description. | |
| private_key | No | PEM-encoded private key (required for create). | |
| is_git_related | No | Mark as a git-related key. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It discloses that create/update are credential writes, requires confirmation, and mentions the collection-level PATCH nuance for update (uuid in body). This adds valuable non-obvious behavioral context, though it doesn't explain what 'fenced' means or potential side effects of delete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the purpose, then a concise action list, then critical operational details. No filler or redundant content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool complexity (9 params, 5 actions) and no output schema, the description covers essential warnings and nuances but could elaborate on return values or per-action behavior. However, the rich schema descriptions compensate, making the description adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds extra meaning by linking confirm to credential writes and explaining that update uses a collection-level PATCH with uuid in the body. This goes beyond the schema field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool manages Coolify SSH private keys and enumerates the supported actions (list, get, create, update, delete). This is a specific verb+resource and distinguishes it from sibling tools like manage_server or manage_storage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context on how to perform actions, notably that create/update are fenced credential writes requiring --allow-destructive and confirm:true. It doesn't explicitly name alternatives, but the tool's scope is clear relative to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_projectsC
Manage Coolify projects and their environments. Actions: list, get, create, update, delete (fenced), list_environments, create_environment, get_environment, delete_environment (fenced).
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Project name (required for create; optional for update) or environment name (required for create_environment). | |
| uuid | No | Project UUID (required for get, update, delete, list_environments, create_environment, get_environment, delete_environment). | |
| action | Yes | The operation to perform. | |
| confirm | No | Must be true to confirm destructive operations (delete, delete_environment). | |
| dry_run | No | If true, show what would be deleted without performing the action (delete, delete_environment). | |
| instance | No | Coolify instance name (omit for the default). | |
| description | No | Project description (optional for create/update). | |
| environment | No | Environment name or UUID (required for get_environment, delete_environment). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, but it only hints at destructive operations with '(fenced)' without explaining what that entails. It fails to disclose side effects, required permissions, or behavior of actions like delete. The schema covers the confirm flag, but the description adds little beyond a vague safety signal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loads the purpose, and uses a compact action list. It is not overly verbose, though the actions could be presented in a more structured way (e.g., categorizing by resource type).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (8 parameters, 9 actions) and lack of output schema, the description is incomplete. It does not explain what each action returns, mention prerequisites (e.g., needing a UUID for get), or provide context beyond the action names. The schema compensates for some parameter details but not overall workflow context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the structured field descriptions already document all parameters. The description adds no additional parameter semantics beyond what the schema provides, maintaining the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly identifies the resource (Coolify projects and their environments) and enumerates specific actions (list, get, create, update, delete). The verb 'Manage' is generic, but the action list provides specificity and distinguishes it from sibling tools like manage_env or manage_server.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides no guidance on when to use this tool versus alternatives. It does not mention that environment-specific tools (e.g., manage_env) should be used for environment variables, nor any prerequisites or contexts for the various actions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| type | Yes | ||
| uuid | Yes | ||
| action | Yes | ||
| command | No | ||
| confirm | No | Required for create, update, and delete. | |
| dry_run | No | If true, show preview without performing the action (create, update, delete). | |
| enabled | No | Whether the task is enabled (Coolify default true). | |
| timeout | No | Task timeout in seconds (Coolify default 300). | |
| instance | No | Coolify instance name (omit for the default). | |
| container | No | Container (within a compose app/service) the command runs in. | |
| frequency | No | Cron expression. | |
| task_uuid | No | Required for update, delete, executions. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It meaningfully discloses that create/update are code-execution writes with special safety requirements, and the 'fenced' label hints at guarded behavior. However, it does not clarify whether delete also requires confirm (schema says yes) or explain what 'fenced' actually means, leaving some behavioral gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two crisp sentences. The first sentence front-loads the action list and resource; the second adds a targeted safety note. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (13 parameters, 5 actions, no annotations or output schema), the description is adequate but not complete. It lists the actions and flags important safety, but leaves 'fenced' undefined and doesn't mention dry_run or the fact that delete also requires confirm per the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 62%, leaving some parameters (name, command, uuid) undocumented. The description adds value by explaining the confirm requirement for create/update, but it omits delete's confirm requirement and does not help clarify the undocumented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear list of specific actions (List, create, update, delete, view executions) tied to a specific resource (scheduled tasks on an application or service). This distinguishes it from sibling tools like manage_storage or manage_backups.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when the tool is relevant (scheduled tasks on applications/services) and provides a key usage constraint (create/update are code-execution writes requiring --allow-destructive and confirm:true). However, it does not explicitly name alternatives or state when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_serverC
Create, update, or delete (fenced) a Coolify server.
| Name | Required | Description | Default |
|---|---|---|---|
| ip | No | Server IP address (required for create). | |
| name | No | Server display name. | |
| port | No | SSH port (default 22). | |
| user | No | SSH user (required for create). | |
| uuid | No | Server UUID (required for update, delete). | |
| action | Yes | Operation to perform. | |
| confirm | No | Must be true to confirm delete. | |
| dry_run | No | Preview delete without executing. | |
| instance | No | Coolify instance name (omit for the default). | |
| description | No | Optional description. | |
| is_build_server | No | Mark as build server. | |
| instant_validate | No | Validate immediately after create. | |
| private_key_uuid | No | UUID of the private key to use (required for create). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavior. It doesn't mention that delete is destructive, requires confirmation, or that there are dry-run capabilities. The 'fenced' term is unexplained, adding confusion rather than transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no filler. It's appropriately short and front-loads the action verbs, making it easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex multi-action tool with 13 parameters and no output schema, yet the description is only 9 words. It doesn't clarify the 'fenced' concept, how operations differ in required fields, or what the tool returns. The minimal description is inadequate for such a complex tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes all 13 parameters with 100% coverage, so the description doesn't need to repeat that. However, the description adds no additional meaning about parameter relationships or operation-specific requirements, so it stays at the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function with the verbs 'create, update, or delete' targeting a 'Coolify server'. However, the term 'fenced' is ambiguous and no differentiation from sibling tools like create_resource or get_servers is provided, so it's not a perfect 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like create_resource or get_servers. There's no mention of required parameter combinations for each operation or any prerequisites, leaving usage context fully to the schema and agent inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| uuid | Yes | ||
| action | Yes | ||
| fields | No | Storage fields for create/update (create requires type and mount_path; also name, host_path, content, is_directory, fs_path), sent verbatim as the request body — any field the Coolify endpoint accepts is allowed. | |
| confirm | No | Required for delete. | |
| dry_run | No | ||
| instance | No | Coolify instance name (omit for the default). | |
| fields_json | No | JSON-encoded alternative to `fields` (mutually exclusive) for clients whose strict schema handling strips free-form object contents. | |
| storage_uuid | No | Required for update and delete. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must bear the full responsibility for behavioral disclosure. It states the tool can 'delete' storage, implying destructiveness, but it does not warn about permanence, permissions, or confirm requirements. It also omits the `dry_run` option and output behavior. This is a significant transparency gap for a mutating operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the primary purpose, and the second sentence adds actionable field guidance. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 9 parameters and 4 actions, no output schema, and no annotations. The description covers core purpose and create/update field requirements, but omits critical context: return values, deletion semantics, how `dry_run` works, and the distinction between `fields` and `fields_json`. This is incomplete for an agent to confidently invoke all actions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description reinforces key parameter requirements: 'For create/update, pass the storage fields in `fields`' and lists required and optional subfields. While this mirrors the schema's description for `fields`, it brings the information to the top level. However, it does not elaborate on `confirm`, `dry_run`, `storage_uuid`, or `instance`, which the schema partially explains. Given 56% schema coverage, the description adds some but not enough compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear multi-verb statement: 'List, create, update, or delete persistent volume storage for an application, database, or service.' This identifies both the actions and the resource type. However, it does not explicitly differentiate this from sibling tools like create_resource or manage_env, so it loses a point on sibling distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives some situational guidance: it notes that create requires `type` and `mount_path`, and that storage fields go in `fields`. However, it doesn't explain when to choose this tool over alternatives, nor does it mention that deletion requires confirmation (only in the schema). Usage is implied rather than explicitly laid out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
provision_hetznerA
Provision a new server on Hetzner Cloud via Coolify (destructive — creates billable infrastructure). Requires --allow-destructive flag and confirm:true.
| Name | Required | Description | Default |
|---|---|---|---|
| ip | No | Override the provisioned IP (advanced). | |
| name | Yes | Display name for the new server. | |
| port | No | SSH port (default 22). | |
| user | No | SSH user (default root). | |
| confirm | No | Must be true to proceed. | |
| dry_run | No | Preview without provisioning. | |
| instance | No | Coolify instance name (omit for the default). | |
| location | Yes | Hetzner datacenter location (e.g. nbg1). Use hetzner_inventory to browse. | |
| description | No | Optional description. | |
| coolify_token | No | Coolify cloud token UUID for the account. | |
| instant_validate | No | Validate connectivity immediately. | |
| private_key_uuid | No | SSH private key UUID to install on the new server. | |
| hetzner_api_token | No | Hetzner API token (if not configured server-side). | |
| hetzner_server_type | Yes | Hetzner server type (e.g. cx11). Use hetzner_inventory to browse. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses that the action is destructive and creates billable infrastructure, along with required confirmation flags. This is significant, but it does not describe what happens after provisioning (e.g., return value, connectivity checks) or irreversible consequences beyond 'destructive'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the main purpose, followed by safety requirements. Every word earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex tool with 14 parameters and no output schema. The description covers the core purpose and safety gate, but it does not explain the provisioning workflow, what the response looks like, or how to use the hetzner_inventory sibling for browsing types/locations (which the schema property descriptions reference). It is minimally viable but lacks depth for such a complex operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds context about the confirm parameter and the --allow-destructive flag, but this is already partially captured in the schema (confirm: 'Must be true to proceed'). No new parameter semantics are added beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States clearly that it provisions a new server on Hetzner Cloud via Coolify, using a specific verb and resource. This distinguishes it from sibling tools like manage_server and hetzner_inventory, which handle existing servers or inventory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for creating new servers by the phrase 'Provision a new server' and provides explicit prerequisites (--allow-destructive flag and confirm:true). However, it does not explicitly contrast with alternatives like manage_server for existing servers, so it misses the 'when-not' guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| uuid | Yes | The Coolify UUID of the resource. | |
| fields | No | Resource fields to update, sent verbatim as the request body — any field the Coolify endpoint accepts is allowed. | |
| confirm | No | Must be true to confirm the update (destructive: code-execution write). | |
| dry_run | No | If true, preview which fields would be updated without performing the action. | |
| instance | No | Coolify instance name (omit for the default). | |
| fields_json | No | JSON-encoded alternative to `fields` (mutually exclusive) for clients whose strict schema handling strips free-form object contents. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden, and it excels: it discloses the destructive code-execution write, the need for confirm:true, that fields are sent verbatim as the PATCH body, and that instant_deploy queues an immediate redeploy. It also highlights type-specific constraints, providing a clear behavioral profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured: it starts with the critical warning, then explains field passing, then details per-type accepted fields. It is longer than ideal but every sentence adds value. The use of lists and parentheticals aids readability. Slight deduction for length, but it is appropriately sized for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (multiple resource types, 7 params, no output schema), the description covers a lot: usage, field lists, and type-specific rules. However, it omits guidance for databases (the third type) and does not mention what the response looks like or expected outcomes on success/failure. These gaps prevent a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers 86% of parameters, but the description adds substantial meaning: it explains how `fields` works (verbatim PATCH body), the purpose of `fields_json` as an alternative for strict schema clients, and lists common field names with specifics (e.g., domains format, docker_compose_domains). This goes well beyond the schema's basic property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Update configuration fields of an existing Coolify resource.' The verb 'update' and resource are specific, and it distinguishes from siblings like create_resource, delete_resource, and control_resource by focusing on configuration field updates. The resource types (applications, databases, services) are also noted.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: requires --allow-destructive and confirm:true, and explains the destructive nature (code-execution write). It also gives detailed field usage per resource type (applications vs services), clarifies common pitfalls (e.g., use docker_compose_domains instead of domains for dockercompose apps), and notes instant_deploy behavior. This is rich guidance beyond generic usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
22 tool updates
v0.3.0- First observed
cancel_deployment - First observed
control_resource - First observed
create_resource - First observed
delete_resource - First observed
deploy - First observed
deploy_watch - First observed
get_deployments - First observed
get_logs - First observed
get_resource - First observed
get_servers - First observed
hetzner_inventory - First observed
list_instances - First observed
list_resources - First observed
manage_backups - First observed
manage_env - First observed
manage_keys - First observed
manage_projects - First observed
manage_scheduled_tasks - First observed
manage_server - First observed
manage_storage - First observed
provision_hetzner - First observed
update_resource
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
- SupabaseOAuthcom.supabase
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.
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.35139 npm6MIT
- AlicenseBqualityBmaintenanceMCP server for managing Coolify instances, enabling control of applications, databases, services, servers, and more via natural language.11617 npmMIT
- AlicenseBqualityAmaintenanceMCP server for Coolify API that enables full deployment workflows from zero to production, including project, server, and application management.6573 npm3MIT
- AlicenseAqualityAmaintenanceOne 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.1932 npmMIT