An agent that can redeploy your production service is not a chatbot with a new party trick. It is a second operator on your platform, and every platform has to decide where that operator plugs in. One answer is a sidecar: a separate MCP server process that talks to the platform over its public REST API, holding its own credentials and its own copy of the truth. The other answer is the one Nixploy just shipped: put the MCP endpoint inside the platform process itself, so the agent's tools dispatch into the exact same routers as the dashboard, the CLI, and the REST API.
Here is the verdict up front, before the mechanism. Three architectures for deploy-via-MCP are shipping today, and they differ on exactly four rows:
| In-process (Nixploy) | Sidecar (Dokploy community servers) | Native-but-gated (Coolify v4) | |
|---|---|---|---|
| Auth boundary | One: API-key verification, rate limiting, and org resolution shared with the REST adapter | Two: the sidecar holds its own key and re-exposes the API on its own terms | One, behind an enable switch: POST /api/v1/mcp/enable with a root token |
| Dashboard/agent state sync | None needed: both call the same tRPC routers, same audit log | Required: the sidecar's view can drift from the panel's the moment either API revs | None needed for reads; lifecycle limited to deploy/stop/restart |
| Tool-surface coherence | 42 hand-designed tools, one canonical surface owned by the platform | Fragmented: 27 curated tools vs 98 vs 400–500+ generated from OpenAPI, depending on which sidecar you pick | Read-heavy discovery plus limited lifecycle |
| Single-process blast radius | Real: one crash takes UI, queue, and agent surface down together | Isolated: the sidecar can die without touching the panel (and vice versa) | Same-process risk, smaller tool surface to abuse |
The rest of this post earns that table: what Nixploy concretely built, what co-location buys, what it inherits, and whether "MCP endpoint in the box" is where every self-hosted PaaS converges once agents become deploy operators rather than chat toys.
What Nixploy actually built
Nixploy is a self-hosted PaaS in the Dokploy/Coolify class: it turns a Docker host into a deployment platform with git deploys, Traefik TLS, managed databases with backups, and one-click templates. Architecturally it is one Node process — a Next.js 16 App Router app with a custom server.ts that hosts the UI, tRPC routers, a REST/OpenAPI adapter, WebSocket streams, an in-memory deploy queue, and node-schedule crons. It drives a single-node Docker Swarm (remote servers join over SSH) and writes Traefik v3 file-provider YAML for routing and TLS.
The MCP server lives in that same process at POST /api/mcp, speaking Streamable HTTP in stateless mode: no server-side sessions, plain JSON responses, every request standalone. Authentication is an API key over Authorization: Bearer or x-api-key, and the effective permission set is the key's scope intersected with the owning user's capabilities — read for an observer agent, deploy for one that ships, write only when it must change configuration.
The important design decision is where tool calls go. Every one of the 42 tools is dispatched through appRouter.createCaller into the same tRPC routers the panel, REST API, and CLI use. The capability check happens in the router, not in the tool: without domains.manage, the remove_domain tool answers FORBIDDEN and nothing changes.
API-key verification, rate limiting, ban checks, and org resolution are shared with the REST adapter through a single module. The HTTP route file is, in the project's own words, only the adapter — tool definitions and transport live in a unit-tested package with no Next.js dependency.
Three details show this was designed for agents rather than demoed at them. First, every tool ships hand-declared behavior annotations — readOnlyHint, destructiveHint, idempotentHint — and a test fails the build when a tool ships without an entry. The docs explain why inference from names was rejected: "readOnlyHint: true on something that mutates is how an agent stops production while it believes it is investigating."
Second, four task tools answer in one call what an agent would otherwise write a loop for: deploy_and_wait (queues a build, waits up to 55 seconds, returns the outcome with failing step and log tail), explain_last_failure, get_service_runtime_summary, and get_service_events. Third, the destructive tools are intentionally missing. There is no MCP tool to delete a project, service, database, or backup, and none to restore a backup over live data — verify_backup restores into a throwaway container instead. Remediation proposals surface through list_incidents, but applying one stays a human's click.
What co-location buys
Three concrete wins fall out of serving the agent interface from the same process as the deploy queue. Each is a missing piece of machinery, which is the best kind of architecture win: there is no code to drift, break, or audit.
No second auth boundary. A sidecar MCP server is a second security principal with its own credential lifecycle: it holds a platform API key, re-validates (or doesn't) the agent's identity, and enforces its own authorization model on top of the platform's. Every one of those layers can disagree with the panel's. In Nixploy's design there is exactly one boundary — the API key at the transport — and everything past it is the platform's own router-level capability system. A scoped key that can deploy but not manage domains behaves identically whether the caller is curl, the CLI, or Claude Desktop, because all three arrive at the same procedure. The audit log sees one actor type, not two.
No sync protocol between dashboard state and agent-visible state. A sidecar's view of the world is only as fresh as its polling loop and only as complete as the REST endpoints it wraps. When the platform revs an endpoint, the sidecar's generated tools drift until someone regenerates them — one Dokploy sidecar generates 400+ tools straight from the OpenAPI spec, which makes it complete on day one and a version-skew liability on every day after. In-process dispatch cannot drift by construction: the agent's get_service_runtime_summary and the dashboard's status page read through the same procedures, so "the agent sees X but the panel shows Y" is not a failure mode that exists.
Agent-native ergonomics a thin REST wrapper can't offer. This is the subtlest win and the one that most justifies platform ownership of the surface. deploy_and_wait encodes the platform's own knowledge of how long a deploy step takes and what an outcome looks like; get_domain_diagnosis returns not just the 502 but the fix, checking DNS, route file, upstream task, and certificate in one call. Environment reads are redaction-aware (secrets.read or you get redacted: true and no keys). Investigation prompts like troubleshoot_service explicitly instruct the agent not to deploy, restart, stop, or roll back while investigating — and prompts grant nothing, since everything they suggest still funnels through capability-checked tools. A sidecar author can imitate any one of these, but only the platform can guarantee them against its own internals changing.
What it inherits
Co-location is not free. Sharing the dashboard's memory means sharing the dashboard's failure modes, and four of them deserve honest treatment.
One process crash takes everything down together. The UI, the tRPC routers, the REST adapter, the WebSocket streams, the in-memory deploy queue, the cron scheduler, and now the agent surface are one Node process. A fatal error, an OOM kill, or a bad deploy of the panel itself silences the agent operator at the exact moment — an incident — when you most want a second operator awake. The project does ship boot recovery and a claim loop, so a restart reclaims unfinished work rather than losing it silently, but in-flight deploys are still interrupted and the agent's view goes dark along with the dashboard's. The sidecar architecture's one genuine advantage is this row: the bridge can die without touching the panel, and the panel can restart without blinding the agent.
Deploy tools are non-idempotent, so retries are not free. The annotations say it plainly: idempotentHint: false on the deploy tools, because calling one twice queues two builds. An agent that times out waiting and retries — the default behavior of most agent frameworks — just doubled the build load and possibly rolled the service twice. deploy_and_wait mitigates this with explicit resume semantics (call it again with the same deploymentId rather than deploying again), but mitigation is not elimination: every MCP client that wraps tool calls in automatic retries needs to know this surface punishes that pattern.
Concurrent edits can lose. set_env is read-merge-write against a single .env blob per scope, so a dashboard edit landing between the agent's read and write is silently overwritten. Values take effect only on the next deploy or reload, which at least bounds the blast radius to the next rollout — but a platform courting agent operators should expect concurrent human-and-agent edits as the normal case, not the edge case, and read-merge-write without versioning is the weakest correct answer.
The agent holds a static, deploy-capable API key. This is the row where 2026 security best practice pushes back hardest. The June 2025 MCP spec revision's direction is unambiguous — short-lived scoped tokens, OAuth 2.1, the MCP server validating tokens rather than issuing them, destructive tools behind confirmation or dry-run — and a static key that can deploy, stop services, and rewrite environment variables is a wide blast radius to hand an autonomous loop. Nixploy's scoping (narrowest scope that lets the job run, capability intersection, redaction without secrets.read) is the right mitigation within the static-key model, and withholding delete/restore tools shrinks the worst case from "agent wiped production" to "agent stopped production." But teams running agents against this surface should still treat the key like a credential with hands: short rotation, minimal scope, and an audit-log review habit.
Is "MCP in the box" where every self-hosted PaaS converges?
The evidence points to yes, with one honest exception. Coolify v4 shipped a native MCP server at /mcp over Streamable HTTP — read-heavy resource discovery plus limited lifecycle when the token carries deploy — which means two independent Dokploy-class platforms have now concluded the agent interface belongs inside the box, behind the platform's own auth. The Dokploy side of the market shows what happens without that conclusion: three community MCP servers with mutually incompatible philosophies (27 hand-curated tools with action enums, 98 tools covering the API, 400–500+ tools generated from OpenAPI, or 4 gateway tools to save context), none canonical, each tracking Dokploy's API by hand. Fragmentation is the tax a platform pays for not blessing a surface.
The exception is the platform that won't bless one — and there the sidecar survives indefinitely. A generated-tools sidecar will always exist for APIs whose owners have other priorities, and gateway-style sidecars that compress 500 endpoints into a handful of context-cheap tools solve a real context-window problem that in-process servers mostly ignore. Convergence is about the default, not the monopoly: the default agent interface for a self-hosted PaaS is becoming a first-party endpoint, with sidecars as the adapter layer for everything else.
Whichever architecture you operate, demand the same five properties before handing an agent deploy authority. They are Nixploy's checklist generalized, and any platform can be graded against them:
- One auth boundary. The agent's permissions should be enforced by the same code that enforces the dashboard's — capability checks in the router, not re-implemented in the tool layer.
- Honest annotations. Every mutating tool needs accurate read/destructive/idempotent hints, verified by test, not inferred from names. An agent that believes it is investigating must never be able to stop production.
- Wait-semantics task tools. Long operations need one-call outcome tools with explicit resume tokens, because agents retry and retries on non-idempotent deploys queue double builds.
- An audit log that sees the agent. "The model called a tool" is not an incident report. Tool calls need actor, capability decision, and outcome in the same log the dashboard writes.
- Destructive tools gated or absent. Delete-project, delete-database, and restore-over-live have no business in an unattended agent surface. Missing tools are a feature; document them as one.
Nixploy's bet is that agents stop being chat toys the day they can ship, and shipping deserves a first-class interface, not a screen-scrape of the REST API. One Node process, one auth boundary, one audit log, and a tool surface the platform owns end to end. The single-process blast radius is real, the static keys want rotation discipline, and the deploy tools punish naive retries — but those are operational problems with operational answers. State drift between what the agent sees and what the dashboard shows has no operational answer at all, only an architectural one. That is the row that decides it, and it decides for in the box.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with agents as first-class operators. Star the repo on GitHub or deploy your first app today.



