Agents on CapRover,read-only first.

better-caprover-mcp is an unofficial MCP server that lets Claude, Cursor and Codex deploy and manage apps on a self-hosted CapRover. It starts read-only: write tools aren't registered until you raise the mode, and deletes need a single-use token.

Star on GitHub

MITnpm: better-caprover-mcpDocker on ghcr.io

CAPROVER_MCP_MODE7 of 14 tools registered

Read 7

  • get_overview
  • list_apps
  • get_app
  • get_app_runtime
  • get_app_logs
  • get_build_logs
  • list_one_click_apps

Change apps 6

  • create_app
  • deploy_image
  • set_env_vars
  • scale_app
  • add_custom_domain
  • enable_ssl

Destructive 1

  • delete_app
tools/list → 7 tools

Write tools aren't registered. The model can't call what it never sees.

Guardrails in code,
not in the prompt.

A CapRover password is full access. Asking the model to be careful is a hope. Here the server enforces it before anything reaches CapRover.

Read-only by default

Write tools aren't registered until you start the server in another mode. The mode is an env var and changes only on restart, so the agent can't promote itself.

CAPROVER_MCP_MODE

Preview before you commit

Any change accepts a dry run. You get what would happen, and no write call goes to CapRover.

dry_run

Deleting needs a token

delete_app first returns a preview and a single-use token. It lasts 5 minutes and is tied to that exact call.

delete_app

Secrets stay out

Env var values are never returned, only whether they're set. The password is masked in logs and errors, and log lines show [REDACTED].

isSet · [REDACTED]

Deleting takes two calls and a yes.

The first delete_app call deletes nothing. The agent has to bring you the preview, get your answer, and call again with the token.

  • Single use. A spent token can't be replayed.
  • Five minutes. Then it expires.
  • Bound to the call. A token from another call is refused.
illustrative
youDelete the app staging-old.
agent→ delete_app staging-old
serverPreview only. This would remove staging-old. Nothing was deleted.
token · single use · 5 min
agentThis removes staging-old. Do you confirm?
youYes.
agent→ delete_app staging-old · user_confirmed · token
serverDeleted. The token is spent.
agent→ delete_app · same token again
serverRefused. Used, expired or issued for another call.

Fourteen operations, and no “send any request”.

There is no raw-request tool, on purpose. Each operation has its own schema and risk level, and the mode decides which ones exist.

Read 7

registered from readonly

  • get_overview

    CapRover version, root domain, app count, and what this server can do.

    Available from readonly
  • list_apps

    Every app on the server.

    Available from readonly
  • get_app

    Details for one app.

    Available from readonly
  • get_app_runtime

    Live state of an app. Needs a CapRover version with that endpoint; 1.15.5 doesn't have it.

    Available from readonly
  • get_app_logs

    Last lines of the running app. Secrets come back as [REDACTED].

    Available from readonly
  • get_build_logs

    Last lines of the latest build, with the same redaction.

    Available from readonly
  • list_one_click_apps

    The one-click templates you can install.

    Available from readonly

Change apps 6

registered from operate

  • create_app

    Create an empty app.

    Available from operate
  • deploy_image

    Deploy a Docker image, in the background.

    Available from operate
  • set_env_vars

    Set and remove variables from KEY=value lines. The rest are kept.

    Available from operate
  • scale_app

    Set the instance count. 0 stops the app.

    Available from operate
  • add_custom_domain

    Attach a custom domain to an app.

    Available from operate
  • enable_ssl

    Turn on HTTPS for a domain.

    Available from operate

Destructive 1

registered in admin only

  • delete_app

    Remove an app, and its volumes only if you ask. Needs a confirmation token.

    Available from admin

Critical operations need one more switch: CAPROVER_MCP_ALLOW_CRITICAL=1 in admin mode. None of the 14 is classified as critical yet.

One command, then ask.

Start in readonly. Ask which apps run a latest tag. Raise the mode when you need writes.

claude mcp add caprover \
  -e CAPROVER_URL=https://captain.your-domain.com \
  -e CAPROVER_PASSWORD=your-password \
  -- npx -y better-caprover-mcp
Configuration
VariableDefaultWhat it does
CAPROVER_URLnoneCapRover address with http:// or https://. Only the origin is used.
CAPROVER_PASSWORDnoneThe CapRover password.
CAPROVER_MCP_MODEreadonlyreadonly, operate or admin. Changes only when the server restarts.
CAPROVER_MCP_ALLOW_CRITICALoffSet to 1 to unlock critical operations in admin mode.

Every call takes the same road. Nothing skips a step.

  1. 01

    Mode

    Is this operation registered in the current mode?

  2. 02

    Schema

    Arguments are validated against the operation's schema.

  3. 03

    Preview

    A dry run, or a confirmation token for deletes.

  4. 04

    CapRover

    One adapter makes the API call.

  5. 05

    Redaction

    Secrets are masked before the answer leaves.

Private by construction

The only network traffic goes to your CAPROVER_URL. There is no telemetry.

The server doesn't run commands on your machine or read files. It only reads environment variables.

Built to be read

TypeScript on Node. One class per operation, each with its schema, risk level and description, and a single manifest feeds every interface and the policy.

The official caprover-api SDK is experimental, so only one adapter imports it. Integration tests run against a real, disposable CapRover.

Questions worth asking first.

Is this the official CapRover MCP?

No. It's unofficial and has no affiliation with CapRover.

Can the agent give itself more permissions?

No. The mode comes from an env var read when the server starts. Changing it means restarting the server, and the agent has no tool for that.

Why is there no “send any request” tool?

A raw request would walk around the mode, preview and redaction layers. The project records this decision as ADR 0003.

Does it work with two-factor auth?

Not yet. Servers with two-factor authentication aren't supported (ADR 0010).

Why does get_app_runtime fail on my server?

It needs a CapRover version that exposes that endpoint. CapRover 1.15.5 doesn't have it.

What's coming next?

The roadmap has four open issues: #3 the remaining SDK methods, #4 diagnose_app and find_issues, #5 a Code Mode with search and execute, and #6 remote HTTP with several CapRover servers.

Start
read-only.

Raise the mode when you trust it. The install is one command.

Star on GitHub