Skip to content

Plinth

by tryplinth.dev · remote · no sign-in to list tools · v1.0.0 · published by dev.tryplinth

App hosting your agent runs: git, deploys, staging/production, Postgres. Owner approves risky steps.

Deletes · 7Final · 5Changes · 342 high findings

72 tools: 7 can delete or cancel things, 5 do something that can't be undone, 34 change things and 26 only read.

Scanned Oct 21, 2026

2 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http plinth https://tryplinth.dev/mcp

Findings

Matches of fixed checks, with the text they matched.

2 high

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

72 tools

Deletes or cancels 7Claude Code: deny
  • agents.revokeOwner only.No findings

    Why it is in this group

    • The name "agents.revoke" says "revoke": a word for removing or ending something.
    Description, as the server wrote it
    Owner only. Remove an agent's access to this account immediately.
  • approval.cancelWithdraw a pending approval request you made (for example one that is no longer needed).No findings

    Why it is in this group

    • The name "approval.cancel" says "cancel": a word for removing or ending something.
    Description, as the server wrote it
    Withdraw a pending approval request you made (for example one that is no longer needed). The owner can no longer approve it.
  • cron.removeDelete a cron job.No findings

    Why it is in this group

    • The name "cron.remove" says "remove": a word for removing or ending something.
    Description, as the server wrote it
    Delete a cron job.
  • domains.removeUnmap a domain.No findings

    Why it is in this group

    • The name "domains.remove" says "remove": a word for removing or ending something.
    Description, as the server wrote it
    Unmap a domain.
  • env.secrets.unsetRemove an environment variable.No findings

    Why it is in this group

    • The description's first verb is "remove": a word for removing or ending something.
    Description, as the server wrote it
    Remove an environment variable.
  • project.deleteDelete a project, its repo, environments and databases.No findings

    Why it is in this group

    • The name "project.delete" says "delete": a word for removing or ending something.
    • The description says "Irreversible".
    Description, as the server wrote it
    Delete a project, its repo, environments and databases. Irreversible. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • webhooks.removeDelete a webhook.No findings

    Why it is in this group

    • The name "webhooks.remove" says "remove": a word for removing or ending something.
    Description, as the server wrote it
    Delete a webhook.
Can't be undone 5Claude Code: ask
  • http.probeSend one HTTP request to the environment from inside Plinth and return status, headers, timing and the first 8 KB of the body.No findings

    Why it is in this group

    • The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
    Description, as the server wrote it
    Send one HTTP request to the environment from inside Plinth and return status, headers, timing and the first 8 KB of the body. Use it to reproduce a failing route.
  • promotePromote the release running on one environment to another (default staging to production).No findings

    Why it is in this group

    • The input addresses people (input.to): what it sends cannot be taken back.
    Description, as the server wrote it
    Promote the release running on one environment to another (default staging to production). Applies pending migrations first. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • support.sendSend the Plinth team a bug report, feature request or question.No findings

    Why it is in this group

    • The name "support.send" says "send": a word for sending, and what is sent cannot be taken back.
    Description, as the server wrote it
    Send the Plinth team a bug report, feature request or question. Include what you tried and what happened. Recent errors for the project are attached automatically. Replies show up in support.list.
  • webhooks.addSend Plinth events to a URL (your bot, Slack, Discord, Telegram, Zapier...).No findings

    Why it is in this group

    • The name "webhooks.add" says "add": a word for a change.
    • The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
    Description, as the server wrote it
    Send Plinth events to a URL (your bot, Slack, Discord, Telegram, Zapier...). Events: deploy.succeeded, deploy.failed, approval.requested, approval.decided, app.down, app.up, support.created, support.replied, charge.succeeded, signup.approved. Leave events empty for all. Payloads are JSON with a "text" summary and an x-plinth-signature HMAC header; Slack/Discord webhook URLs and Telegram sendMessage URLs work as-is.
  • webhooks.testSend a test event to all your webhooks; check webhooks.list a few seconds later for the result.No findings

    Why it is in this group

    • The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
    Description, as the server wrote it
    Send a test event to all your webhooks; check webhooks.list a few seconds later for the result.
Changes things 34Claude Code: ask
  • account.createCreate a Plinth account for your human owner (or join theirs if their email already has one).No findings

    Why it is in this group

    • The name "account.create" says "create": a word for a change.
    Description, as the server wrote it
    Create a Plinth account for your human owner (or join theirs if their email already has one). Plinth emails them a link to approve; then call account.status with the returned signup_id and poll to collect your token.
  • billing.cardAsk the owner to add or replace the payment card.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Ask the owner to add or replace the payment card. Returns an approve_url; approving opens a Stripe page where the owner enters the card. Plinth never sees card numbers. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • code.writeCommit files to the project without git: for agents that cannot run git or the CLI (e.g.No findings

    Why it is in this group

    • The name "code.write" says "write": a word for a change.
    Description, as the server wrote it
    Commit files to the project without git: for agents that cannot run git or the CLI (e.g. Claude or ChatGPT in the cloud). Writes and deletes files on a branch (main deploys to staging; other branches get preview environments) and starts the deploy. Send whole files; text as utf8, binary as base64. Up to 5 MB per file.
  • cron.addSchedule a job: Plinth POSTs to path on the environment at each tick (5-field cron, UTC), with the header x-plinth-cron-secret.No findings

    Why it is in this group

    • The name "cron.add" says "add": a word for a change.
    Description, as the server wrote it
    Schedule a job: Plinth POSTs to path on the environment at each tick (5-field cron, UTC), with the header x-plinth-cron-secret. Paths under /api/cron/ refuse any other caller. Outside production jobs start paused unless enabled is true. Jobs can also be declared in plinth.json "crons".
  • cron.pausePause a cron job (it stays defined but does not run).No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Pause a cron job (it stays defined but does not run).
  • cron.resumeResume a paused cron job.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Resume a paused cron job.
  • cron.runRun a cron job now and return its result.No findings

    Why it is in this group

    • The name "cron.run" says "run": a word for a change.
    Description, as the server wrote it
    Run a cron job now and return its result.
  • cron.runsRecent runs of a cron job.No findings

    Why it is in this group

    • The name "cron.runs" says "run": a word for a change.
    Description, as the server wrote it
    Recent runs of a cron job.
  • db.migrateApply pending migrations from the live release now (deploys do this automatically).No findings

    Why it is in this group

    • The description's first verb is "apply": a word for a change.
    Description, as the server wrote it
    Apply pending migrations from the live release now (deploys do this automatically). Takes a snapshot first. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • db.migrationsApplied and pending migrations (files in migrations/*.sql, applied in name order).No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Applied and pending migrations (files in migrations/*.sql, applied in name order).
  • db.queryRun SQL against an environment database.No findings

    Why it is in this group

    • The name "db.query" says "query": a word for reading.
    • The description's first verb is "run": a word for a change.
    • The input takes a statement or command to run (input.sql), which can change anything it can reach.
    Description, as the server wrote it
    Run SQL against an environment database. Returns up to 500 rows. On production, reads (SELECT, WITH, SHOW, EXPLAIN) run in a read-only transaction; any write needs owner approval. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • db.restoreRestore an environment database from a snapshot.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Restore an environment database from a snapshot. Takes a safety snapshot first. Production needs owner approval. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • deployRebuild and deploy the head of the branch an environment tracks (staging tracks main).No findings

    Why it is in this group

    • The name "deploy" says "deploy": a word for a change.
    Description, as the server wrote it
    Rebuild and deploy the head of the branch an environment tracks (staging tracks main). Production only changes via promote.
  • deploy.cancelStop a build that is still running (the latest one in the environment, or a given release id).No findings

    Why it is in this group

    • The name "deploy.cancel" says "deploy": a word for a change.
    Description, as the server wrote it
    Stop a build that is still running (the latest one in the environment, or a given release id). The live release keeps serving.
  • deploy.statusReleases for an environment, newest first, with status and build log of the latest.No findings

    Why it is in this group

    • The name "deploy.status" says "deploy": a word for a change.
    Description, as the server wrote it
    Releases for an environment, newest first, with status and build log of the latest. Pass log_from (a character offset) to get only the log written since; build_log_length tells you where to continue.
  • domains.buyBuy a domain and connect it to an environment: registers it, points DNS at Plinth, issues HTTPS.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Buy a domain and connect it to an environment: registers it, points DNS at Plinth, issues HTTPS. Always shows the owner the exact price first. Standard registrations only. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • domains.connectMap a domain you own to an environment.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Map a domain you own to an environment. Point its DNS at the Plinth host; returns the record to create.
  • domains.ordersDomains bought through Plinth on this account, with price, status and expiry.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Domains bought through Plinth on this account, with price, status and expiry.
  • domains.verifyCheck the TXT record of a connected domain; once it matches, the domain is served.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Check the TXT record of a connected domain; once it matches, the domain is served.
  • env.execProduction needs owner approval.No findings

    Why it is in this group

    • The name "env.exec" says "exec": a word for a change.
    • The input takes a statement or command to run (input.command), which can change anything it can reach.
    Description, as the server wrote it
    Production needs owner approval. Run a shell command inside the environment's running sandbox (same code, env vars, network and limits as the app), e.g. "node -e '...'", "ls", "env | sort". 30s timeout, 20 KB of output. Code is read-only; /tmp is writable. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • env.restartRestart an environment on its current release (fresh sandbox, same code and data).No findings

    Why it is in this group

    • The name "env.restart" says "restart": a word for a change.
    Description, as the server wrote it
    Restart an environment on its current release (fresh sandbox, same code and data).
  • env.secrets.importSet many environment variables at once from .env text (KEY=value lines; # comments, quotes and "export" are fine).2 findings

    Why it is in this group

    • The name "env.secrets.import" says "import": a word for a change.

    Findings

    • High

      The description refers to ".env".

      Matched text

      description: "...many environment variables at once from .env text (KEY=value lines; # comments, quot..."

      What this check looks for
    • High

      The input schema at properties.dotenv.description refers to ".env".

      Matched text

      inputSchema.properties.dotenv.description: "Contents of a .env file"

      What this check looks for
    Description, as the server wrote it
    Set many environment variables at once from .env text (KEY=value lines; # comments, quotes and "export" are fine). One restart at the end. Keys starting with VITE_/NEXT_PUBLIC_/PUBLIC_ also reach the build.
  • env.secrets.setSet an environment variable for an environment.No findings

    Why it is in this group

    • The name "env.secrets.set" says "set": a word for a change.
    Description, as the server wrote it
    Set an environment variable for an environment. Restarts the env so it takes effect.
  • git.branchesBranches and their head commits.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Branches and their head commits.
  • git.revertRevert a commit on a branch server-side.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Revert a commit on a branch server-side. The new commit deploys like a push.
  • metrics.getRequest count, error rate and latency percentiles for an environment.No findings

    Why it is in this group

    • The name "metrics.get" says "get": a word for reading.
    • The description's first verb is "request": a word for a change.
    Description, as the server wrote it
    Request count, error rate and latency percentiles for an environment.
  • policy.setOwner only.No findings

    Why it is in this group

    • The name "policy.set" says "set": a word for a change.
    Description, as the server wrote it
    Owner only. Choose which approval types run without asking. Keys: project.create, project.delete, promote.production, migration.destructive, db.restore.production, billing.
  • project.createCreate a project: a git repo plus production and staging environments, each with its own Postgres database.No findings

    Why it is in this group

    • The name "project.create" says "create": a word for a change.
    Description, as the server wrote it
    Create a project: a git repo plus production and staging environments, each with its own Postgres database. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • project.downgradeMove a project back to the free plan.No findings

    Why it is in this group

    • The description's first verb is "move": a word for a change.
    Description, as the server wrote it
    Move a project back to the free plan. Its custom domains stop being served. The subscription shrinks with a prorated credit.
  • project.upgradeMove a project to Pro ($19/month per project): own domains and more room.No findings

    Why it is in this group

    • The description's first verb is "move": a word for a change.
    Description, as the server wrote it
    Move a project to Pro ($19/month per project): own domains and more room. Charges the owner's card now (prorated) after they approve. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • requests.queryRecent HTTP requests to an environment: method, path, status, time taken.No findings

    Why it is in this group

    • The name "requests.query" says "request": a word for a change.
    Description, as the server wrote it
    Recent HTTP requests to an environment: method, path, status, time taken. Filter to failures with min_status 500, or by path.
  • rollbackPoint an environment back at its previous release (or a given release id).No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Point an environment back at its previous release (or a given release id). Does not roll back the database.
  • seo.setupCheck how search engines see an environment (title, description, robots.txt, sitemap, noindex) and get the steps to connect OpenSEO (openseo.so), an open-source SEO tool your agent…No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Check how search engines see an environment (title, description, robots.txt, sitemap, noindex) and get the steps to connect OpenSEO (openseo.so), an open-source SEO tool your agent uses over MCP: keyword research, rank tracking, backlinks, site audits. The owner signs up on OpenSEO; Plinth does not share any data with it.
  • token.rotateReplace your own agent token with a new one; the old one stops working immediately.No findings

    Why it is in this group

    • The description's first verb is "replace": a word for a change.
    Description, as the server wrote it
    Replace your own agent token with a new one; the old one stops working immediately. Save the new token in ~/.plinth/config.json (the CLI does this for you).
Only reads 26Claude Code: allow
  • account.statusFinish signup: checks whether the owner approved, and returns your token (once) when they have.No findings

    Why it is in this group

    • The name "account.status" says "status": a word for reading.
    Description, as the server wrote it
    Finish signup: checks whether the owner approved, and returns your token (once) when they have.
  • agents.listAgents that have a key to this account, when each was last used, and which one you are.No findings

    Why it is in this group

    • The name "agents.list" says "list": a word for reading.
    Description, as the server wrote it
    Agents that have a key to this account, when each was last used, and which one you are.
  • analytics.getVisitors and page views per day, top pages, where visitors come from, and phone vs desktop.No findings

    Why it is in this group

    • The name "analytics.get" says "get": a word for reading.
    Description, as the server wrote it
    Visitors and page views per day, top pages, where visitors come from, and phone vs desktop. No cookies; visitors are counted per day. Free shows today; Pro up to 90 days.
  • approval.statusCheck an approval.No findings

    Why it is in this group

    • The name "approval.status" says "status": a word for reading.
    Description, as the server wrote it
    Check an approval. When approved, result holds the action output.
  • approvals.listApprovals requested by this account, newest first.No findings

    Why it is in this group

    • The name "approvals.list" says "list": a word for reading.
    Description, as the server wrote it
    Approvals requested by this account, newest first. status: pending, approved, denied, cancelled, superseded (default all). Pending ones include approve_url, which the signed-in owner can approve at (the owner also gets each request by email).
  • billing.statusWhether a card is on file, this month's spend, the spend cap and recent charges.No findings

    Why it is in this group

    • The name "billing.status" says "status": a word for reading.
    Description, as the server wrote it
    Whether a card is on file, this month's spend, the spend cap and recent charges.
  • code.listList files in the project repo (path and size) on a branch or commit.No findings

    Why it is in this group

    • The name "code.list" says "list": a word for reading.
    Description, as the server wrote it
    List files in the project repo (path and size) on a branch or commit.
  • code.readRead one file from the project repo.No findings

    Why it is in this group

    • The name "code.read" says "read": a word for reading.
    Description, as the server wrote it
    Read one file from the project repo. Text comes back as utf8; binary files as base64.
  • console.signinGet the owner into the web console.No findings

    Why it is in this group

    • The description's first verb is "get": a word for reading.
    Description, as the server wrote it
    Get the owner into the web console. Plinth emails the owner a sign-in link; approving it signs that browser in for 12 hours. The agent never receives a session. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • cron.listCron jobs on an environment with last run and next run.No findings

    Why it is in this group

    • The name "cron.list" says "list": a word for reading.
    Description, as the server wrote it
    Cron jobs on an environment with last run and next run.
  • db.connectionGet the DATABASE_URL for an environment (the same one the app receives).No findings

    Why it is in this group

    • The description's first verb is "get": a word for reading.
    Description, as the server wrote it
    Get the DATABASE_URL for an environment (the same one the app receives). Production needs owner approval. May return pending_approval: the owner is emailed a link to approve; tell them it is waiting, then poll approval.status.
  • db.snapshotTake a snapshot (pg_dump) of an environment database.No findings

    Why it is in this group

    • The name "db.snapshot" says "snapshot": a word for reading.
    Description, as the server wrote it
    Take a snapshot (pg_dump) of an environment database.
  • db.snapshotsList snapshots for an environment.No findings

    Why it is in this group

    • The name "db.snapshots" says "snapshot": a word for reading.
    Description, as the server wrote it
    List snapshots for an environment. Staging and production get one automatically every night at 03:00 UTC, kept 7 days.
  • domains.listDomains mapped to a project.No findings

    Why it is in this group

    • The name "domains.list" says "list": a word for reading.
    Description, as the server wrote it
    Domains mapped to a project.
  • domains.searchCheck if domains can be bought here, with price.No findings

    Why it is in this group

    • The name "domains.search" says "search": a word for reading.
    Description, as the server wrote it
    Check if domains can be bought here, with price. Pass a name ("acme" checks acme.com, .dev, .app, .io, .co, .net, .ai, .org) or a full domain.
  • env.listEnvironments for a project with live release and URL.No findings

    Why it is in this group

    • The name "env.list" says "list": a word for reading.
    Description, as the server wrote it
    Environments for a project with live release and URL.
  • env.secrets.listList environment variable names (values are never returned).No findings

    Why it is in this group

    • The name "env.secrets.list" says "list": a word for reading.
    Description, as the server wrote it
    List environment variable names (values are never returned).
  • env.statusDebug an environment: is it running, restarts, out-of-memory kills, memory/CPU use, live release, and the last errors from its logs.No findings

    Why it is in this group

    • The name "env.status" says "status": a word for reading.
    Description, as the server wrote it
    Debug an environment: is it running, restarts, out-of-memory kills, memory/CPU use, live release, and the last errors from its logs.
  • git.logRecent commits on a branch.No findings

    Why it is in this group

    • The name "git.log" says "log": a word for reading.
    Description, as the server wrote it
    Recent commits on a branch.
  • git.remoteGet the authenticated git remote URL for pushing.No findings

    Why it is in this group

    • The description's first verb is "get": a word for reading.
    Description, as the server wrote it
    Get the authenticated git remote URL for pushing. Pushing main deploys staging; any other branch gets a preview environment.
  • logs.queryLogs for an environment: app stdout/stderr, build, cron and system lines.No findings

    Why it is in this group

    • The name "logs.query" says "log": a word for reading.
    Description, as the server wrote it
    Logs for an environment: app stdout/stderr, build, cron and system lines. Filter by text and stream.
  • project.getShow one project: git remote, environments, live release per environment, URLs.No findings

    Why it is in this group

    • The name "project.get" says "get": a word for reading.
    Description, as the server wrote it
    Show one project: git remote, environments, live release per environment, URLs.
  • project.listList projects with their environments, live releases and URLs.No findings

    Why it is in this group

    • The name "project.list" says "list": a word for reading.
    Description, as the server wrote it
    List projects with their environments, live releases and URLs.
  • support.listYour support tickets with their status and the team's reply.No findings

    Why it is in this group

    • The name "support.list" says "list": a word for reading.
    Description, as the server wrote it
    Your support tickets with their status and the team's reply.
  • webhooks.listYour webhooks with their last delivery status.No findings

    Why it is in this group

    • The name "webhooks.list" says "list": a word for reading.
    Description, as the server wrote it
    Your webhooks with their last delivery status.
  • whoamiShow the account this token belongs to, its policy and projects.No findings

    Why it is in this group

    • The name "whoami" says "whoami": a word for reading.
    Description, as the server wrote it
    Show the account this token belongs to, its policy and projects.

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 1.0.0. Values in angle brackets are yours to fill in.

claude mcp add --transport http plinth https://tryplinth.dev/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__plinth__account_status",
      "mcp__plinth__whoami",
      "mcp__plinth__project_list",
      "mcp__plinth__project_get",
      "mcp__plinth__code_list",
      "mcp__plinth__code_read",
      "mcp__plinth__git_remote",
      "mcp__plinth__git_log",
      "mcp__plinth__env_list",
      "mcp__plinth__env_secrets_list",
      "mcp__plinth__db_snapshot",
      "mcp__plinth__db_snapshots",
      "mcp__plinth__db_connection",
      "mcp__plinth__cron_list",
      "mcp__plinth__domains_list",
      "mcp__plinth__billing_status",
      "mcp__plinth__domains_search",
      "mcp__plinth__logs_query",
      "mcp__plinth__analytics_get",
      "mcp__plinth__env_status",
      "mcp__plinth__approvals_list",
      "mcp__plinth__approval_status",
      "mcp__plinth__support_list",
      "mcp__plinth__webhooks_list",
      "mcp__plinth__console_signin",
      "mcp__plinth__agents_list"
    ],
    "ask": [
      "mcp__plinth__account_create",
      "mcp__plinth__project_create",
      "mcp__plinth__code_write",
      "mcp__plinth__git_branches",
      "mcp__plinth__git_revert",
      "mcp__plinth__env_secrets_set",
      "mcp__plinth__env_secrets_import",
      "mcp__plinth__deploy",
      "mcp__plinth__deploy_status",
      "mcp__plinth__deploy_cancel",
      "mcp__plinth__promote",
      "mcp__plinth__rollback",
      "mcp__plinth__db_query",
      "mcp__plinth__db_migrations",
      "mcp__plinth__db_migrate",
      "mcp__plinth__db_restore",
      "mcp__plinth__cron_add",
      "mcp__plinth__cron_pause",
      "mcp__plinth__cron_resume",
      "mcp__plinth__cron_run",
      "mcp__plinth__cron_runs",
      "mcp__plinth__domains_connect",
      "mcp__plinth__domains_verify",
      "mcp__plinth__project_upgrade",
      "mcp__plinth__project_downgrade",
      "mcp__plinth__billing_card",
      "mcp__plinth__domains_buy",
      "mcp__plinth__domains_orders",
      "mcp__plinth__metrics_get",
      "mcp__plinth__seo_setup",
      "mcp__plinth__env_restart",
      "mcp__plinth__env_exec",
      "mcp__plinth__http_probe",
      "mcp__plinth__requests_query",
      "mcp__plinth__support_send",
      "mcp__plinth__webhooks_add",
      "mcp__plinth__webhooks_test",
      "mcp__plinth__token_rotate",
      "mcp__plinth__policy_set"
    ],
    "deny": [
      "mcp__plinth__project_delete",
      "mcp__plinth__env_secrets_unset",
      "mcp__plinth__cron_remove",
      "mcp__plinth__domains_remove",
      "mcp__plinth__approval_cancel",
      "mcp__plinth__webhooks_remove",
      "mcp__plinth__agents_revoke"
    ]
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as plinth. Review it before you use it.