pterodactyl-mcp
Provides tools for interacting with a Pterodactyl game panel via its client and application API trees. Capabilities include managing account and server resources, files and raw contents, databases, backups, schedules and tasks, network allocations, startup variables, settings, subusers, console access over the wings websocket, and admin surfaces such as users, nodes, locations, servers, nests, and eggs. Destructive operations are denied by default unless explicitly allowlisted.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@pterodactyl-mcplist my Pterodactyl servers"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@bippy-s-ai-helpers/pterodactyl-mcp
A stdio MCP (Model Context Protocol) server for the Pterodactyl game panel, covering both API trees in one server:
the client tree (
/api/client, authenticated with aptlc_client API key), andthe application tree (
/api/application, authenticated with aptla_application API key),
speaking plain JSON-RPC 2.0 over stdio: no network listener, no HTTP framework, no config files. The MCP client spawns this binary and talks to it over stdin and stdout; every HTTP request happens inside the server process toward the panel.
Features
105 tools over both Pterodactyl API trees (65 client tree, 40 application tree at panel v1.15.x): account surfaces, server core, databases, backups, schedules and tasks, network allocations, files (including upload, download, and raw contents), startup variables, settings, subusers, an 8-tool console suite over the wings websocket, and the admin tree (users, nodes and allocations, locations, servers, server databases, nests and eggs).
Default-deny destructive gate: 21 tools classified as destructive (deletes, reinstalls, suspends, power kill, and the subuser access-grant trio) are registered but deny by default with zero panel requests until you explicitly allowlist them.
Tree toggles to control context cost: expose only the client tree, only the application tree, or both. Every disabled family registers nothing, so a partial deployment keeps the tools/list payload small.
Lean dependency set: the MCP SDK,
ws, andzodonly. No HTTP framework, no dotenv, no runtime config files.Deterministic generated docs:
docs/endpoint-reference.md(every mapped and doctrine-excluded panel endpoint with tool attribution, gate class, and route-file citation) anddocs/census.md(registry counts, LOC census, test counts) ship in the repo and regenerate byte-identically withnpm run docs.Strictly typed client core: Fractal-envelope parsing, typed error classes for 401/403, 404, 422, 429, 5xx, non-JSON bodies, and network failures, pagination with a hard page cap, and a console bridge with a bounded in-memory tail ring.
Related MCP server: PterodactylMCP
Prerequisites
Node.js 18 or newer and npm.
A reachable Pterodactyl panel (v1.15.x; built and tested against 1.15.1).
An application API key (
ptla_prefix) for the admin tree, and/or a client API key (ptlc_prefix) for the client tree; at least one is required, and only the tree(s) whose key you configured are exposed.An MCP-capable client (opencode works for sure) that can spawn a local stdio MCP server.
Installation (humans)
Step 1: get the code
Either clone with git:
git clone https://github.com/Bippy-s-AI-Helpers/pterodactyl-mcp.git
cd pterodactyl-mcpOr download the repository as a zip / copy the tree manually and cd into
the folder.
Step 2: install and build
npm install
npm run buildnpm run build compiles src/ (TypeScript, strict, NodeNext) into
dist/index.js; that file is the entrypoint your MCP configuration below
launches.
npm scripts
Script | What it does |
| TypeScript build (strict, NodeNext) into |
|
|
| the full vitest suite (mock panel + stub wings socket, loopback only) |
| eslint over src, test, scripts |
| spawns the real |
| regenerates |
| build, then typecheck, lint, test, smoke in that order |
Step 3: configure your MCP client (no keys pasted into config)
opencode style entry
Values that carry secret material reference files instead of inlining their contents; see the key handling note below the table.
"mcp": {
"pterodactyl": {
"type": "local",
"command": ["node", "~/.config/opencode/repos/pterodactyl-mcp/dist/index.js"],
"enabled": true,
"environment": {
"PTERODACTYL_URL": "https://panel.example.com",
"PTERODACTYL_CLIENT_KEY": "{file:~/.config/opencode/secrets/PTERODACTYL_CLIENT_KEY}",
"PTERODACTYL_APPLICATION_KEY": "{file:~/.config/opencode/secrets/PTERODACTYL_APPLICATION_KEY}",
"PTERODACTYL_TREES": "client,application"
}
}
}Contract notes: type is required (local); command is an array of
strings, never a single string; enabled gates the whole entry; use an
absolute path to dist/index.js if your client does not expand ~.
generic JSON MCP client entry
{
"mcpServers": {
"pterodactyl": {
"command": "node",
"args": ["/absolute/path/to/pterodactyl-mcp/dist/index.js"],
"env": {
"PTERODACTYL_URL": "https://panel.example.com",
"PTERODACTYL_CLIENT_KEY": "your-client-api-key",
"PTERODACTYL_APPLICATION_KEY": "your-application-api-key",
"PTERODACTYL_TREES": "client,application"
}
}
}
}For generic clients the two standard patterns are: environment variables
exported into the client's process environment before it spawns the
server, or a dotenv-style file that the loading shell (or the client, if
it supports envFile) applies before launch. Never commit such a file;
see SECURITY.md.
Environment variables
The server reads configuration from the environment only. There is no dotenv and no config file; a dotenv-style loader invoked by the launching shell is fine, but the server itself never opens one.
Variable | Required | Default | Meaning |
| yes | none | Panel base URL, absolute |
| one key minimum | none |
|
| one key minimum | none |
|
| no | every tree whose key is set | Comma list of |
| no | empty (deny all destructive) | Comma list of gated tool names permitted past the destructive gate; unknown names are dropped with one warning and can never enable anything; a change requires a restart |
| no |
| Permits the |
| no |
| Per request HTTP timeout in whole milliseconds (positive integer) |
| no |
| Console read window tail cap in lines (whole number between 1 and 5000) |
Startup prints exactly one redacted configuration line to stderr (key prefixes and lengths only, plus the tree list); key material is never logged, echoed into errors, or returned by any request path. stdout carries only JSON-RPC. A failed startup prints one line per configuration error to stderr and exits 1.
Key handling
Keys enter the server only through environment variables, at spawn time from your MCP client.
In opencode, the supported pattern is a
{file:PATH}reference: opencode reads the file at load time, trims it, and substitutes the raw value for the entry (a missing file fails the config load loudly, which is the intended behavior). Keep the key files themselves out of any repository and chmod them0600(and0700on the containing directory).In generic MCP clients, pass the key values in the
envmap of the entry, or export them into the client's process environment (a dotenv-style file sourced by your shell works; keep it out of every repository, keep it0600).The raw key values never appear in any configuration you commit, in any log, in any error message, or in any tool result. The startup line prints only the prefix and the length of each configured key. Key material moves strictly inside the
Authorizationheader of panel requests, so panel error bodies can never quote it back.Changing any entry your client uses to launch this server (including any
{file:}referenced key file) requires the client to reload MCP configuration, and in a typical MCP client configuration is read once at startup: after changing the entry or the key files, restart the client (in opencode, a full restart) before the change is live.
Agentic installation (fresh build agent, follow verbatim)
Read this entire README section, plus
SECURITY.md, before touching anything.Create the install directory and fetch the repo:
mkdir -p ~/.config/opencode/repos && cd ~/.config/opencode/repos && git clone https://github.com/Bippy-s-AI-Helpers/pterodactyl-mcp.git && cd pterodactyl-mcp. If the host has no git remote access, copy the repository tree manually into that directory withcp -rfrom wherever the source is available.Run
npm install(network access to the npm registry is required for the dependencies only).Run
npm run build.Run
npm run smokeand require exit code 0 (it validates handshake, tool registry, gate annotations, and redaction; no panel is touched).STOP HEREat the user breakpoint. The two API keys are user-supplied material: never fabricate, never echo, never write key-shaped values of your own. Editing the user's MCP client configuration and restarting the client are user-owned steps. Do not create themcpentry, do not setPTERODACTYL_DESTRUCTIVE_ALLOWLISTorPTERODACTYL_ALLOW_KILLyourself, and do not restart the client. Report the built path (the absolute path ofdist/index.js) and hand the user steps 7 to 9.(User) install the two panel API key files at
~/.config/opencode/secrets/PTERODACTYL_CLIENT_KEYand~/.config/opencode/secrets/PTERODACTYL_APPLICATION_KEY(raw values,0600,0700directory).(User) add the
mcpentry from the installation section above, with the absolute path from your report.(User) restart the client and confirm the server answers; the one redacted line on stderr confirms the loaded configuration.
Tool catalog summary and tree toggles
The registry closes at 105 tools:
Tree | Family | Tools |
client | account, activity list, permissions dictionary, servers list (the api-key, two-factor, ssh-keys, and account credential routes are doctrine-excluded) | 4 |
client | server core (server view, resources, activity, stdin command, power) | 5 |
client | databases | 4 |
client | backups | 7 |
client | schedules + tasks | 9 |
client | network (allocations) | 5 |
client | files (incl. upload, download URL, raw contents) | 13 |
client | startup (variables) | 2 |
client | settings | 3 |
client | console suite (websocket bridge) | 8 |
client | subusers | 5 |
admin | users | 6 |
admin | nodes + allocations | 9 |
admin | locations | 5 |
admin | servers | 11 |
admin | server databases | 5 |
admin | nests + eggs | 4 |
Total: 65 client tree + 40 application tree = 105.
PTERODACTYL_TREES semantics (code truth, src/config.ts):
unset: every tree whose key is set is exposed (client only with just a client key; both with both keys).
set to a comma list of
clientand/orapplication: exactly those trees are exposed; each named tree must have its key configured, and an unknown name is a startup error.tree gating happens at registration: a disabled family registers no tools at all, which shrinks
tools/listand the context your client spends on it.
The 21 gated tools (deny by default)
All 21 register even while denied (discoverable failure: the call returns a structured denial naming the enabling variable, with zero panel requests). 13 client tree:
server_power (kill sub-flag), database_delete, backup_restore
(truncate sub-flag), backup_delete, schedule_delete,
schedule_task_delete, allocation_delete, files_delete, files_pull,
settings_reinstall, subuser_create, subuser_update, subuser_delete
(the access-grant trio is gated because granting panel access is
consequential regardless of the HTTP verb).
8 application tree: admin_user_delete, admin_node_delete,
admin_node_allocation_delete, admin_location_delete,
admin_server_suspend, admin_server_reinstall, admin_server_delete
(the force variant is covered by the tool's single allowlist entry),
admin_server_database_delete.
The complete endpoint table (all 111 panel endpoints: method, path, tool,
gate class, exclusion reason, citation) is generated at
docs/endpoint-reference.md; registry and test counts live in
docs/census.md.
Security model
Transport: stdio only. The server never opens a network listener; the MCP client spawns it as a child process.
Tree gate at startup: a tool family registers only when its tree is enabled (
PTERODACTYL_TREESplus the key present).Discoverable denial: every gated tool that its tree permits is registered even while denied; calling it answers with a structured denial naming the enabling variable and makes zero HTTP requests.
Immutable gate snapshot: every gate decision reads a snapshot resolved once at startup, never the runtime environment, so env changes mid-session cannot flip a gate. Fail-closed: unknown or malformed allowlist entries never enable anything and are reported once at startup.
Annotations as hints, never enforcement: every tool carries accurate
readOnlyHint/destructiveHint/idempotentHintannotations; the gate decides before annotations could matter.
PTERODACTYL_DESTRUCTIVE_ALLOWLIST semantics: by default empty and every
gated tool denies. Entries must name one of the 21 gated tool names above;
anything else (a read or write tool's name, a typo, an unknown family
tool) is dropped with exactly one stderr warning and can never enable
anything. The allowlist is restart-grade: after changing it, restart the
MCP server (restart your MCP client).
PTERODACTYL_ALLOW_KILL semantics: the kill action of server_power
additionally requires this sub-flag true even when server_power itself
is allowlisted; start, stop, and restart do not need it. The
snapshot is read once at startup, so enabling it is also restart-grade.
TLS verification status of the console bridge: the ticket exchange runs
through the normal client-tree REST client, and the wings upgrade is a
plain wss/ws connection with the library default TLS verification left
strictly on (no rejectUnauthorized: false and no certificate-relaxing
environment variable exists anywhere in the code). A wrong or self-signed
certificate fails loudly as a network error.
Keys and tickets: key material exists only in the environment and inside request headers to the panel; the startup line prints prefixes and lengths only; error messages carry method, path, status, and a truncated panel message (never headers). Console tickets (short-lived JWTs from the panel) exist only in process memory while a console session is connected. Console sessions and their bounded tail rings live in memory for the server process lifetime; nothing is persisted to disk.
Testing posture
Mock-first: every vitest suite runs against the in-process mock panel and stub wings websocket server on loopback (
test/mock/); no test touches a real panel.The two route file copies under
test/fixtures/are byte-identical captures of the panel's route files with pinned sha256 digests; the drift test reconciles all 111 endpoints, method, path, tree, and citation against the route table, so a panel update that changes routes fails with the named row.npm run smokeruns the realdist/index.jsover real stdio with fake key shapes and asserts the handshake, the exact 105-tool registry, the 21 gate annotations, and the short-description doctrine (every tool describes when to call it, and carries annotations).scripts/live-smoke.mjsis the read-only battery driver for a run against a real panel; it reads key material only from the files named byPTERO_KEY_FILE_APPandPTERO_KEY_FILE_CLIENT, never prints values, appends a defensive redactor between every transcript write, and its default battery is strictly read-only (zero panel state changed). Point it at the mock first (scripts/mock-panel-start.mjsboots the same mock the test suite uses) before you ever aim it at a real panel.
Troubleshooting
Startup errors (each prints one stderr line, exit 1):
PTERODACTYL_URL is required (panel base URL, for example https://panel.example.test): the URL variable is missing or empty.PTERODACTYL_URL must be an absolute http or https URL (got: ...): malformed URL.PTERODACTYL_CLIENT_KEY must start with ptlc_ (got a different prefix, length N)(and the mirroredptla_wording for the application key) : the variables were swapped or truncated. Verify each key against Pterodactyl's key prefix conventions (ptlc_is a client key,ptla_an application key).At least one API key is required: PTERODACTYL_CLIENT_KEY (ptlc_, client tree) and/or PTERODACTYL_APPLICATION_KEY (ptla_, application tree): both missing.PTERODACTYL_TREES has an unknown tree name (got: X; expected: client, application): typo in the tree list.PTERODACTYL_TREES names the client tree but PTERODACTYL_CLIENT_KEY is not set(and the application-tree mirror) : the tree list names a tree with no key configured.pteromcp gating: dropped unknown PTERODACTYL_DESTRUCTIVE_ALLOWLIST entries (...): one warning line; the dropped names never enable anything. Fix the names to the gated tool names above.In opencode a missing
{file:...}key file fails the config load loudly at startup: restore the file (raw value only) and restart.
Runtime:
A gated tool call answers
DENIED (destructive gate): "<tool>" is registered but its gate class is G (destructive), request row <method> <path>, citation <route line>. By default PTERODACTYL_DESTRUCTIVE_ALLOWLIST is empty and every gated tool is denied. To enable exactly this tool, set PTERODACTYL_DESTRUCTIVE_ALLOWLIST to a comma list containing "<tool>" and restart the MCP server. No panel request was made.: expected default-deny behavior; add the tool toPTERODACTYL_DESTRUCTIVE_ALLOWLISTand restart the client.DENIED (kill sub-gate): the "kill" action of "server_power" additionally requires PTERODACTYL_ALLOW_KILL=true ...: allowlistingserver_powercovers start, stop, and restart; killing additionally needs the sub-flag.401/403 answers from the panel surface as authentication errors (
PteroAuthError-class text with method, path, and status): the key is wrong, expired, or lacks the subuser permissions the route needs.429 answers surface as rate-limit errors carrying the panel's
Retry-Afterhint.502-style HTML from a reverse proxy answers as a non-JSON-body error (the guard exists exactly for that case).
Certificate failures on the console websocket surface as console connect network errors; the bridge never relaxes TLS verification.
MCP config loads at client startup only: after any server-side env change, restart the client before retesting.
License
MIT; see LICENSE and CHANGELOG.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
Official Porkbun MCP server: domains, DNS, SSL, hosting and Cloudflare via the Porkbun API.
Manage game servers, configurations, players, and groups through the GameServerApp MCP server.
One OAuth connector for your team's remote MCP servers, with Tool Packs, guardrails and logs.
Related MCP Servers
- AlicenseAqualityNot gradedmaintenanceMCP server for Pterodactyl and Pelican game server panels. 73 tools for server management, power control, file operations, backups, schedules, databases, users, nodes, and eggs.3414 npm-
- AlicenseDqualityDmaintenanceMCP server for managing Pterodactyl game panel resources (users, servers, nodes, locations, etc.) via the Application API.503MIT
- AlicenseNot gradedqualityDmaintenanceEnables managing Pterodactyl Game Panel servers via Client and Application APIs, including power actions, files, databases, backups, schedules, and administrative operations.115 npmMIT
- AlicenseNot gradedqualityBmaintenanceAn MCP server that lets AI clients manage game servers hosted on a Calagopus panel: list and inspect servers, read logs and files, edit configs, run console commands and power actions, and search, install, update, or remove plugins and mods from Modrinth and CurseForge. Every action is bounded by the user's panel API key and server permissions, with read-only/destructive hints and token-efficient tool responses.MIT