Command Palette

Search for a command to run...

UnylyUnyly
Browse all

helbertparanhos/easypanel-mcp-server

FreeNot checked

Full Easypanel control from Claude Code and Cursor — 37 tools for deployments, services, env vars, logs, domains, databases and monitoring. Safety guards requir

GitHubEmbed

About

Full Easypanel control from Claude Code and Cursor — 37 tools for deployments, services, env vars, logs, domains, databases and monitoring. Safety guards require explicit confirmation for all destructive actions.

README

MCP Server for full Easypanel control via Claude Code, Cursor and Claude Desktop.

npm version License: MIT GitHub Stars GitHub Forks GitHub Issues CI Glama Quality

TypeScript Node.js MCP Claude Code Cursor Claude Desktop

Instagram YouTube LinkedIn Buy Me A Coffee Strat Academy


What is this

easypanel-mcp-server connects Claude Code, Cursor and Claude Desktop directly to your Easypanel instance — a modern Docker-based server control panel — through the Model Context Protocol.

Instead of switching between your editor and the Easypanel dashboard, you control everything from inside Claude: deploy from GitHub, update env vars, read live logs, exec into containers, manage domains, databases, volumes and ports, set resource limits, run Docker maintenance and monitor your server — all in natural language.

It maps the Easypanel API to 57 typed tools across 15 categories, plus a single easypanel_raw escape hatch that reaches any of Easypanel's ~375 API operations for everything not covered by a dedicated tool. It speaks all three API generations — the tRPC API of panels ≤ 2.30, the RPC layer of 2.31–2.32, and the public API introduced in Easypanel 2.33 — auto-detecting which one your panel uses. Every destructive action is gated behind an explicit confirmation, every response opens with a context banner so Claude always knows what it is touching, and an optional read-only mode lets you connect safely to a production panel.

📖 API reference: docs/easypanel-api.md — architecture, the API generations, confirmed operations mapped tool-by-tool, and how to discover new ones.


Compatibility

Easypanel changed its API twice in quick succession:

  • 2.31 replaced the internal tRPC API with an RPC layer (/api/rpc/*). On panels ≥ 2.31, every v1.x call that carries parameters fails with 400 Input validation failed.
  • 2.33 shipped a documented public API (/api/<operation>, GET for reads, POST for writes) and stated that the old internal API "may change without notice and should not be relied upon". v3 targets the public API on those panels.
Your Easypanel version Use
any (recommended) easypanel-mcp-server@latest (v3.x) — auto-detects the generation, works on all three
≤ 2.30.x only, pinned easypanel-mcp-server@legacy (v1.3.x) — frozen tRPC-only line, last validated against v2.30.1

v3 detects the generation with a single probe request on first call (cached) and logs the panel version to stderr. To skip detection, set EASYPANEL_API_FLAVOR to trpc (≤ 2.30), rpc (2.31–2.32) or public (≥ 2.33).

Upgrading from v2? If you pinned EASYPANEL_API_FLAVOR=rpc to work around the 2.32 issues, remove it — otherwise the client stays on the internal API that Easypanel now declares unstable.

This MCP vs. Easypanel's built-in MCP

Easypanel 2.33 also ships its own MCP endpoint (/api/mcp, connection details next to your API key). It's a thin wrapper over the public API. This server is a different trade-off:

Easypanel built-in MCP easypanel-mcp-server
Runtime container logs ✅ via /ws/serviceLogs (no Loki/licence needed)
Exec inside a container exec_in_container with destructive-command gate
Live Docker events get_docker_events
Read-only mode MCP_ACCESS_MODE=readonly blocks every write at the source
Confirmation gate on destructive ops confirm: "CONFIRMO"
Secret redaction (list_users) ✅ strips apiToken / twoFactorSecret
Env var read-modify-write ✅ never clobbers other variables
Connection-string building inspect_database
Coverage of every API operation ✅ via easypanel_raw
Zero install needs npx/node

Using both at once is fine — they don't conflict.


Prerequisites

  • Easypanel instance running and accessible
  • API token — generate at Easypanel → Settings → API → Generate Token
  • Node.js ≥ 18 and Claude Code, Cursor or Claude Desktop

Quick start

Option A — npx (no install needed)

Add .mcp.json to your project root:

{
  "mcpServers": {
    "easypanel-mcp": {
      "command": "npx",
      "args": ["-y", "easypanel-mcp-server"],
      "env": {
        "EASYPANEL_URL": "https://your-panel.example.com",
        "EASYPANEL_TOKEN": "your-api-token"
      }
    }
  }
}

Option B — local build

git clone https://github.com/helbertparanhos/easypanel-mcp-server
cd easypanel-mcp-server
npm install && npm run build
{
  "mcpServers": {
    "easypanel-mcp": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/easypanel-mcp-server/dist/index.js"],
      "env": {
        "EASYPANEL_URL": "https://your-panel.example.com",
        "EASYPANEL_TOKEN": "your-api-token"
      }
    }
  }
}

Cursor — reuse env vars across projects

In Cursor Settings → Tools & MCPs → Environment Variables, set:

  • EASYPANEL_URL = https://your-panel.example.com
  • EASYPANEL_TOKEN = your-api-token

Then your .cursor/mcp.json uses references that apply automatically to every project:

{
  "mcpServers": {
    "easypanel-mcp": {
      "command": "npx",
      "args": ["-y", "easypanel-mcp-server"],
      "env": {
        "EASYPANEL_URL": "${EASYPANEL_URL}",
        "EASYPANEL_TOKEN": "${EASYPANEL_TOKEN}"
      }
    }
  }
}

Environment variables

Variable Required Default Description
EASYPANEL_URL Panel URL, no trailing slash (e.g. https://panel.example.com)
EASYPANEL_TOKEN API token (Easypanel → Settings → API → Generate Token)
MCP_ACCESS_MODE full Set to readonly to block all writes (curated tools and easypanel_raw). Reads stay available — ideal for connecting to a production panel for inspection only.
EASYPANEL_API_FLAVOR (auto) Force the panel's API generation instead of auto-detecting: trpc (≤ 2.30), rpc (2.31–2.32) or public (≥ 2.33). Aliases: legacy / modern. Leave unset unless you have a reason — a stale rpc pin keeps a 2.33 panel on the internal API.
EASYPANEL_RAW_DISABLED (enabled) Set to 1 to fully disable the easypanel_raw escape hatch. Recommended when the MCP is exposed to untrusted content (prompt-injection risk), since easypanel_raw reads can return secrets and are not covered by read-only mode.

Adding context to a project

Place this in your project's CLAUDE.md so Claude knows which Easypanel project and service it should operate on by default:

## Easypanel
Project: `my-project` | Service: `my-api` | Branch: `main`
Repo: `owner/repo`

No folder copying needed — one MCP install serves all your projects.


Use cases

"Deploy my app" — Claude lists projects, inspects the current service, triggers deploy_service, then watches list_actions until it completes.

"Why is my service down?" — Claude calls get_service_error, get_service_logs and get_build_logs, and can exec_in_container to inspect files/env live.

"Add DATABASE_URL to staging" — Claude reads current env vars with get_env_vars, adds only the new key with set_env_var (never wipes others), and reminds you to redeploy.

"Give this service 512MB and half a core" — Claude calls set_service_resources (reads current limits and merges your change) and reminds you to restart.

"Persist /app/data and expose port 5432" — Claude calls create_mount (named volume) and create_port, both applied on the next deploy.

"My disk is full" — Claude runs get_storage_stats, then cleanup_docker_images or prune_docker (with confirmation) to reclaim space.

"Show me the Traefik dashboard config" — for anything without a dedicated tool, Claude uses easypanel_raw to call the procedure directly.


Available tools (57)

Category Tools
Projects list_projects, get_project, create_project, delete_project ⚠️
Services inspect_service, create_service, rename_service ⚠️, destroy_service ⚠️, deploy_service, start_service, stop_service ⚠️, restart_service, get_service_error, get_exposed_ports, get_service_notes, set_service_notes, set_service_resources
Deploy / GitHub set_source_github, set_source_image, enable_github_deploy, disable_github_deploy, list_actions, get_action
Env Vars get_env_vars, set_env_var, delete_env_var ⚠️
Logs get_service_logs, get_build_logs, get_system_stats
Containers list_containers, exec_in_container ⚠️, get_docker_events
Domains list_domains, add_domain, remove_domain ⚠️, set_primary_domain
Databases create_database, inspect_database, destroy_database ⚠️
Volumes / Mounts list_mounts, create_mount ⚠️
Ports list_ports, create_port ⚠️
Compose create_compose, inspect_compose, deploy_compose
Monitoring get_docker_stats, get_storage_stats, get_service_stats
Maintenance prune_docker ⚠️, cleanup_docker_images
Server / Infra list_users, list_certificates, list_nodes, restart_panel ⚠️, reboot_server ⚠️
Raw access easypanel_raw ⚠️

⚠️ = requires confirm: "CONFIRMO". For exec_in_container, create_mount, create_port and easypanel_raw the confirmation is conditional (only for destructive commands, sensitive host-path bind mounts, privileged ports < 1024, and writes respectively).

Full tool descriptions with parameters are in llms.txt. For the underlying API (all generations), see docs/easypanel-api.md.

easypanel_raw — reach any of the ~375 operations

Covering every Easypanel operation with a typed tool isn't practical, so anything without a dedicated tool is reachable directly:

// read (default) — flat name, as documented in your panel's /api/openapi.json
{ "procedure": "listCertificates" }
{ "procedure": "getPanelDomain" }
{ "procedure": "listVolumeBackups", "input": { "projectName": "app", "serviceName": "api" } }

// the old dot notation still works and is translated
{ "procedure": "certificates.listCertificates" }

// write — requires isMutation:true AND confirm:"CONFIRMO"
{ "procedure": "setLogoSettings", "input": { /* ... */ },
  "isMutation": true, "confirm": "CONFIRMO" }

Areas only reachable via easypanel_raw: Traefik, branding, Cloudflare Tunnel, Box, middlewares, notifications, volume/database backups, WordPress, storage providers, Docker builders, Git keys, cluster and update management. To discover names, read GET <your-panel>/api/openapi.json.

The client classifies each operation against the panel's own OpenAPI spec, fail-closed: a read only executes if the spec says it's a read, so writes can't sneak past readonly mode or the confirmation gate — and the reverse is caught too (calling a read with isMutation:true is refused with a clear message). On 2.33+ that classification is exact, since the public API declares GET for reads and POST for writes. On 2.31 it's the documented HTTP method; on 2.32, where the spec is POST-only and carries no such marker, the client falls back to the panel's naming convention (get/list/inspect/check/query/search = read, anything else = write), restricted to operations present in the spec.

One deliberate exception: on 2.33+ the panel validates query params without type coercion, so ?limit=5 arrives as the string "5" and is rejected. Whenever an input carries a non-string value, the client routes that read through the internal /api/rpc transport (which sends JSON in the body) and logs the reason to stderr. The read/write classification still comes from the spec first, so the guard is unaffected.


Safety features

Context banner

Every response that touches a specific project/service starts with:

[Contexto ativo: projeto="my-project" | serviço="my-api"]

Claude always knows what it is modifying before taking any action.

Confirmation guard

Destructive or production-impacting actions return BLOQUEADO until they receive confirm: "CONFIRMO":

{
  "status": "BLOQUEADO",
  "acao": "stop_service",
  "alvo": "serviço \"api\" (usuários perderão acesso)",
  "instrucao": "Para confirmar, passe o parâmetro: confirm: \"CONFIRMO\"",
  "aviso": "⚠️  Esta ação pode ser IRREVERSÍVEL. Confirme apenas se tiver certeza."
}

This gates project/service deletion, stop/rename, env/domain removal, database destruction, the global server ops (prune_docker, restart_panel, reboot_server), and — conditionally — dangerous container commands, sensitive bind mounts, privileged ports and raw mutations.

Read-only mode

Set MCP_ACCESS_MODE=readonly to block every write at the source (client.mutate), covering both curated tools and easypanel_raw. Reads remain available — perfect for a production panel you only want to inspect.

Raw escape-hatch controls

easypanel_raw validates the operation name (flat or namespace.procedure, no path/query injection), requires the input to be an object (≤ 50KB), and demands CONFIRMO for any mutation. Set EASYPANEL_RAW_DISABLED=1 to turn it off entirely.

Secret redaction

list_users strips apiToken, twoFactorSecret and password fields before returning — only id, email, admin, twoFactorEnabled and createdAt reach the model.

Safe env vars (read-modify-write)

set_env_var and delete_env_var read the current state, apply only the requested change, and write back. The Easypanel API replaces the entire env string on every update — without this protection it is easy to accidentally wipe all variables at once.

Sensitive value masking

get_env_vars masks values whose key matches *SECRET*, *PASSWORD*, *TOKEN*, *KEY* by default. Pass include_values: true to reveal.

Token never leaks

HTTP errors and WebSocket failures are logged to stderr and surfaced to the model as a generic message — the bearer token (sent in the WebSocket query string, as Easypanel requires) never reaches the model context.

Input validation

projectName / serviceName are validated against ^[a-z0-9][a-z0-9_-]*$ before being used to build a Docker service name or WebSocket query (defense-in-depth against target confusion / parameter injection). Ports are validated as integers 1–65535; resource values must be positive numbers.


Companion skill /ep

Install the workflow skill for guided deploy operations in Claude Code:

mkdir -p ~/.claude/skills/ep
cp skill/SKILL.md ~/.claude/skills/ep/SKILL.md

Then use /ep for an interactive deploy workflow without needing to remember tool names.


How it works

The Easypanel panel talks to its backend over tRPC (/api/trpc/<router>.<procedure>), not a public REST API. This server uses the same endpoints:

  • Reads are tRPC queries; writes are tRPC mutations — see docs/easypanel-api.md.
  • Live logs, container exec and Docker events use the panel's WebSocket channels (/ws/serviceLogs, /ws/containerShell, /ws/dockerEvents) — the same ones the UI uses — so they work without the licensed Advanced Logs (Loki).
  • A few input schemas (mounts, ports, resources) were validated against a live Easypanel and are documented in the API reference.

Known limitations

  • WordPress / Box service types — not exposed as dedicated tools; reach them via easypanel_raw (e.g. inspectWordPressService, createBoxService).
  • easypanel_raw reads bypass read-only mode — read-only blocks writes only. A raw read can return sensitive data; use EASYPANEL_RAW_DISABLED=1 in untrusted environments.
  • Cluster toolslist_nodes returns the local node only on single-server setups (no Swarm cluster).
  • Docker events are real-time only (no history) — an idle server may return an empty window.

Testing without Claude

npx @modelcontextprotocol/inspector dist/index.js

Opens a browser UI where you can call any tool manually and inspect the response.


Comparison with similar packages

Feature easypanel-mcp-server easypanel-mcp (sitp2k)
Curated tools 57 ~15
Raw access to all ~375 API operations ✅ (easypanel_raw)
Auth method Bearer token Email + password
Confirmation guard
Read-only mode
Container exec + live logs (WebSocket)
Volumes / ports / compose / resources
Server maintenance (prune / reboot)
Safe env update (read-modify-write)
Secret redaction & value masking
Companion Claude skill
Known limitations documented

🤝 Contributing

Contributions are welcome! See CONTRIBUTING.md for how to add tools, report bugs and open PRs.


👤 Author

Created by Helbert Paranhos from Strat Academy.

Instagram YouTube LinkedIn Buy Me A Coffee

If this project was useful, consider giving it a ⭐ and following Strat Academy for more AI automation content.


📄 License

MIT © Helbert Paranhos / Strat Academy

See LICENSE for details.

from github.com/helbertparanhos/easypanel-mcp-server

Installing helbertparanhos/easypanel-mcp-server

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/helbertparanhos/easypanel-mcp-server

FAQ

Is helbertparanhos/easypanel-mcp-server MCP free?

Yes, helbertparanhos/easypanel-mcp-server MCP is free — one-click install via Unyly at no cost.

Does helbertparanhos/easypanel-mcp-server need an API key?

No, helbertparanhos/easypanel-mcp-server runs without API keys or environment variables.

Is helbertparanhos/easypanel-mcp-server hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install helbertparanhos/easypanel-mcp-server in Claude Desktop, Claude Code or Cursor?

Open helbertparanhos/easypanel-mcp-server on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare helbertparanhos/easypanel-mcp-server with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs