"Restart the PostgreSQL database container immediately." That is not a runbook entry — it is a chat message. Type it into AnythingLLM with xlop-dev/coolify-anythingllm-mcp wired up, and an AI agent translates the sentence into Coolify API calls that restart your production database on your home lab or VPS. No dashboard, no SSH session, no docker restart typed by a human. Deploy-from-chat has reached the self-hosted PaaS: a community Model Context Protocol server bridges Coolify's API into AnythingLLM so an agent can list apps, read deployment logs, trigger builds, restart services, and roll back releases, all from a prompt.
Here is the shape of the answer up front — what the bridge hands an agent, what the cheapest serious setup costs, and where the credential story breaks:
| The bridge | The bill | The catch | |
|---|---|---|---|
| What it is | stdio MCP server: Coolify API → AnythingLLM agent tools | Coolify Cloud $5/mo for 2 servers + $3 per extra | One API token with deploy-level-or-broader power |
| Agent can do | List apps, read logs, deploy, restart, roll back | Runs on your servers — Cloud is the control plane only | Same token also covers destructive actions |
| Cheapest fleet | 2× Hetzner CX22 (€3.79 each: 2 vCPU, 4 GB RAM) | ≈ $13/mo all-in for agent-operated PaaS | stdio transport: no OAuth, no step-up, ambient authority |
Two details make the table more interesting than a parts list. First, the bridge's own README disclaims responsibility for "server downtime, data loss, or accidental resource deletion caused by your AI model" and begs you to enable human-in-the-loop confirmations — the authors know exactly what they built. Second, Coolify's API tokens do have permission levels (read-only, read:sensitive, deploy, write, *), but nothing in the bridge's setup steers you toward the narrowest one that works, and the granularity stops at the team level: there is no per-app or per-environment scope. That frames this post: not whether deploy-from-chat works — it demonstrably does — but what deploy authority an agent should hold, and which credential primitive is still missing before you hand it the keys.
The bridge: your PaaS API as agent tools
The setup is deliberately boring, which is the point. The MCP server is a Node process speaking stdio. You give it two environment variables — COOLIFY_API_URL pointing at your instance's /api/v1, and COOLIFY_API_TOKEN from Coolify's Keys & Tokens page — and register it in AnythingLLM under Agent Custom Tools / MCP Servers with a command (node) and an argument (the path to dist/index.js). From there the agent sees Coolify as tools: app diagnostics (which apps are running, container status, resource usage), log fetching (application and deployment logs for troubleshooting), and deployment automation (trigger builds, restart services, roll back releases).
The README calls this "Secure by Design," and the evidence offered is that credentials come from environment variables instead of hardcoded strings. That is table stakes, not a security model — but it is worth steelmanning what the bridge gets right. The token never transits through the chat transcript as a pasted secret; it lives in the server process environment, the same place a CI runner keeps its deploy key. The threat model the authors actually address is the casual one (don't paste secrets into prompts, don't commit them to git), and the suggested prompts stay in the diagnostic-to-lifecycle range most operators reach for first: list my apps, why did the frontend deploy fail, restart the database.
The bridge is also not alone — it is the pattern, not the exception. StuMason/coolify-mcp, with around 590 stars, exposes 42-plus token-optimized tools for Claude Desktop, Claude Code, and Cursor against the same single-API-token design, including one-click .mcpb installs that prompt for your Coolify URL and token. Claude Code skills for driving Coolify's API directly (coolify-skill repos, SKILL.md files teaching agents the endpoint shapes) multiply the same shape: ambient credentials plus a capable model. When every bridge in the ecosystem converges on "paste one powerful token into an env var," the security question stops being about any single project's README and starts being about the primitive every project is missing.
What the agent's token can actually do
Coolify deserves credit here: its API tokens are not a single god-token. Tokens are scoped to a team, and each carries a permission level — roughly read-only by default (operational reads, no secrets), read:sensitive (reads including passwords and keys), deploy (deployments and lifecycle controls), write (application and environment changes), and * (full access, including deletes and sensitive data). A read-only token genuinely cannot restart your database. The ladder exists.
The problem is what the bridge needs to stand on. "Restart the PostgreSQL database container immediately" is a lifecycle action: it requires deploy-level authority at minimum, and the bridge's full feature set (builds, restarts, rollbacks, plus whatever the agent improvises from the API surface) pushes toward write or * in practice. Community guides say the quiet part out loud: "Create with * permission for full access," "the token needs * permission for management operations." And the ladder has no middle rungs where agents need them most — there is no "deploy this one app but not touch the database," no "staging yes, production only with approval," no "restart but never delete." Team scoping helps multi-team setups and does nothing for the solo operator whose team contains everything.
Then there is the transport. The bridge speaks MCP over stdio: a local process with the token in its environment. That rules out everything the MCP authorization spec has been building for remote servers — OAuth 2.1 flows, SEP-835 scope definitions, RFC 8707 resource indicators that bind a token to the resource it was issued for, step-up authorization that escalates only when the agent reaches for something sensitive. Over stdio there is no handshake to negotiate scopes through; the token is ambient authority, available to every tool call the process makes, with the same power whether the agent is listing apps or deleting one.
AnythingLLM's human-in-the-loop confirmations are the only gate between "restart Postgres" and "delete Postgres," and that gate is a UI setting, not a credential boundary. Turn it off for convenience — or run the agent headless, where there is nobody in the loop at all — and there is nothing left between the model and full API power except the model's own judgment.
This is the exact failure mode the bridge's disclaimer names: "accidental resource deletion caused by your AI model." The authors are honest about it. But a disclaimer is not a control, and "we strongly recommend human-in-the-loop" is doing a lot of work for every unattended agent deployment the MCP ecosystem is otherwise encouraging.
The missing primitive, shipped elsewhere
Contrast this with what agent-first credential design actually looks like. Better-PaaS v2.0.0 — release-titled "Agent-first" — built its Cursor and Claude Code story around scoped agent tokens from the start. The flow is paas connect (browser authorization against your self-hosted control plane; the admin token is never saved on the laptop), which mints a bpagt_… token with an explicit scope set: roles like Deployer or Operator, resource scopes like apps:read, apps:write, logs:read, and environment restrictions like staging-only. paas setup then registers the MCP tools in the editor against that token. Every credential is revocable and audited; the blast radius of a compromised or confused agent is whatever you granted, not everything the platform can do.
Three properties make that shape the right primitive, and each maps to something the MCP spec is converging on for remote servers:
- Least privilege by construction, not by README. The Coolify bridge can technically run on a narrow token, but nothing in the setup produces one, names one, or explains which rung each tool needs. Better-PaaS mints the narrow token as the default path — the agent never sees a credential broader than its job. On the spec side, this is SEP-835's scope definitions plus servers advertising
scopes_supported: the client requests what it needs now and steps up later. - Dimensions beyond read/write. Roles (who the agent acts as) and environments (where it may act) are the axes real incidents turn on — staging-vs-production, app-vs-database. Coolify's ladder has one axis (permission level) and one boundary (team). The MCP direction is RFC 8707 resource indicators: tokens bound to the specific resource they were issued for, so a credential minted for one server cannot wander to another.
- Revocable and audited. A per-agent token can be killed without rotating the admin credential, and its calls can be traced to the agent that made them. A shared
*token in a.envfile offers neither: rotation breaks every consumer at once, and the audit log (if any) just says the token did it.
None of this requires exotic cryptography. It requires the platform to treat agents as a distinct class of principal — not "a user typing fast," but a credential holder with its own scope vocabulary — and to mint those credentials through a flow (browser authorization, per-agent issuance) that never exposes the admin secret to the machine the agent runs on. Better-PaaS is one small project's proof that the shape is shippable today; the MCP spec's OAuth 2.1 profile, protected-resource metadata, and step-up authorization are the standard converging on the same shape for remote servers. The stdio-local world — where most self-hosted bridges live — has no equivalent yet, which is precisely why the next section exists.
A scoping checklist you can apply today
You do not need to wait for the spec or switch platforms to narrow what your Coolify-bridged agent can do. Five steps, in order of leverage:
- Mint the narrowest token the job allows — and test the rung below. Start from the bridge's actual needs: diagnostics and log reading work on
read-only(plusread:sensitiveonly if log output redacts what you need); deploys and restarts needdeploy. Resist the guides that default to*. If the bridge errors on a narrow token, that error is information — it tells you which tool overreaches, and whether you want that tool enabled at all. - Give the agent its own team. Coolify scopes tokens to teams, so a dedicated agent team containing only the apps the agent may operate is the closest available thing to per-app scoping. Production databases and one-shot infrastructure live on a team whose tokens never enter an agent's environment. Crude, but it converts "the agent can touch everything" into "the agent can touch its lane."
- Keep human-in-the-loop on for destructive tools — and define "destructive" down. Restarts of stateful services, rollbacks, environment changes, and anything touching volumes count, not just deletes. If you run headless, replace the UI gate with a policy gate: strip the destructive tools from the MCP config the agent sees rather than hoping the model declines to use them.
- Rotate on a schedule and rehearse revocation. A token in a
.envfile on the box that also runs the agent is one backup, one dotfile repo, one overly helpfulcataway from exposure. Rotate the agent token periodically, and verify that revoking it breaks only the agent — if killing the agent's credential also breaks your CI or your own CLI, the credential was shared and the blast radius was a lie. - Demand the primitive from the platform. Per-agent scoped tokens with roles, environment restrictions, and audit trails are a feature request with a shipped reference implementation. Every bridge converging on "paste one powerful token" is market signal that the platform should mint narrow credentials itself. Ask Coolify — or whichever PaaS you run — for the
bpagt_shape: issued per agent, scoped by role and environment, revocable without collateral.
None of these steps costs money. The $13/mo fleet from the opening table — Coolify Cloud's $5 control plane plus two €3.79 Hetzner boxes — stays $13/mo whether the agent holds a god-token or a scoped one. Scoping is pure upside: the same deploy-from-chat demo, with a credential story you could explain to an auditor without wincing.
Agents are principals now — credential them like it
The arc here is familiar. Every interface generation — SSH keys, CI deploy keys, cloud IAM roles — started with one powerful credential passed around by convention, then learned least privilege the hard way after the first wave of incidents. Agent bridges are at the "passed around by convention" stage: the tokens work, the demos are delightful, and the disclaimers confess what the design cannot yet prevent. The Coolify↔AnythingLLM bridge is worth studying precisely because it is ordinary — a competent community project doing exactly what the ecosystem's current primitives allow, no more.
What comes next is also familiar: platforms minting agent-shaped credentials as a first-class feature, the way they eventually minted deploy keys and service accounts. Better-PaaS shows the shape fits in a small project's scope; the MCP authorization spec shows the standard is walking the same direction for remote servers. The gap is the stdio-local bridge on your own VPS — the setup this post's $13/mo fleet represents — where ambient env-var authority is still the only option. Close that gap with the checklist above, and keep asking the platform for the primitive: your agent should hold a credential that describes its job, not your admin session.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Agents are first-class operators there too: machine-readable infrastructure state and scoped credentials from the start, not bolted on after the first incident. Star the repo on GitHub or deploy your first app today.



