Plinth

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

Should I use this

Quality & Safety

B
Description quality
92%
Schema completeness
85%
Naming quality
52%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Findings (78)

  • LOWTool 'git.log' description lacks action verbin git.log
  • LOWTool 'git.branches' description lacks action verbin git.branches
  • LOWTool 'git.revert' description lacks action verbin git.revert
  • LOWTool 'env.list' description lacks action verbin env.list
  • LOWTool 'db.migrations' description lacks action verbin db.migrations
  • LOWTool 'db.snapshot' description lacks action verbin db.snapshot
  • LOWTool 'domains.list' description lacks action verbin domains.list
  • LOWTool 'domains.remove' description lacks action verbin domains.remove
  • LOWTool 'billing.status' description lacks action verbin billing.status
  • LOWTool 'support.list' description lacks action verbin support.list

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~6,318Tokens (tool definitions)
~582 BTypical response size
Significant attention impact (4.94% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "plinth": {
      "url": "https://tryplinth.dev/mcp"
    }
  }
}

Remote endpoints

https://tryplinth.dev/mcpstreamable-http

What it can do

Tool inventory

Tools (72)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟡account.create(email, agent, project)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "email": {
      "type": "string",
      "description": "Owner email"
    },
    "agent": {
      "type": "string",
      "description": "Your name, e.g. Claude"
    },
    "project": {
      "type": "string",
      "description": "Optional first project name"
    }
  },
  "required": [
    "email"
  ]
}
⚪account.status(signup_id, poll)

Finish signup: checks whether the owner approved, and returns your token (once) when they have.

Input Schema

{
  "type": "object",
  "properties": {
    "signup_id": {
      "type": "string",
      "description": "From account.create"
    },
    "poll": {
      "type": "string",
      "description": "From account.create"
    }
  },
  "required": [
    "signup_id",
    "poll"
  ]
}
🟢whoami

Show the account this token belongs to, its policy and projects.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🟡project.create(name)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Lowercase name, 3-40 chars, e.g. acme-crm"
    }
  },
  "required": [
    "name"
  ]
}
🟢project.list

List projects with their environments, live releases and URLs.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🟢project.get(project)

Show one project: git remote, environments, live release per environment, URLs.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
🔴project.delete(project)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
🟡code.write(project, branch, message, files, delete)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "branch": {
      "type": "string",
      "description": "Default main"
    },
    "message": {
      "type": "string",
      "description": "Commit message"
    },
    "files": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "encoding": {
            "type": "string",
            "description": "utf8 (default) or base64"
          }
        },
        "required": [
          "path",
          "content"
        ]
      }
    },
    "delete": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Paths to remove"
    }
  },
  "required": [
    "project"
  ]
}
🟢code.list(project, ref, prefix)

List files in the project repo (path and size) on a branch or commit.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "ref": {
      "type": "string",
      "description": "Branch or commit, default main"
    },
    "prefix": {
      "type": "string",
      "description": "Only files under this folder"
    }
  },
  "required": [
    "project"
  ]
}
🟢code.read(project, path, ref)

Read one file from the project repo. Text comes back as utf8; binary files as base64.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "path": {
      "type": "string"
    },
    "ref": {
      "type": "string",
      "description": "Branch or commit, default main"
    }
  },
  "required": [
    "project",
    "path"
  ]
}
🟢git.remote(project)

Get the authenticated git remote URL for pushing. Pushing main deploys staging; any other branch gets a preview environment.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
⚪git.log(project, branch, limit)

Recent commits on a branch.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "branch": {
      "type": "string",
      "description": "Default main"
    },
    "limit": {
      "type": "number"
    }
  },
  "required": [
    "project"
  ]
}
⚪git.branches(project)

Branches and their head commits.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
⚪git.revert(project, commit, branch)

Revert a commit on a branch server-side. The new commit deploys like a push.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "commit": {
      "type": "string"
    },
    "branch": {
      "type": "string",
      "description": "Default main"
    }
  },
  "required": [
    "project",
    "commit"
  ]
}
⚪env.list(project)

Environments for a project with live release and URL.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
🟡env.secrets.set(project, env, key, value)

Set an environment variable for an environment. Restarts the env so it takes effect.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "key": {
      "type": "string"
    },
    "value": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "key",
    "value"
  ]
}
🟢env.secrets.list(project, env)

List environment variable names (values are never returned).

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
🟡env.secrets.import(project, env, dotenv, replace)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "dotenv": {
      "type": "string",
      "description": "Contents of a .env file"
    },
    "replace": {
      "type": "boolean",
      "description": "Remove variables not in the file (default false)"
    }
  },
  "required": [
    "project",
    "env",
    "dotenv"
  ]
}
🔴env.secrets.unset(project, env, key)

Remove an environment variable.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "key": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "key"
  ]
}
🟡deploy(project, env, commit)

Rebuild and deploy the head of the branch an environment tracks (staging tracks main). Production only changes via promote.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "commit": {
      "type": "string",
      "description": "Optional commit sha; defaults to branch head"
    }
  },
  "required": [
    "project"
  ]
}
🟢deploy.status(project, env, limit, log_from)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "limit": {
      "type": "number"
    },
    "log_from": {
      "type": "number"
    }
  },
  "required": [
    "project"
  ]
}
⚪deploy.cancel(project, env, release)

Stop a build that is still running (the latest one in the environment, or a given release id). The live release keeps serving.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "release": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪promote(project, from, to)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "from": {
      "type": "string",
      "description": "Default staging"
    },
    "to": {
      "type": "string",
      "description": "Default production"
    }
  },
  "required": [
    "project"
  ]
}
⚪rollback(project, env, release)

Point an environment back at its previous release (or a given release id). Does not roll back the database.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "release": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
🟡db.query(project, env, sql, params)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "sql": {
      "type": "string"
    },
    "params": {
      "type": "array",
      "items": {}
    }
  },
  "required": [
    "project",
    "env",
    "sql"
  ]
}
⚪db.migrations(project, env)

Applied and pending migrations (files in migrations/*.sql, applied in name order).

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪db.migrate(project, env)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪db.snapshot(project, env, label)

Take a snapshot (pg_dump) of an environment database.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "label": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
🟢db.snapshots(project, env)

List snapshots for an environment. Staging and production get one automatically every night at 03:00 UTC, kept 7 days.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪db.restore(project, env, snapshot)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "snapshot": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "snapshot"
  ]
}
🟢db.connection(project, env)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪cron.add(project, env, name, schedule, path, ...)

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".

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "name": {
      "type": "string"
    },
    "schedule": {
      "type": "string",
      "description": "e.g. \"0 9 * * 1\" or \"*/5 * * * *\""
    },
    "path": {
      "type": "string",
      "description": "e.g. /api/cron/digest"
    },
    "enabled": {
      "type": "boolean"
    }
  },
  "required": [
    "project",
    "env",
    "name",
    "schedule",
    "path"
  ]
}
⚪cron.list(project, env)

Cron jobs on an environment with last run and next run.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪cron.pause(project, env, name)

Pause a cron job (it stays defined but does not run).

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "name"
  ]
}
⚪cron.resume(project, env, name)

Resume a paused cron job.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "name"
  ]
}
🔴cron.remove(project, env, name)

Delete a cron job.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "name"
  ]
}
⚪cron.run(project, env, name)

Run a cron job now and return its result.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "name"
  ]
}
⚪cron.runs(project, env, name)

Recent runs of a cron job.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env",
    "name"
  ]
}
⚪domains.connect(project, env, host)

Map a domain you own to an environment. Point its DNS at the Plinth host; returns the record to create.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "host": {
      "type": "string",
      "description": "e.g. crm.acme.co"
    }
  },
  "required": [
    "project",
    "env",
    "host"
  ]
}
⚪domains.list(project)

Domains mapped to a project.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
🟢domains.verify(project, host)

Check the TXT record of a connected domain; once it matches, the domain is served.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "host": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "host"
  ]
}
⚪domains.remove(project, host)

Unmap a domain.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "host": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "host"
  ]
}
⚪billing.status

Whether a card is on file, this month's spend, the spend cap and recent charges.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
⚪project.upgrade(project)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
⚪project.downgrade(project)

Move a project back to the free plan. Its custom domains stop being served. The subscription shrinks with a prorated credit.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    }
  },
  "required": [
    "project"
  ]
}
🟡billing.card

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.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🟢domains.search(query)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "e.g. acme or acme.dev"
    }
  },
  "required": [
    "query"
  ]
}
⚪domains.buy(project, env, domain, years)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "domain": {
      "type": "string",
      "description": "e.g. acme.dev (run domains.search first)"
    },
    "years": {
      "type": "number",
      "description": "1-10, default 1"
    }
  },
  "required": [
    "project",
    "env",
    "domain"
  ]
}
⚪domains.orders

Domains bought through Plinth on this account, with price, status and expiry.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
⚪logs.query(project, env, since, grep, stream, ...)

Logs for an environment: app stdout/stderr, build, cron and system lines. Filter by text and stream.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "since": {
      "type": "string",
      "description": "30s, 15m, 2h, 7d (default 15m)"
    },
    "grep": {
      "type": "string"
    },
    "stream": {
      "type": "string",
      "description": "stdout, stderr, build, cron, system"
    },
    "limit": {
      "type": "number"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪metrics.get(project, env, since)

Request count, error rate and latency percentiles for an environment.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "since": {
      "type": "string"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪analytics.get(project, env, days)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "days": {
      "type": "number",
      "description": "Default 30 (Pro) or 1 (Free)"
    }
  },
  "required": [
    "project"
  ]
}
🟢seo.setup(project, env)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Default production"
    }
  },
  "required": [
    "project"
  ]
}
⚪env.status(project, env)

Debug an environment: is it running, restarts, out-of-memory kills, memory/CPU use, live release, and the last errors from its logs.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪env.restart(project, env)

Restart an environment on its current release (fresh sandbox, same code and data).

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
🟢env.exec(project, env, command, timeout_seconds)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "command": {
      "type": "string"
    },
    "timeout_seconds": {
      "type": "number"
    }
  },
  "required": [
    "project",
    "env",
    "command"
  ]
}
🟡http.probe(project, env, path, method, body, ...)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "path": {
      "type": "string",
      "description": "e.g. /api/orders?id=3"
    },
    "method": {
      "type": "string"
    },
    "body": {
      "type": "string"
    },
    "headers": {
      "type": "object"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪requests.query(project, env, since, min_status, path, ...)

Recent HTTP requests to an environment: method, path, status, time taken. Filter to failures with min_status 500, or by path.

Input Schema

{
  "type": "object",
  "properties": {
    "project": {
      "type": "string",
      "description": "Project name"
    },
    "env": {
      "type": "string",
      "description": "Environment: production, staging, or a preview name"
    },
    "since": {
      "type": "string"
    },
    "min_status": {
      "type": "number"
    },
    "path": {
      "type": "string"
    },
    "limit": {
      "type": "number"
    }
  },
  "required": [
    "project",
    "env"
  ]
}
⚪approvals.list(status)

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).

Input Schema

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "description": "pending, approved, denied, cancelled, superseded (default all)"
    }
  },
  "required": []
}
⚪approval.cancel(id)

Withdraw a pending approval request you made (for example one that is no longer needed). The owner can no longer approve it.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ]
}
🟢approval.status(id)

Check an approval. When approved, result holds the action output.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ]
}
🟡support.send(kind, title, body, project, env)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "kind": {
      "type": "string",
      "description": "bug, feature, question or other"
    },
    "title": {
      "type": "string",
      "description": "One line"
    },
    "body": {
      "type": "string",
      "description": "Details: steps, expected vs actual, commands, error text"
    },
    "project": {
      "type": "string",
      "description": "Optional project it is about"
    },
    "env": {
      "type": "string",
      "description": "Optional environment"
    }
  },
  "required": [
    "kind",
    "title",
    "body"
  ]
}
⚪support.list

Your support tickets with their status and the team's reply.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🟡webhooks.add(url, events, authorization)

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.

Input Schema

{
  "type": "object",
  "properties": {
    "url": {
      "type": "string",
      "description": "https URL"
    },
    "events": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "authorization": {
      "type": "string",
      "description": "Optional Authorization header value, e.g. \"Bearer abc\". Stored encrypted."
    }
  },
  "required": [
    "url"
  ]
}
⚪webhooks.list

Your webhooks with their last delivery status.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🔴webhooks.remove(id)

Delete a webhook.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ]
}
🟡webhooks.test

Send a test event to all your webhooks; check webhooks.list a few seconds later for the result.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🟢console.signin

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.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🟡token.rotate

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).

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
⚪agents.list

Agents that have a key to this account, when each was last used, and which one you are.

Input Schema

{
  "type": "object",
  "properties": {},
  "required": []
}
🔴agents.revoke(id)

Owner only. Remove an agent's access to this account immediately.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    }
  },
  "required": [
    "id"
  ]
}
⚪policy.set(auto_approve)

Owner only. Choose which approval types run without asking. Keys: project.create, project.delete, promote.production, migration.destructive, db.restore.production, billing.

Input Schema

{
  "type": "object",
  "properties": {
    "auto_approve": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "auto_approve"
  ]
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded72 tools