Skip to main content
Glama
VBCDX
by VBCDX

@vbcdx/coolify-plugin

An MCP server for a bounded, write-controlled subset of the Coolify v4 API. Contract vbcdx.coolify/1. It gives an agent per-call credential-file selection, a fixed catalog of 27 tools, honest result reporting, and explicit accidental-write controls.

This README covers what the package needs to be installed and run. Exhaustive tool-by-tool documentation and independent runtime verification are tracked separately.

What it is (and is not)

Coolify ships a native MCP endpoint. This package deliberately adds per-call credential-file selection, a bounded catalog, and an accidental-write interlock. It does not replace every native capability or provide stronger authorization than the OS and the service token allow. Native endpoint enablement, infrastructure provisioning, backup/restore, arbitrary shell/API calls, private-key/cloud-token management, and rollback/pin-to-SHA are out of scope in v1.

Related MCP server: Coolify MCP Server

Coolify's native MCP server

Coolify has shipped its own MCP server since v4.1.0 (18 May 2026), which added instance-level MCP with read-only tools over Coolify resources plus API/UI enablement controls. v4.2.0 (21 Jul 2026) added per-team MCP, and later 4.3.x releases extended the tool surface (deploy and cancellation operations, gated by token scope). Coolify's release cadence is its own; for the authoritative, current capability list, follow the vendor docs rather than this README.

Enabling it (self-hosted). Settings → Configuration → Advanced → API and MCP: enable API access, then set MCP server to Enabled. It must also be enabled for the active team ("Enabled for this team" in that team's settings). Coolify Cloud has instance MCP enabled already, with team access on by default.

Connecting. Endpoint https://<your-coolify-host>/mcp, transport Streamable HTTP, header Authorization: Bearer <token>. Tokens come from Keys & Tokens → API Tokens while the target team is active. Scope the token to the least privilege the client needs: read for inspection, read:sensitive for sensitive values and log summaries, deploy for deploy/start/stop/restart/cancel. Coolify's docs advise against using root for ordinary clients. A client denied by team settings gets 403; consult the docs for the current, exact failure modes.

Native MCP vs. this package

If you want direct, full-surface access to a Coolify instance from a single team's token, and you trust the caller with whatever that token permits, the native MCP server is sufficient — reach for it first. This package exists for a narrower situation: several agents that each present their own credential file per call, a fixed and auditable catalog rather than Coolify's evolving full surface, an accidental-write interlock (off / write / full, plus a confirmation string on destructive tools), and result envelopes that refuse to over-claim an unverified outcome. It deliberately covers less than native MCP; use it when per-call credential isolation and write-blast-radius control matter more than breadth.

Requirements

  • Node.js >= 22 (tested on Node 22 and 24).

  • Runnable JavaScript, no build step. One runtime dependency: the maintained @modelcontextprotocol/sdk (pinned).

Install

This package is not yet published to a public npm registry. Once a version is published and tested, the supported install will be:

npm install @vbcdx/coolify-plugin

Until then, install a packed, reviewed artifact into a clean prefix and register the absolute entrypoint. From an immutable reviewed commit of your own checkout or mirror:

npx --yes --package='<git-remote-url>#<reviewed-commit>' vbcdx-coolify mcp

Substitute your git remote and the delivered commit, not a moving branch. An npm name/version launch command is advertised only after that version is published to a registry and tested.

Network mode (serve): MCP over Streamable HTTP

vbcdx-coolify serve runs the same finite tool catalogue as an MCP server over the Streamable HTTP transport (stateless: a fresh server per request), for hosts that cannot run the stdio companion next to the agent — e.g. an MCP gateway (LiteLLM true_passthrough) or a harness container without Node.js.

VBCDX_COOLIFY_URL=https://coolify.example \
VBCDX_COOLIFY_WRITES=off \
npx vbcdx-coolify serve
# → MCP endpoint:  POST http://0.0.0.0:8080/mcp
# → liveness:      GET  http://0.0.0.0:8080/healthz

Credentials per request, by header. There is no credential file and no credential_file argument in this mode — the tool schemas drop it. The Coolify API token arrives in Authorization: Bearer <token> (or token <token>), is used for that one request, registered with the redactor and never cached or logged. Coolify has no password authentication, so there is no Basic scheme. Tool discovery works without a credential; a call without one returns a redacted credential_missing refusal before any Coolify request. The gate order (inputs → write gate → confirmation → server config → credential → HTTP), the write gate and the destructive confirmation are identical to stdio.

A POST /mcp body larger than 1 MiB is refused with 413 before it is buffered (checked against Content-Length and, for chunked bodies, while reading); a body that is not JSON gets 400. Both happen before any credential check or Coolify request.

Setting

Meaning

VBCDX_COOLIFY_HTTP_PORT

Listen port (default 8080).

VBCDX_COOLIFY_HTTP_HOST

Bind address (default 0.0.0.0). healthcheck always probes 127.0.0.1, so a specific non-loopback address makes the container report unhealthy; keep 0.0.0.0 (or a loopback address) in a container.

VBCDX_COOLIFY_TLS_CERT / VBCDX_COOLIFY_TLS_KEY

Serve HTTPS directly (both or neither).

Container. Dockerfile builds vbcdx-coolify serve on a pinned Node 22 Alpine image as the unprivileged node user, with a HEALTHCHECK (vbcdx-coolify healthcheck, which probes 127.0.0.1:<port>/healthz). No credential is baked into any layer. Plain HTTP is for trusted networks only; put TLS in front otherwise.

For the main consumer of this mode, see Using with Hermes Agent.

Using with Hermes Agent

Hermes Agent (checked against v0.15.1, tag v2026.5.29) connects to MCP servers over stdio or Streamable HTTP. Use serve for Hermes, not the stdio companion.

Why serve and not stdio. A Hermes agent keeps its config, .env and state in its own HERMES_HOME: one per profile, and /opt/data in the official container image. The stdio companion has to run next to the agent. It needs Node.js >= 22 where the agent runs, plus a 0600 credential file on that same filesystem. A containerised Hermes, or one without Node.js, can't meet that from the host. With serve, Hermes only needs a URL and a header.

Request path.

Hermes profile ──► LiteLLM (auth_type: true_passthrough) ──► vbcdx-coolify serve ──► Coolify API

Each Hermes profile holds its own Coolify API token and sends it as Authorization: Bearer <token> on every request. LiteLLM true_passthrough forwards the client's Authorization header verbatim and stores nothing. serve uses the token for that one request only. It never caches or logs it (see above). The token's Coolify permissions, and VBCDX_COOLIFY_WRITES on the serve host, bound what each agent can do. You can also point Hermes straight at serve and skip LiteLLM; the Hermes config below is the same apart from the URL.

Hermes config. Add to mcp_servers in the profile's $HERMES_HOME/config.yaml (~/.hermes/config.yaml by default). A url entry uses Streamable HTTP. Hermes resolves ${VAR} in the entry from the environment, including the profile's $HERMES_HOME/.env, so the token stays out of config.yaml:

mcp_servers:
  coolify:
    url: "https://litellm.example/coolify/mcp"   # or https://coolify-mcp.example/mcp for serve directly
    headers:
      Authorization: "Bearer ${COOLIFY_API_TOKEN}"
# $HERMES_HOME/.env — one token per profile (agent)
COOLIFY_API_TOKEN=<this-agent's-coolify-api-token>

The LiteLLM server entry for serve needs auth_type: true_passthrough. The path segment (coolify above) is that entry's name in LiteLLM's mcp_servers.

Configuration (environment only)

The server takes no secret, URL, role, or credential CLI options. Configuration comes from the environment:

Variable

Meaning

VBCDX_COOLIFY_URL

Coolify instance URL. Required for any API call. An optional deployment path prefix and an optional trailing /api/v1 are accepted; the API suffix is appended exactly once. Userinfo/query/fragment are rejected. Plain HTTP is allowed on a trusted network (noted once); TLS verification is never disabled.

VBCDX_COOLIFY_WRITES

off (default), write, or full. off permits reads only; write also permits ordinary configuration/deploy writes; full additionally permits destructive tools. An invalid value behaves as off.

VBCDX_COOLIFY_TIMEOUT_MS

Total per-call budget, integer 1000–120000 (default 30000). Spans the credential read, any preflight, the mutation, and verification.

Credentials

Every tool except public health takes an explicit absolute credential_file argument at call time. The file is read fresh on each call (one snapshot per call so a rotation cannot switch identity midway). There is no token/URL/role option, directory scan, home-directory search, ambient secret, or between-call cache.

The file must be a regular, non-symlink file owned by you at mode 0600, in an immediate parent directory owned by you at mode 0700, with no symlink component in the path. It contains VBCDX_AGENTS_ROLE (descriptive) and a nonblank VBCDX_AGENTS_TOKEN. The token is sent as Authorization: Bearer <token>; Coolify has no password fallback. See examples/credential-file.env.example. Every environment variable the server reads is listed in .env.example.

Token permissions (read, read:sensitive, write, deploy, root) are the token's, scoped to its team and role. A deploy-only token is legitimate. The server never infers permission from the role, decodes token authority, or retries a 403 with another identity.

Commands

vbcdx-coolify mcp        # stdio MCP server (protocol frames on stdout; diagnostics on stderr)
vbcdx-coolify manifest   # deterministic nonsecret JSON tool contract (no network, no credential reads)
vbcdx-coolify --help
vbcdx-coolify --version

Unknown commands or options exit 2.

Registration

The MCP identity is coolify. See examples/mcp-registration.md for Claude Code, Codex, OpenCode, and DSH. The tool catalog is discoverable without credentials; a call without credentials returns an actionable error, not a crash.

Write controls and honest results

  • Every tool declares an effect: read, write, or destructive. Gates run before any file read or HTTP call, and all tools remain listed even when disabled.

  • Destructive tools (restart_application, stop_application, cancel_deployment, delete_application_env, delete_application) require VBCDX_COOLIFY_WRITES=full and an exact confirmation string that binds the normalized target and options. The confirmation is an accident interlock, not proof of human approval, and is never sent upstream.

  • Results never over-claim. HTTP status is checked before body shape (a 403 with success:true is a failure). A 2xx alone is not completion. A read never turns an error into an empty list. A mutation whose outcome cannot be confirmed is unverified or indeterminate and is never replayed.

Each result carries outcome, effect, request:{method,path,attempted}, verification, and — for failures — a fixed reason and a secret-free message.

Tool catalog (27)

Reads (17): health, version, list_applications, get_application, get_application_logs, list_application_envs, list_databases, get_database, list_services, get_service, list_projects, get_project, list_servers, get_server, list_resources, list_deployments, get_deployment.

Writes (5): create_application, deploy, start_application, create_application_env, update_application_env.

Destructive (5): restart_application, stop_application, cancel_deployment, delete_application_env, delete_application.

Run vbcdx-coolify manifest for the exact input/output schemas, effects, and required permissions.

Development

npm ci
npm test        # node --test; route-level fixtures, adversarial cases, no network

Continuous integration

CI (.forgejo/workflows/ci.yml) runs on a self-hosted runner chosen by the CI_RUNNER_LABEL repository (or org) variable, so the runner's label is not baked into the published source. If you fork this repo and run its Forgejo workflows, set CI_RUNNER_LABEL to a label your runner advertises (for a GitHub-parity self-hosted runner, self-hosted). If it is left unset the jobs are silently skipped — an empty runs-on matches no runner.

License

MIT — see LICENSE.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    F
    maintenance
    Enables interaction with Coolify applications and resources through the Coolify API via a standardized interface, supporting application management operations such as listing, starting, stopping, restarting, and deploying.
    11
    13
    -
  • A
    license
    B
    quality
    B
    maintenance
    Enables control and management of Coolify self-hosted PaaS instances, allowing you to deploy applications, manage databases, monitor servers, and execute operations directly from AI assistants.
    89
    8 npm
    29
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables LLMs to manage a self-hosted Coolify instance, including applications, databases, services, servers, projects, deployments, environment variables, tags, teams, private keys, and S3 backup storages via the Coolify REST API.
    241 npm
    MIT